Merge ^/head r323559 through r325504.
This commit is contained in:
commit
c2c014f24c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/bsd_rdma_4_9/; revision=325505
40
Makefile
40
Makefile
@ -34,12 +34,16 @@
|
||||
# for world and kernel targets.
|
||||
# toolchains - Build a toolchain for all world and kernel targets.
|
||||
# xdev - xdev-build + xdev-install for the architecture
|
||||
# specified with XDEV and XDEV_ARCH.
|
||||
# specified with TARGET and TARGET_ARCH.
|
||||
# xdev-build - Build cross-development tools.
|
||||
# xdev-install - Install cross-development tools.
|
||||
# xdev-links - Create traditional links in /usr/bin for cc, etc
|
||||
# native-xtools - Create host binaries that produce target objects
|
||||
# for use in qemu user-mode jails.
|
||||
# for use in qemu user-mode jails. TARGET and
|
||||
# TARGET_ARCH should be defined.
|
||||
# native-xtools-install
|
||||
# - Install the files to the given DESTDIR/NXTP where
|
||||
# NXTP defaults to /nxb-bin.
|
||||
#
|
||||
# "quick" way to test all kernel builds:
|
||||
# _jflag=`sysctl -n hw.ncpu`
|
||||
@ -118,6 +122,7 @@
|
||||
TGTS= all all-man buildenv buildenvvars buildkernel buildworld \
|
||||
check check-old check-old-dirs check-old-files check-old-libs \
|
||||
checkdpadd checkworld clean cleandepend cleandir cleanworld \
|
||||
cleanuniverse \
|
||||
delete-old delete-old-dirs delete-old-files delete-old-libs \
|
||||
depend distribute distributekernel distributekernel.debug \
|
||||
distributeworld distrib-dirs distribution doxygen \
|
||||
@ -130,11 +135,16 @@ TGTS= all all-man buildenv buildenvvars buildkernel buildworld \
|
||||
_build-tools _build-metadata _cross-tools _includes _libraries \
|
||||
build32 distribute32 install32 buildsoft distributesoft installsoft \
|
||||
builddtb xdev xdev-build xdev-install \
|
||||
xdev-links native-xtools stageworld stagekernel stage-packages \
|
||||
xdev-links native-xtools native-xtools-install stageworld stagekernel \
|
||||
stage-packages \
|
||||
create-packages-world create-packages-kernel create-packages \
|
||||
packages installconfig real-packages sign-packages package-pkg \
|
||||
print-dir test-system-compiler
|
||||
|
||||
# These targets require a TARGET and TARGET_ARCH be defined.
|
||||
XTGTS= native-xtools native-xtools-install xdev xdev-build xdev-install \
|
||||
xdev-links
|
||||
|
||||
# XXX: r156740: This can't work since bsd.subdir.mk is not included ever.
|
||||
# It will only work for SUBDIR_TARGETS in make.conf.
|
||||
TGTS+= ${SUBDIR_TARGETS}
|
||||
@ -179,7 +189,7 @@ META_TGT_WHITELIST+= \
|
||||
|
||||
PATH= /sbin:/bin:/usr/sbin:/usr/bin
|
||||
MAKEOBJDIRPREFIX?= /usr/obj
|
||||
_MAKEOBJDIRPREFIX!= /usr/bin/env -i PATH=${PATH} MK_AUTO_OBJ=no ${MAKE} \
|
||||
_MAKEOBJDIRPREFIX!= /usr/bin/env -i PATH=${PATH} ${MAKE} MK_AUTO_OBJ=no \
|
||||
${.MAKEFLAGS:MMAKEOBJDIRPREFIX=*} __MAKE_CONF=${__MAKE_CONF} \
|
||||
-f /dev/null -V MAKEOBJDIRPREFIX dummy
|
||||
.if !empty(_MAKEOBJDIRPREFIX)
|
||||
@ -199,7 +209,7 @@ WANT_MAKE_VERSION= 20160604
|
||||
# 20160220 - support .dinclude for FAST_DEPEND.
|
||||
WANT_MAKE_VERSION= 20160220
|
||||
.endif
|
||||
MYMAKE= ${MAKEOBJDIRPREFIX}${.CURDIR}/make.${MACHINE}/${WANT_MAKE}
|
||||
MYMAKE= ${OBJROOT}make.${MACHINE}/${WANT_MAKE}
|
||||
.if defined(.PARSEDIR)
|
||||
HAVE_MAKE= bmake
|
||||
.else
|
||||
@ -270,6 +280,11 @@ _TARGET= ${XDEV}
|
||||
.if defined(XDEV_ARCH)
|
||||
_TARGET_ARCH= ${XDEV_ARCH}
|
||||
.endif
|
||||
# Some targets require a set TARGET/TARGET_ARCH, check before the default
|
||||
# MACHINE and after the compatibility handling.
|
||||
.if !defined(_TARGET) || !defined(_TARGET_ARCH)
|
||||
${XTGTS}: _assert_target
|
||||
.endif
|
||||
# Otherwise, default to current machine type and architecture.
|
||||
_TARGET?= ${MACHINE}
|
||||
_TARGET_ARCH?= ${MACHINE_ARCH}
|
||||
@ -278,6 +293,14 @@ _TARGET_ARCH?= ${MACHINE_ARCH}
|
||||
.SILENT:
|
||||
.endif
|
||||
|
||||
_assert_target: .PHONY .MAKE
|
||||
.for _tgt in ${XTGTS}
|
||||
.if make(${_tgt})
|
||||
@echo "*** Error: Both TARGET and TARGET_ARCH must be defined for \"${_tgt}\" target"
|
||||
@false
|
||||
.endif
|
||||
.endfor
|
||||
|
||||
#
|
||||
# Make sure we have an up-to-date make(1). Only world and buildworld
|
||||
# should do this as those are the initial targets used for upgrades.
|
||||
@ -384,10 +407,13 @@ upgrade_checks: .PHONY
|
||||
# headers, libraries and tools. Also, allow the location of
|
||||
# the system bsdmake-like utility to be overridden.
|
||||
#
|
||||
MMAKEENV= MAKEOBJDIRPREFIX=${MYMAKE:H} \
|
||||
MMAKEENV= \
|
||||
DESTDIR= \
|
||||
INSTALL="sh ${.CURDIR}/tools/install.sh"
|
||||
MMAKE= ${MMAKEENV} ${MAKE} \
|
||||
OBJTOP=${MYMAKE:H}/obj \
|
||||
OBJROOT='$${OBJTOP}/' \
|
||||
MAKEOBJDIRPREFIX= \
|
||||
MAN= -DNO_SHARED \
|
||||
-DNO_CPU_CFLAGS -DNO_WERROR \
|
||||
-DNO_SUBDIR \
|
||||
@ -435,7 +461,7 @@ worlds: .PHONY
|
||||
.if make(universe) || make(universe_kernels) || make(tinderbox) || make(targets)
|
||||
TARGETS?=amd64 arm arm64 i386 mips powerpc riscv sparc64
|
||||
_UNIVERSE_TARGETS= ${TARGETS}
|
||||
TARGET_ARCHES_arm?= arm armeb armv6
|
||||
TARGET_ARCHES_arm?= arm armeb armv6 armv7
|
||||
TARGET_ARCHES_arm64?= aarch64
|
||||
TARGET_ARCHES_mips?= mipsel mips mips64el mips64 mipsn32 mipselhf mipshf mips64elhf mips64hf
|
||||
TARGET_ARCHES_powerpc?= powerpc powerpc64 powerpcspe
|
||||
|
513
Makefile.inc1
513
Makefile.inc1
@ -78,18 +78,11 @@ MK_CLANG_BOOTSTRAP= no
|
||||
MK_GCC_BOOTSTRAP= no
|
||||
.endif
|
||||
|
||||
MAKEOBJDIRPREFIX?= /usr/obj
|
||||
.if ${MACHINE} == ${TARGET} && ${MACHINE_ARCH} == ${TARGET_ARCH} && !defined(CROSS_BUILD_TESTING)
|
||||
OBJTREE= ${MAKEOBJDIRPREFIX}
|
||||
.else
|
||||
OBJTREE= ${MAKEOBJDIRPREFIX}/${TARGET}.${TARGET_ARCH}
|
||||
.endif
|
||||
|
||||
# Pull in compiler metadata from buildworld/toolchain if possible to avoid
|
||||
# running CC from bsd.compiler.mk.
|
||||
.if make(installworld) || make(install) || make(distributeworld) || \
|
||||
make(stageworld)
|
||||
.-include "${OBJTREE}${.CURDIR}/compiler-metadata.mk"
|
||||
.-include "${OBJTOP}/compiler-metadata.mk"
|
||||
.endif
|
||||
|
||||
# Pull in COMPILER_TYPE and COMPILER_FREEBSD_VERSION early.
|
||||
@ -133,7 +126,7 @@ WANT_COMPILER_VERSION!= \
|
||||
# TARGET_ARCH!=MACHINE_ARCH.
|
||||
.if ${MK_SYSTEM_COMPILER} == "yes" && \
|
||||
(${MK_CLANG_BOOTSTRAP} == "yes" || ${MK_GCC_BOOTSTRAP} == "yes") && \
|
||||
!make(showconfig) && !make(native-xtools) && !make(xdev*) && \
|
||||
!make(showconfig) && !make(xdev*) && \
|
||||
${WANT_COMPILER_TYPE} == ${COMPILER_TYPE} && \
|
||||
(${COMPILER_TYPE} == "clang" || ${TARGET_ARCH} == ${MACHINE_ARCH}) && \
|
||||
${COMPILER_VERSION} == ${WANT_COMPILER_VERSION} && \
|
||||
@ -308,7 +301,7 @@ CLEANDIR= cleandir
|
||||
|
||||
.if defined(WORLDFAST)
|
||||
NO_CLEAN= t
|
||||
NO_OBJ= t
|
||||
NO_OBJWALK= t
|
||||
.endif
|
||||
|
||||
.if ${MK_META_MODE} == "yes"
|
||||
@ -319,11 +312,11 @@ NO_OBJ= t
|
||||
NO_CLEAN= t
|
||||
.endif
|
||||
.endif
|
||||
.if defined(NO_OBJ) || ${MK_AUTO_OBJ} == "yes"
|
||||
NO_OBJ= t
|
||||
.if defined(NO_OBJWALK) || ${MK_AUTO_OBJ} == "yes"
|
||||
NO_OBJWALK= t
|
||||
NO_KERNELOBJ= t
|
||||
.endif
|
||||
.if !defined(NO_OBJ)
|
||||
.if !defined(NO_OBJWALK)
|
||||
_obj= obj
|
||||
.endif
|
||||
|
||||
@ -365,11 +358,11 @@ OSRELDATE= 0
|
||||
|
||||
# Set VERSION for CTFMERGE to use via the default CTFFLAGS=-L VERSION.
|
||||
.if !defined(_REVISION)
|
||||
_REVISION!= MK_AUTO_OBJ=no ${MAKE} -C ${SRCDIR}/release -V REVISION
|
||||
_REVISION!= ${MAKE} -C ${SRCDIR}/release MK_AUTO_OBJ=no -V REVISION
|
||||
.export _REVISION
|
||||
.endif
|
||||
.if !defined(_BRANCH)
|
||||
_BRANCH!= MK_AUTO_OBJ=no ${MAKE} -C ${SRCDIR}/release -V BRANCH
|
||||
_BRANCH!= ${MAKE} -C ${SRCDIR}/release MK_AUTO_OBJ=no -V BRANCH
|
||||
.export _BRANCH
|
||||
.endif
|
||||
.if !defined(SRCRELDATE)
|
||||
@ -398,6 +391,7 @@ KNOWN_ARCHES?= aarch64/arm64 \
|
||||
arm \
|
||||
armeb/arm \
|
||||
armv6/arm \
|
||||
armv7/arm \
|
||||
i386 \
|
||||
mips \
|
||||
mipsel/mips \
|
||||
@ -438,8 +432,8 @@ _TARGET_CPUTYPE=${TARGET_CPUTYPE}
|
||||
.else
|
||||
_TARGET_CPUTYPE=dummy
|
||||
.endif
|
||||
_CPUTYPE!= MK_AUTO_OBJ=no MAKEFLAGS= CPUTYPE=${_TARGET_CPUTYPE} ${MAKE} \
|
||||
-f /dev/null -m ${.CURDIR}/share/mk -V CPUTYPE
|
||||
_CPUTYPE!= MAKEFLAGS= CPUTYPE=${_TARGET_CPUTYPE} ${MAKE} -f /dev/null \
|
||||
-m ${.CURDIR}/share/mk MK_AUTO_OBJ=no -V CPUTYPE
|
||||
.if ${_CPUTYPE} != ${_TARGET_CPUTYPE}
|
||||
.error CPUTYPE global should be set with ?=.
|
||||
.endif
|
||||
@ -449,7 +443,7 @@ BUILD_ARCH!= uname -p
|
||||
.error To cross-build, set TARGET_ARCH.
|
||||
.endif
|
||||
.endif
|
||||
WORLDTMP= ${OBJTREE}${.CURDIR}/tmp
|
||||
WORLDTMP?= ${OBJTOP}/tmp
|
||||
BPATH= ${CCACHE_WRAPPER_PATH_PFX}${WORLDTMP}/legacy/usr/sbin:${WORLDTMP}/legacy/usr/bin:${WORLDTMP}/legacy/bin
|
||||
XPATH= ${WORLDTMP}/usr/sbin:${WORLDTMP}/usr/bin
|
||||
STRICTTMPPATH= ${BPATH}:${XPATH}
|
||||
@ -507,7 +501,7 @@ MINIMUM_SUPPORTED_OSREL?= 900044
|
||||
MINIMUM_SUPPORTED_REL?= 9.1
|
||||
|
||||
# Common environment for world related stages
|
||||
CROSSENV+= MAKEOBJDIRPREFIX=${OBJTREE} \
|
||||
CROSSENV+= \
|
||||
MACHINE_ARCH=${TARGET_ARCH} \
|
||||
MACHINE=${TARGET} \
|
||||
CPUTYPE=${TARGET_CPUTYPE}
|
||||
@ -527,6 +521,9 @@ BMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \
|
||||
MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}"
|
||||
# need to keep this in sync with targets/pseudo/bootstrap-tools/Makefile
|
||||
BSARGS= DESTDIR= \
|
||||
OBJTOP='${WORLDTMP}/obj-tools' \
|
||||
OBJROOT='$${OBJTOP}/' \
|
||||
MAKEOBJDIRPREFIX= \
|
||||
BOOTSTRAPPING=${OSRELDATE} \
|
||||
BWPHASE=${.TARGET:C,^_,,} \
|
||||
SSP_CFLAGS= \
|
||||
@ -537,12 +534,12 @@ BSARGS= DESTDIR= \
|
||||
MK_LLDB=no MK_TESTS=no \
|
||||
MK_INCLUDES=yes
|
||||
|
||||
BMAKE= MAKEOBJDIRPREFIX=${WORLDTMP} \
|
||||
BMAKE= \
|
||||
${BMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \
|
||||
${BSARGS}
|
||||
|
||||
# build-tools stage
|
||||
TMAKE= MAKEOBJDIRPREFIX=${OBJTREE} \
|
||||
TMAKE= \
|
||||
${BMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \
|
||||
TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \
|
||||
DESTDIR= \
|
||||
@ -555,7 +552,8 @@ TMAKE= MAKEOBJDIRPREFIX=${OBJTREE} \
|
||||
MK_LLDB=no MK_TESTS=no
|
||||
|
||||
# cross-tools stage
|
||||
XMAKE= TOOLS_PREFIX=${WORLDTMP} ${BMAKE} \
|
||||
# TOOLS_PREFIX set in BMAKE
|
||||
XMAKE= ${BMAKE} \
|
||||
TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \
|
||||
MK_GDB=no MK_LLD_IS_LD=${MK_LLD_BOOTSTRAP} MK_TESTS=no
|
||||
|
||||
@ -563,9 +561,12 @@ XMAKE= TOOLS_PREFIX=${WORLDTMP} ${BMAKE} \
|
||||
KTMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \
|
||||
PATH=${BPATH}:${PATH} \
|
||||
WORLDTMP=${WORLDTMP}
|
||||
KTMAKE= TOOLS_PREFIX=${WORLDTMP} MAKEOBJDIRPREFIX=${WORLDTMP} \
|
||||
KTMAKE= TOOLS_PREFIX=${WORLDTMP} \
|
||||
${KTMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \
|
||||
DESTDIR= \
|
||||
OBJTOP='${WORLDTMP}/obj-kernel-tools' \
|
||||
OBJROOT='$${OBJTOP}/' \
|
||||
MAKEOBJDIRPREFIX= \
|
||||
BOOTSTRAPPING=${OSRELDATE} \
|
||||
SSP_CFLAGS= \
|
||||
MK_HTML=no -DNO_LINT MK_MAN=no \
|
||||
@ -614,7 +615,7 @@ BFLAGS+= -B${CROSS_BINUTILS_PREFIX}
|
||||
BFLAGS+= -B${WORLDTMP}/usr/bin
|
||||
.endif
|
||||
.if ${TARGET} == "arm"
|
||||
.if ${TARGET_ARCH:Marmv6*} != "" && ${TARGET_CPUTYPE:M*soft*} == ""
|
||||
.if ${TARGET_ARCH:Marmv[67]*} != "" && ${TARGET_CPUTYPE:M*soft*} == ""
|
||||
TARGET_ABI= gnueabihf
|
||||
.else
|
||||
TARGET_ABI= gnueabi
|
||||
@ -636,6 +637,8 @@ XCXXFLAGS+= -isystem ${WORLDTMP}/usr/include/c++/v1 -std=c++11 \
|
||||
.endif
|
||||
.elif ${WANT_COMPILER_TYPE} == clang || \
|
||||
(defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == clang)
|
||||
MACHINE_ABI?= unknown
|
||||
MACHINE_TRIPLE?=${MACHINE_ARCH:C/amd64/x86_64/}-${MACHINE_ABI}-freebsd12.0
|
||||
TARGET_ABI?= unknown
|
||||
TARGET_TRIPLE?= ${TARGET_ARCH:C/amd64/x86_64/}-${TARGET_ABI}-freebsd12.0
|
||||
XCFLAGS+= -target ${TARGET_TRIPLE}
|
||||
@ -650,7 +653,7 @@ XCFLAGS+= ${BFLAGS}
|
||||
${TARGET_ARCH} == "powerpc64" || ${TARGET_ARCH:Mmips64*} != "")
|
||||
LIBCOMPAT= 32
|
||||
.include "Makefile.libcompat"
|
||||
.elif ${MK_LIBSOFT} != "no" && ${TARGET_ARCH} == "armv6"
|
||||
.elif ${MK_LIBSOFT} != "no" && ${TARGET_ARCH:Marmv[67]*} != ""
|
||||
LIBCOMPAT= SOFT
|
||||
.include "Makefile.libcompat"
|
||||
.endif
|
||||
@ -666,11 +669,11 @@ LIBCOMPAT= SOFT
|
||||
META_MODE_BAD_ABI_VERS+= 1200031
|
||||
|
||||
.if !defined(OBJDIR_HOST_OSRELDATE)
|
||||
.if exists(${OBJTREE}${.CURDIR}/host-osreldate.h)
|
||||
.if exists(${OBJTOP}/host-osreldate.h)
|
||||
OBJDIR_HOST_OSRELDATE!= \
|
||||
awk '/^\#define[[:space:]]*__FreeBSD_version/ { print $$3 }' \
|
||||
${OBJTREE}${.CURDIR}/host-osreldate.h
|
||||
.else
|
||||
${OBJTOP}/host-osreldate.h
|
||||
.elif exists(${WORLDTMP}/usr/include/osreldate.h)
|
||||
OBJDIR_HOST_OSRELDATE= 0
|
||||
.endif
|
||||
.export OBJDIR_HOST_OSRELDATE
|
||||
@ -679,6 +682,7 @@ OBJDIR_HOST_OSRELDATE= 0
|
||||
# Note that this logic is the opposite of normal BOOTSTRAP handling. We want
|
||||
# to compare the WORLDTMP's OSRELDATE to the host's OSRELDATE. If the WORLDTMP
|
||||
# is older than the ABI-breakage OSRELDATE of the HOST then we rebuild.
|
||||
.if defined(OBJDIR_HOST_OSRELDATE)
|
||||
.for _ver in ${META_MODE_BAD_ABI_VERS}
|
||||
.if ${OSRELDATE} >= ${_ver} && ${OBJDIR_HOST_OSRELDATE} < ${_ver}
|
||||
_meta_mode_need_rebuild= ${_ver}
|
||||
@ -688,8 +692,9 @@ _meta_mode_need_rebuild= ${_ver}
|
||||
.info META_MODE: Rebuilding host tools due to ABI breakage in __FreeBSD_version ${_meta_mode_need_rebuild}.
|
||||
NO_META_IGNORE_HOST_HEADERS= 1
|
||||
.export NO_META_IGNORE_HOST_HEADERS
|
||||
.endif
|
||||
.endif
|
||||
.endif # defined(_meta_mode_need_rebuild)
|
||||
.endif # defined(OBJDIR_HOST_OSRELDATE)
|
||||
.endif # ${MK_META_MODE} == "yes" && defined(NO_CLEAN) ...
|
||||
# This is only used for META_MODE+filemon to track what the oldest
|
||||
# __FreeBSD_version is in WORLDTMP. This purposely does NOT have
|
||||
# a make dependency on /usr/include/osreldate.h as the file should
|
||||
@ -747,34 +752,76 @@ KMAKE= ${KMAKEENV} ${MAKE} ${.MAKEFLAGS} ${KERNEL_FLAGS} KERNEL=${INSTKERNNAME}
|
||||
# Attempt to rebuild the entire system, with reasonable chance of
|
||||
# success, regardless of how old your existing system is.
|
||||
#
|
||||
_worldtmp: .PHONY
|
||||
_sanity_check: .PHONY .MAKE
|
||||
.if ${.CURDIR:C/[^,]//g} != ""
|
||||
# The m4 build of sendmail files doesn't like it if ',' is used
|
||||
# anywhere in the path of it's files.
|
||||
@echo
|
||||
@echo "*** Error: path to source tree contains a comma ','"
|
||||
@echo
|
||||
false
|
||||
@false
|
||||
.elif ${.CURDIR:M*\:*} != ""
|
||||
# Using ':' leaks into PATH and breaks finding cross-tools.
|
||||
@echo
|
||||
@echo "*** Error: path to source tree contains a colon ':'"
|
||||
@echo
|
||||
@false
|
||||
.endif
|
||||
|
||||
# Our current approach to dependency tracking cannot cope with certain source
|
||||
# tree changes, particularly with respect to removing source files and
|
||||
# replacing generated files. Handle these cases here in an ad-hoc fashion.
|
||||
_cleanobj_fast_depend_hack: .PHONY
|
||||
# Syscall stubs rewritten in C
|
||||
# Date SVN Rev Syscalls
|
||||
# 20160829 r305012 ptrace
|
||||
# 20170624 r320278 fstat fstatat fstatfs getdirentries getfsstat statfs
|
||||
.for f in fstat fstatat fstatfs getdirentries getfsstat ptrace statfs
|
||||
.if exists(${OBJTOP}/lib/libc/.depend.${f}.o)
|
||||
@if egrep -qw '${f}\.[sS]' \
|
||||
${OBJTOP}/lib/libc/.depend.${f}.o; then \
|
||||
echo Removing stale dependencies for ${f} syscall wrappers; \
|
||||
rm -f ${OBJTOP}/lib/libc/.depend.${f}.* \
|
||||
${LIBCOMPAT:D${LIBCOMPAT_OBJTOP}/lib/libc/.depend.${f}.*}; \
|
||||
fi
|
||||
.endif
|
||||
.endfor
|
||||
# 20170607 remove stale dependencies for utimens* wrappers removed in r319663
|
||||
.for f in futimens utimensat
|
||||
.if exists(${OBJTOP}/lib/libc/.depend.${f}.o)
|
||||
@if egrep -q '/${f}.c' \
|
||||
${OBJTOP}/lib/libc/.depend.${f}.o; then \
|
||||
echo Removing stale dependencies for ${f} syscall wrappers; \
|
||||
rm -f ${OBJTOP}/lib/libc/.depend.${f}.* \
|
||||
${LIBCOMPAT:D${LIBCOMPAT_OBJTOP}/lib/libc/.depend.${f}.*}; \
|
||||
fi
|
||||
.endif
|
||||
.endfor
|
||||
# 20170523 remove stale generated asm files for functions which are no longer
|
||||
# syscalls after r302092 (pipe) and r318736 (others)
|
||||
.for f in getdents lstat mknod pipe stat
|
||||
.if exists(${OBJTOP}/lib/libc/${f}.s) || \
|
||||
exists(${OBJTOP}/lib/libc/${f}.S)
|
||||
@echo Removing stale generated ${f} syscall files
|
||||
@rm -f ${OBJTOP}/lib/libc/${f}.* \
|
||||
${OBJTOP}/lib/libc/.depend.${f}.* \
|
||||
${LIBCOMPAT:D${LIBCOMPAT_OBJTOP}/lib/libc/${f}.*} \
|
||||
${LIBCOMPAT:D${LIBCOMPAT_OBJTOP}/lib/libc/.depend.${f}.*}
|
||||
.endif
|
||||
.endfor
|
||||
|
||||
_worldtmp: .PHONY
|
||||
@echo
|
||||
@echo "--------------------------------------------------------------"
|
||||
@echo ">>> Rebuilding the temporary build tree"
|
||||
@echo "--------------------------------------------------------------"
|
||||
.if !defined(NO_CLEAN)
|
||||
rm -rf ${WORLDTMP}
|
||||
.if defined(LIBCOMPAT)
|
||||
rm -rf ${LIBCOMPATTMP}
|
||||
.endif
|
||||
.else
|
||||
.if exists(${WORLDTMP})
|
||||
@echo ">>> Deleting stale files in build tree..."
|
||||
${_+_}cd ${.CURDIR}; ${WMAKE} -DBATCH_DELETE_OLD_FILES \
|
||||
delete-old delete-old-libs >/dev/null
|
||||
.endif
|
||||
.if defined(LIBCOMPAT) && exists(${LIBCOMPATTMP})
|
||||
${_+_}cd ${.CURDIR}; ${WMAKE} -DBATCH_DELETE_OLD_FILES \
|
||||
DESTDIR=${LIBCOMPATTMP} \
|
||||
delete-old delete-old-libs >/dev/null
|
||||
.endif
|
||||
rm -rf ${WORLDTMP}/legacy/usr/include
|
||||
.if ${USING_SYSTEM_COMPILER} == "yes"
|
||||
@ -785,50 +832,9 @@ _worldtmp: .PHONY
|
||||
fi
|
||||
.endfor
|
||||
.endif # ${USING_SYSTEM_COMPILER} == "yes"
|
||||
|
||||
# Our current approach to dependency tracking cannot cope with certain source
|
||||
# tree changes, particularly with respect to removing source files and
|
||||
# replacing generated files. Handle these cases here in an ad-hoc fashion.
|
||||
#
|
||||
# Syscall stubs rewritten in C
|
||||
# Date SVN Rev Syscalls
|
||||
# 20160829 r305012 ptrace
|
||||
# 20170624 r320278 fstat fstatat fstatfs getdirentries getfsstat statfs
|
||||
.for f in fstat fstatat fstatfs getdirentries getfsstat ptrace statfs
|
||||
.if exists(${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.o)
|
||||
@if egrep -qw '${f}\.[sS]' \
|
||||
${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.o; then \
|
||||
echo Removing stale dependencies for ${f} syscall wrappers; \
|
||||
rm -f ${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.* \
|
||||
${OBJTREE}${.CURDIR}/world32/${.CURDIR}/lib/libc/.depend.${f}.*; \
|
||||
fi
|
||||
.endif
|
||||
.endfor
|
||||
# 20170607 remove stale dependencies for utimens* wrappers removed in r319663
|
||||
.for f in futimens utimensat
|
||||
.if exists(${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.o)
|
||||
@if egrep -q '/${f}.c' \
|
||||
${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.o; then \
|
||||
echo Removing stale dependencies for ${f} syscall wrappers; \
|
||||
rm -f ${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.* \
|
||||
${OBJTREE}${.CURDIR}/world32/${.CURDIR}/lib/libc/.depend.${f}.*; \
|
||||
fi
|
||||
.endif
|
||||
.endfor
|
||||
# 20170523 remove stale generated asm files for functions which are no longer
|
||||
# syscalls after r302092 (pipe) and r318736 (others)
|
||||
.for f in getdents lstat mknod pipe stat
|
||||
.if exists(${OBJTREE}${.CURDIR}/lib/libc/${f}.s) || \
|
||||
exists(${OBJTREE}${.CURDIR}/lib/libc/${f}.S)
|
||||
@echo Removing stale generated ${f} syscall files
|
||||
@rm -f ${OBJTREE}${.CURDIR}/lib/libc/${f}.* \
|
||||
${OBJTREE}${.CURDIR}/lib/libc/.depend.${f}.* \
|
||||
${OBJTREE}${.CURDIR}/world32/${.CURDIR}/lib/libc/${f}.* \
|
||||
${OBJTREE}${.CURDIR}/world32/${.CURDIR}/lib/libc/.depend.${f}.*
|
||||
.endif
|
||||
.endfor
|
||||
|
||||
.endif # !defined(NO_CLEAN)
|
||||
@mkdir -p ${WORLDTMP}
|
||||
@touch ${WORLDTMP}/${.TARGET}
|
||||
|
||||
.for _dir in \
|
||||
lib lib/casper usr legacy/bin legacy/usr
|
||||
@ -844,32 +850,11 @@ _worldtmp: .PHONY
|
||||
-p ${WORLDTMP}/usr/include >/dev/null
|
||||
ln -sf ${.CURDIR}/sys ${WORLDTMP}
|
||||
.if ${MK_DEBUG_FILES} != "no"
|
||||
# We could instead disable debug files for these build stages
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \
|
||||
-p ${WORLDTMP}/legacy/usr/lib >/dev/null
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \
|
||||
-p ${WORLDTMP}/usr/lib >/dev/null
|
||||
.endif
|
||||
.if defined(LIBCOMPAT)
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib${libcompat}.dist \
|
||||
-p ${WORLDTMP}/usr >/dev/null
|
||||
.if ${MK_DEBUG_FILES} != "no"
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib${libcompat}.dist \
|
||||
-p ${WORLDTMP}/legacy/usr/lib/debug/usr >/dev/null
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.lib${libcompat}.dist \
|
||||
-p ${WORLDTMP}/usr/lib/debug/usr >/dev/null
|
||||
.endif
|
||||
.endif
|
||||
.if ${MK_TESTS} != "no"
|
||||
mkdir -p ${WORLDTMP}${TESTSBASE}
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \
|
||||
-p ${WORLDTMP}${TESTSBASE} >/dev/null
|
||||
.if ${MK_DEBUG_FILES} != "no"
|
||||
mkdir -p ${WORLDTMP}/usr/lib/debug/${TESTSBASE}
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \
|
||||
-p ${WORLDTMP}/usr/lib/debug/${TESTSBASE} >/dev/null
|
||||
.endif
|
||||
.endif
|
||||
.for _mtree in ${LOCAL_MTREE}
|
||||
mtree -deU -f ${.CURDIR}/${_mtree} -p ${WORLDTMP} > /dev/null
|
||||
.endfor
|
||||
@ -895,7 +880,9 @@ _cleanobj:
|
||||
.if defined(LIBCOMPAT)
|
||||
${_+_}cd ${.CURDIR}; ${LIBCOMPATWMAKE} -f Makefile.inc1 ${CLEANDIR}
|
||||
.endif
|
||||
.endif
|
||||
.else
|
||||
${_+_}cd ${.CURDIR}; ${WMAKE} _cleanobj_fast_depend_hack
|
||||
.endif # !defined(NO_CLEAN)
|
||||
_obj:
|
||||
@echo
|
||||
@echo "--------------------------------------------------------------"
|
||||
@ -913,7 +900,7 @@ _cross-tools:
|
||||
@echo "--------------------------------------------------------------"
|
||||
@echo ">>> stage 3: cross tools"
|
||||
@echo "--------------------------------------------------------------"
|
||||
@rm -f ${OBJTREE}${.CURDIR}/compiler-metadata.mk
|
||||
@rm -f ${OBJTOP}/compiler-metadata.mk
|
||||
${_+_}cd ${.CURDIR}; ${XMAKE} cross-tools
|
||||
${_+_}cd ${.CURDIR}; ${XMAKE} kernel-tools
|
||||
_build-metadata:
|
||||
@ -952,12 +939,12 @@ everything: .PHONY
|
||||
|
||||
WMAKE_TGTS=
|
||||
.if !defined(WORLDFAST)
|
||||
WMAKE_TGTS+= _worldtmp _legacy
|
||||
WMAKE_TGTS+= _sanity_check _worldtmp _legacy
|
||||
.if empty(SUBDIR_OVERRIDE)
|
||||
WMAKE_TGTS+= _bootstrap-tools
|
||||
.endif
|
||||
WMAKE_TGTS+= _cleanobj
|
||||
.if !defined(NO_OBJ)
|
||||
.if !defined(NO_OBJWALK)
|
||||
WMAKE_TGTS+= _obj
|
||||
.endif
|
||||
WMAKE_TGTS+= _build-tools _cross-tools
|
||||
@ -1006,12 +993,15 @@ buildenv: .PHONY
|
||||
.if ${BUILDENV_SHELL:M*zsh*}
|
||||
@echo For ZSH you must run: export CPUTYPE=${TARGET_CPUTYPE}
|
||||
.endif
|
||||
@cd ${BUILDENV_DIR} && env ${WMAKEENV} BUILDENV=1 ${BUILDENV_SHELL} \
|
||||
|| true
|
||||
@cd ${BUILDENV_DIR} && env ${WMAKEENV} BUILDENV=1 ${BUILDENV_SHELL}
|
||||
|
||||
TOOLCHAIN_TGTS= ${WMAKE_TGTS:Neverything:Nbuild${libcompat}}
|
||||
toolchain: ${TOOLCHAIN_TGTS} .PHONY
|
||||
kernel-toolchain: ${TOOLCHAIN_TGTS:N_includes:N_libraries} .PHONY
|
||||
KERNEL_TOOLCHAIN_TGTS= ${TOOLCHAIN_TGTS:N_obj:N_cleanobj:N_includes:N_libraries}
|
||||
.if make(kernel-toolchain)
|
||||
.ORDER: ${KERNEL_TOOLCHAIN_TGTS}
|
||||
.endif
|
||||
kernel-toolchain: ${KERNEL_TOOLCHAIN_TGTS} .PHONY
|
||||
|
||||
#
|
||||
# installcheck
|
||||
@ -1082,7 +1072,7 @@ __installcheck_UGID: .PHONY
|
||||
(empty(DESTDIR) || ${DESTDIR} == "/") && empty(BYPASS_INSTALLCHECK_SH)
|
||||
_installcheck_world: __installcheck_sh_check
|
||||
__installcheck_sh_check: .PHONY
|
||||
@if [ "`${OBJTREE}${.CURDIR}/rescue/rescue/rescue sh -c 'echo OK'`" != \
|
||||
@if [ "`${OBJTOP}/rescue/rescue/rescue sh -c 'echo OK'`" != \
|
||||
OK ]; then \
|
||||
echo "rescue/sh check failed, installation aborted" >&2; \
|
||||
false; \
|
||||
@ -1344,7 +1334,7 @@ INSTKERNNAME?= kernel
|
||||
|
||||
KERNSRCDIR?= ${.CURDIR}/sys
|
||||
KRNLCONFDIR= ${KERNSRCDIR}/${TARGET}/conf
|
||||
KRNLOBJDIR= ${OBJTREE}${KERNSRCDIR}
|
||||
KRNLOBJDIR= ${OBJTOP}${KERNSRCDIR:C,^${.CURDIR},,}
|
||||
KERNCONFDIR?= ${KRNLCONFDIR}
|
||||
|
||||
BUILDKERNELS=
|
||||
@ -1359,6 +1349,10 @@ BUILDKERNELS+= ${_kernel}
|
||||
.if empty(INSTALLKERNEL) && !defined(NO_INSTALLKERNEL)
|
||||
INSTALLKERNEL= ${_kernel}
|
||||
.endif
|
||||
.else
|
||||
.if make(buildkernel)
|
||||
.error Missing KERNCONF ${KERNCONFDIR}/${_kernel}
|
||||
.endif
|
||||
.endif
|
||||
.endfor
|
||||
|
||||
@ -1548,9 +1542,9 @@ stagekernel: .PHONY
|
||||
${_+_}${MAKE} -C ${.CURDIR} ${.MAKEFLAGS} distributekernel
|
||||
|
||||
PORTSDIR?= /usr/ports
|
||||
WSTAGEDIR?= ${MAKEOBJDIRPREFIX}${.CURDIR}/${TARGET}.${TARGET_ARCH}/worldstage
|
||||
KSTAGEDIR?= ${MAKEOBJDIRPREFIX}${.CURDIR}/${TARGET}.${TARGET_ARCH}/kernelstage
|
||||
REPODIR?= ${MAKEOBJDIRPREFIX}${.CURDIR}/repo
|
||||
WSTAGEDIR?= ${OBJTOP}/worldstage
|
||||
KSTAGEDIR?= ${OBJTOP}/kernelstage
|
||||
REPODIR?= ${OBJROOT}repo
|
||||
PKGSIGNKEY?= # empty
|
||||
|
||||
.ORDER: stage-packages create-packages
|
||||
@ -1812,11 +1806,11 @@ legacy: .PHONY
|
||||
.for _tool in tools/build ${_elftoolchain_libs}
|
||||
${_+_}@${ECHODIR} "===> ${_tool} (obj,includes,all,install)"; \
|
||||
cd ${.CURDIR}/${_tool}; \
|
||||
if [ -z "${NO_OBJ}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy includes; \
|
||||
if [ -z "${NO_OBJWALK}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${WORLDTMP}/legacy includes; \
|
||||
${MAKE} DIRPRFX=${_tool}/ MK_INCLUDES=no all; \
|
||||
${MAKE} DIRPRFX=${_tool}/ MK_INCLUDES=no \
|
||||
DESTDIR=${MAKEOBJDIRPREFIX}/legacy install
|
||||
DESTDIR=${WORLDTMP}/legacy install
|
||||
.endfor
|
||||
|
||||
#
|
||||
@ -1840,7 +1834,6 @@ _vtfontcvt= usr.bin/vtfontcvt
|
||||
.endif
|
||||
|
||||
.if ${BOOTSTRAPPING} < 1000033
|
||||
_libopenbsd= lib/libopenbsd
|
||||
_m4= usr.bin/m4
|
||||
_lex= usr.bin/lex
|
||||
|
||||
@ -1926,9 +1919,6 @@ _kerberos5_bootstrap_tools= \
|
||||
.ORDER: ${_kerberos5_bootstrap_tools:C/^/${_bt}-/g}
|
||||
.endif
|
||||
|
||||
# r283777 makewhatis(1) replaced with mandoc version which builds a database.
|
||||
_libopenbsd?= lib/libopenbsd
|
||||
_makewhatis= usr.bin/mandoc
|
||||
${_bt}-usr.bin/mandoc: ${_bt}-lib/libopenbsd
|
||||
|
||||
bootstrap-tools: .PHONY
|
||||
@ -1945,8 +1935,8 @@ bootstrap-tools: .PHONY
|
||||
${_cat} \
|
||||
${_kbdcontrol} \
|
||||
usr.bin/lorder \
|
||||
${_libopenbsd} \
|
||||
${_makewhatis} \
|
||||
lib/libopenbsd \
|
||||
usr.bin/mandoc \
|
||||
usr.bin/rpcgen \
|
||||
${_yacc} \
|
||||
${_m4} \
|
||||
@ -1962,9 +1952,9 @@ bootstrap-tools: .PHONY
|
||||
${_bt}-${_tool}: .PHONY .MAKE
|
||||
${_+_}@${ECHODIR} "===> ${_tool} (obj,all,install)"; \
|
||||
cd ${.CURDIR}/${_tool}; \
|
||||
if [ -z "${NO_OBJ}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
if [ -z "${NO_OBJWALK}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
${MAKE} DIRPRFX=${_tool}/ all; \
|
||||
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy install
|
||||
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${WORLDTMP}/legacy install
|
||||
|
||||
bootstrap-tools: ${_bt}-${_tool}
|
||||
.endfor
|
||||
@ -1989,6 +1979,12 @@ _rescue=rescue/rescue
|
||||
_tcsh=bin/csh
|
||||
.endif
|
||||
|
||||
# kernel-toolchain skips _cleanobj, so handle cleaning up previous
|
||||
# build-tools directories if needed.
|
||||
.if !defined(NO_CLEAN) && make(kernel-toolchain)
|
||||
_bt_clean= ${CLEANDIR}
|
||||
.endif
|
||||
|
||||
.for _tool in \
|
||||
${_tcsh} \
|
||||
bin/sh \
|
||||
@ -2001,21 +1997,14 @@ _tcsh=bin/csh
|
||||
lib/libmagic \
|
||||
usr.bin/mkesdb_static \
|
||||
usr.bin/mkcsmapper_static \
|
||||
usr.bin/vi/catalog
|
||||
build-tools_${_tool}: .PHONY
|
||||
${_+_}@${ECHODIR} "===> ${_tool} (obj,build-tools)"; \
|
||||
cd ${.CURDIR}/${_tool}; \
|
||||
if [ -z "${NO_OBJ}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
${MAKE} DIRPRFX=${_tool}/ build-tools
|
||||
build-tools: build-tools_${_tool}
|
||||
.endfor
|
||||
.for _tool in \
|
||||
usr.bin/vi/catalog \
|
||||
${_gcc_tools}
|
||||
build-tools_${_tool}: .PHONY
|
||||
${_+_}@${ECHODIR} "===> ${_tool} (obj,all)"; \
|
||||
${_+_}@${ECHODIR} "===> ${_tool} (${_bt_clean:D${_bt_clean},}obj,build-tools)"; \
|
||||
cd ${.CURDIR}/${_tool}; \
|
||||
if [ -z "${NO_OBJ}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
${MAKE} DIRPRFX=${_tool}/ all
|
||||
if [ -n "${_bt_clean}" ]; then ${MAKE} DIRPRFX=${_tool}/ ${_bt_clean}; fi; \
|
||||
if [ -z "${NO_OBJWALK}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
${MAKE} DIRPRFX=${_tool}/ build-tools
|
||||
build-tools: build-tools_${_tool}
|
||||
.endfor
|
||||
|
||||
@ -2023,9 +2012,9 @@ build-tools: build-tools_${_tool}
|
||||
# kernel-tools: Build kernel-building tools
|
||||
#
|
||||
kernel-tools: .PHONY
|
||||
mkdir -p ${MAKEOBJDIRPREFIX}/usr
|
||||
mkdir -p ${WORLDTMP}/usr
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
|
||||
-p ${MAKEOBJDIRPREFIX}/usr >/dev/null
|
||||
-p ${WORLDTMP}/usr >/dev/null
|
||||
|
||||
#
|
||||
# cross-tools: All the tools needed to build the rest of the system after
|
||||
@ -2099,52 +2088,30 @@ cross-tools: .MAKE .PHONY
|
||||
${_usb_tools}
|
||||
${_+_}@${ECHODIR} "===> ${_tool} (obj,all,install)"; \
|
||||
cd ${.CURDIR}/${_tool}; \
|
||||
if [ -z "${NO_OBJ}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
if [ -z "${NO_OBJWALK}" ]; then ${MAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
${MAKE} DIRPRFX=${_tool}/ all; \
|
||||
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX} install
|
||||
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${WORLDTMP} install
|
||||
.endfor
|
||||
|
||||
NXBDESTDIR= ${OBJTREE}/nxb-bin
|
||||
NXBENV= MAKEOBJDIRPREFIX=${OBJTREE}/nxb \
|
||||
TOOLS_PREFIX= \
|
||||
INSTALL="sh ${.CURDIR}/tools/install.sh" \
|
||||
PATH=${PATH}:${OBJTREE}/gperf_for_gcc/usr/bin
|
||||
NXBMAKE= ${NXBENV} ${MAKE} \
|
||||
LLVM_TBLGEN=${NXBDESTDIR}/usr/bin/llvm-tblgen \
|
||||
CLANG_TBLGEN=${NXBDESTDIR}/usr/bin/clang-tblgen \
|
||||
MACHINE=${TARGET} MACHINE_ARCH=${TARGET_ARCH} \
|
||||
MK_GDB=no MK_TESTS=no \
|
||||
SSP_CFLAGS= \
|
||||
MK_HTML=no NO_LINT=yes MK_MAN=no MK_MAN_UTILS=yes \
|
||||
-DNO_PIC MK_PROFILE=no -DNO_SHARED \
|
||||
-DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \
|
||||
MK_CLANG_EXTRAS=no MK_CLANG_FULL=no \
|
||||
MK_LLDB=no MK_DEBUG_FILES=no
|
||||
|
||||
#
|
||||
# native-xtools is the current target for qemu-user cross builds of ports
|
||||
# via poudriere and the imgact_binmisc kernel module.
|
||||
# For non-clang enabled targets that are still using the in tree gcc
|
||||
# we must build a gperf binary for one instance of its Makefiles. On
|
||||
# clang-enabled systems, the gperf binary is obsolete.
|
||||
native-xtools: .PHONY
|
||||
.if ${MK_GCC_BOOTSTRAP} != "no"
|
||||
mkdir -p ${OBJTREE}/gperf_for_gcc/usr/bin
|
||||
${_+_}@${ECHODIR} "===> ${_gperf} (obj,all,install)"; \
|
||||
cd ${.CURDIR}/${_gperf}; \
|
||||
if [ -z "${NO_OBJ}" ]; then ${NXBMAKE} DIRPRFX=${_gperf}/ obj; fi; \
|
||||
${NXBMAKE} DIRPRFX=${_gperf}/ all; \
|
||||
${NXBMAKE} DIRPRFX=${_gperf}/ DESTDIR=${OBJTREE}/gperf_for_gcc install
|
||||
# This target merely builds a toolchan/sysroot, then builds the tools it wants
|
||||
# with the options it wants in a special MAKEOBJDIRPREFIX, using the toolchain
|
||||
# already built. It then installs the static tools to NXBDESTDIR for Poudriere
|
||||
# to pickup.
|
||||
#
|
||||
NXBOBJROOT= ${OBJROOT}${MACHINE}.${MACHINE_ARCH}/nxb/
|
||||
NXBOBJTOP= ${NXBOBJROOT}${TARGET}.${TARGET_ARCH}
|
||||
NXTP?= /nxb-bin
|
||||
.if ${NXTP:N/*}
|
||||
.error NXTP variable should be an absolute path
|
||||
.endif
|
||||
mkdir -p ${NXBDESTDIR}/bin ${NXBDESTDIR}/sbin ${NXBDESTDIR}/usr
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
|
||||
-p ${NXBDESTDIR}/usr >/dev/null
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \
|
||||
-p ${NXBDESTDIR}/usr/include >/dev/null
|
||||
.if ${MK_DEBUG_FILES} != "no"
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.debug.dist \
|
||||
-p ${NXBDESTDIR}/usr/lib >/dev/null
|
||||
.endif
|
||||
.for _tool in \
|
||||
NXBDESTDIR?= ${DESTDIR}${NXTP}
|
||||
|
||||
# This is the list of tools to be built/installed as static and where
|
||||
# appropriate to build for the given TARGET.TARGET_ARCH.
|
||||
NXBDIRS+= \
|
||||
bin/cat \
|
||||
bin/chmod \
|
||||
bin/cp \
|
||||
@ -2162,24 +2129,18 @@ native-xtools: .PHONY
|
||||
bin/rmdir \
|
||||
bin/sh \
|
||||
bin/sleep \
|
||||
${_clang_tblgen} \
|
||||
usr.bin/ar \
|
||||
${_binutils} \
|
||||
${_elftctools} \
|
||||
${_gcc} \
|
||||
${_gcc_tools} \
|
||||
${_clang_libs} \
|
||||
${_clang} \
|
||||
${_lld} \
|
||||
sbin/md5 \
|
||||
sbin/sysctl \
|
||||
usr.bin/diff \
|
||||
usr.bin/addr2line \
|
||||
usr.bin/ar \
|
||||
usr.bin/awk \
|
||||
usr.bin/basename \
|
||||
usr.bin/bmake \
|
||||
usr.bin/bzip2 \
|
||||
usr.bin/cmp \
|
||||
usr.bin/diff \
|
||||
usr.bin/dirname \
|
||||
usr.bin/elfcopy \
|
||||
usr.bin/env \
|
||||
usr.bin/fetch \
|
||||
usr.bin/find \
|
||||
@ -2189,14 +2150,16 @@ native-xtools: .PHONY
|
||||
usr.bin/lex \
|
||||
usr.bin/limits \
|
||||
usr.bin/lorder \
|
||||
${_libopenbsd} \
|
||||
${_makewhatis} \
|
||||
usr.bin/mandoc \
|
||||
usr.bin/mktemp \
|
||||
usr.bin/mt \
|
||||
usr.bin/nm \
|
||||
usr.bin/patch \
|
||||
usr.bin/readelf \
|
||||
usr.bin/sed \
|
||||
usr.bin/size \
|
||||
usr.bin/sort \
|
||||
usr.bin/strings \
|
||||
usr.bin/tar \
|
||||
usr.bin/touch \
|
||||
usr.bin/tr \
|
||||
@ -2208,12 +2171,82 @@ native-xtools: .PHONY
|
||||
usr.bin/xz \
|
||||
usr.bin/yacc \
|
||||
usr.sbin/chown
|
||||
${_+_}@${ECHODIR} "===> ${_tool} (obj,all,install)"; \
|
||||
cd ${.CURDIR}/${_tool}; \
|
||||
if [ -z "${NO_OBJ}" ]; then ${NXBMAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
${NXBMAKE} DIRPRFX=${_tool}/ all; \
|
||||
${NXBMAKE} DIRPRFX=${_tool}/ DESTDIR=${NXBDESTDIR} install
|
||||
.endfor
|
||||
|
||||
.if ${MK_CLANG} != "no"
|
||||
NXBDIRS+= lib/clang
|
||||
SUBDIR_DEPEND_usr.bin/clang= lib/clang
|
||||
NXBDIRS+= usr.bin/clang
|
||||
.elif ${MK_GCC} != "no"
|
||||
NXBDIRS+= gnu/usr.bin/cc
|
||||
.endif
|
||||
.if ${MK_BINUTILS} != "no"
|
||||
NXBDIRS+= gnu/usr.bin/binutils
|
||||
.endif
|
||||
|
||||
NXBMAKEARGS+= \
|
||||
OBJTOP=${NXBOBJTOP:Q} \
|
||||
OBJROOT=${NXBOBJROOT:Q} \
|
||||
-DNO_SHARED \
|
||||
-DNO_CPU_CFLAGS \
|
||||
-DNO_PIC \
|
||||
SSP_CFLAGS= \
|
||||
MK_CLANG_EXTRAS=no \
|
||||
MK_CLANG_FULL=no \
|
||||
MK_CTF=no \
|
||||
MK_DEBUG_FILES=no \
|
||||
MK_GDB=no \
|
||||
MK_HTML=no \
|
||||
MK_LLDB=no \
|
||||
MK_MAN=no \
|
||||
MK_MAN_UTILS=yes \
|
||||
MK_OFED=no \
|
||||
MK_OPENSSH=no \
|
||||
MK_PROFILE=no \
|
||||
MK_SENDMAIL=no \
|
||||
MK_SVNLITE=no \
|
||||
MK_TESTS=no \
|
||||
MK_WARNS=no \
|
||||
MK_ZFS=no
|
||||
|
||||
|
||||
# For 'toolchain' we want to produce native binaries that themselves generate
|
||||
# native binaries.
|
||||
NXBTMAKE= ${NXBMAKEENV} ${MAKE} ${NXBMAKEARGS:N-DNO_PIC:N-DNO_SHARED} \
|
||||
TARGET=${MACHINE} TARGET_ARCH=${MACHINE_ARCH}
|
||||
# For 'everything' we want to produce native binaries (hence -target to
|
||||
# be MACHINE) that themselves generate TARGET.TARGET_ARCH binaries.
|
||||
# TARGET/TARGET_ARCH are still passed along from user.
|
||||
NXBMAKE= ${NXBMAKEENV} ${MAKE} ${NXBMAKEARGS} \
|
||||
TARGET_TRIPLE=${MACHINE_TRIPLE:Q}
|
||||
native-xtools: .PHONY
|
||||
# Build the bootstrap/host/cross tools that produce native binaries
|
||||
${_+_}cd ${.CURDIR}; ${NXBTMAKE} kernel-toolchain
|
||||
# Populate includes/libraries sysroot that produce native binaries.
|
||||
# This is split out from 'toolchain' above mostly so that target LLVM
|
||||
# libraries have a proper LLVM_DEFAULT_TARGET_TRIPLE without
|
||||
# polluting the cross-compiler build. The LLVM/GCC libs are skipped
|
||||
# here to avoid the problem but are kept in 'toolchain' so that
|
||||
# needed build tools are built.
|
||||
${_+_}cd ${.CURDIR}; ${NXBTMAKE} _includes MK_CLANG=no MK_GCC=no
|
||||
${_+_}cd ${.CURDIR}; ${NXBTMAKE} _libraries MK_CLANG=no MK_GCC=no
|
||||
.if !defined(NO_OBJWALK)
|
||||
${_+_}cd ${.CURDIR}; ${NXBMAKE} SUBDIR_OVERRIDE="${NXBDIRS:M*}" _obj
|
||||
.endif
|
||||
${_+_}cd ${.CURDIR}; ${NXBMAKE} SUBDIR_OVERRIDE="${NXBDIRS:M*}" \
|
||||
everything
|
||||
@echo ">> native-xtools done. Use 'make native-xtools-install' to install to a given DESTDIR"
|
||||
|
||||
native-xtools-install: .PHONY
|
||||
mkdir -p ${NXBDESTDIR}/bin ${NXBDESTDIR}/sbin ${NXBDESTDIR}/usr
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
|
||||
-p ${NXBDESTDIR}/usr >/dev/null
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \
|
||||
-p ${NXBDESTDIR}/usr/include >/dev/null
|
||||
${_+_}cd ${.CURDIR}; ${NXBMAKE} -f Makefile.inc1 \
|
||||
DESTDIR=${NXBDESTDIR} \
|
||||
SUBDIR_OVERRIDE="${NXBDIRS:M*}" \
|
||||
-DNO_ROOT \
|
||||
install
|
||||
|
||||
#
|
||||
# hierarchy - ensure that all the needed directories are present
|
||||
@ -2473,7 +2506,7 @@ ${_lib}__PL: .PHONY .MAKE
|
||||
.if exists(${.CURDIR}/${_lib})
|
||||
${_+_}@${ECHODIR} "===> ${_lib} (obj,all,install)"; \
|
||||
cd ${.CURDIR}/${_lib}; \
|
||||
if [ -z "${NO_OBJ}" ]; then ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj; fi; \
|
||||
if [ -z "${NO_OBJWALK}" ]; then ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj; fi; \
|
||||
${MAKE} MK_TESTS=no MK_PROFILE=no -DNO_PIC \
|
||||
DIRPRFX=${_lib}/ all; \
|
||||
${MAKE} MK_TESTS=no MK_PROFILE=no -DNO_PIC \
|
||||
@ -2486,7 +2519,7 @@ ${_lib}__L: .PHONY .MAKE
|
||||
.if exists(${.CURDIR}/${_lib})
|
||||
${_+_}@${ECHODIR} "===> ${_lib} (obj,all,install)"; \
|
||||
cd ${.CURDIR}/${_lib}; \
|
||||
if [ -z "${NO_OBJ}" ]; then ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj; fi; \
|
||||
if [ -z "${NO_OBJWALK}" ]; then ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj; fi; \
|
||||
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ all; \
|
||||
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ install
|
||||
.endif
|
||||
@ -2559,7 +2592,7 @@ delete-old-files: .PHONY
|
||||
done
|
||||
# Remove catpages without corresponding manpages.
|
||||
@exec 3<&0; \
|
||||
find ${DESTDIR}/usr/share/man/cat* ! -type d | \
|
||||
find ${DESTDIR}/usr/share/man/cat* ! -type d 2>/dev/null | \
|
||||
sed -ep -e's:${DESTDIR}/usr/share/man/cat:${DESTDIR}/usr/share/man/man:' | \
|
||||
while read catpage; do \
|
||||
read manpage; \
|
||||
@ -2585,7 +2618,7 @@ check-old-files: .PHONY
|
||||
done; \
|
||||
done
|
||||
# Check for catpages without corresponding manpages.
|
||||
@find ${DESTDIR}/usr/share/man/cat* ! -type d | \
|
||||
@find ${DESTDIR}/usr/share/man/cat* ! -type d 2>/dev/null | \
|
||||
sed -ep -e's:${DESTDIR}/usr/share/man/cat:${DESTDIR}/usr/share/man/man:' | \
|
||||
while read catpage; do \
|
||||
read manpage; \
|
||||
@ -2723,21 +2756,29 @@ builddtb: .PHONY
|
||||
#
|
||||
# It is expected that BW_CANONICALOBJDIR == the CANONICALOBJDIR as would be
|
||||
# created by bsd.obj.mk, except that we don't want to .include that file
|
||||
# in this makefile.
|
||||
# in this makefile. We don't do a cleandir walk if MK_AUTO_OBJ is yes
|
||||
# since it is not possible for files to land in the wrong place.
|
||||
#
|
||||
BW_CANONICALOBJDIR:=${OBJTREE}${.CURDIR}
|
||||
cleanworld: .PHONY
|
||||
.if exists(${BW_CANONICALOBJDIR}/)
|
||||
-rm -rf ${BW_CANONICALOBJDIR}/*
|
||||
-chflags -R 0 ${BW_CANONICALOBJDIR}
|
||||
rm -rf ${BW_CANONICALOBJDIR}/*
|
||||
.if make(cleanworld)
|
||||
BW_CANONICALOBJDIR:=${OBJTOP}/
|
||||
.elif make(cleanuniverse)
|
||||
BW_CANONICALOBJDIR:=${OBJROOT}
|
||||
.if ${MK_UNIFIED_OBJDIR} == "no"
|
||||
.error ${.TARGETS} only supported with WITH_UNIFIED_OBJDIR enabled.
|
||||
.endif
|
||||
.endif
|
||||
cleanworld cleanuniverse: .PHONY
|
||||
.if !empty(BW_CANONICALOBJDIR) && exists(${BW_CANONICALOBJDIR})
|
||||
-rm -rf ${BW_CANONICALOBJDIR}*
|
||||
-chflags -R 0 ${BW_CANONICALOBJDIR}
|
||||
rm -rf ${BW_CANONICALOBJDIR}*
|
||||
.endif
|
||||
.if make(cleanworld) && ${MK_AUTO_OBJ} == "no"
|
||||
.if ${.CURDIR} == ${.OBJDIR} || ${.CURDIR}/obj == ${.OBJDIR}
|
||||
# To be safe in this case, fall back to a 'make cleandir'
|
||||
${_+_}@cd ${.CURDIR}; ${MAKE} cleandir
|
||||
.endif
|
||||
|
||||
.if defined(TARGET) && defined(TARGET_ARCH)
|
||||
.endif
|
||||
|
||||
.if ${TARGET} == ${MACHINE} && ${TARGET_ARCH} == ${MACHINE_ARCH}
|
||||
XDEV_CPUTYPE?=${CPUTYPE}
|
||||
@ -2757,10 +2798,16 @@ XDTP?=/usr/${XDDIR}
|
||||
.error XDTP variable should be an absolute path
|
||||
.endif
|
||||
|
||||
CDBENV=MAKEOBJDIRPREFIX=${MAKEOBJDIRPREFIX}/${XDDIR} \
|
||||
CDBOBJROOT= ${OBJROOT}${MACHINE}.${MACHINE_ARCH}/xdev/
|
||||
CDBOBJTOP= ${CDBOBJROOT}${XDDIR}
|
||||
CDBENV= \
|
||||
INSTALL="sh ${.CURDIR}/tools/install.sh"
|
||||
CDENV= ${CDBENV} \
|
||||
TOOLS_PREFIX=${XDTP}
|
||||
CDMAKEARGS= \
|
||||
OBJTOP=${CDBOBJTOP:Q} \
|
||||
OBJROOT=${CDBOBJROOT:Q}
|
||||
CD2MAKEARGS= ${CDMAKEARGS}
|
||||
|
||||
.if ${WANT_COMPILER_TYPE} == gcc || \
|
||||
(defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc)
|
||||
@ -2782,14 +2829,15 @@ CD2ENV=${CDENV} CC="${CC} ${CD2CFLAGS}" CXX="${CXX} ${CD2CXXFLAGS} ${CD2CFLAGS}"
|
||||
CPP="${CPP} ${CD2CFLAGS}" \
|
||||
MACHINE=${TARGET} MACHINE_ARCH=${TARGET_ARCH}
|
||||
|
||||
CDTMP= ${MAKEOBJDIRPREFIX}/${XDDIR}/${.CURDIR}/tmp
|
||||
CDMAKE=${CDENV} PATH=${CDTMP}/usr/bin:${PATH} ${MAKE} ${NOFUN}
|
||||
CD2MAKE=${CD2ENV} PATH=${CDTMP}/usr/bin:${XDDESTDIR}/usr/bin:${PATH} ${MAKE} ${NOFUN}
|
||||
CDTMP= ${OBJTOP}/${XDDIR}/tmp
|
||||
CDMAKE=${CDENV} PATH=${CDTMP}/usr/bin:${PATH} ${MAKE} ${CDMAKEARGS} ${NOFUN}
|
||||
CD2MAKE=${CD2ENV} PATH=${CDTMP}/usr/bin:${XDDESTDIR}/usr/bin:${PATH} \
|
||||
${MAKE} ${CD2MAKEARGS} ${NOFUN}
|
||||
.if ${MK_META_MODE} != "no"
|
||||
# Don't rebuild build-tools targets during normal build.
|
||||
CD2MAKE+= BUILD_TOOLS_META=.NOMETA
|
||||
.endif
|
||||
XDDESTDIR=${DESTDIR}/${XDTP}
|
||||
XDDESTDIR=${DESTDIR}${XDTP}
|
||||
|
||||
.ORDER: xdev-build xdev-install xdev-links
|
||||
xdev: xdev-build xdev-install .PHONY
|
||||
@ -2809,26 +2857,29 @@ _xb-bootstrap-tools: .PHONY
|
||||
${_yacc}
|
||||
${_+_}@${ECHODIR} "===> ${_tool} (obj,all,install)"; \
|
||||
cd ${.CURDIR}/${_tool}; \
|
||||
if [ -z "${NO_OBJ}" ]; then ${CDMAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
if [ -z "${NO_OBJWALK}" ]; then ${CDMAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
${CDMAKE} DIRPRFX=${_tool}/ all; \
|
||||
${CDMAKE} DIRPRFX=${_tool}/ DESTDIR=${CDTMP} install
|
||||
.endfor
|
||||
|
||||
_xb-build-tools: .PHONY
|
||||
${_+_}@cd ${.CURDIR}; \
|
||||
${CDBENV} ${MAKE} -f Makefile.inc1 ${NOFUN} build-tools
|
||||
${CDBENV} ${MAKE} ${CDMAKEARGS} -f Makefile.inc1 ${NOFUN} build-tools
|
||||
|
||||
_xb-cross-tools: .PHONY
|
||||
.for _tool in \
|
||||
XDEVDIRS= \
|
||||
${_clang_libs} \
|
||||
${_lld} \
|
||||
${_binutils} \
|
||||
${_elftctools} \
|
||||
usr.bin/ar \
|
||||
${_clang_libs} \
|
||||
${_clang} \
|
||||
${_gcc}
|
||||
|
||||
_xb-cross-tools: .PHONY
|
||||
.for _tool in ${XDEVDIRS}
|
||||
${_+_}@${ECHODIR} "===> xdev ${_tool} (obj,all)"; \
|
||||
cd ${.CURDIR}/${_tool}; \
|
||||
if [ -z "${NO_OBJ}" ]; then ${CDMAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
if [ -z "${NO_OBJWALK}" ]; then ${CDMAKE} DIRPRFX=${_tool}/ obj; fi; \
|
||||
${CDMAKE} DIRPRFX=${_tool}/ all
|
||||
.endfor
|
||||
|
||||
@ -2856,19 +2907,17 @@ xdev-install: xdev-build _xi-mtree _xi-cross-tools _xi-includes _xi-libraries .P
|
||||
|
||||
_xi-cross-tools: .PHONY
|
||||
@echo "_xi-cross-tools"
|
||||
.for _tool in \
|
||||
${_binutils} \
|
||||
${_elftctools} \
|
||||
usr.bin/ar \
|
||||
${_clang_libs} \
|
||||
${_clang} \
|
||||
${_gcc}
|
||||
.for _tool in ${XDEVDIRS}
|
||||
${_+_}@${ECHODIR} "===> xdev ${_tool} (install)"; \
|
||||
cd ${.CURDIR}/${_tool}; \
|
||||
${CDMAKE} DIRPRFX=${_tool}/ install DESTDIR=${XDDESTDIR}
|
||||
.endfor
|
||||
|
||||
_xi-includes: .PHONY
|
||||
.if !defined(NO_OBJWALK)
|
||||
${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 _obj \
|
||||
DESTDIR=${XDDESTDIR}
|
||||
.endif
|
||||
${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 includes \
|
||||
DESTDIR=${XDDESTDIR}
|
||||
|
||||
@ -2885,7 +2934,3 @@ xdev-links: .PHONY
|
||||
ln -sf ../../${XDTP}/usr/bin/$$i \
|
||||
../../../../usr/bin/${XDDIR}${_REVISION}-$$i; \
|
||||
done
|
||||
.else
|
||||
xdev xdev-build xdev-install xdev-links: .PHONY
|
||||
@echo "*** Error: Both TARGET and TARGET_ARCH must be defined for \"${.TARGET}\" target"
|
||||
.endif
|
||||
|
@ -59,10 +59,10 @@ LIB32WMAKEFLAGS+= -DCOMPAT_32BIT
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# soft-fp world
|
||||
.if ${TARGET_ARCH} == "armv6"
|
||||
.if ${TARGET_ARCH:Marmv[67]*} != ""
|
||||
LIBSOFTCFLAGS= -DCOMPAT_SOFTFP
|
||||
LIBSOFTCPUFLAGS= -mfloat-abi=softfp
|
||||
LIBSOFTWMAKEENV= CPUTYPE=soft MACHINE=arm MACHINE_ARCH=armv6
|
||||
LIBSOFTWMAKEENV= CPUTYPE=soft MACHINE=arm MACHINE_ARCH=${TARGET_ARCH}
|
||||
LIBSOFTWMAKEFLAGS= -DCOMPAT_SOFTFP
|
||||
.endif
|
||||
|
||||
@ -70,7 +70,7 @@ LIBSOFTWMAKEFLAGS= -DCOMPAT_SOFTFP
|
||||
# Generic code for each type.
|
||||
# Set defaults based on type.
|
||||
libcompat= ${LIBCOMPAT:tl}
|
||||
_LIBCOMPAT_MAKEVARS= _OBJTREE TMP CPUFLAGS CFLAGS CXXFLAGS WMAKEENV \
|
||||
_LIBCOMPAT_MAKEVARS= _OBJTOP TMP CPUFLAGS CFLAGS CXXFLAGS WMAKEENV \
|
||||
WMAKEFLAGS WMAKE
|
||||
.for _var in ${_LIBCOMPAT_MAKEVARS}
|
||||
.if !empty(LIB${LIBCOMPAT}${_var})
|
||||
@ -79,8 +79,8 @@ LIBCOMPAT${_var}?= ${LIB${LIBCOMPAT}${_var}}
|
||||
.endfor
|
||||
|
||||
# Shared flags
|
||||
LIBCOMPAT_OBJTREE?= ${OBJTREE}${.CURDIR}/world${libcompat}
|
||||
LIBCOMPATTMP?= ${OBJTREE}${.CURDIR}/lib${libcompat}
|
||||
LIBCOMPAT_OBJTOP?= ${OBJTOP}/obj-lib${libcompat}
|
||||
LIBCOMPATTMP?= ${LIBCOMPAT_OBJTOP}/tmp
|
||||
|
||||
LIBCOMPATCFLAGS+= ${LIBCOMPATCPUFLAGS} \
|
||||
-L${LIBCOMPATTMP}/usr/lib${libcompat} \
|
||||
@ -107,7 +107,7 @@ LIBCOMPATCXXFLAGS+= -isystem ${LIBCOMPATTMP}/usr/include/c++/v1 -std=c++11 \
|
||||
.endif
|
||||
|
||||
# Yes, the flags are redundant.
|
||||
LIBCOMPATWMAKEENV+= MAKEOBJDIRPREFIX=${LIBCOMPAT_OBJTREE} \
|
||||
LIBCOMPATWMAKEENV+= \
|
||||
INSTALL="sh ${.CURDIR}/tools/install.sh" \
|
||||
PATH=${TMPPATH} \
|
||||
SYSROOT=${LIBCOMPATTMP} \
|
||||
@ -127,6 +127,9 @@ LIBCOMPATWMAKEFLAGS+= CC="${XCC} ${LIBCOMPATCFLAGS}" \
|
||||
-DNO_LINT \
|
||||
MK_TESTS=no
|
||||
LIBCOMPATWMAKE+= ${LIBCOMPATWMAKEENV} ${MAKE} ${LIBCOMPATWMAKEFLAGS} \
|
||||
OBJTOP=${LIBCOMPAT_OBJTOP} \
|
||||
OBJROOT='$${OBJTOP}/' \
|
||||
MAKEOBJDIRPREFIX= \
|
||||
MK_MAN=no MK_HTML=no
|
||||
LIBCOMPATIMAKE+= ${LIBCOMPATWMAKE:NINSTALL=*:NDESTDIR=*} \
|
||||
MK_TOOLCHAIN=no ${IMAKE_INSTALL} \
|
||||
@ -148,6 +151,16 @@ build${libcompat}: .PHONY
|
||||
@echo "--------------------------------------------------------------"
|
||||
@echo ">>> stage 5.1: building lib${libcompat} shim libraries"
|
||||
@echo "--------------------------------------------------------------"
|
||||
.if !defined(NO_CLEAN)
|
||||
rm -rf ${LIBCOMPATTMP}
|
||||
.else
|
||||
.if exists(${LIBCOMPATTMP})
|
||||
${_+_}cd ${.CURDIR}; ${WMAKE} -DBATCH_DELETE_OLD_FILES \
|
||||
DESTDIR=${LIBCOMPATTMP} \
|
||||
delete-old delete-old-libs >/dev/null
|
||||
.endif
|
||||
.endif # !defined(NO_CLEAN)
|
||||
|
||||
mkdir -p ${LIBCOMPATTMP}/usr/include
|
||||
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
|
||||
-p ${LIBCOMPATTMP}/usr >/dev/null
|
||||
@ -173,16 +186,21 @@ build${libcompat}: .PHONY
|
||||
${_+_}cd ${.CURDIR}/${_dir}; \
|
||||
WORLDTMP=${WORLDTMP} \
|
||||
MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}" \
|
||||
MAKEOBJDIRPREFIX=${LIBCOMPAT_OBJTREE} ${MAKE} SSP_CFLAGS= DESTDIR= \
|
||||
${MAKE} SSP_CFLAGS= DESTDIR= \
|
||||
OBJTOP=${LIBCOMPAT_OBJTOP} \
|
||||
OBJROOT='$${OBJTOP}/' \
|
||||
MAKEOBJDIRPREFIX= \
|
||||
DIRPRFX=${_dir}/ -DNO_LINT -DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \
|
||||
build-tools
|
||||
.endfor
|
||||
${_+_}cd ${.CURDIR}; \
|
||||
${LIBCOMPATWMAKE} -f Makefile.inc1 -DNO_FSCHG libraries
|
||||
.if ${libcompat} == "32" && !defined(NO_RTLD)
|
||||
.if ${libcompat} == "32"
|
||||
.for _t in ${_obj} all
|
||||
.if !defined(NO_RTLD)
|
||||
${_+_}cd ${.CURDIR}/libexec/rtld-elf; PROG=ld-elf32.so.1 ${LIBCOMPATWMAKE} \
|
||||
-DNO_FSCHG DIRPRFX=libexec/rtld-elf/ ${_t}
|
||||
.endif
|
||||
${_+_}cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIBCOMPATWMAKE} \
|
||||
DIRPRFX=usr.bin/ldd ${_t}
|
||||
.endfor
|
||||
@ -192,9 +210,11 @@ distribute${libcompat} install${libcompat}: .PHONY
|
||||
.for _dir in ${_LC_LIBDIRS.yes}
|
||||
${_+_}cd ${.CURDIR}/${_dir}; ${LIBCOMPATIMAKE} ${.TARGET:S/${libcompat}$//}
|
||||
.endfor
|
||||
.if ${libcompat} == "32" && !defined(NO_RTLD)
|
||||
.if ${libcompat} == "32"
|
||||
.if !defined(NO_RTLD)
|
||||
${_+_}cd ${.CURDIR}/libexec/rtld-elf; \
|
||||
PROG=ld-elf32.so.1 ${LIBCOMPATIMAKE} ${.TARGET:S/32$//}
|
||||
.endif
|
||||
${_+_}cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIBCOMPATIMAKE} \
|
||||
${.TARGET:S/32$//}
|
||||
.endif
|
||||
|
@ -38,16 +38,205 @@
|
||||
# xargs -n1 | sort | uniq -d;
|
||||
# done
|
||||
|
||||
# 20171108: badsect(8) removal
|
||||
OLD_FILES+=sbin/badsect
|
||||
OLD_FILES+=rescue/badsect
|
||||
OLD_FILES+=usr/share/man/man8/badsect.8.gz
|
||||
# 20171105: fixing lib/libclang_rt CRTARCH for arm:armv[67].
|
||||
.if ${MACHINE} == "arm"
|
||||
.if ${MACHINE_ARCH:Marmv[67]*} != "" && ${CPUTYPE:M*soft*} == ""
|
||||
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.asan-preinit-arm.a
|
||||
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.asan-arm.a
|
||||
OLD_LIBS+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.asan-arm.so
|
||||
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.asan_cxx-arm.a
|
||||
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.profile-arm.a
|
||||
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.safestack-arm.a
|
||||
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.stats-arm.a
|
||||
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.stats_client-arm.a
|
||||
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.ubsan_standalone-arm.a
|
||||
OLD_FILES+=usr/lib/clang/5.0.0/lib/freebsd/libclang_rt.ubsan_standalone_cxx-arm.a
|
||||
.endif
|
||||
.endif
|
||||
# 20171104: libcap_random should be in /lib not in /usr/lib
|
||||
OLD_LIBS+=usr/lib/libcap_random.so.0
|
||||
# 20171104: Casper can work only as shared library
|
||||
OLD_FILES+=usr/lib/libcasper.a
|
||||
OLD_FILES+=usr/lib/libcasper_p.a
|
||||
OLD_FILES+=usr/lib/libcap_dns.a
|
||||
OLD_FILES+=usr/lib/libcap_dns_p.a
|
||||
OLD_FILES+=usr/lib/libcap_grp.a
|
||||
OLD_FILES+=usr/lib/libcap_grp_p.a
|
||||
OLD_FILES+=usr/lib/libcap_pwd.a
|
||||
OLD_FILES+=usr/lib/libcap_pwd_p.a
|
||||
OLD_FILES+=usr/lib/libcap_random.a
|
||||
OLD_FILES+=usr/lib/libcap_random_p.a
|
||||
OLD_FILES+=usr/lib/libcap_sysctl.a
|
||||
OLD_FILES+=usr/lib/libcap_sysctl_p.a
|
||||
# 20171031: Removal of obsolete man files
|
||||
OLD_FILES+=usr/share/man/man7/adding_user.7.gz
|
||||
# 20171031: Disconnected libpathconv tests
|
||||
OLD_DIRS+=usr/tests/lib/libpathconv
|
||||
# 20171017: Removal of mbpool(9)
|
||||
OLD_FILES+=usr/include/sys/mbpool.h
|
||||
OLD_FILES+=usr/share/man/man9/mbpool.9.gz
|
||||
OLD_FILES+=usr/share/man/man9/mbp_destroy.9.gz
|
||||
OLD_FILES+=usr/share/man/man9/mbp_alloc.9.gz
|
||||
OLD_FILES+=usr/share/man/man9/mbp_ext_free.9.gz
|
||||
OLD_FILES+=usr/share/man/man9/mbp_count.9.gz
|
||||
OLD_FILES+=usr/share/man/man9/mbp_card_free.9.gz
|
||||
OLD_FILES+=usr/share/man/man9/mbp_get_keep.9.gz
|
||||
OLD_FILES+=usr/share/man/man9/mbp_free.9.gz
|
||||
OLD_FILES+=usr/share/man/man9/mbp_get.9.gz
|
||||
OLD_FILES+=usr/share/man/man9/mbp_create.9.gz
|
||||
OLD_FILES+=usr/share/man/man9/mbp_sync.9.gz
|
||||
# 20171010: Remove libstand
|
||||
OLD_FILES+=usr/lib/libstand.a
|
||||
OLD_FILES+=usr/lib/libstand_p.a
|
||||
OLD_FILES+=usr/include/stand.h
|
||||
OLD_FILES+=usr/share/man/man3/libstand.3
|
||||
# 20171003: remove RCMDS
|
||||
OLD_FILES+=bin/rcp
|
||||
OLD_FILES+=rescue/rcp
|
||||
OLD_FILES+=usr/bin/rlogin
|
||||
OLD_FILES+=usr/bin/rsh
|
||||
OLD_FILES+=usr/libexec/rlogind
|
||||
OLD_FILES+=usr/libexec/rshd
|
||||
OLD_FILES+=usr/share/man/man1/rcp.1.gz
|
||||
OLD_FILES+=usr/share/man/man1/rlogin.1.gz
|
||||
OLD_FILES+=usr/share/man/man1/rsh.1.gz
|
||||
OLD_FILES+=usr/share/man/man8/rlogind.8.gz
|
||||
OLD_FILES+=usr/share/man/man8/rshd.8.gz
|
||||
# 20170927: crshared
|
||||
OLD_FILES+=usr/share/man/man9/crshared.9.gz
|
||||
# 20170927: procctl
|
||||
OLD_FILES+=usr/share/man/man8/procctl.8.gz
|
||||
OLD_FILES+=usr/sbin/procctl
|
||||
# 20170926: remove unneeded man aliases and locales directory
|
||||
OLD_FILES+=usr/share/man/en.ISO8859-1/man1
|
||||
OLD_FILES+=usr/share/man/en.ISO8859-1/man2
|
||||
OLD_FILES+=usr/share/man/en.ISO8859-1/man3
|
||||
OLD_FILES+=usr/share/man/en.ISO8859-1/man4
|
||||
OLD_FILES+=usr/share/man/en.ISO8859-1/man5
|
||||
OLD_FILES+=usr/share/man/en.ISO8859-1/man6
|
||||
OLD_FILES+=usr/share/man/en.ISO8859-1/man7
|
||||
OLD_FILES+=usr/share/man/en.ISO8859-1/man8
|
||||
OLD_FILES+=usr/share/man/en.ISO8859-1/man9
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1
|
||||
OLD_FILES+=usr/share/man/en.ISO8859-1/mandoc.db
|
||||
OLD_FILES+=usr/share/man/en.UTF-8/man1
|
||||
OLD_FILES+=usr/share/man/en.UTF-8/man2
|
||||
OLD_FILES+=usr/share/man/en.UTF-8/man3
|
||||
OLD_FILES+=usr/share/man/en.UTF-8/man4
|
||||
OLD_FILES+=usr/share/man/en.UTF-8/man5
|
||||
OLD_FILES+=usr/share/man/en.UTF-8/man6
|
||||
OLD_FILES+=usr/share/man/en.UTF-8/man7
|
||||
OLD_FILES+=usr/share/man/en.UTF-8/man8
|
||||
OLD_FILES+=usr/share/man/en.UTF-8/man9
|
||||
OLD_FILES+=usr/share/man/en.UTF-8/mandoc.db
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8
|
||||
OLD_FILES+=usr/share/man/en.ISO8859-15
|
||||
OLD_FILES+=usr/share/openssl/man/en.ISO8859-1/man1
|
||||
OLD_FILES+=usr/share/openssl/man/en.ISO8859-1/man3
|
||||
OLD_FILES+=usr/share/openssl/man/en.ISO8859-1/mandoc.db
|
||||
OLD_DIRS+=usr/share/openssl/man/en.ISO8859-1
|
||||
OLD_FILES+=usr/share/openssl/man/en.ISO8859-15
|
||||
OLD_DIRS+=usr/share/man/ja/man1
|
||||
OLD_DIRS+=usr/share/man/ja/man2
|
||||
OLD_DIRS+=usr/share/man/ja/man3
|
||||
OLD_DIRS+=usr/share/man/ja/man4
|
||||
OLD_DIRS+=usr/share/man/ja/man5
|
||||
OLD_DIRS+=usr/share/man/ja/man6
|
||||
OLD_DIRS+=usr/share/man/ja/man7
|
||||
OLD_DIRS+=usr/share/man/ja/man8
|
||||
OLD_DIRS+=usr/share/man/ja/man9
|
||||
OLD_DIRS+=usr/share/man/ja
|
||||
# 20170913: remove unneeded catman utility
|
||||
OLD_FILES+=etc/periodic/weekly/330.catman
|
||||
OLD_FILES+=usr/bin/catman
|
||||
OLD_FILES+=usr/libexec/catman.local
|
||||
OLD_FILES+=usr/share/man/man1/catman.1.gz
|
||||
OLD_FILES+=usr/share/man/man8/catman.local.8.gz
|
||||
|
||||
OLD_DIRS+=usr/share/man/cat1
|
||||
OLD_DIRS+=usr/share/man/cat2
|
||||
OLD_DIRS+=usr/share/man/cat3
|
||||
OLD_DIRS+=usr/share/man/cat4/amd64
|
||||
OLD_DIRS+=usr/share/man/cat4/arm
|
||||
OLD_DIRS+=usr/share/man/cat4/i386
|
||||
OLD_DIRS+=usr/share/man/cat4/powerpc
|
||||
OLD_DIRS+=usr/share/man/cat4/sparc64
|
||||
OLD_DIRS+=usr/share/man/cat4
|
||||
OLD_DIRS+=usr/share/man/cat5
|
||||
OLD_DIRS+=usr/share/man/cat6
|
||||
OLD_DIRS+=usr/share/man/cat7
|
||||
OLD_DIRS+=usr/share/man/cat8/amd64
|
||||
OLD_DIRS+=usr/share/man/cat8/arm
|
||||
OLD_DIRS+=usr/share/man/cat8/i386
|
||||
OLD_DIRS+=usr/share/man/cat8/powerpc
|
||||
OLD_DIRS+=usr/share/man/cat8/sparc64
|
||||
OLD_DIRS+=usr/share/man/cat8
|
||||
OLD_DIRS+=usr/share/man/cat9
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat1
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat2
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat3
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat4/amd64
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat4/arm
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat4/i386
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat4/powerpc
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat4/sparc64
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat4
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat5
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat6
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat7
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat8/amd64
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat8/arm
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat8/i386
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat8/powerpc
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat8/sparc64
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat8
|
||||
OLD_DIRS+=usr/share/man/en.ISO8859-1/cat9
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat1
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat2
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat3
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat4/amd64
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat4/arm
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat4/i386
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat4/powerpc
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat4/sparc64
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat4
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat5
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat6
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat7
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat8/amd64
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat8/arm
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat8/i386
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat8/powerpc
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat8/sparc64
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat8
|
||||
OLD_DIRS+=usr/share/man/en.UTF-8/cat9
|
||||
OLD_DIRS+=usr/share/man/ja/cat1
|
||||
OLD_DIRS+=usr/share/man/ja/cat2
|
||||
OLD_DIRS+=usr/share/man/ja/cat3
|
||||
OLD_DIRS+=usr/share/man/ja/cat4/amd64
|
||||
OLD_DIRS+=usr/share/man/ja/cat4/arm
|
||||
OLD_DIRS+=usr/share/man/ja/cat4/i386
|
||||
OLD_DIRS+=usr/share/man/ja/cat4/powerpc
|
||||
OLD_DIRS+=usr/share/man/ja/cat4/sparc64
|
||||
OLD_DIRS+=usr/share/man/ja/cat4
|
||||
OLD_DIRS+=usr/share/man/ja/cat5
|
||||
OLD_DIRS+=usr/share/man/ja/cat6
|
||||
OLD_DIRS+=usr/share/man/ja/cat7
|
||||
OLD_DIRS+=usr/share/man/ja/cat8/amd64
|
||||
OLD_DIRS+=usr/share/man/ja/cat8/arm
|
||||
OLD_DIRS+=usr/share/man/ja/cat8/powerpc
|
||||
OLD_DIRS+=usr/share/man/ja/cat8/sparc64
|
||||
OLD_DIRS+=usr/share/man/ja/cat8
|
||||
OLD_DIRS+=usr/share/man/ja/cat9
|
||||
OLD_DIRS+=usr/share/openssl/man/cat1
|
||||
OLD_DIRS+=usr/share/openssl/man/cat3
|
||||
OLD_DIRS+=usr/share/openssl/man/en.ISO8859-1/cat1
|
||||
OLD_DIRS+=usr/share/openssl/man/en.ISO8859-1/cat3
|
||||
# 20170802: ksyms(4) ioctl interface was removed
|
||||
OLD_FILES+=usr/include/sys/ksyms.h
|
||||
|
||||
# 20170722: new clang import which bumps version from 4.0.0 to 5.0.0.
|
||||
OLD_FILES+=usr/lib/clang/4.0.0/include/sanitizer/allocator_interface.h
|
||||
OLD_FILES+=usr/lib/clang/4.0.0/include/sanitizer/asan_interface.h
|
||||
|
6
README
6
README
@ -9,7 +9,7 @@ more information).
|
||||
|
||||
The Makefile in this directory supports a number of targets for
|
||||
building components (or all) of the FreeBSD source tree. See build(7)
|
||||
and http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html
|
||||
and https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html
|
||||
for more information, including setting make(1) variables.
|
||||
|
||||
The `buildkernel` and `installkernel` targets build and install
|
||||
@ -18,7 +18,7 @@ the Makefile in this directory for more information on the
|
||||
standard build targets and compile-time flags.
|
||||
|
||||
Building a kernel is a somewhat more involved process. See build(7), config(8),
|
||||
and http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig.html
|
||||
and https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig.html
|
||||
for more information.
|
||||
|
||||
Note: If you want to build and install the kernel with the
|
||||
@ -81,4 +81,4 @@ usr.sbin System administration commands.
|
||||
For information on synchronizing your source tree with one or more of
|
||||
the FreeBSD Project's development branches, please see:
|
||||
|
||||
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/updating-src.html
|
||||
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/current-stable.html
|
||||
|
@ -11,7 +11,7 @@ more information).
|
||||
|
||||
The Makefile in this directory supports a number of targets for
|
||||
building components (or all) of the FreeBSD source tree. See build(7)
|
||||
and http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html
|
||||
and https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html
|
||||
for more information, including setting make(1) variables.
|
||||
|
||||
The `buildkernel` and `installkernel` targets build and install
|
||||
@ -20,7 +20,7 @@ the Makefile in this directory for more information on the
|
||||
standard build targets and compile-time flags.
|
||||
|
||||
Building a kernel is a somewhat more involved process. See build(7), config(8),
|
||||
and http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig.html
|
||||
and https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig.html
|
||||
for more information.
|
||||
|
||||
Note: If you want to build and install the kernel with the
|
||||
@ -83,4 +83,4 @@ usr.sbin System administration commands.
|
||||
For information on synchronizing your source tree with one or more of
|
||||
the FreeBSD Project's development branches, please see:
|
||||
|
||||
http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/synching.html
|
||||
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/current-stable.html
|
||||
|
83
UPDATING
83
UPDATING
@ -6,7 +6,7 @@ COMMON ITEMS: section later in the file. These instructions assume that you
|
||||
basically know what you are doing. If not, then please consult the FreeBSD
|
||||
handbook:
|
||||
|
||||
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/updating-src.html
|
||||
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/current-stable.html
|
||||
|
||||
Items affecting the ports and packages system can be found in
|
||||
/usr/ports/UPDATING. Please read that file before running portupgrade.
|
||||
@ -51,6 +51,60 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW:
|
||||
|
||||
****************************** SPECIAL WARNING: ******************************
|
||||
|
||||
20171106:
|
||||
The naive and non-compliant support of posix_fallocate(2) in ZFS
|
||||
has been removed as of r325320. The system call now returns EINVAL
|
||||
when used on a ZFS file. Although the new behavior complies with the
|
||||
standard, some consumers are not prepared to cope with it.
|
||||
One known victim is lld prior to r325420.
|
||||
|
||||
20171102:
|
||||
Building in a FreeBSD src checkout will automatically create object
|
||||
directories now rather than store files in the current directory if
|
||||
'make obj' was not ran. Calling 'make obj' is no longer necesarry.
|
||||
This feature can be disabled by setting WITHOUT_AUTO_OBJ=yes in
|
||||
/etc/src-env.conf (not /etc/src.conf), or passing the option in the
|
||||
environment.
|
||||
|
||||
20171101:
|
||||
The default MAKEOBJDIR has changed from /usr/obj/<srcdir> for native
|
||||
builds, and /usr/obj/<arch>/<srcdir> for cross-builds, to a unified
|
||||
/usr/obj/<srcdir>/<arch>. This behavior can be changed to the old
|
||||
format by setting WITHOUT_UNIFIED_OBJDIR=yes in /etc/src-env.conf,
|
||||
the environment, or with -DWITHOUT_UNIFIED_OBJDIR when building.
|
||||
The UNIFIED_OBJDIR option is a transitional feature that will be
|
||||
removed for 12.0 release; please migrate to the new format for any
|
||||
tools by looking up the OBJDIR used by 'make -V .OBJDIR' means rather
|
||||
than hardcoding paths.
|
||||
|
||||
20171028:
|
||||
The native-xtools target no longer installs the files by default to the
|
||||
OBJDIR. Use the native-xtools-install target with a DESTDIR to install
|
||||
to ${DESTDIR}/${NXTP} where NXTP defaults to /nxb-bin.
|
||||
|
||||
20171021:
|
||||
As part of the boot loader infrastructure cleanup, LOADER_*_SUPPORT
|
||||
options are changing from controlling the build if defined / undefined
|
||||
to controlling the build with explicit 'yes' or 'no' values. They will
|
||||
shift to WITH/WITHOUT options to match other options in the system.
|
||||
|
||||
20171010:
|
||||
libstand has turned into a private library for sys/boot use only.
|
||||
It is no longer supported as a public interface outside of sys/boot.
|
||||
|
||||
20171005:
|
||||
The arm port has split armv6 into armv6 and armv7. armv7 is now
|
||||
a valid TARGET_ARCH/MACHINE_ARCH setting. If you have an armv7 system
|
||||
and are running a kernel from before r324363, you will need to add
|
||||
MACHINE_ARCH=armv7 to 'make buildworld' to do a native build.
|
||||
|
||||
20171003:
|
||||
When building multiple kernels using KERNCONF, non-existent KERNCONF
|
||||
files will produce an error and buildkernel will fail. Previously
|
||||
missing KERNCONF files silently failed giving no indication as to
|
||||
why, only to subsequently discover during installkernel that the
|
||||
desired kernel was never built in the first place.
|
||||
|
||||
20170912:
|
||||
The default serial number format for CTL LUNs has changed. This will
|
||||
affect users who use /dev/diskid/* device nodes, or whose FibreChannel
|
||||
@ -66,8 +120,8 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW:
|
||||
soft-float everything else should be affected.
|
||||
|
||||
20170826:
|
||||
During boot the geli passphrase will be hidden. To restore previous
|
||||
behavior see geli(8) configuration options.
|
||||
The geli password typed at boot is now hidden. To restore the previous
|
||||
behavior, see geli(8) for configuration options.
|
||||
|
||||
20170825:
|
||||
Move PMTUD blackhole counters to TCPSTATS and remove them from bare
|
||||
@ -1815,21 +1869,6 @@ COMMON ITEMS:
|
||||
make installkernel KERNCONF=YOUR_KERNEL_HERE KODIR=/boot/testkernel
|
||||
nextboot -k testkernel
|
||||
|
||||
To just build a kernel when you know that it won't mess you up
|
||||
--------------------------------------------------------------
|
||||
This assumes you are already running a CURRENT system. Replace
|
||||
${arch} with the architecture of your machine (e.g. "i386",
|
||||
"arm", "amd64", "ia64", "pc98", "sparc64", "powerpc", "mips", etc).
|
||||
|
||||
cd src/sys/${arch}/conf
|
||||
config KERNEL_NAME_HERE
|
||||
cd ../compile/KERNEL_NAME_HERE
|
||||
make depend
|
||||
make
|
||||
make install
|
||||
|
||||
If this fails, go to the "To build a kernel" section.
|
||||
|
||||
To rebuild everything and install it on the current system.
|
||||
-----------------------------------------------------------
|
||||
# Note: sometimes if you are running current you gotta do more than
|
||||
@ -1837,7 +1876,8 @@ COMMON ITEMS:
|
||||
|
||||
<make sure you have good level 0 dumps>
|
||||
make buildworld
|
||||
make kernel KERNCONF=YOUR_KERNEL_HERE
|
||||
make buildkernel KERNCONF=YOUR_KERNEL_HERE
|
||||
make installkernel KERNCONF=YOUR_KERNEL_HERE
|
||||
[1]
|
||||
<reboot in single user> [3]
|
||||
mergemaster -Fp [5]
|
||||
@ -1937,10 +1977,7 @@ COMMON ITEMS:
|
||||
Make sure that you merge any new devices from GENERIC since the
|
||||
last time you updated your kernel config file.
|
||||
|
||||
[9] When checking out sources, you must include the -P flag to have
|
||||
cvs prune empty directories.
|
||||
|
||||
If CPUTYPE is defined in your /etc/make.conf, make sure to use the
|
||||
[9] If CPUTYPE is defined in your /etc/make.conf, make sure to use the
|
||||
"?=" instead of the "=" assignment operator, so that buildworld can
|
||||
override the CPUTYPE if it needs to.
|
||||
|
||||
|
@ -40,7 +40,6 @@ SUBDIR= cat \
|
||||
test \
|
||||
uuidgen
|
||||
|
||||
SUBDIR.${MK_RCMDS}+= rcp
|
||||
SUBDIR.${MK_SENDMAIL}+= rmail
|
||||
SUBDIR.${MK_TCSH}+= csh
|
||||
SUBDIR.${MK_TESTS}+= tests
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -226,10 +226,16 @@ cook_cat(FILE *fp)
|
||||
} else
|
||||
gobble = 0;
|
||||
}
|
||||
if (nflag && (!bflag || ch != '\n')) {
|
||||
(void)fprintf(stdout, "%6d\t", ++line);
|
||||
if (ferror(stdout))
|
||||
break;
|
||||
if (nflag) {
|
||||
if (!bflag || ch != '\n') {
|
||||
(void)fprintf(stdout, "%6d\t", ++line);
|
||||
if (ferror(stdout))
|
||||
break;
|
||||
} else if (eflag) {
|
||||
(void)fprintf(stdout, "%6s\t", "");
|
||||
if (ferror(stdout))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ch == '\n') {
|
||||
|
@ -17,10 +17,4 @@ ${PACKAGE}FILES+= d_vt_output.out
|
||||
|
||||
.include <netbsd-tests.test.mk>
|
||||
|
||||
d_align.out: ${TESTSRC}/d_align.out
|
||||
sed -E -e 's,^[[:space:]]{7}\$$$$,\$$,' < ${.ALLSRC} > ${.TARGET}.tmp
|
||||
mv ${.TARGET}.tmp ${.TARGET}
|
||||
|
||||
CLEANFILES+= d_align.out d_align.out.tmp
|
||||
|
||||
.include <bsd.test.mk>
|
||||
|
@ -1,6 +1,8 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
|
||||
PACKAGE=runtime
|
||||
PROG= chflags
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
11
bin/chflags/tests/Makefile.depend
Normal file
11
bin/chflags/tests/Makefile.depend
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
# Autogenerated - do NOT edit!
|
||||
|
||||
DIRDEPS = \
|
||||
|
||||
|
||||
.include <dirdeps.mk>
|
||||
|
||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
||||
# local dependencies - needed for -jN in clean tree
|
||||
.endif
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
11
bin/chmod/tests/Makefile.depend
Normal file
11
bin/chmod/tests/Makefile.depend
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
# Autogenerated - do NOT edit!
|
||||
|
||||
DIRDEPS = \
|
||||
|
||||
|
||||
.include <dirdeps.mk>
|
||||
|
||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
||||
# local dependencies - needed for -jN in clean tree
|
||||
.endif
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/arpa \
|
||||
include/xlocale \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/protocols \
|
||||
include/xlocale \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
11
bin/echo/tests/Makefile.depend
Normal file
11
bin/echo/tests/Makefile.depend
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
# Autogenerated - do NOT edit!
|
||||
|
||||
DIRDEPS = \
|
||||
|
||||
|
||||
.include <dirdeps.mk>
|
||||
|
||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
||||
# local dependencies - needed for -jN in clean tree
|
||||
.endif
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
11
bin/ln/tests/Makefile.depend
Normal file
11
bin/ln/tests/Makefile.depend
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
# Autogenerated - do NOT edit!
|
||||
|
||||
DIRDEPS = \
|
||||
|
||||
|
||||
.include <dirdeps.mk>
|
||||
|
||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
||||
# local dependencies - needed for -jN in clean tree
|
||||
.endif
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -1,6 +1,8 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
|
||||
PACKAGE=runtime
|
||||
PROG= mkdir
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
11
bin/mkdir/tests/Makefile.depend
Normal file
11
bin/mkdir/tests/Makefile.depend
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
# Autogenerated - do NOT edit!
|
||||
|
||||
DIRDEPS = \
|
||||
|
||||
|
||||
.include <dirdeps.mk>
|
||||
|
||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
||||
# local dependencies - needed for -jN in clean tree
|
||||
.endif
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -199,7 +199,8 @@ static VAR var[] = {
|
||||
{"tdaddr", "TDADDR", NULL, "thread-address", 0, kvar, KOFF(ki_tdaddr),
|
||||
KPTR, "lx", 0},
|
||||
{"tdev", "TDEV", NULL, "terminal-device", 0, tdev, 0, CHAR, NULL, 0},
|
||||
{"tdnam", "TDNAM", NULL, "terminal-device-name", LJUST, tdnam, 0, CHAR,
|
||||
{"tdnam", "", "tdname", NULL, 0, NULL, 0, CHAR, NULL, 0},
|
||||
{"tdname", "TDNAME", NULL, "thread-name", LJUST, tdnam, 0, CHAR,
|
||||
NULL, 0},
|
||||
{"time", "TIME", NULL, "cpu-time", USER, cputime, 0, CHAR, NULL, 0},
|
||||
{"tpgid", "TPGID", NULL, "terminal-process-gid", 0, kvar,
|
||||
|
@ -29,7 +29,7 @@
|
||||
.\" @(#)ps.1 8.3 (Berkeley) 4/18/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 7, 2017
|
||||
.Dd October 9, 2017
|
||||
.Dt PS 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -675,6 +675,8 @@ saved UID from a setuid executable
|
||||
accumulated system CPU time
|
||||
.It Cm tdaddr
|
||||
thread address
|
||||
.It Cm tdname
|
||||
thread name
|
||||
.It Cm tdev
|
||||
control terminal device number
|
||||
.It Cm time
|
||||
|
@ -523,7 +523,11 @@ main(int argc, char *argv[])
|
||||
*/
|
||||
nentries = -1;
|
||||
kp = kvm_getprocs(kd, what, flag, &nentries);
|
||||
if ((kp == NULL && nentries > 0) || (kp != NULL && nentries < 0))
|
||||
/*
|
||||
* Ignore ESRCH to preserve behaviour of "ps -p nonexistent-pid"
|
||||
* not reporting an error.
|
||||
*/
|
||||
if ((kp == NULL && errno != ESRCH) || (kp != NULL && nentries < 0))
|
||||
xo_errx(1, "%s", kvm_geterr(kd));
|
||||
nkept = 0;
|
||||
if (nentries > 0) {
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -1,17 +0,0 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 7/19/93
|
||||
# $FreeBSD$
|
||||
|
||||
PACKAGE=rcmds
|
||||
PROG= rcp
|
||||
SRCS= rcp.c util.c
|
||||
CFLAGS+=-DBINDIR=${BINDIR}
|
||||
|
||||
PACKAGE=rcmds
|
||||
|
||||
BINOWN= root
|
||||
BINMODE=4555
|
||||
|
||||
HAS_TESTS=
|
||||
SUBDIR.${MK_TESTS}+= tests
|
||||
|
||||
.include <bsd.prog.mk>
|
160
bin/rcp/rcp.1
160
bin/rcp/rcp.1
@ -1,160 +0,0 @@
|
||||
.\"-
|
||||
.\" Copyright (c) 1983, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)rcp.1 8.1 (Berkeley) 5/31/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 3, 2017
|
||||
.Dt RCP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rcp
|
||||
.Nd remote file copy
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl 46p
|
||||
.Ar file1 file2
|
||||
.Nm
|
||||
.Op Fl 46pr
|
||||
.Ar
|
||||
.Ar directory
|
||||
.Sh DEPRECATION NOTICE
|
||||
.Nm
|
||||
is deprecated and will be removed from future versions of the
|
||||
.Fx
|
||||
base system.
|
||||
If
|
||||
.Nm
|
||||
is still required, it can be installed from ports or packages
|
||||
(net/bsdrcmds).
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility copies files between machines.
|
||||
Each
|
||||
.Ar file
|
||||
or
|
||||
.Ar directory
|
||||
argument is either a remote file name of the
|
||||
form
|
||||
.Dq ruser@rhost:path ,
|
||||
or a local file name (containing no
|
||||
.Ql :\&
|
||||
characters,
|
||||
or a
|
||||
.Ql /
|
||||
before any
|
||||
.Ql :\& Ns
|
||||
s).
|
||||
.Pp
|
||||
The following options are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl 4
|
||||
Use IPv4 addresses only.
|
||||
.It Fl 6
|
||||
Use IPv6 addresses only.
|
||||
.It Fl p
|
||||
Cause
|
||||
.Nm
|
||||
to attempt to preserve (duplicate) in its copies the modification
|
||||
times and modes of the source files, ignoring the
|
||||
.Xr umask 2 .
|
||||
By default, the mode and owner of
|
||||
.Ar file2
|
||||
are preserved if it already existed; otherwise the mode of the source file
|
||||
modified by the
|
||||
.Xr umask 2
|
||||
on the destination host is used.
|
||||
.It Fl r
|
||||
If any of the source files are directories,
|
||||
.Nm
|
||||
copies each subtree rooted at that name; in this case
|
||||
the destination must be a directory.
|
||||
.El
|
||||
.Pp
|
||||
If
|
||||
.Ar path
|
||||
is not a full path name, it is interpreted relative to
|
||||
the login directory of the specified user
|
||||
.Ar ruser
|
||||
on
|
||||
.Ar rhost ,
|
||||
or your current user name if no other remote user name is specified.
|
||||
A
|
||||
.Ar path
|
||||
on a remote host may be quoted (using
|
||||
.Ql \e ,
|
||||
.Ql \&" ,
|
||||
or
|
||||
.Ql \(aa )
|
||||
so that the metacharacters are interpreted remotely.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility does not prompt for passwords; it performs remote execution
|
||||
via
|
||||
.Xr rsh 1 ,
|
||||
and requires the same authorization.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility handles third party copies, where neither source nor target files
|
||||
are on the current machine.
|
||||
.Sh SEE ALSO
|
||||
.Xr cp 1 ,
|
||||
.Xr ftp 1 ,
|
||||
.Xr rlogin 1 ,
|
||||
.Xr rsh 1 ,
|
||||
.Xr hosts.equiv 5
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
||||
The version of
|
||||
.Nm
|
||||
described here
|
||||
has been reimplemented with Kerberos in
|
||||
.Bx 4.3 Reno .
|
||||
.Sh BUGS
|
||||
Does not detect all cases where the target of a copy might
|
||||
be a file in cases where only a directory should be legal.
|
||||
.Pp
|
||||
Is confused by any output generated by commands in a
|
||||
.Pa .login ,
|
||||
.Pa .profile ,
|
||||
or
|
||||
.Pa .cshrc
|
||||
file on the remote host.
|
||||
.Pp
|
||||
The destination user and hostname may have to be specified as
|
||||
.Dq rhost.ruser
|
||||
when the destination machine is running the
|
||||
.Bx 4.2
|
||||
version of
|
||||
.Nm .
|
791
bin/rcp/rcp.c
791
bin/rcp/rcp.c
@ -1,791 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1983, 1990, 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 2002 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed for the FreeBSD Project by
|
||||
* ThinkSec AS and NAI Labs, the Security Research Division of Network
|
||||
* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
|
||||
* ("CBOSS"), as part of the DARPA CHATS research program.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char const copyright[] =
|
||||
"@(#) Copyright (c) 1983, 1990, 1992, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)rcp.c 8.2 (Berkeley) 4/2/94";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <netdb.h>
|
||||
#include <paths.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
#define OPTIONS "46dfprt"
|
||||
|
||||
static struct passwd *pwd;
|
||||
static u_short port;
|
||||
static uid_t userid;
|
||||
static int errs, rem;
|
||||
int iamremote;
|
||||
static int pflag, iamrecursive, targetshouldbedirectory;
|
||||
static int family = PF_UNSPEC;
|
||||
|
||||
static int argc_copy;
|
||||
static const char **argv_copy;
|
||||
|
||||
static char period[] = ".";
|
||||
|
||||
#define CMDNEEDS 64
|
||||
static char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
|
||||
|
||||
int response(void);
|
||||
void rsource(char *, struct stat *);
|
||||
void sink(int, char *[]);
|
||||
void source(int, char *[]);
|
||||
void tolocal(int, char *[]);
|
||||
void toremote(char *, int, char *[]);
|
||||
void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct servent *sp;
|
||||
int ch, fflag, i, tflag;
|
||||
char *targ;
|
||||
|
||||
/*
|
||||
* Prepare for execing ourselves.
|
||||
*/
|
||||
argc_copy = argc + 1;
|
||||
argv_copy = malloc((argc_copy + 1) * sizeof(*argv_copy));
|
||||
if (argv_copy == NULL)
|
||||
err(1, "malloc");
|
||||
argv_copy[0] = argv[0];
|
||||
argv_copy[1] = "-K";
|
||||
for (i = 1; i < argc; ++i) {
|
||||
argv_copy[i + 1] = strdup(argv[i]);
|
||||
if (argv_copy[i + 1] == NULL)
|
||||
errx(1, "strdup: out of memory");
|
||||
}
|
||||
argv_copy[argc + 1] = NULL;
|
||||
|
||||
fflag = tflag = 0;
|
||||
while ((ch = getopt(argc, argv, OPTIONS)) != -1)
|
||||
switch(ch) { /* User-visible flags. */
|
||||
case '4':
|
||||
family = PF_INET;
|
||||
break;
|
||||
|
||||
case '6':
|
||||
family = PF_INET6;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
pflag = 1;
|
||||
break;
|
||||
case 'r':
|
||||
iamrecursive = 1;
|
||||
break;
|
||||
/* Server options. */
|
||||
case 'd':
|
||||
targetshouldbedirectory = 1;
|
||||
break;
|
||||
case 'f': /* "from" */
|
||||
iamremote = 1;
|
||||
fflag = 1;
|
||||
break;
|
||||
case 't': /* "to" */
|
||||
iamremote = 1;
|
||||
tflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
sp = getservbyname("shell", "tcp");
|
||||
if (sp == NULL)
|
||||
errx(1, "shell/tcp: unknown service");
|
||||
port = sp->s_port;
|
||||
|
||||
if ((pwd = getpwuid(userid = getuid())) == NULL)
|
||||
errx(1, "unknown user %d", (int)userid);
|
||||
|
||||
rem = STDIN_FILENO; /* XXX */
|
||||
|
||||
if (fflag) { /* Follow "protocol", send data. */
|
||||
(void)response();
|
||||
(void)setuid(userid);
|
||||
source(argc, argv);
|
||||
exit(errs);
|
||||
}
|
||||
|
||||
if (tflag) { /* Receive data. */
|
||||
(void)setuid(userid);
|
||||
sink(argc, argv);
|
||||
exit(errs);
|
||||
}
|
||||
|
||||
if (argc < 2)
|
||||
usage();
|
||||
if (argc > 2)
|
||||
targetshouldbedirectory = 1;
|
||||
|
||||
rem = -1;
|
||||
/* Command to be executed on remote system using "rsh". */
|
||||
(void)snprintf(cmd, sizeof(cmd), "rcp%s%s%s",
|
||||
iamrecursive ? " -r" : "", pflag ? " -p" : "",
|
||||
targetshouldbedirectory ? " -d" : "");
|
||||
|
||||
(void)signal(SIGPIPE, lostconn);
|
||||
|
||||
if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */
|
||||
toremote(targ, argc, argv);
|
||||
else {
|
||||
tolocal(argc, argv); /* Dest is local host. */
|
||||
if (targetshouldbedirectory)
|
||||
verifydir(argv[argc - 1]);
|
||||
}
|
||||
exit(errs);
|
||||
}
|
||||
|
||||
void
|
||||
toremote(char *targ, int argc, char *argv[])
|
||||
{
|
||||
int i, tos;
|
||||
char *bp, *host, *src, *suser, *thost, *tuser;
|
||||
|
||||
*targ++ = 0;
|
||||
if (*targ == 0)
|
||||
targ = period;
|
||||
|
||||
if ((thost = strchr(argv[argc - 1], '@'))) {
|
||||
/* user@host */
|
||||
*thost++ = 0;
|
||||
tuser = argv[argc - 1];
|
||||
if (*tuser == '\0')
|
||||
tuser = NULL;
|
||||
else if (!okname(tuser))
|
||||
exit(1);
|
||||
} else {
|
||||
thost = argv[argc - 1];
|
||||
tuser = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < argc - 1; i++) {
|
||||
src = colon(argv[i]);
|
||||
if (src) { /* remote to remote */
|
||||
*src++ = 0;
|
||||
if (*src == 0)
|
||||
src = period;
|
||||
host = strchr(argv[i], '@');
|
||||
if (host) {
|
||||
*host++ = 0;
|
||||
suser = argv[i];
|
||||
if (*suser == '\0')
|
||||
suser = pwd->pw_name;
|
||||
else if (!okname(suser)) {
|
||||
++errs;
|
||||
continue;
|
||||
}
|
||||
if (asprintf(&bp,
|
||||
"%s %s -l %s -n %s %s '%s%s%s:%s'",
|
||||
_PATH_RSH, host, suser, cmd, src,
|
||||
tuser ? tuser : "", tuser ? "@" : "",
|
||||
thost, targ) == -1)
|
||||
err(1, "asprintf");
|
||||
} else
|
||||
if (asprintf(&bp,
|
||||
"exec %s %s -n %s %s '%s%s%s:%s'",
|
||||
_PATH_RSH, argv[i], cmd, src,
|
||||
tuser ? tuser : "", tuser ? "@" : "",
|
||||
thost, targ) == -1)
|
||||
err(1, "asprintf");
|
||||
(void)susystem(bp, userid);
|
||||
(void)free(bp);
|
||||
} else { /* local to remote */
|
||||
if (rem == -1) {
|
||||
if (asprintf(&bp, "%s -t %s", cmd, targ)
|
||||
== -1)
|
||||
err(1, "asprintf");
|
||||
host = thost;
|
||||
rem = rcmd_af(&host, port,
|
||||
pwd->pw_name,
|
||||
tuser ? tuser : pwd->pw_name,
|
||||
bp, 0, family);
|
||||
if (rem < 0)
|
||||
exit(1);
|
||||
if (family == PF_INET) {
|
||||
tos = IPTOS_THROUGHPUT;
|
||||
if (setsockopt(rem, IPPROTO_IP, IP_TOS,
|
||||
&tos, sizeof(int)) < 0)
|
||||
warn("TOS (ignored)");
|
||||
}
|
||||
if (response() < 0)
|
||||
exit(1);
|
||||
(void)free(bp);
|
||||
(void)setuid(userid);
|
||||
}
|
||||
source(1, argv+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
tolocal(int argc, char *argv[])
|
||||
{
|
||||
int i, len, tos;
|
||||
char *bp, *host, *src, *suser;
|
||||
|
||||
for (i = 0; i < argc - 1; i++) {
|
||||
if (!(src = colon(argv[i]))) { /* Local to local. */
|
||||
len = strlen(_PATH_CP) + strlen(argv[i]) +
|
||||
strlen(argv[argc - 1]) + 20;
|
||||
if (!(bp = malloc(len)))
|
||||
err(1, "malloc");
|
||||
(void)snprintf(bp, len, "exec %s%s%s %s %s", _PATH_CP,
|
||||
iamrecursive ? " -PR" : "", pflag ? " -p" : "",
|
||||
argv[i], argv[argc - 1]);
|
||||
if (susystem(bp, userid))
|
||||
++errs;
|
||||
(void)free(bp);
|
||||
continue;
|
||||
}
|
||||
*src++ = 0;
|
||||
if (*src == 0)
|
||||
src = period;
|
||||
if ((host = strchr(argv[i], '@')) == NULL) {
|
||||
host = argv[i];
|
||||
suser = pwd->pw_name;
|
||||
} else {
|
||||
*host++ = 0;
|
||||
suser = argv[i];
|
||||
if (*suser == '\0')
|
||||
suser = pwd->pw_name;
|
||||
else if (!okname(suser)) {
|
||||
++errs;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
len = strlen(src) + CMDNEEDS + 20;
|
||||
if ((bp = malloc(len)) == NULL)
|
||||
err(1, "malloc");
|
||||
(void)snprintf(bp, len, "%s -f %s", cmd, src);
|
||||
rem = rcmd_af(&host, port, pwd->pw_name, suser, bp, 0,
|
||||
family);
|
||||
(void)free(bp);
|
||||
if (rem < 0) {
|
||||
++errs;
|
||||
continue;
|
||||
}
|
||||
(void)seteuid(userid);
|
||||
if (family == PF_INET) {
|
||||
tos = IPTOS_THROUGHPUT;
|
||||
if (setsockopt(rem, IPPROTO_IP, IP_TOS, &tos,
|
||||
sizeof(int)) < 0)
|
||||
warn("TOS (ignored)");
|
||||
}
|
||||
sink(1, argv + argc - 1);
|
||||
(void)seteuid(0);
|
||||
(void)close(rem);
|
||||
rem = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
source(int argc, char *argv[])
|
||||
{
|
||||
struct stat stb;
|
||||
static BUF buffer;
|
||||
BUF *bp;
|
||||
off_t i;
|
||||
int amt, fd, haderr, indx, result;
|
||||
char *last, *name, buf[BUFSIZ];
|
||||
|
||||
for (indx = 0; indx < argc; ++indx) {
|
||||
name = argv[indx];
|
||||
if ((fd = open(name, O_RDONLY, 0)) < 0)
|
||||
goto syserr;
|
||||
if (fstat(fd, &stb)) {
|
||||
syserr: run_err("%s: %s", name, strerror(errno));
|
||||
goto next;
|
||||
}
|
||||
switch (stb.st_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
break;
|
||||
case S_IFDIR:
|
||||
if (iamrecursive) {
|
||||
rsource(name, &stb);
|
||||
goto next;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
run_err("%s: not a regular file", name);
|
||||
goto next;
|
||||
}
|
||||
if ((last = strrchr(name, '/')) == NULL)
|
||||
last = name;
|
||||
else
|
||||
++last;
|
||||
if (pflag) {
|
||||
/*
|
||||
* Make it compatible with possible future
|
||||
* versions expecting microseconds.
|
||||
*/
|
||||
(void)snprintf(buf, sizeof(buf), "T%ld 0 %ld 0\n",
|
||||
(long)stb.st_mtim.tv_sec,
|
||||
(long)stb.st_atim.tv_sec);
|
||||
(void)write(rem, buf, strlen(buf));
|
||||
if (response() < 0)
|
||||
goto next;
|
||||
}
|
||||
#define MODEMASK (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO)
|
||||
(void)snprintf(buf, sizeof(buf), "C%04o %jd %s\n",
|
||||
stb.st_mode & MODEMASK, (intmax_t)stb.st_size, last);
|
||||
(void)write(rem, buf, strlen(buf));
|
||||
if (response() < 0)
|
||||
goto next;
|
||||
if ((bp = allocbuf(&buffer, fd, BUFSIZ)) == NULL) {
|
||||
next: if (fd >= 0)
|
||||
(void)close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Keep writing after an error so that we stay sync'd up. */
|
||||
for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
|
||||
amt = bp->cnt;
|
||||
if (i + amt > stb.st_size)
|
||||
amt = stb.st_size - i;
|
||||
if (!haderr) {
|
||||
result = read(fd, bp->buf, amt);
|
||||
if (result != amt)
|
||||
haderr = result >= 0 ? EIO : errno;
|
||||
}
|
||||
if (haderr)
|
||||
(void)write(rem, bp->buf, amt);
|
||||
else {
|
||||
result = write(rem, bp->buf, amt);
|
||||
if (result != amt)
|
||||
haderr = result >= 0 ? EIO : errno;
|
||||
}
|
||||
}
|
||||
if (close(fd) && !haderr)
|
||||
haderr = errno;
|
||||
if (!haderr)
|
||||
(void)write(rem, "", 1);
|
||||
else
|
||||
run_err("%s: %s", name, strerror(haderr));
|
||||
(void)response();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rsource(char *name, struct stat *statp)
|
||||
{
|
||||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
char *last, *vect[1], path[PATH_MAX];
|
||||
|
||||
if (!(dirp = opendir(name))) {
|
||||
run_err("%s: %s", name, strerror(errno));
|
||||
return;
|
||||
}
|
||||
last = strrchr(name, '/');
|
||||
if (last == NULL)
|
||||
last = name;
|
||||
else
|
||||
last++;
|
||||
if (pflag) {
|
||||
(void)snprintf(path, sizeof(path), "T%ld 0 %ld 0\n",
|
||||
(long)statp->st_mtim.tv_sec,
|
||||
(long)statp->st_atim.tv_sec);
|
||||
(void)write(rem, path, strlen(path));
|
||||
if (response() < 0) {
|
||||
closedir(dirp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
(void)snprintf(path, sizeof(path),
|
||||
"D%04o %d %s\n", statp->st_mode & MODEMASK, 0, last);
|
||||
(void)write(rem, path, strlen(path));
|
||||
if (response() < 0) {
|
||||
closedir(dirp);
|
||||
return;
|
||||
}
|
||||
while ((dp = readdir(dirp))) {
|
||||
if (dp->d_ino == 0)
|
||||
continue;
|
||||
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
|
||||
continue;
|
||||
if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path)) {
|
||||
run_err("%s/%s: name too long", name, dp->d_name);
|
||||
continue;
|
||||
}
|
||||
(void)snprintf(path, sizeof(path), "%s/%s", name, dp->d_name);
|
||||
vect[0] = path;
|
||||
source(1, vect);
|
||||
}
|
||||
(void)closedir(dirp);
|
||||
(void)write(rem, "E\n", 2);
|
||||
(void)response();
|
||||
}
|
||||
|
||||
void
|
||||
sink(int argc, char *argv[])
|
||||
{
|
||||
static BUF buffer;
|
||||
struct stat stb;
|
||||
struct timeval tv[2];
|
||||
enum { YES, NO, DISPLAYED } wrerr;
|
||||
BUF *bp;
|
||||
off_t i, j, size;
|
||||
int amt, exists, first, mask, mode, ofd, omode;
|
||||
size_t count;
|
||||
int setimes, targisdir, wrerrno = 0;
|
||||
char ch, *cp, *np, *targ, *vect[1], buf[BUFSIZ], path[PATH_MAX];
|
||||
const char *why;
|
||||
|
||||
#define atime tv[0]
|
||||
#define mtime tv[1]
|
||||
#define SCREWUP(str) { why = str; goto screwup; }
|
||||
|
||||
setimes = targisdir = 0;
|
||||
mask = umask(0);
|
||||
if (!pflag)
|
||||
(void)umask(mask);
|
||||
if (argc != 1) {
|
||||
run_err("ambiguous target");
|
||||
exit(1);
|
||||
}
|
||||
targ = *argv;
|
||||
if (targetshouldbedirectory)
|
||||
verifydir(targ);
|
||||
(void)write(rem, "", 1);
|
||||
if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
|
||||
targisdir = 1;
|
||||
for (first = 1;; first = 0) {
|
||||
cp = buf;
|
||||
if (read(rem, cp, 1) <= 0)
|
||||
return;
|
||||
if (*cp++ == '\n')
|
||||
SCREWUP("unexpected <newline>");
|
||||
do {
|
||||
if (read(rem, &ch, sizeof(ch)) != sizeof(ch))
|
||||
SCREWUP("lost connection");
|
||||
*cp++ = ch;
|
||||
} while (cp < &buf[BUFSIZ - 1] && ch != '\n');
|
||||
*cp = 0;
|
||||
|
||||
if (buf[0] == '\01' || buf[0] == '\02') {
|
||||
if (iamremote == 0)
|
||||
(void)write(STDERR_FILENO,
|
||||
buf + 1, strlen(buf + 1));
|
||||
if (buf[0] == '\02')
|
||||
exit(1);
|
||||
++errs;
|
||||
continue;
|
||||
}
|
||||
if (buf[0] == 'E') {
|
||||
(void)write(rem, "", 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ch == '\n')
|
||||
*--cp = 0;
|
||||
|
||||
cp = buf;
|
||||
if (*cp == 'T') {
|
||||
setimes++;
|
||||
cp++;
|
||||
mtime.tv_sec = strtol(cp, &cp, 10);
|
||||
if (!cp || *cp++ != ' ')
|
||||
SCREWUP("mtime.sec not delimited");
|
||||
mtime.tv_usec = strtol(cp, &cp, 10);
|
||||
if (!cp || *cp++ != ' ')
|
||||
SCREWUP("mtime.usec not delimited");
|
||||
atime.tv_sec = strtol(cp, &cp, 10);
|
||||
if (!cp || *cp++ != ' ')
|
||||
SCREWUP("atime.sec not delimited");
|
||||
atime.tv_usec = strtol(cp, &cp, 10);
|
||||
if (!cp || *cp++ != '\0')
|
||||
SCREWUP("atime.usec not delimited");
|
||||
(void)write(rem, "", 1);
|
||||
continue;
|
||||
}
|
||||
if (*cp != 'C' && *cp != 'D') {
|
||||
/*
|
||||
* Check for the case "rcp remote:foo\* local:bar".
|
||||
* In this case, the line "No match." can be returned
|
||||
* by the shell before the rcp command on the remote is
|
||||
* executed so the ^Aerror_message convention isn't
|
||||
* followed.
|
||||
*/
|
||||
if (first) {
|
||||
run_err("%s", cp);
|
||||
exit(1);
|
||||
}
|
||||
SCREWUP("expected control record");
|
||||
}
|
||||
mode = 0;
|
||||
for (++cp; cp < buf + 5; cp++) {
|
||||
if (*cp < '0' || *cp > '7')
|
||||
SCREWUP("bad mode");
|
||||
mode = (mode << 3) | (*cp - '0');
|
||||
}
|
||||
if (*cp++ != ' ')
|
||||
SCREWUP("mode not delimited");
|
||||
|
||||
for (size = 0; isdigit(*cp);)
|
||||
size = size * 10 + (*cp++ - '0');
|
||||
if (*cp++ != ' ')
|
||||
SCREWUP("size not delimited");
|
||||
if (targisdir) {
|
||||
if (strlen(targ) + (*targ ? 1 : 0) + strlen(cp)
|
||||
>= sizeof(path)) {
|
||||
run_err("%s%s%s: name too long", targ,
|
||||
*targ ? "/" : "", cp);
|
||||
exit(1);
|
||||
}
|
||||
(void)snprintf(path, sizeof(path), "%s%s%s", targ,
|
||||
*targ ? "/" : "", cp);
|
||||
np = path;
|
||||
} else
|
||||
np = targ;
|
||||
exists = stat(np, &stb) == 0;
|
||||
if (buf[0] == 'D') {
|
||||
int mod_flag = pflag;
|
||||
if (exists) {
|
||||
if (!S_ISDIR(stb.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
goto bad;
|
||||
}
|
||||
if (pflag)
|
||||
(void)chmod(np, mode);
|
||||
} else {
|
||||
/* Handle copying from a read-only directory */
|
||||
mod_flag = 1;
|
||||
if (mkdir(np, mode | S_IRWXU) < 0)
|
||||
goto bad;
|
||||
}
|
||||
vect[0] = np;
|
||||
sink(1, vect);
|
||||
if (setimes) {
|
||||
setimes = 0;
|
||||
if (utimes(np, tv) < 0)
|
||||
run_err("%s: set times: %s",
|
||||
np, strerror(errno));
|
||||
}
|
||||
if (mod_flag)
|
||||
(void)chmod(np, mode);
|
||||
continue;
|
||||
}
|
||||
omode = mode;
|
||||
mode |= S_IWRITE;
|
||||
if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
|
||||
bad: run_err("%s: %s", np, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
(void)write(rem, "", 1);
|
||||
if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == NULL) {
|
||||
(void)close(ofd);
|
||||
continue;
|
||||
}
|
||||
cp = bp->buf;
|
||||
wrerr = NO;
|
||||
for (count = i = 0; i < size; i += BUFSIZ) {
|
||||
amt = BUFSIZ;
|
||||
if (i + amt > size)
|
||||
amt = size - i;
|
||||
count += amt;
|
||||
do {
|
||||
j = read(rem, cp, amt);
|
||||
if (j <= 0) {
|
||||
run_err("%s", j ? strerror(errno) :
|
||||
"dropped connection");
|
||||
exit(1);
|
||||
}
|
||||
amt -= j;
|
||||
cp += j;
|
||||
} while (amt > 0);
|
||||
if (count == bp->cnt) {
|
||||
/* Keep reading so we stay sync'd up. */
|
||||
if (wrerr == NO) {
|
||||
j = write(ofd, bp->buf, count);
|
||||
if (j != (off_t)count) {
|
||||
wrerr = YES;
|
||||
wrerrno = j >= 0 ? EIO : errno;
|
||||
}
|
||||
}
|
||||
count = 0;
|
||||
cp = bp->buf;
|
||||
}
|
||||
}
|
||||
if (count != 0 && wrerr == NO &&
|
||||
(j = write(ofd, bp->buf, count)) != (off_t)count) {
|
||||
wrerr = YES;
|
||||
wrerrno = j >= 0 ? EIO : errno;
|
||||
}
|
||||
if (ftruncate(ofd, size)) {
|
||||
run_err("%s: truncate: %s", np, strerror(errno));
|
||||
wrerr = DISPLAYED;
|
||||
}
|
||||
if (pflag) {
|
||||
if (exists || omode != mode)
|
||||
if (fchmod(ofd, omode))
|
||||
run_err("%s: set mode: %s",
|
||||
np, strerror(errno));
|
||||
} else {
|
||||
if (!exists && omode != mode)
|
||||
if (fchmod(ofd, omode & ~mask))
|
||||
run_err("%s: set mode: %s",
|
||||
np, strerror(errno));
|
||||
}
|
||||
(void)close(ofd);
|
||||
(void)response();
|
||||
if (setimes && wrerr == NO) {
|
||||
setimes = 0;
|
||||
if (utimes(np, tv) < 0) {
|
||||
run_err("%s: set times: %s",
|
||||
np, strerror(errno));
|
||||
wrerr = DISPLAYED;
|
||||
}
|
||||
}
|
||||
switch(wrerr) {
|
||||
case YES:
|
||||
run_err("%s: %s", np, strerror(wrerrno));
|
||||
break;
|
||||
case NO:
|
||||
(void)write(rem, "", 1);
|
||||
break;
|
||||
case DISPLAYED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
screwup:
|
||||
run_err("protocol error: %s", why);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
response(void)
|
||||
{
|
||||
char ch, *cp, resp, rbuf[BUFSIZ];
|
||||
|
||||
if (read(rem, &resp, sizeof(resp)) != sizeof(resp))
|
||||
lostconn(0);
|
||||
|
||||
cp = rbuf;
|
||||
switch(resp) {
|
||||
case 0: /* ok */
|
||||
return (0);
|
||||
default:
|
||||
*cp++ = resp;
|
||||
/* FALLTHROUGH */
|
||||
case 1: /* error, followed by error msg */
|
||||
case 2: /* fatal error, "" */
|
||||
do {
|
||||
if (read(rem, &ch, sizeof(ch)) != sizeof(ch))
|
||||
lostconn(0);
|
||||
*cp++ = ch;
|
||||
} while (cp < &rbuf[BUFSIZ] && ch != '\n');
|
||||
|
||||
if (!iamremote)
|
||||
(void)write(STDERR_FILENO, rbuf, cp - rbuf);
|
||||
++errs;
|
||||
if (resp == 1)
|
||||
return (-1);
|
||||
exit(1);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr, "%s\n%s\n",
|
||||
"usage: rcp [-46p] file1 file2",
|
||||
" rcp [-46pr] file ... directory");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
void
|
||||
run_err(const char *fmt, ...)
|
||||
{
|
||||
static FILE *fp;
|
||||
va_list ap;
|
||||
|
||||
++errs;
|
||||
if (fp == NULL && !(fp = fdopen(rem, "w")))
|
||||
return;
|
||||
(void)fprintf(fp, "%c", 0x01);
|
||||
(void)fprintf(fp, "rcp: ");
|
||||
va_start(ap, fmt);
|
||||
(void)vfprintf(fp, fmt, ap);
|
||||
va_end(ap);
|
||||
(void)fprintf(fp, "\n");
|
||||
(void)fflush(fp);
|
||||
|
||||
if (!iamremote) {
|
||||
va_start(ap, fmt);
|
||||
vwarnx(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
ATF_TESTS_SH+= rcp_test
|
||||
|
||||
.include <bsd.test.mk>
|
@ -1,60 +0,0 @@
|
||||
#
|
||||
# Copyright 2017 Shivansh Rai
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
usage_output='usage: rcp'
|
||||
|
||||
atf_test_case invalid_usage
|
||||
invalid_usage_head()
|
||||
{
|
||||
atf_set "descr" "Verify that an invalid usage with a supported option produces a valid error message"
|
||||
}
|
||||
|
||||
invalid_usage_body()
|
||||
{
|
||||
atf_check -s not-exit:0 -e match:"$usage_output" rcp -4
|
||||
atf_check -s not-exit:0 -e match:"$usage_output" rcp -6
|
||||
atf_check -s not-exit:0 -e match:"$usage_output" rcp -p
|
||||
atf_check -s not-exit:0 -e match:"$usage_output" rcp -r
|
||||
}
|
||||
|
||||
atf_test_case no_arguments
|
||||
no_arguments_head()
|
||||
{
|
||||
atf_set "descr" "Verify that rcp(1) fails and generates a valid usage message when no arguments are supplied"
|
||||
}
|
||||
|
||||
no_arguments_body()
|
||||
{
|
||||
atf_check -s not-exit:0 -e match:"$usage_output" rcp
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case invalid_usage
|
||||
atf_add_test_case no_arguments
|
||||
}
|
159
bin/rcp/util.c
159
bin/rcp/util.c
@ -1,159 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static const char sccsid[] = "@(#)util.c 8.2 (Berkeley) 4/2/94";
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <paths.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
char *
|
||||
colon(char *cp)
|
||||
{
|
||||
if (*cp == ':') /* Leading colon is part of file name. */
|
||||
return (0);
|
||||
|
||||
for (; *cp; ++cp) {
|
||||
if (*cp == ':')
|
||||
return (cp);
|
||||
if (*cp == '/')
|
||||
return (0);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
verifydir(char *cp)
|
||||
{
|
||||
struct stat stb;
|
||||
|
||||
if (!stat(cp, &stb)) {
|
||||
if (S_ISDIR(stb.st_mode))
|
||||
return;
|
||||
errno = ENOTDIR;
|
||||
}
|
||||
run_err("%s: %s", cp, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
okname(char *cp0)
|
||||
{
|
||||
int c;
|
||||
char *cp;
|
||||
|
||||
cp = cp0;
|
||||
do {
|
||||
c = *cp;
|
||||
if (c & 0200)
|
||||
goto bad;
|
||||
if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
|
||||
goto bad;
|
||||
} while (*++cp);
|
||||
return (1);
|
||||
|
||||
bad: warnx("%s: invalid user name", cp0);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
susystem(char *s, int userid)
|
||||
{
|
||||
sig_t istat, qstat;
|
||||
int status;
|
||||
pid_t pid;
|
||||
|
||||
pid = vfork();
|
||||
switch (pid) {
|
||||
case -1:
|
||||
return (127);
|
||||
|
||||
case 0:
|
||||
(void)setuid(userid);
|
||||
execl(_PATH_BSHELL, "sh", "-c", s, (char *)NULL);
|
||||
_exit(127);
|
||||
}
|
||||
istat = signal(SIGINT, SIG_IGN);
|
||||
qstat = signal(SIGQUIT, SIG_IGN);
|
||||
if (waitpid(pid, &status, 0) < 0)
|
||||
status = -1;
|
||||
(void)signal(SIGINT, istat);
|
||||
(void)signal(SIGQUIT, qstat);
|
||||
return (status);
|
||||
}
|
||||
|
||||
BUF *
|
||||
allocbuf(BUF *bp, int fd, int blksize)
|
||||
{
|
||||
struct stat stb;
|
||||
size_t size;
|
||||
|
||||
if (fstat(fd, &stb) < 0) {
|
||||
run_err("fstat: %s", strerror(errno));
|
||||
return (0);
|
||||
}
|
||||
size = roundup(stb.st_blksize, blksize);
|
||||
if (size == 0)
|
||||
size = blksize;
|
||||
if (bp->cnt >= size)
|
||||
return (bp);
|
||||
if ((bp->buf = realloc(bp->buf, size)) == NULL) {
|
||||
bp->cnt = 0;
|
||||
run_err("%s", strerror(errno));
|
||||
return (0);
|
||||
}
|
||||
bp->cnt = size;
|
||||
return (bp);
|
||||
}
|
||||
|
||||
void
|
||||
lostconn(int signo __unused)
|
||||
{
|
||||
if (!iamremote)
|
||||
warnx("lost connection");
|
||||
exit(1);
|
||||
}
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
lib/${CSU_DIR} \
|
||||
lib/libc \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -515,7 +515,7 @@ check(const char *path, const char *name, struct stat *sp)
|
||||
"%s: -P was specified, but file is not writable",
|
||||
path);
|
||||
(void)fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ",
|
||||
modep + 1, modep[9] == ' ' ? "" : " ",
|
||||
modep + 1, modep[10] == ' ' ? "" : " ",
|
||||
user_from_uid(sp->st_uid, 0),
|
||||
group_from_gid(sp->st_gid, 0),
|
||||
*flagsp ? flagsp : "", *flagsp ? " " : "",
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -1,9 +1,10 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
|
||||
PACKAGE=runtime
|
||||
PROG= rmdir
|
||||
|
||||
HAS_TESTS=
|
||||
SUBDIR.${MK_TESTS}+= tests
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
11
bin/rmdir/tests/Makefile.depend
Normal file
11
bin/rmdir/tests/Makefile.depend
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
# Autogenerated - do NOT edit!
|
||||
|
||||
DIRDEPS = \
|
||||
|
||||
|
||||
.include <dirdeps.mk>
|
||||
|
||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
||||
# local dependencies - needed for -jN in clean tree
|
||||
.endif
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
11
bin/sh/tests/invocation/Makefile.depend
Normal file
11
bin/sh/tests/invocation/Makefile.depend
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
# Autogenerated - do NOT edit!
|
||||
|
||||
DIRDEPS = \
|
||||
|
||||
|
||||
.include <dirdeps.mk>
|
||||
|
||||
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
|
||||
# local dependencies - needed for -jN in clean tree
|
||||
.endif
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
lib/${CSU_DIR} \
|
||||
lib/libc \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
include/xlocale \
|
||||
lib/${CSU_DIR} \
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
lib/${CSU_DIR} \
|
||||
lib/libc \
|
||||
|
@ -35,13 +35,13 @@ main(int argc, char **argv)
|
||||
sigset_t ss;
|
||||
|
||||
(void) sigemptyset(&ss);
|
||||
(void) sigaddset(&ss, SIGINT);
|
||||
(void) sigaddset(&ss, SIGUSR1);
|
||||
(void) sigprocmask(SIG_BLOCK, &ss, NULL);
|
||||
|
||||
do {
|
||||
(void) getpid();
|
||||
(void) sigpending(&ss);
|
||||
} while (!sigismember(&ss, SIGINT));
|
||||
} while (!sigismember(&ss, SIGUSR1));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ syscall::getpid:entry
|
||||
/pid == $1/
|
||||
{
|
||||
trace("raised");
|
||||
raise(SIGINT);
|
||||
raise(SIGUSR1);
|
||||
/*
|
||||
* Wait no more than half a second for the process to die.
|
||||
*/
|
||||
@ -55,6 +55,7 @@ syscall::getpid:entry
|
||||
}
|
||||
|
||||
syscall::exit:entry
|
||||
/pid == $1/
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ main(int argc, char **argv)
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
|
||||
(void) sigaction(SIGINT, &sa, NULL);
|
||||
(void) sigaction(SIGUSR1, &sa, NULL);
|
||||
|
||||
for (;;) {
|
||||
(void) getpid();
|
||||
|
@ -47,7 +47,7 @@ syscall::getpid:return
|
||||
/pid == $1/
|
||||
{
|
||||
trace("raised");
|
||||
raise(SIGINT);
|
||||
raise(SIGUSR1);
|
||||
/*
|
||||
* Wait no more than half a second for the process to die.
|
||||
*/
|
||||
@ -55,6 +55,7 @@ syscall::getpid:return
|
||||
}
|
||||
|
||||
syscall::exit:entry
|
||||
/pid == $1/
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ main(int argc, char **argv)
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
|
||||
(void) sigaction(SIGINT, &sa, NULL);
|
||||
(void) sigaction(SIGUSR1, &sa, NULL);
|
||||
|
||||
for (;;) {
|
||||
(void) getpid();
|
||||
|
@ -47,7 +47,7 @@ syscall::getpid:entry
|
||||
/pid == $1/
|
||||
{
|
||||
trace("raised");
|
||||
raise(SIGINT);
|
||||
raise(SIGUSR1);
|
||||
/*
|
||||
* Wait no more than half a second for the process to die.
|
||||
*/
|
||||
@ -55,6 +55,7 @@ syscall::getpid:entry
|
||||
}
|
||||
|
||||
syscall::exit:entry
|
||||
/pid == $1/
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
'\" te
|
||||
.\" Copyright (c) 2012, Martin Matuska <mm@FreeBSD.org>.
|
||||
.\" All Rights Reserved.
|
||||
.\"
|
||||
.\" This file and its contents are supplied under the terms of the
|
||||
.\" Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
@ -13,71 +10,75 @@
|
||||
.\"
|
||||
.\"
|
||||
.\" Copyright 2012, Richard Lowe.
|
||||
.\" Copyright (c) 2012, Marcelo Araujo <araujo@FreeBSD.org>.
|
||||
.\" Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||
.\" All Rights Reserved.
|
||||
.\" Copyright (c) 2012, 2017 by Delphix. All rights reserved.
|
||||
.\" Copyright 2017 Nexenta Systems, Inc.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 26, 2014
|
||||
.Dd October 06, 2017
|
||||
.Dt ZDB 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm zdb
|
||||
.Nd Display zpool debugging and consistency information
|
||||
.Nd display zpool debugging and consistency information
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl CumdibcsDvhLMXFPA
|
||||
.Op Fl e Op Fl p Ar path...
|
||||
.Op Fl t Ar txg
|
||||
.Op Fl U Ar cache
|
||||
.Op Fl AbcdDFGhiLMPsvX
|
||||
.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
|
||||
.Op Fl I Ar inflight I/Os
|
||||
.Op Fl x Ar dumpdir
|
||||
.Ar poolname
|
||||
.Op Ar object ...
|
||||
.Nm
|
||||
.Op Fl divPA
|
||||
.Op Fl e Op Fl p Ar path...
|
||||
.Op Fl U Ar cache
|
||||
.Ar dataset
|
||||
.Op Ar object ...
|
||||
.Nm
|
||||
.Fl m Op Fl MLXFPA
|
||||
.Oo Fl o Ar var Ns = Ns Ar value Oc Ns ...
|
||||
.Op Fl t Ar txg
|
||||
.Op Fl e Op Fl p Ar path...
|
||||
.Op Fl U Ar cache
|
||||
.Ar poolname
|
||||
.Op Fl x Ar dumpdir
|
||||
.Op Ar poolname Op Ar object ...
|
||||
.Nm
|
||||
.Fl R Op Fl A
|
||||
.Op Fl e Op Fl p Ar path...
|
||||
.Op Fl AdiPv
|
||||
.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
|
||||
.Op Fl U Ar cache
|
||||
.Ar poolname
|
||||
.Ar poolname
|
||||
.Ar vdev Ns : Ns Ar offset Ns : Ns Ar size Ns Op Ns : Ns Ar flags
|
||||
.Nm
|
||||
.Fl S
|
||||
.Op Fl AP
|
||||
.Op Fl e Op Fl p Ar path...
|
||||
.Op Fl U Ar cache
|
||||
.Ar poolname
|
||||
.Ar poolname
|
||||
.Nm
|
||||
.Fl l
|
||||
.Op Fl uA
|
||||
.Ar device
|
||||
.Ar dataset Op Ar object ...
|
||||
.Nm
|
||||
.Fl C
|
||||
.Op Fl A
|
||||
.Op Fl U Ar cache
|
||||
.Nm
|
||||
.Fl E
|
||||
.Op Fl A
|
||||
.Ar word0 Ns \&: Ns Ar word1 Ns :...: Ns Ar word15
|
||||
.Nm
|
||||
.Fl l
|
||||
.Op Fl Aqu
|
||||
.Ar device
|
||||
.Nm
|
||||
.Fl m
|
||||
.Op Fl AFLPX
|
||||
.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
|
||||
.Op Fl t Ar txg
|
||||
.Op Fl U Ar cache
|
||||
.Ar poolname Op Ar vdev Op Ar metaslab ...
|
||||
.Nm
|
||||
.Fl O
|
||||
.Ar dataset path
|
||||
.Nm
|
||||
.Fl R
|
||||
.Op Fl A
|
||||
.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
|
||||
.Op Fl U Ar cache
|
||||
.Ar poolname vdev Ns \&: Ns Ar offset Ns \&: Ns Ar size Ns Op : Ns Ar flags
|
||||
.Nm
|
||||
.Fl S
|
||||
.Op Fl AP
|
||||
.Op Fl e Oo Fl V Oc Op Fl p Ar path ...
|
||||
.Op Fl U Ar cache
|
||||
.Ar poolname
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility displays information about a ZFS pool useful for debugging and
|
||||
performs some amount of consistency checking.
|
||||
It is a not a general purpose tool and options (and facilities) may change.
|
||||
utility displays information about a ZFS pool useful for debugging and performs
|
||||
some amount of consistency checking.
|
||||
It is a not a general purpose tool and options
|
||||
.Pq and facilities
|
||||
may change.
|
||||
This is neither a
|
||||
.Xr fsck 8
|
||||
nor a
|
||||
nor an
|
||||
.Xr fsdb 8
|
||||
utility.
|
||||
.Pp
|
||||
@ -89,73 +90,96 @@ internals is assumed.
|
||||
If the
|
||||
.Ar dataset
|
||||
argument does not contain any
|
||||
.Sy /
|
||||
.Qq Sy /
|
||||
or
|
||||
.Sy @
|
||||
.Qq Sy @
|
||||
characters, it is interpreted as a pool name.
|
||||
The root dataset can be specified as
|
||||
.Pa pool Ns Sy /
|
||||
(pool name followed by a slash).
|
||||
.Ar pool Ns /
|
||||
.Pq pool name followed by a slash .
|
||||
.Pp
|
||||
When operating on an imported and active pool it is possible, though unlikely,
|
||||
that zdb may interpret inconsistent pool data and behave erratically.
|
||||
.Sh OPTIONS
|
||||
Display options:
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width Ds
|
||||
.It Fl b
|
||||
Display statistics regarding the number, size (logical, physical and
|
||||
allocated) and deduplication of blocks.
|
||||
Display statistics regarding the number, size
|
||||
.Pq logical, physical and allocated
|
||||
and deduplication of blocks.
|
||||
.It Fl c
|
||||
Verify the checksum of all metadata blocks while printing block statistics
|
||||
(see
|
||||
.Fl b Ns ).
|
||||
.Po see
|
||||
.Fl b
|
||||
.Pc .
|
||||
.Pp
|
||||
If specified multiple times, verify the checksums of all blocks.
|
||||
.It Fl C
|
||||
Display information about the configuration. If specified with no other
|
||||
options, instead display information about the cache file
|
||||
.Po Pa /etc/zfs/zpool.cache Pc .
|
||||
Display information about the configuration.
|
||||
If specified with no other options, instead display information about the cache
|
||||
file
|
||||
.Pq Pa /boot/zfs/zpool.cache .
|
||||
To specify the cache file to display, see
|
||||
.Fl U
|
||||
.Fl U .
|
||||
.Pp
|
||||
If specified multiple times, and a pool name is also specified display both
|
||||
the cached configuration and the on-disk configuration.
|
||||
If specified multiple times, and a pool name is also specified display both the
|
||||
cached configuration and the on-disk configuration.
|
||||
If specified multiple times with
|
||||
.Fl e
|
||||
also display the configuration that would be used were the pool to be
|
||||
imported.
|
||||
also display the configuration that would be used were the pool to be imported.
|
||||
.It Fl d
|
||||
Display information about datasets. Specified once, displays basic dataset
|
||||
information: ID, create transaction, size, and object count.
|
||||
Display information about datasets.
|
||||
Specified once, displays basic dataset information: ID, create transaction,
|
||||
size, and object count.
|
||||
.Pp
|
||||
If specified multiple times provides greater and greater verbosity.
|
||||
.Pp
|
||||
If object IDs are specified, display information about those specific objects only.
|
||||
If object IDs are specified, display information about those specific objects
|
||||
only.
|
||||
.It Fl D
|
||||
Display deduplication statistics, including the deduplication ratio (dedup),
|
||||
compression ratio (compress), inflation due to the zfs copies property
|
||||
(copies), and an overall effective ratio (dedup * compress / copies).
|
||||
.Pp
|
||||
If specified twice, display a histogram of deduplication statistics, showing
|
||||
the allocated (physically present on disk) and referenced (logically
|
||||
referenced in the pool) block counts and sizes by reference count.
|
||||
.Pp
|
||||
If specified a third time, display the statistics independently for each deduplication table.
|
||||
.Pp
|
||||
If specified a fourth time, dump the contents of the deduplication tables describing duplicate blocks.
|
||||
.Pp
|
||||
If specified a fifth time, also dump the contents of the deduplication tables describing unique blocks.
|
||||
Display deduplication statistics, including the deduplication ratio
|
||||
.Pq Sy dedup ,
|
||||
compression ratio
|
||||
.Pq Sy compress ,
|
||||
inflation due to the zfs copies property
|
||||
.Pq Sy copies ,
|
||||
and an overall effective ratio
|
||||
.Pq Sy dedup No * Sy compress No / Sy copies .
|
||||
.It Fl DD
|
||||
Display a histogram of deduplication statistics, showing the allocated
|
||||
.Pq physically present on disk
|
||||
and referenced
|
||||
.Pq logically referenced in the pool
|
||||
block counts and sizes by reference count.
|
||||
.It Fl DDD
|
||||
Display the statistics independently for each deduplication table.
|
||||
.It Fl DDDD
|
||||
Dump the contents of the deduplication tables describing duplicate blocks.
|
||||
.It Fl DDDDD
|
||||
Also dump the contents of the deduplication tables describing unique blocks.
|
||||
.It Fl E Ar word0 Ns \&: Ns Ar word1 Ns :...: Ns Ar word15
|
||||
Decode and display block from an embedded block pointer specified by the
|
||||
.Ar word
|
||||
arguments.
|
||||
.It Fl h
|
||||
Display pool history similar to
|
||||
.Cm zpool history ,
|
||||
.Nm zpool Cm history ,
|
||||
but include internal changes, transaction, and dataset information.
|
||||
.It Fl i
|
||||
Display information about intent log (ZIL) entries relating to each
|
||||
dataset.
|
||||
If specified multiple times, display counts of each intent log transaction
|
||||
type.
|
||||
Display information about intent log
|
||||
.Pq ZIL
|
||||
entries relating to each dataset.
|
||||
If specified multiple times, display counts of each intent log transaction type.
|
||||
.It Fl l Ar device
|
||||
Display the vdev labels from the specified device.
|
||||
Read the vdev labels from the specified device.
|
||||
.Nm Fl l
|
||||
will return 0 if valid label was found, 1 if error occurred, and 2 if no valid
|
||||
labels were found.
|
||||
.Pp
|
||||
If the
|
||||
.Fl q
|
||||
option is also specified, don't print the labels.
|
||||
.Pp
|
||||
If the
|
||||
.Fl u
|
||||
option is also specified, also display the uberblocks on this device.
|
||||
@ -166,36 +190,55 @@ By default,
|
||||
verifies that all non-free blocks are referenced, which can be very expensive.
|
||||
.It Fl m
|
||||
Display the offset, spacemap, and free space of each metaslab.
|
||||
When specified twice, also display information about the on-disk free
|
||||
space histogram associated with each metaslab. When specified three time,
|
||||
display the maximum contiguous free space, the in-core free space histogram,
|
||||
and the percentage of free space in each space map. When specified
|
||||
four times display every spacemap record.
|
||||
.It Fl mm
|
||||
Also display information about the on-disk free space histogram associated with
|
||||
each metaslab.
|
||||
.It Fl mmm
|
||||
Display the maximum contiguous free space, the in-core free space histogram, and
|
||||
the percentage of free space in each space map.
|
||||
.It Fl mmmm
|
||||
Display every spacemap record.
|
||||
.It Fl M
|
||||
Display the offset, spacemap, and free space of each metaslab.
|
||||
When specified twice, also display information about the maximum contiguous
|
||||
free space and the percentage of free space in each space map.
|
||||
When specified three times display every spacemap record.
|
||||
.It Fl MM
|
||||
Also display information about the maximum contiguous free space and the
|
||||
percentage of free space in each space map.
|
||||
.It Fl MMM
|
||||
Display every spacemap record.
|
||||
.It Fl O Ar dataset path
|
||||
Look up the specified
|
||||
.Ar path
|
||||
inside of the
|
||||
.Ar dataset
|
||||
and display its metadata and indirect blocks.
|
||||
Specified
|
||||
.Ar path
|
||||
must be relative to the root of
|
||||
.Ar dataset .
|
||||
This option can be combined with
|
||||
.Fl v
|
||||
for increasing verbosity.
|
||||
.It Xo
|
||||
.Fl R Ar poolname
|
||||
.Ar vdev Ns : Ns Ar offset Ns : Ns Ar size Ns Op Ns : Ns Ar flags
|
||||
.Fl R Ar poolname vdev Ns \&: Ns Ar offset Ns \&: Ns Ar size Ns Op : Ns Ar flags
|
||||
.Xc
|
||||
Read and display a block from the specified device. By default the block is
|
||||
displayed as a hex dump, but see the description of the
|
||||
.Fl r
|
||||
Read and display a block from the specified device.
|
||||
By default the block is displayed as a hex dump, but see the description of the
|
||||
.Sy r
|
||||
flag, below.
|
||||
.Pp
|
||||
The block is specified in terms of a colon-separated tuple
|
||||
.Ar vdev
|
||||
(an integer vdev identifier)
|
||||
.Pq an integer vdev identifier
|
||||
.Ar offset
|
||||
(the offset within the vdev)
|
||||
.Pq the offset within the vdev
|
||||
.Ar size
|
||||
(the size of the block to read) and, optionally,
|
||||
.Pq the size of the block to read
|
||||
and, optionally,
|
||||
.Ar flags
|
||||
(a set of flags, described below).
|
||||
.Bl -tag -width indent
|
||||
.It Sy b offset
|
||||
.Pq a set of flags, described below .
|
||||
.Pp
|
||||
.Bl -tag -compact -width "b offset"
|
||||
.It Sy b Ar offset
|
||||
Print block pointer
|
||||
.It Sy d
|
||||
Decompress the block
|
||||
@ -210,19 +253,20 @@ Dump raw uninterpreted block data
|
||||
.El
|
||||
.It Fl s
|
||||
Report statistics on
|
||||
.Nm Ns 's
|
||||
.Nm zdb
|
||||
I/O.
|
||||
Display operation counts, bandwidth, and error counts of I/O to the pool from
|
||||
.Nm .
|
||||
.It Fl S
|
||||
Simulate the effects of deduplication, constructing a DDT and then display
|
||||
that DDT as with \fB-DD\fR.
|
||||
that DDT as with
|
||||
.Fl DD .
|
||||
.It Fl u
|
||||
Display the current uberblock.
|
||||
.El
|
||||
.Pp
|
||||
Other options:
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width Ds
|
||||
.It Fl A
|
||||
Do not abort should any assertion fail.
|
||||
.It Fl AA
|
||||
@ -230,28 +274,41 @@ Enable panic recovery, certain errors which would otherwise be fatal are
|
||||
demoted to warnings.
|
||||
.It Fl AAA
|
||||
Do not abort if asserts fail and also enable panic recovery.
|
||||
.It Fl e Op Fl p Ar path...
|
||||
.It Fl e Op Fl p Ar path ...
|
||||
Operate on an exported pool, not present in
|
||||
.Pa /etc/zfs/zpool.cache .
|
||||
.Pa /boot/zfs/zpool.cache .
|
||||
The
|
||||
.Fl p
|
||||
flag specifies the path under which devices are to be searched.
|
||||
.It Fl x Ar dumpdir
|
||||
All blocks accessed will be copied to files in the specified directory.
|
||||
The blocks will be placed in sparse files whose name is the same as
|
||||
that of the file or device read. zdb can be then run on the generated files.
|
||||
that of the file or device read.
|
||||
.Nm
|
||||
can be then run on the generated files.
|
||||
Note that the
|
||||
.Fl bbc
|
||||
flags are sufficient to access (and thus copy)
|
||||
flags are sufficient to access
|
||||
.Pq and thus copy
|
||||
all metadata on the pool.
|
||||
.It Fl F
|
||||
Attempt to make an unreadable pool readable by trying progressively older
|
||||
transactions.
|
||||
.It Fl G
|
||||
Dump the contents of the zfs_dbgmsg buffer before exiting
|
||||
.Nm .
|
||||
zfs_dbgmsg is a buffer used by ZFS to dump advanced debug information.
|
||||
.It Fl I Ar inflight I/Os
|
||||
Limit the number of outstanding checksum I/Os to the specified value.
|
||||
The default value is 200. This option affects the performance of the
|
||||
The default value is 200.
|
||||
This option affects the performance of the
|
||||
.Fl c
|
||||
option.
|
||||
.It Fl o Ar var Ns = Ns Ar value ...
|
||||
Set the given global libzpool variable to the provided value.
|
||||
The value must be an unsigned 32-bit integer.
|
||||
Currently only little-endian systems are supported to avoid accidentally setting
|
||||
the high 32 bits of 64-bit variables.
|
||||
.It Fl P
|
||||
Print numbers in an unscaled form more amenable to parsing, eg. 1000000 rather
|
||||
than 1M.
|
||||
@ -269,9 +326,14 @@ Use a cache file other than
|
||||
.It Fl v
|
||||
Enable verbosity.
|
||||
Specify multiple times for increased verbosity.
|
||||
.It Fl V
|
||||
Attempt verbatim import.
|
||||
This mimics the behavior of the kernel when loading a pool from a cachefile.
|
||||
Only usable with
|
||||
.Fl e .
|
||||
.It Fl X
|
||||
Attempt
|
||||
.Ql extreme
|
||||
.Qq extreme
|
||||
transaction rewind, that is attempt the same recovery as
|
||||
.Fl F
|
||||
but read transactions otherwise deemed too old.
|
||||
@ -283,46 +345,58 @@ option, with more occurrences enabling more verbosity.
|
||||
If no options are specified, all information about the named pool will be
|
||||
displayed at default verbosity.
|
||||
.Sh EXAMPLES
|
||||
.Bl -tag -width 0n
|
||||
.It Sy Example 1 Display the configuration of imported pool 'rpool'
|
||||
.Bd -literal -offset 2n
|
||||
.Li # Ic zdb -C rpool
|
||||
.Bl -tag -width Ds
|
||||
.It Xo
|
||||
.Sy Example 1
|
||||
Display the configuration of imported pool
|
||||
.Pa rpool
|
||||
.Xc
|
||||
.Bd -literal
|
||||
# zdb -C rpool
|
||||
|
||||
MOS Configuration:
|
||||
version: 28
|
||||
name: 'rpool'
|
||||
...
|
||||
.Ed
|
||||
.It Sy Example 2 Display basic dataset information about 'rpool'
|
||||
.Bd -literal -offset 2n
|
||||
.Li # Ic zdb -d rpool
|
||||
.It Xo
|
||||
.Sy Example 2
|
||||
Display basic dataset information about
|
||||
.Pa rpool
|
||||
.Xc
|
||||
.Bd -literal
|
||||
# zdb -d rpool
|
||||
Dataset mos [META], ID 0, cr_txg 4, 26.9M, 1051 objects
|
||||
Dataset rpool/swap [ZVOL], ID 59, cr_txg 356, 486M, 2 objects
|
||||
...
|
||||
.Ed
|
||||
.It Xo Sy Example 3 Display basic information about object 0 in
|
||||
.Sy 'rpool/export/home'
|
||||
.It Xo
|
||||
.Sy Example 3
|
||||
Display basic information about object 0 in
|
||||
.Pa rpool/export/home
|
||||
.Xc
|
||||
.Bd -literal -offset 2n
|
||||
.Li # Ic zdb -d rpool/export/home 0
|
||||
.Bd -literal
|
||||
# zdb -d rpool/export/home 0
|
||||
Dataset rpool/export/home [ZPL], ID 137, cr_txg 1546, 32K, 8 objects
|
||||
|
||||
Object lvl iblk dblk dsize lsize %full type
|
||||
0 7 16K 16K 15.0K 16K 25.00 DMU dnode
|
||||
.Ed
|
||||
.It Xo Sy Example 4 Display the predicted effect of enabling deduplication on
|
||||
.Sy 'rpool'
|
||||
.It Xo
|
||||
.Sy Example 4
|
||||
Display the predicted effect of enabling deduplication on
|
||||
.Pa rpool
|
||||
.Xc
|
||||
.Bd -literal -offset 2n
|
||||
.Li # Ic zdb -S rpool
|
||||
.Bd -literal
|
||||
# zdb -S rpool
|
||||
Simulated DDT histogram:
|
||||
|
||||
bucket allocated referenced
|
||||
______ ______________________________ ______________________________
|
||||
refcnt blocks LSIZE PSIZE DSIZE blocks LSIZE PSIZE DSIZE
|
||||
------ ------ ----- ----- ----- ------ ----- ----- -----
|
||||
1 694K 27.1G 15.0G 15.0G 694K 27.1G 15.0G 15.0G
|
||||
2 35.0K 1.33G 699M 699M 74.7K 2.79G 1.45G 1.45G
|
||||
bucket allocated referenced
|
||||
______ ______________________________ ______________________________
|
||||
refcnt blocks LSIZE PSIZE DSIZE blocks LSIZE PSIZE DSIZE
|
||||
------ ------ ----- ----- ----- ------ ----- ----- -----
|
||||
1 694K 27.1G 15.0G 15.0G 694K 27.1G 15.0G 15.0G
|
||||
2 35.0K 1.33G 699M 699M 74.7K 2.79G 1.45G 1.45G
|
||||
...
|
||||
dedup = 1.11, compress = 1.80, copies = 1.00, dedup * compress / copies = 2.00
|
||||
.Ed
|
||||
@ -330,22 +404,3 @@ dedup = 1.11, compress = 1.80, copies = 1.00, dedup * compress / copies = 2.00
|
||||
.Sh SEE ALSO
|
||||
.Xr zfs 8 ,
|
||||
.Xr zpool 8
|
||||
.Sh AUTHORS
|
||||
This manual page is a
|
||||
.Xr mdoc 7
|
||||
reimplementation of the
|
||||
.Tn illumos
|
||||
manual page
|
||||
.Em zdb(1M) ,
|
||||
modified and customized for
|
||||
.Fx
|
||||
and licensed under the
|
||||
Common Development and Distribution License
|
||||
.Pq Tn CDDL .
|
||||
.Pp
|
||||
The
|
||||
.Xr mdoc 7
|
||||
implementation of this manual page was initially written by
|
||||
.An Martin Matuska Aq mm@FreeBSD.org
|
||||
and
|
||||
.An Marcelo Araujo Aq araujo@FreeBSD.org .
|
||||
|
@ -23,6 +23,7 @@
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2014 Integros [integros.com]
|
||||
* Copyright 2017 Nexenta Systems, Inc.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -60,7 +61,9 @@
|
||||
#include <sys/ddt.h>
|
||||
#include <sys/zfeature.h>
|
||||
#include <sys/abd.h>
|
||||
#include <sys/blkptr.h>
|
||||
#include <zfs_comutil.h>
|
||||
#include <libcmdutils.h>
|
||||
#undef verify
|
||||
#include <libzfs.h>
|
||||
|
||||
@ -120,18 +123,24 @@ static void
|
||||
usage(void)
|
||||
{
|
||||
(void) fprintf(stderr,
|
||||
"Usage: %s [-CumMdibcsDvhLXFPAG] [-t txg] [-e [-p path...]] "
|
||||
"[-U config] [-I inflight I/Os] [-x dumpdir] poolname [object...]\n"
|
||||
" %s [-divPA] [-e -p path...] [-U config] dataset "
|
||||
"[object...]\n"
|
||||
" %s -mM [-LXFPA] [-t txg] [-e [-p path...]] [-U config] "
|
||||
"poolname [vdev [metaslab...]]\n"
|
||||
" %s -R [-A] [-e [-p path...]] poolname "
|
||||
"vdev:offset:size[:flags]\n"
|
||||
" %s -S [-PA] [-e [-p path...]] [-U config] poolname\n"
|
||||
" %s -l [-uA] device\n"
|
||||
" %s -C [-A] [-U config]\n\n",
|
||||
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname);
|
||||
"Usage:\t%s [-AbcdDFGhiLMPsvX] [-e [-V] [-p <path> ...]] "
|
||||
"[-I <inflight I/Os>]\n"
|
||||
"\t\t[-o <var>=<value>]... [-t <txg>] [-U <cache>] [-x <dumpdir>]\n"
|
||||
"\t\t[<poolname> [<object> ...]]\n"
|
||||
"\t%s [-AdiPv] [-e [-V] [-p <path> ...]] [-U <cache>] <dataset> "
|
||||
"[<object> ...]\n"
|
||||
"\t%s -C [-A] [-U <cache>]\n"
|
||||
"\t%s -l [-Aqu] <device>\n"
|
||||
"\t%s -m [-AFLPX] [-e [-V] [-p <path> ...]] [-t <txg>] "
|
||||
"[-U <cache>]\n\t\t<poolname> [<vdev> [<metaslab> ...]]\n"
|
||||
"\t%s -O <dataset> <path>\n"
|
||||
"\t%s -R [-A] [-e [-V] [-p <path> ...]] [-U <cache>]\n"
|
||||
"\t\t<poolname> <vdev>:<offset>:<size>[:<flags>]\n"
|
||||
"\t%s -E [-A] word0:word1:...:word15\n"
|
||||
"\t%s -S [-AP] [-e [-V] [-p <path> ...]] [-U <cache>] "
|
||||
"<poolname>\n\n",
|
||||
cmdname, cmdname, cmdname, cmdname, cmdname, cmdname, cmdname,
|
||||
cmdname, cmdname);
|
||||
|
||||
(void) fprintf(stderr, " Dataset name must include at least one "
|
||||
"separator character '/' or '@'\n");
|
||||
@ -140,49 +149,57 @@ usage(void)
|
||||
(void) fprintf(stderr, " If object numbers are specified, only "
|
||||
"those objects are dumped\n\n");
|
||||
(void) fprintf(stderr, " Options to control amount of output:\n");
|
||||
(void) fprintf(stderr, " -u uberblock\n");
|
||||
(void) fprintf(stderr, " -d dataset(s)\n");
|
||||
(void) fprintf(stderr, " -i intent logs\n");
|
||||
(void) fprintf(stderr, " -C config (or cachefile if alone)\n");
|
||||
(void) fprintf(stderr, " -h pool history\n");
|
||||
(void) fprintf(stderr, " -b block statistics\n");
|
||||
(void) fprintf(stderr, " -m metaslabs\n");
|
||||
(void) fprintf(stderr, " -M metaslab groups\n");
|
||||
(void) fprintf(stderr, " -c checksum all metadata (twice for "
|
||||
"all data) blocks\n");
|
||||
(void) fprintf(stderr, " -s report stats on zdb's I/O\n");
|
||||
(void) fprintf(stderr, " -C config (or cachefile if alone)\n");
|
||||
(void) fprintf(stderr, " -d dataset(s)\n");
|
||||
(void) fprintf(stderr, " -D dedup statistics\n");
|
||||
(void) fprintf(stderr, " -S simulate dedup to measure effect\n");
|
||||
(void) fprintf(stderr, " -v verbose (applies to all others)\n");
|
||||
(void) fprintf(stderr, " -l dump label contents\n");
|
||||
(void) fprintf(stderr, " -E decode and display block from an "
|
||||
"embedded block pointer\n");
|
||||
(void) fprintf(stderr, " -h pool history\n");
|
||||
(void) fprintf(stderr, " -i intent logs\n");
|
||||
(void) fprintf(stderr, " -l read label contents\n");
|
||||
(void) fprintf(stderr, " -L disable leak tracking (do not "
|
||||
"load spacemaps)\n");
|
||||
(void) fprintf(stderr, " -m metaslabs\n");
|
||||
(void) fprintf(stderr, " -M metaslab groups\n");
|
||||
(void) fprintf(stderr, " -O perform object lookups by path\n");
|
||||
(void) fprintf(stderr, " -R read and display block from a "
|
||||
"device\n\n");
|
||||
"device\n");
|
||||
(void) fprintf(stderr, " -s report stats on zdb's I/O\n");
|
||||
(void) fprintf(stderr, " -S simulate dedup to measure effect\n");
|
||||
(void) fprintf(stderr, " -v verbose (applies to all "
|
||||
"others)\n\n");
|
||||
(void) fprintf(stderr, " Below options are intended for use "
|
||||
"with other options:\n");
|
||||
(void) fprintf(stderr, " -A ignore assertions (-A), enable "
|
||||
"panic recovery (-AA) or both (-AAA)\n");
|
||||
(void) fprintf(stderr, " -F attempt automatic rewind within "
|
||||
"safe range of transaction groups\n");
|
||||
(void) fprintf(stderr, " -U <cachefile_path> -- use alternate "
|
||||
"cachefile\n");
|
||||
(void) fprintf(stderr, " -X attempt extreme rewind (does not "
|
||||
"work with dataset)\n");
|
||||
(void) fprintf(stderr, " -e pool is exported/destroyed/"
|
||||
"has altroot/not in a cachefile\n");
|
||||
(void) fprintf(stderr, " -p <path> -- use one or more with "
|
||||
"-e to specify path to vdev dir\n");
|
||||
(void) fprintf(stderr, " -x <dumpdir> -- "
|
||||
"dump all read blocks into specified directory\n");
|
||||
(void) fprintf(stderr, " -P print numbers in parseable form\n");
|
||||
(void) fprintf(stderr, " -t <txg> -- highest txg to use when "
|
||||
"searching for uberblocks\n");
|
||||
(void) fprintf(stderr, " -F attempt automatic rewind within "
|
||||
"safe range of transaction groups\n");
|
||||
(void) fprintf(stderr, " -G dump zfs_dbgmsg buffer before "
|
||||
"exiting\n");
|
||||
(void) fprintf(stderr, " -I <number of inflight I/Os> -- "
|
||||
"specify the maximum number of "
|
||||
"checksumming I/Os [default is 200]\n");
|
||||
(void) fprintf(stderr, " -G dump zfs_dbgmsg buffer before "
|
||||
"exiting\n");
|
||||
(void) fprintf(stderr, " -o <variable>=<value> set global "
|
||||
"variable to an unsigned 32-bit integer value\n");
|
||||
(void) fprintf(stderr, " -p <path> -- use one or more with "
|
||||
"-e to specify path to vdev dir\n");
|
||||
(void) fprintf(stderr, " -P print numbers in parseable form\n");
|
||||
(void) fprintf(stderr, " -q don't print label contents\n");
|
||||
(void) fprintf(stderr, " -t <txg> -- highest txg to use when "
|
||||
"searching for uberblocks\n");
|
||||
(void) fprintf(stderr, " -u uberblock\n");
|
||||
(void) fprintf(stderr, " -U <cachefile_path> -- use alternate "
|
||||
"cachefile\n");
|
||||
(void) fprintf(stderr, " -V do verbatim import\n");
|
||||
(void) fprintf(stderr, " -x <dumpdir> -- "
|
||||
"dump all read blocks into specified directory\n");
|
||||
(void) fprintf(stderr, " -X attempt extreme rewind (does not "
|
||||
"work with dataset)\n\n");
|
||||
(void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
|
||||
"to make only that option verbose\n");
|
||||
(void) fprintf(stderr, "Default is to dump everything non-verbosely\n");
|
||||
@ -260,12 +277,12 @@ dump_history_offsets(objset_t *os, uint64_t object, void *data, size_t size)
|
||||
}
|
||||
|
||||
static void
|
||||
zdb_nicenum(uint64_t num, char *buf)
|
||||
zdb_nicenum(uint64_t num, char *buf, size_t buflen)
|
||||
{
|
||||
if (dump_opt['P'])
|
||||
(void) sprintf(buf, "%llu", (longlong_t)num);
|
||||
(void) snprintf(buf, buflen, "%llu", (longlong_t)num);
|
||||
else
|
||||
nicenum(num, buf);
|
||||
nicenum(num, buf, sizeof (buf));
|
||||
}
|
||||
|
||||
const char histo_stars[] = "****************************************";
|
||||
@ -442,12 +459,17 @@ dump_bpobj(objset_t *os, uint64_t object, void *data, size_t size)
|
||||
bpobj_phys_t *bpop = data;
|
||||
char bytes[32], comp[32], uncomp[32];
|
||||
|
||||
/* make sure the output won't get truncated */
|
||||
CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (comp) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (uncomp) >= NN_NUMBUF_SZ);
|
||||
|
||||
if (bpop == NULL)
|
||||
return;
|
||||
|
||||
zdb_nicenum(bpop->bpo_bytes, bytes);
|
||||
zdb_nicenum(bpop->bpo_comp, comp);
|
||||
zdb_nicenum(bpop->bpo_uncomp, uncomp);
|
||||
zdb_nicenum(bpop->bpo_bytes, bytes, sizeof (bytes));
|
||||
zdb_nicenum(bpop->bpo_comp, comp, sizeof (comp));
|
||||
zdb_nicenum(bpop->bpo_uncomp, uncomp, sizeof (uncomp));
|
||||
|
||||
(void) printf("\t\tnum_blkptrs = %llu\n",
|
||||
(u_longlong_t)bpop->bpo_num_blkptrs);
|
||||
@ -740,7 +762,10 @@ dump_metaslab_stats(metaslab_t *msp)
|
||||
avl_tree_t *t = &msp->ms_size_tree;
|
||||
int free_pct = range_tree_space(rt) * 100 / msp->ms_size;
|
||||
|
||||
zdb_nicenum(metaslab_block_maxsize(msp), maxbuf);
|
||||
/* max sure nicenum has enough space */
|
||||
CTASSERT(sizeof (maxbuf) >= NN_NUMBUF_SZ);
|
||||
|
||||
zdb_nicenum(metaslab_block_maxsize(msp), maxbuf, sizeof (maxbuf));
|
||||
|
||||
(void) printf("\t %25s %10lu %7s %6s %4s %4d%%\n",
|
||||
"segments", avl_numnodes(t), "maxsize", maxbuf,
|
||||
@ -757,7 +782,8 @@ dump_metaslab(metaslab_t *msp)
|
||||
space_map_t *sm = msp->ms_sm;
|
||||
char freebuf[32];
|
||||
|
||||
zdb_nicenum(msp->ms_size - space_map_allocated(sm), freebuf);
|
||||
zdb_nicenum(msp->ms_size - space_map_allocated(sm), freebuf,
|
||||
sizeof (freebuf));
|
||||
|
||||
(void) printf(
|
||||
"\tmetaslab %6llu offset %12llx spacemap %6llu free %5s\n",
|
||||
@ -1340,6 +1366,9 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
|
||||
time_t crtime;
|
||||
char nice[32];
|
||||
|
||||
/* make sure nicenum has enough space */
|
||||
CTASSERT(sizeof (nice) >= NN_NUMBUF_SZ);
|
||||
|
||||
if (dd == NULL)
|
||||
return;
|
||||
|
||||
@ -1355,15 +1384,15 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
|
||||
(u_longlong_t)dd->dd_origin_obj);
|
||||
(void) printf("\t\tchild_dir_zapobj = %llu\n",
|
||||
(u_longlong_t)dd->dd_child_dir_zapobj);
|
||||
zdb_nicenum(dd->dd_used_bytes, nice);
|
||||
zdb_nicenum(dd->dd_used_bytes, nice, sizeof (nice));
|
||||
(void) printf("\t\tused_bytes = %s\n", nice);
|
||||
zdb_nicenum(dd->dd_compressed_bytes, nice);
|
||||
zdb_nicenum(dd->dd_compressed_bytes, nice, sizeof (nice));
|
||||
(void) printf("\t\tcompressed_bytes = %s\n", nice);
|
||||
zdb_nicenum(dd->dd_uncompressed_bytes, nice);
|
||||
zdb_nicenum(dd->dd_uncompressed_bytes, nice, sizeof (nice));
|
||||
(void) printf("\t\tuncompressed_bytes = %s\n", nice);
|
||||
zdb_nicenum(dd->dd_quota, nice);
|
||||
zdb_nicenum(dd->dd_quota, nice, sizeof (nice));
|
||||
(void) printf("\t\tquota = %s\n", nice);
|
||||
zdb_nicenum(dd->dd_reserved, nice);
|
||||
zdb_nicenum(dd->dd_reserved, nice, sizeof (nice));
|
||||
(void) printf("\t\treserved = %s\n", nice);
|
||||
(void) printf("\t\tprops_zapobj = %llu\n",
|
||||
(u_longlong_t)dd->dd_props_zapobj);
|
||||
@ -1373,7 +1402,8 @@ dump_dsl_dir(objset_t *os, uint64_t object, void *data, size_t size)
|
||||
(u_longlong_t)dd->dd_flags);
|
||||
|
||||
#define DO(which) \
|
||||
zdb_nicenum(dd->dd_used_breakdown[DD_USED_ ## which], nice); \
|
||||
zdb_nicenum(dd->dd_used_breakdown[DD_USED_ ## which], nice, \
|
||||
sizeof (nice)); \
|
||||
(void) printf("\t\tused_breakdown[" #which "] = %s\n", nice)
|
||||
DO(HEAD);
|
||||
DO(SNAP);
|
||||
@ -1392,15 +1422,22 @@ dump_dsl_dataset(objset_t *os, uint64_t object, void *data, size_t size)
|
||||
char used[32], compressed[32], uncompressed[32], unique[32];
|
||||
char blkbuf[BP_SPRINTF_LEN];
|
||||
|
||||
/* make sure nicenum has enough space */
|
||||
CTASSERT(sizeof (used) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (compressed) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (uncompressed) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (unique) >= NN_NUMBUF_SZ);
|
||||
|
||||
if (ds == NULL)
|
||||
return;
|
||||
|
||||
ASSERT(size == sizeof (*ds));
|
||||
crtime = ds->ds_creation_time;
|
||||
zdb_nicenum(ds->ds_referenced_bytes, used);
|
||||
zdb_nicenum(ds->ds_compressed_bytes, compressed);
|
||||
zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed);
|
||||
zdb_nicenum(ds->ds_unique_bytes, unique);
|
||||
zdb_nicenum(ds->ds_referenced_bytes, used, sizeof (used));
|
||||
zdb_nicenum(ds->ds_compressed_bytes, compressed, sizeof (compressed));
|
||||
zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed,
|
||||
sizeof (uncompressed));
|
||||
zdb_nicenum(ds->ds_unique_bytes, unique, sizeof (unique));
|
||||
snprintf_blkptr(blkbuf, sizeof (blkbuf), &ds->ds_bp);
|
||||
|
||||
(void) printf("\t\tdir_obj = %llu\n",
|
||||
@ -1459,12 +1496,15 @@ dump_bptree(objset_t *os, uint64_t obj, char *name)
|
||||
bptree_phys_t *bt;
|
||||
dmu_buf_t *db;
|
||||
|
||||
/* make sure nicenum has enough space */
|
||||
CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
|
||||
|
||||
if (dump_opt['d'] < 3)
|
||||
return;
|
||||
|
||||
VERIFY3U(0, ==, dmu_bonus_hold(os, obj, FTAG, &db));
|
||||
bt = db->db_data;
|
||||
zdb_nicenum(bt->bt_bytes, bytes);
|
||||
zdb_nicenum(bt->bt_bytes, bytes, sizeof (bytes));
|
||||
(void) printf("\n %s: %llu datasets, %s\n",
|
||||
name, (unsigned long long)(bt->bt_end - bt->bt_begin), bytes);
|
||||
dmu_buf_rele(db, FTAG);
|
||||
@ -1496,13 +1536,18 @@ dump_full_bpobj(bpobj_t *bpo, char *name, int indent)
|
||||
char comp[32];
|
||||
char uncomp[32];
|
||||
|
||||
/* make sure nicenum has enough space */
|
||||
CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (comp) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (uncomp) >= NN_NUMBUF_SZ);
|
||||
|
||||
if (dump_opt['d'] < 3)
|
||||
return;
|
||||
|
||||
zdb_nicenum(bpo->bpo_phys->bpo_bytes, bytes);
|
||||
zdb_nicenum(bpo->bpo_phys->bpo_bytes, bytes, sizeof (bytes));
|
||||
if (bpo->bpo_havesubobj && bpo->bpo_phys->bpo_subobjs != 0) {
|
||||
zdb_nicenum(bpo->bpo_phys->bpo_comp, comp);
|
||||
zdb_nicenum(bpo->bpo_phys->bpo_uncomp, uncomp);
|
||||
zdb_nicenum(bpo->bpo_phys->bpo_comp, comp, sizeof (comp));
|
||||
zdb_nicenum(bpo->bpo_phys->bpo_uncomp, uncomp, sizeof (uncomp));
|
||||
(void) printf(" %*s: object %llu, %llu local blkptrs, "
|
||||
"%llu subobjs in object %llu, %s (%s/%s comp)\n",
|
||||
indent * 8, name,
|
||||
@ -1556,6 +1601,11 @@ dump_deadlist(dsl_deadlist_t *dl)
|
||||
char comp[32];
|
||||
char uncomp[32];
|
||||
|
||||
/* make sure nicenum has enough space */
|
||||
CTASSERT(sizeof (bytes) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (comp) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (uncomp) >= NN_NUMBUF_SZ);
|
||||
|
||||
if (dump_opt['d'] < 3)
|
||||
return;
|
||||
|
||||
@ -1564,9 +1614,9 @@ dump_deadlist(dsl_deadlist_t *dl)
|
||||
return;
|
||||
}
|
||||
|
||||
zdb_nicenum(dl->dl_phys->dl_used, bytes);
|
||||
zdb_nicenum(dl->dl_phys->dl_comp, comp);
|
||||
zdb_nicenum(dl->dl_phys->dl_uncomp, uncomp);
|
||||
zdb_nicenum(dl->dl_phys->dl_used, bytes, sizeof (bytes));
|
||||
zdb_nicenum(dl->dl_phys->dl_comp, comp, sizeof (comp));
|
||||
zdb_nicenum(dl->dl_phys->dl_uncomp, uncomp, sizeof (uncomp));
|
||||
(void) printf("\n Deadlist: %s (%s/%s comp)\n",
|
||||
bytes, comp, uncomp);
|
||||
|
||||
@ -1582,8 +1632,9 @@ dump_deadlist(dsl_deadlist_t *dl)
|
||||
dle = AVL_NEXT(&dl->dl_tree, dle)) {
|
||||
if (dump_opt['d'] >= 5) {
|
||||
char buf[128];
|
||||
(void) snprintf(buf, sizeof (buf), "mintxg %llu -> "
|
||||
"obj %llu", (longlong_t)dle->dle_mintxg,
|
||||
(void) snprintf(buf, sizeof (buf),
|
||||
"mintxg %llu -> obj %llu",
|
||||
(longlong_t)dle->dle_mintxg,
|
||||
(longlong_t)dle->dle_bpobj.bpo_object);
|
||||
dump_full_bpobj(&dle->dle_bpobj, buf, 0);
|
||||
} else {
|
||||
@ -1597,8 +1648,55 @@ dump_deadlist(dsl_deadlist_t *dl)
|
||||
static avl_tree_t idx_tree;
|
||||
static avl_tree_t domain_tree;
|
||||
static boolean_t fuid_table_loaded;
|
||||
static boolean_t sa_loaded;
|
||||
sa_attr_type_t *sa_attr_table;
|
||||
static objset_t *sa_os = NULL;
|
||||
static sa_attr_type_t *sa_attr_table = NULL;
|
||||
|
||||
static int
|
||||
open_objset(const char *path, dmu_objset_type_t type, void *tag, objset_t **osp)
|
||||
{
|
||||
int err;
|
||||
uint64_t sa_attrs = 0;
|
||||
uint64_t version = 0;
|
||||
|
||||
VERIFY3P(sa_os, ==, NULL);
|
||||
err = dmu_objset_own(path, type, B_TRUE, tag, osp);
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr, "failed to own dataset '%s': %s\n", path,
|
||||
strerror(err));
|
||||
return (err);
|
||||
}
|
||||
|
||||
if (dmu_objset_type(*osp) == DMU_OST_ZFS) {
|
||||
(void) zap_lookup(*osp, MASTER_NODE_OBJ, ZPL_VERSION_STR,
|
||||
8, 1, &version);
|
||||
if (version >= ZPL_VERSION_SA) {
|
||||
(void) zap_lookup(*osp, MASTER_NODE_OBJ, ZFS_SA_ATTRS,
|
||||
8, 1, &sa_attrs);
|
||||
}
|
||||
err = sa_setup(*osp, sa_attrs, zfs_attr_table, ZPL_END,
|
||||
&sa_attr_table);
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr, "sa_setup failed: %s\n",
|
||||
strerror(err));
|
||||
dmu_objset_disown(*osp, tag);
|
||||
*osp = NULL;
|
||||
}
|
||||
}
|
||||
sa_os = *osp;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
close_objset(objset_t *os, void *tag)
|
||||
{
|
||||
VERIFY3P(os, ==, sa_os);
|
||||
if (os->os_sa != NULL)
|
||||
sa_tear_down(os);
|
||||
dmu_objset_disown(os, tag);
|
||||
sa_attr_table = NULL;
|
||||
sa_os = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
fuid_table_destroy()
|
||||
@ -1670,25 +1768,7 @@ dump_znode(objset_t *os, uint64_t object, void *data, size_t size)
|
||||
int idx = 0;
|
||||
int error;
|
||||
|
||||
if (!sa_loaded) {
|
||||
uint64_t sa_attrs = 0;
|
||||
uint64_t version;
|
||||
|
||||
VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZPL_VERSION_STR,
|
||||
8, 1, &version) == 0);
|
||||
if (version >= ZPL_VERSION_SA) {
|
||||
VERIFY(zap_lookup(os, MASTER_NODE_OBJ, ZFS_SA_ATTRS,
|
||||
8, 1, &sa_attrs) == 0);
|
||||
}
|
||||
if ((error = sa_setup(os, sa_attrs, zfs_attr_table,
|
||||
ZPL_END, &sa_attr_table)) != 0) {
|
||||
(void) printf("sa_setup failed errno %d, can't "
|
||||
"display znode contents\n", error);
|
||||
return;
|
||||
}
|
||||
sa_loaded = B_TRUE;
|
||||
}
|
||||
|
||||
VERIFY3P(os, ==, sa_os);
|
||||
if (sa_handle_get(os, object, NULL, SA_HDL_PRIVATE, &hdl)) {
|
||||
(void) printf("Failed to get handle for SA znode\n");
|
||||
return;
|
||||
@ -1837,6 +1917,13 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
|
||||
char aux[50];
|
||||
int error;
|
||||
|
||||
/* make sure nicenum has enough space */
|
||||
CTASSERT(sizeof (iblk) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (dblk) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (lsize) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (asize) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (bonus_size) >= NN_NUMBUF_SZ);
|
||||
|
||||
if (*print_header) {
|
||||
(void) printf("\n%10s %3s %5s %5s %5s %5s %6s %s\n",
|
||||
"Object", "lvl", "iblk", "dblk", "dsize", "lsize",
|
||||
@ -1857,11 +1944,11 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
|
||||
}
|
||||
dmu_object_info_from_dnode(dn, &doi);
|
||||
|
||||
zdb_nicenum(doi.doi_metadata_block_size, iblk);
|
||||
zdb_nicenum(doi.doi_data_block_size, dblk);
|
||||
zdb_nicenum(doi.doi_max_offset, lsize);
|
||||
zdb_nicenum(doi.doi_physical_blocks_512 << 9, asize);
|
||||
zdb_nicenum(doi.doi_bonus_size, bonus_size);
|
||||
zdb_nicenum(doi.doi_metadata_block_size, iblk, sizeof (iblk));
|
||||
zdb_nicenum(doi.doi_data_block_size, dblk, sizeof (dblk));
|
||||
zdb_nicenum(doi.doi_max_offset, lsize, sizeof (lsize));
|
||||
zdb_nicenum(doi.doi_physical_blocks_512 << 9, asize, sizeof (asize));
|
||||
zdb_nicenum(doi.doi_bonus_size, bonus_size, sizeof (bonus_size));
|
||||
(void) sprintf(fill, "%6.2f", 100.0 * doi.doi_fill_count *
|
||||
doi.doi_data_block_size / (object == 0 ? DNODES_PER_BLOCK : 1) /
|
||||
doi.doi_max_offset);
|
||||
@ -1924,6 +2011,8 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
|
||||
|
||||
for (;;) {
|
||||
char segsize[32];
|
||||
/* make sure nicenum has enough space */
|
||||
CTASSERT(sizeof (segsize) >= NN_NUMBUF_SZ);
|
||||
error = dnode_next_offset(dn,
|
||||
0, &start, minlvl, blkfill, 0);
|
||||
if (error)
|
||||
@ -1931,7 +2020,7 @@ dump_object(objset_t *os, uint64_t object, int verbosity, int *print_header)
|
||||
end = start;
|
||||
error = dnode_next_offset(dn,
|
||||
DNODE_FIND_HOLE, &end, minlvl, blkfill, 0);
|
||||
zdb_nicenum(end - start, segsize);
|
||||
zdb_nicenum(end - start, segsize, sizeof (segsize));
|
||||
(void) printf("\t\tsegment [%016llx, %016llx)"
|
||||
" size %5s\n", (u_longlong_t)start,
|
||||
(u_longlong_t)end, segsize);
|
||||
@ -1962,6 +2051,9 @@ dump_dir(objset_t *os)
|
||||
int print_header = 1;
|
||||
int i, error;
|
||||
|
||||
/* make sure nicenum has enough space */
|
||||
CTASSERT(sizeof (numbuf) >= NN_NUMBUF_SZ);
|
||||
|
||||
dsl_pool_config_enter(dmu_objset_pool(os), FTAG);
|
||||
dmu_objset_fast_stat(os, &dds);
|
||||
dsl_pool_config_exit(dmu_objset_pool(os), FTAG);
|
||||
@ -1980,7 +2072,7 @@ dump_dir(objset_t *os)
|
||||
|
||||
ASSERT3U(usedobjs, ==, BP_GET_FILL(os->os_rootbp));
|
||||
|
||||
zdb_nicenum(refdbytes, numbuf);
|
||||
zdb_nicenum(refdbytes, numbuf, sizeof (numbuf));
|
||||
|
||||
if (verbosity >= 4) {
|
||||
(void) snprintf(blkbuf, sizeof (blkbuf), ", rootbp ");
|
||||
@ -2156,44 +2248,154 @@ dump_label_uberblocks(vdev_label_t *lbl, uint64_t ashift)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
static char curpath[PATH_MAX];
|
||||
|
||||
/*
|
||||
* Iterate through the path components, recursively passing
|
||||
* current one's obj and remaining path until we find the obj
|
||||
* for the last one.
|
||||
*/
|
||||
static int
|
||||
dump_path_impl(objset_t *os, uint64_t obj, char *name)
|
||||
{
|
||||
int err;
|
||||
int header = 1;
|
||||
uint64_t child_obj;
|
||||
char *s;
|
||||
dmu_buf_t *db;
|
||||
dmu_object_info_t doi;
|
||||
|
||||
if ((s = strchr(name, '/')) != NULL)
|
||||
*s = '\0';
|
||||
err = zap_lookup(os, obj, name, 8, 1, &child_obj);
|
||||
|
||||
(void) strlcat(curpath, name, sizeof (curpath));
|
||||
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr, "failed to lookup %s: %s\n",
|
||||
curpath, strerror(err));
|
||||
return (err);
|
||||
}
|
||||
|
||||
child_obj = ZFS_DIRENT_OBJ(child_obj);
|
||||
err = sa_buf_hold(os, child_obj, FTAG, &db);
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr,
|
||||
"failed to get SA dbuf for obj %llu: %s\n",
|
||||
(u_longlong_t)child_obj, strerror(err));
|
||||
return (EINVAL);
|
||||
}
|
||||
dmu_object_info_from_db(db, &doi);
|
||||
sa_buf_rele(db, FTAG);
|
||||
|
||||
if (doi.doi_bonus_type != DMU_OT_SA &&
|
||||
doi.doi_bonus_type != DMU_OT_ZNODE) {
|
||||
(void) fprintf(stderr, "invalid bonus type %d for obj %llu\n",
|
||||
doi.doi_bonus_type, (u_longlong_t)child_obj);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (dump_opt['v'] > 6) {
|
||||
(void) printf("obj=%llu %s type=%d bonustype=%d\n",
|
||||
(u_longlong_t)child_obj, curpath, doi.doi_type,
|
||||
doi.doi_bonus_type);
|
||||
}
|
||||
|
||||
(void) strlcat(curpath, "/", sizeof (curpath));
|
||||
|
||||
switch (doi.doi_type) {
|
||||
case DMU_OT_DIRECTORY_CONTENTS:
|
||||
if (s != NULL && *(s + 1) != '\0')
|
||||
return (dump_path_impl(os, child_obj, s + 1));
|
||||
/*FALLTHROUGH*/
|
||||
case DMU_OT_PLAIN_FILE_CONTENTS:
|
||||
dump_object(os, child_obj, dump_opt['v'], &header);
|
||||
return (0);
|
||||
default:
|
||||
(void) fprintf(stderr, "object %llu has non-file/directory "
|
||||
"type %d\n", (u_longlong_t)obj, doi.doi_type);
|
||||
break;
|
||||
}
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the blocks for the object specified by path inside the dataset.
|
||||
*/
|
||||
static int
|
||||
dump_path(char *ds, char *path)
|
||||
{
|
||||
int err;
|
||||
objset_t *os;
|
||||
uint64_t root_obj;
|
||||
|
||||
err = open_objset(ds, DMU_OST_ZFS, FTAG, &os);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
err = zap_lookup(os, MASTER_NODE_OBJ, ZFS_ROOT_OBJ, 8, 1, &root_obj);
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr, "can't lookup root znode: %s\n",
|
||||
strerror(err));
|
||||
dmu_objset_disown(os, FTAG);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
(void) snprintf(curpath, sizeof (curpath), "dataset=%s path=/", ds);
|
||||
|
||||
err = dump_path_impl(os, root_obj, path);
|
||||
|
||||
close_objset(os, FTAG);
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
dump_label(const char *dev)
|
||||
{
|
||||
int fd;
|
||||
vdev_label_t label;
|
||||
char *path, *buf = label.vl_vdev_phys.vp_nvlist;
|
||||
char path[MAXPATHLEN];
|
||||
char *buf = label.vl_vdev_phys.vp_nvlist;
|
||||
size_t buflen = sizeof (label.vl_vdev_phys.vp_nvlist);
|
||||
struct stat64 statbuf;
|
||||
uint64_t psize, ashift;
|
||||
int len = strlen(dev) + 1;
|
||||
boolean_t label_found = B_FALSE;
|
||||
|
||||
if (strncmp(dev, ZFS_DISK_ROOTD, strlen(ZFS_DISK_ROOTD)) == 0) {
|
||||
len++;
|
||||
path = malloc(len);
|
||||
(void) snprintf(path, len, "%s%s", ZFS_RDISK_ROOTD,
|
||||
dev + strlen(ZFS_DISK_ROOTD));
|
||||
} else {
|
||||
path = strdup(dev);
|
||||
(void) strlcpy(path, dev, sizeof (path));
|
||||
if (dev[0] == '/') {
|
||||
if (strncmp(dev, ZFS_DISK_ROOTD,
|
||||
strlen(ZFS_DISK_ROOTD)) == 0) {
|
||||
(void) snprintf(path, sizeof (path), "%s%s",
|
||||
ZFS_RDISK_ROOTD, dev + strlen(ZFS_DISK_ROOTD));
|
||||
}
|
||||
} else if (stat64(path, &statbuf) != 0) {
|
||||
char *s;
|
||||
|
||||
(void) snprintf(path, sizeof (path), "%s%s", ZFS_RDISK_ROOTD,
|
||||
dev);
|
||||
if (((s = strrchr(dev, 's')) == NULL &&
|
||||
(s = strchr(dev, 'p')) == NULL) ||
|
||||
!isdigit(*(s + 1)))
|
||||
(void) strlcat(path, "s0", sizeof (path));
|
||||
}
|
||||
|
||||
if ((fd = open64(path, O_RDONLY)) < 0) {
|
||||
(void) printf("cannot open '%s': %s\n", path, strerror(errno));
|
||||
free(path);
|
||||
(void) fprintf(stderr, "cannot open '%s': %s\n", path,
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (fstat64(fd, &statbuf) != 0) {
|
||||
(void) printf("failed to stat '%s': %s\n", path,
|
||||
(void) fprintf(stderr, "failed to stat '%s': %s\n", path,
|
||||
strerror(errno));
|
||||
free(path);
|
||||
(void) close(fd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (S_ISBLK(statbuf.st_mode)) {
|
||||
(void) printf("cannot use '%s': character device required\n",
|
||||
path);
|
||||
free(path);
|
||||
(void) fprintf(stderr,
|
||||
"cannot use '%s': character device required\n", path);
|
||||
(void) close(fd);
|
||||
exit(1);
|
||||
}
|
||||
@ -2204,36 +2406,43 @@ dump_label(const char *dev)
|
||||
for (int l = 0; l < VDEV_LABELS; l++) {
|
||||
nvlist_t *config = NULL;
|
||||
|
||||
(void) printf("--------------------------------------------\n");
|
||||
(void) printf("LABEL %d\n", l);
|
||||
(void) printf("--------------------------------------------\n");
|
||||
if (!dump_opt['q']) {
|
||||
(void) printf("------------------------------------\n");
|
||||
(void) printf("LABEL %d\n", l);
|
||||
(void) printf("------------------------------------\n");
|
||||
}
|
||||
|
||||
if (pread64(fd, &label, sizeof (label),
|
||||
vdev_label_offset(psize, l, 0)) != sizeof (label)) {
|
||||
(void) printf("failed to read label %d\n", l);
|
||||
if (!dump_opt['q'])
|
||||
(void) printf("failed to read label %d\n", l);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nvlist_unpack(buf, buflen, &config, 0) != 0) {
|
||||
(void) printf("failed to unpack label %d\n", l);
|
||||
if (!dump_opt['q'])
|
||||
(void) printf("failed to unpack label %d\n", l);
|
||||
ashift = SPA_MINBLOCKSHIFT;
|
||||
} else {
|
||||
nvlist_t *vdev_tree = NULL;
|
||||
|
||||
dump_nvlist(config, 4);
|
||||
if (!dump_opt['q'])
|
||||
dump_nvlist(config, 4);
|
||||
if ((nvlist_lookup_nvlist(config,
|
||||
ZPOOL_CONFIG_VDEV_TREE, &vdev_tree) != 0) ||
|
||||
(nvlist_lookup_uint64(vdev_tree,
|
||||
ZPOOL_CONFIG_ASHIFT, &ashift) != 0))
|
||||
ashift = SPA_MINBLOCKSHIFT;
|
||||
nvlist_free(config);
|
||||
label_found = B_TRUE;
|
||||
}
|
||||
if (dump_opt['u'])
|
||||
dump_label_uberblocks(&label, ashift);
|
||||
}
|
||||
|
||||
free(path);
|
||||
(void) close(fd);
|
||||
|
||||
return (label_found ? 0 : 2);
|
||||
}
|
||||
|
||||
static uint64_t dataset_feature_count[SPA_FEATURES];
|
||||
@ -2245,11 +2454,9 @@ dump_one_dir(const char *dsname, void *arg)
|
||||
int error;
|
||||
objset_t *os;
|
||||
|
||||
error = dmu_objset_own(dsname, DMU_OST_ANY, B_TRUE, FTAG, &os);
|
||||
if (error) {
|
||||
(void) printf("Could not open %s, error %d\n", dsname, error);
|
||||
error = open_objset(dsname, DMU_OST_ANY, FTAG, &os);
|
||||
if (error != 0)
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (spa_feature_t f = 0; f < SPA_FEATURES; f++) {
|
||||
if (!dmu_objset_ds(os)->ds_feature_inuse[f])
|
||||
@ -2260,9 +2467,8 @@ dump_one_dir(const char *dsname, void *arg)
|
||||
}
|
||||
|
||||
dump_dir(os);
|
||||
dmu_objset_disown(os, FTAG);
|
||||
close_objset(os, FTAG);
|
||||
fuid_table_destroy();
|
||||
sa_loaded = B_FALSE;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -2513,6 +2719,9 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
|
||||
int sec_remaining =
|
||||
(zcb->zcb_totalasize - bytes) / 1024 / kb_per_sec;
|
||||
|
||||
/* make sure nicenum has enough space */
|
||||
CTASSERT(sizeof (buf) >= NN_NUMBUF_SZ);
|
||||
|
||||
zfs_nicenum(bytes, buf, sizeof (buf));
|
||||
(void) fprintf(stderr,
|
||||
"\r%5s completed (%4dMB/s) "
|
||||
@ -2862,6 +3071,14 @@ dump_block_stats(spa_t *spa)
|
||||
char avg[32], gang[32];
|
||||
char *typename;
|
||||
|
||||
/* make sure nicenum has enough space */
|
||||
CTASSERT(sizeof (csize) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (lsize) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (psize) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (asize) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (avg) >= NN_NUMBUF_SZ);
|
||||
CTASSERT(sizeof (gang) >= NN_NUMBUF_SZ);
|
||||
|
||||
if (t < DMU_OT_NUMTYPES)
|
||||
typename = dmu_ot[t].ot_name;
|
||||
else
|
||||
@ -2895,12 +3112,17 @@ dump_block_stats(spa_t *spa)
|
||||
zcb.zcb_type[ZB_TOTAL][t].zb_asize)
|
||||
continue;
|
||||
|
||||
zdb_nicenum(zb->zb_count, csize);
|
||||
zdb_nicenum(zb->zb_lsize, lsize);
|
||||
zdb_nicenum(zb->zb_psize, psize);
|
||||
zdb_nicenum(zb->zb_asize, asize);
|
||||
zdb_nicenum(zb->zb_asize / zb->zb_count, avg);
|
||||
zdb_nicenum(zb->zb_gangs, gang);
|
||||
zdb_nicenum(zb->zb_count, csize,
|
||||
sizeof (csize));
|
||||
zdb_nicenum(zb->zb_lsize, lsize,
|
||||
sizeof (lsize));
|
||||
zdb_nicenum(zb->zb_psize, psize,
|
||||
sizeof (psize));
|
||||
zdb_nicenum(zb->zb_asize, asize,
|
||||
sizeof (asize));
|
||||
zdb_nicenum(zb->zb_asize / zb->zb_count, avg,
|
||||
sizeof (avg));
|
||||
zdb_nicenum(zb->zb_gangs, gang, sizeof (gang));
|
||||
|
||||
(void) printf("%6s\t%5s\t%5s\t%5s\t%5s"
|
||||
"\t%5.2f\t%6.2f\t",
|
||||
@ -3497,6 +3719,33 @@ zdb_read_block(char *thing, spa_t *spa)
|
||||
free(dup);
|
||||
}
|
||||
|
||||
static void
|
||||
zdb_embedded_block(char *thing)
|
||||
{
|
||||
blkptr_t bp = { 0 };
|
||||
unsigned long long *words = (void *)&bp;
|
||||
char buf[SPA_MAXBLOCKSIZE];
|
||||
int err;
|
||||
|
||||
err = sscanf(thing, "%llx:%llx:%llx:%llx:%llx:%llx:%llx:%llx:"
|
||||
"%llx:%llx:%llx:%llx:%llx:%llx:%llx:%llx",
|
||||
words + 0, words + 1, words + 2, words + 3,
|
||||
words + 4, words + 5, words + 6, words + 7,
|
||||
words + 8, words + 9, words + 10, words + 11,
|
||||
words + 12, words + 13, words + 14, words + 15);
|
||||
if (err != 16) {
|
||||
(void) printf("invalid input format\n");
|
||||
exit(1);
|
||||
}
|
||||
ASSERT3U(BPE_GET_LSIZE(&bp), <=, SPA_MAXBLOCKSIZE);
|
||||
err = decode_embedded_bp(&bp, buf, BPE_GET_LSIZE(&bp));
|
||||
if (err != 0) {
|
||||
(void) printf("decode failed: %u\n", err);
|
||||
exit(1);
|
||||
}
|
||||
zdb_dump_block_raw(buf, BPE_GET_LSIZE(&bp), 0);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
pool_match(nvlist_t *cfg, char *tgt)
|
||||
{
|
||||
@ -3595,6 +3844,7 @@ main(int argc, char **argv)
|
||||
char *target;
|
||||
nvlist_t *policy = NULL;
|
||||
uint64_t max_txg = UINT64_MAX;
|
||||
int flags = ZFS_IMPORT_MISSING_LOG;
|
||||
int rewind = ZPOOL_NEVER_REWIND;
|
||||
char *spa_config_path_env;
|
||||
boolean_t target_is_spa = B_TRUE;
|
||||
@ -3614,34 +3864,38 @@ main(int argc, char **argv)
|
||||
spa_config_path = spa_config_path_env;
|
||||
|
||||
while ((c = getopt(argc, argv,
|
||||
"bcdhilmMI:suCDRSAFLXx:evp:t:U:PG")) != -1) {
|
||||
"AbcCdDeEFGhiI:lLmMo:Op:PqRsSt:uU:vVx:X")) != -1) {
|
||||
switch (c) {
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'C':
|
||||
case 'd':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'G':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 's':
|
||||
case 'u':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'M':
|
||||
case 'O':
|
||||
case 'R':
|
||||
case 's':
|
||||
case 'S':
|
||||
case 'G':
|
||||
case 'u':
|
||||
dump_opt[c]++;
|
||||
dump_all = 0;
|
||||
break;
|
||||
case 'A':
|
||||
case 'e':
|
||||
case 'F':
|
||||
case 'L':
|
||||
case 'X':
|
||||
case 'e':
|
||||
case 'P':
|
||||
case 'q':
|
||||
case 'X':
|
||||
dump_opt[c]++;
|
||||
break;
|
||||
/* NB: Sort single match options below. */
|
||||
case 'I':
|
||||
max_inflight = strtoull(optarg, NULL, 0);
|
||||
if (max_inflight == 0) {
|
||||
@ -3651,6 +3905,11 @@ main(int argc, char **argv)
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
error = set_global_var(optarg);
|
||||
if (error != 0)
|
||||
usage();
|
||||
break;
|
||||
case 'p':
|
||||
if (searchdirs == NULL) {
|
||||
searchdirs = umem_alloc(sizeof (char *),
|
||||
@ -3676,10 +3935,19 @@ main(int argc, char **argv)
|
||||
break;
|
||||
case 'U':
|
||||
spa_config_path = optarg;
|
||||
if (spa_config_path[0] != '/') {
|
||||
(void) fprintf(stderr,
|
||||
"cachefile must be an absolute path "
|
||||
"(i.e. start with a slash)\n");
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
case 'V':
|
||||
flags = ZFS_IMPORT_VERBATIM;
|
||||
break;
|
||||
case 'x':
|
||||
vn_dumpdir = optarg;
|
||||
break;
|
||||
@ -3721,7 +3989,7 @@ main(int argc, char **argv)
|
||||
verbose = MAX(verbose, 1);
|
||||
|
||||
for (c = 0; c < 256; c++) {
|
||||
if (dump_all && !strchr("elAFLRSXP", c))
|
||||
if (dump_all && strchr("AeEFlLOPRSX", c) == NULL)
|
||||
dump_opt[c] = 1;
|
||||
if (dump_opt[c])
|
||||
dump_opt[c] += verbose;
|
||||
@ -3735,6 +4003,14 @@ main(int argc, char **argv)
|
||||
|
||||
if (argc < 2 && dump_opt['R'])
|
||||
usage();
|
||||
|
||||
if (dump_opt['E']) {
|
||||
if (argc != 1)
|
||||
usage();
|
||||
zdb_embedded_block(argv[0]);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (argc < 1) {
|
||||
if (!dump_opt['e'] && dump_opt['C']) {
|
||||
dump_cachefile(spa_config_path);
|
||||
@ -3743,9 +4019,14 @@ main(int argc, char **argv)
|
||||
usage();
|
||||
}
|
||||
|
||||
if (dump_opt['l']) {
|
||||
dump_label(argv[0]);
|
||||
return (0);
|
||||
if (dump_opt['l'])
|
||||
return (dump_label(argv[0]));
|
||||
|
||||
if (dump_opt['O']) {
|
||||
if (argc != 2)
|
||||
usage();
|
||||
dump_opt['v'] = verbose + 3;
|
||||
return (dump_path(argv[0], argv[1]));
|
||||
}
|
||||
|
||||
if (dump_opt['X'] || dump_opt['F'])
|
||||
@ -3775,11 +4056,7 @@ main(int argc, char **argv)
|
||||
fatal("can't open '%s': %s",
|
||||
target, strerror(ENOMEM));
|
||||
}
|
||||
if ((error = spa_import(name, cfg, NULL,
|
||||
ZFS_IMPORT_MISSING_LOG)) != 0) {
|
||||
error = spa_import(name, cfg, NULL,
|
||||
ZFS_IMPORT_VERBATIM);
|
||||
}
|
||||
error = spa_import(name, cfg, NULL, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3822,8 +4099,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error = dmu_objset_own(target, DMU_OST_ANY,
|
||||
B_TRUE, FTAG, &os);
|
||||
error = open_objset(target, DMU_OST_ANY, FTAG, &os);
|
||||
}
|
||||
}
|
||||
nvlist_free(policy);
|
||||
@ -3866,10 +4142,12 @@ main(int argc, char **argv)
|
||||
zdb_read_block(argv[i], spa);
|
||||
}
|
||||
|
||||
(os != NULL) ? dmu_objset_disown(os, FTAG) : spa_close(spa, FTAG);
|
||||
if (os != NULL)
|
||||
close_objset(os, FTAG);
|
||||
else
|
||||
spa_close(spa, FTAG);
|
||||
|
||||
fuid_table_destroy();
|
||||
sa_loaded = B_FALSE;
|
||||
|
||||
dump_debug_buffer();
|
||||
|
||||
|
536
cddl/contrib/opensolaris/cmd/zfs/zfs-program.8
Normal file
536
cddl/contrib/opensolaris/cmd/zfs/zfs-program.8
Normal file
@ -0,0 +1,536 @@
|
||||
.\" This file and its contents are supplied under the terms of the
|
||||
.\" Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
.\" You may only use this file in accordance with the terms of version
|
||||
.\" 1.0 of the CDDL.
|
||||
.\"
|
||||
.\" A full copy of the text of the CDDL should have accompanied this
|
||||
.\" source. A copy of the CDDL is also available via the Internet at
|
||||
.\" http://www.illumos.org/license/CDDL.
|
||||
.\"
|
||||
.\"
|
||||
.\" Copyright (c) 2016, 2017 by Delphix. All rights reserved.
|
||||
.\"
|
||||
.Dd October 02, 2017
|
||||
.Dt ZFS-PROGRAM 1M
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm zfs program
|
||||
.Nd executes ZFS channel programs
|
||||
.Sh SYNOPSIS
|
||||
.Cm zfs program
|
||||
.Op Fl t Ar instruction-limit
|
||||
.Op Fl m Ar memory-limit
|
||||
.Ar pool
|
||||
.Ar script
|
||||
.\".Op Ar optional arguments to channel program
|
||||
.Sh DESCRIPTION
|
||||
The ZFS channel program interface allows ZFS administrative operations to be
|
||||
run programmatically as a Lua script.
|
||||
The entire script is executed atomically, with no other administrative
|
||||
operations taking effect concurrently.
|
||||
A library of ZFS calls is made available to channel program scripts.
|
||||
Channel programs may only be run with root privileges.
|
||||
.Pp
|
||||
A modified version of the Lua 5.2 interpreter is used to run channel program
|
||||
scripts.
|
||||
The Lua 5.2 manual can be found at:
|
||||
.Bd -centered -offset indent
|
||||
.Lk http://www.lua.org/manual/5.2/
|
||||
.Ed
|
||||
.Pp
|
||||
The channel program given by
|
||||
.Ar script
|
||||
will be run on
|
||||
.Ar pool ,
|
||||
and any attempts to access or modify other pools will cause an error.
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width "-t"
|
||||
.It Fl t Ar instruction-limit
|
||||
Execution time limit, in number of Lua instructions to execute.
|
||||
If a channel program executes more than the specified number of instructions,
|
||||
it will be stopped and an error will be returned.
|
||||
The default limit is 10 million instructions, and it can be set to a maximum of
|
||||
100 million instructions.
|
||||
.It Fl m Ar memory-limit
|
||||
Memory limit, in bytes.
|
||||
If a channel program attempts to allocate more memory than the given limit, it
|
||||
will be stopped and an error returned.
|
||||
The default memory limit is 10 MB, and can be set to a maximum of 100 MB.
|
||||
.El
|
||||
.Pp
|
||||
All remaining argument strings will be passed directly to the Lua script as
|
||||
described in the
|
||||
.Sx LUA INTERFACE
|
||||
section below.
|
||||
.Sh LUA INTERFACE
|
||||
A channel program can be invoked either from the command line, or via a library
|
||||
call to
|
||||
.Fn lzc_channel_program .
|
||||
.Ss Arguments
|
||||
Arguments passed to the channel program are converted to a Lua table.
|
||||
If invoked from the command line, extra arguments to the Lua script will be
|
||||
accessible as an array stored in the argument table with the key 'argv':
|
||||
.Bd -literal -offset indent
|
||||
args = ...
|
||||
argv = args["argv"]
|
||||
-- argv == {1="arg1", 2="arg2", ...}
|
||||
.Ed
|
||||
.Pp
|
||||
If invoked from the libZFS interface, an arbitrary argument list can be
|
||||
passed to the channel program, which is accessible via the same
|
||||
"..." syntax in Lua:
|
||||
.Bd -literal -offset indent
|
||||
args = ...
|
||||
-- args == {"foo"="bar", "baz"={...}, ...}
|
||||
.Ed
|
||||
.Pp
|
||||
Note that because Lua arrays are 1-indexed, arrays passed to Lua from the
|
||||
libZFS interface will have their indices incremented by 1.
|
||||
That is, the element
|
||||
in
|
||||
.Va arr[0]
|
||||
in a C array passed to a channel program will be stored in
|
||||
.Va arr[1]
|
||||
when accessed from Lua.
|
||||
.Ss Return Values
|
||||
Lua return statements take the form:
|
||||
.Bd -literal -offset indent
|
||||
return ret0, ret1, ret2, ...
|
||||
.Ed
|
||||
.Pp
|
||||
Return statements returning multiple values are permitted internally in a
|
||||
channel program script, but attempting to return more than one value from the
|
||||
top level of the channel program is not permitted and will throw an error.
|
||||
However, tables containing multiple values can still be returned.
|
||||
If invoked from the command line, a return statement:
|
||||
.Bd -literal -offset indent
|
||||
a = {foo="bar", baz=2}
|
||||
return a
|
||||
.Ed
|
||||
.Pp
|
||||
Will be output formatted as:
|
||||
.Bd -literal -offset indent
|
||||
Channel program fully executed with return value:
|
||||
return:
|
||||
baz: 2
|
||||
foo: 'bar'
|
||||
.Ed
|
||||
.Ss Fatal Errors
|
||||
If the channel program encounters a fatal error while running, a non-zero exit
|
||||
status will be returned.
|
||||
If more information about the error is available, a singleton list will be
|
||||
returned detailing the error:
|
||||
.Bd -literal -offset indent
|
||||
error: "error string, including Lua stack trace"
|
||||
.Ed
|
||||
.Pp
|
||||
If a fatal error is returned, the channel program may have not executed at all,
|
||||
may have partially executed, or may have fully executed but failed to pass a
|
||||
return value back to userland.
|
||||
.Pp
|
||||
If the channel program exhausts an instruction or memory limit, a fatal error
|
||||
will be generated and the program will be stopped, leaving the program partially
|
||||
executed.
|
||||
No attempt is made to reverse or undo any operations already performed.
|
||||
Note that because both the instruction count and amount of memory used by a
|
||||
channel program are deterministic when run against the same inputs and
|
||||
filesystem state, as long as a channel program has run successfully once, you
|
||||
can guarantee that it will finish successfully against a similar size system.
|
||||
.Pp
|
||||
If a channel program attempts to return too large a value, the program will
|
||||
fully execute but exit with a nonzero status code and no return value.
|
||||
.Pp
|
||||
.Em Note:
|
||||
ZFS API functions do not generate Fatal Errors when correctly invoked, they
|
||||
return an error code and the channel program continues executing.
|
||||
See the
|
||||
.Sx ZFS API
|
||||
section below for function-specific details on error return codes.
|
||||
.Ss Lua to C Value Conversion
|
||||
When invoking a channel program via the libZFS interface, it is necessary to
|
||||
translate arguments and return values from Lua values to their C equivalents,
|
||||
and vice-versa.
|
||||
.Pp
|
||||
There is a correspondence between nvlist values in C and Lua tables.
|
||||
A Lua table which is returned from the channel program will be recursively
|
||||
converted to an nvlist, with table values converted to their natural
|
||||
equivalents:
|
||||
.Bd -literal -offset indent
|
||||
string -> string
|
||||
number -> int64
|
||||
boolean -> boolean_value
|
||||
nil -> boolean (no value)
|
||||
table -> nvlist
|
||||
.Ed
|
||||
.Pp
|
||||
Likewise, table keys are replaced by string equivalents as follows:
|
||||
.Bd -literal -offset indent
|
||||
string -> no change
|
||||
number -> signed decimal string ("%lld")
|
||||
boolean -> "true" | "false"
|
||||
.Ed
|
||||
.Pp
|
||||
Any collision of table key strings (for example, the string "true" and a
|
||||
true boolean value) will cause a fatal error.
|
||||
.Pp
|
||||
Lua numbers are represented internally as signed 64-bit integers.
|
||||
.Sh LUA STANDARD LIBRARY
|
||||
The following Lua built-in base library functions are available:
|
||||
.Bd -literal -offset indent
|
||||
assert rawlen
|
||||
collectgarbage rawget
|
||||
error rawset
|
||||
getmetatable select
|
||||
ipairs setmetatable
|
||||
next tonumber
|
||||
pairs tostring
|
||||
rawequal type
|
||||
.Ed
|
||||
.Pp
|
||||
All functions in the
|
||||
.Em coroutine ,
|
||||
.Em string ,
|
||||
and
|
||||
.Em table
|
||||
built-in submodules are also available.
|
||||
A complete list and documentation of these modules is available in the Lua
|
||||
manual.
|
||||
.Pp
|
||||
The following functions base library functions have been disabled and are
|
||||
not available for use in channel programs:
|
||||
.Bd -literal -offset indent
|
||||
dofile
|
||||
loadfile
|
||||
load
|
||||
pcall
|
||||
print
|
||||
xpcall
|
||||
.Ed
|
||||
.Sh ZFS API
|
||||
.Ss Function Arguments
|
||||
Each API function takes a fixed set of required positional arguments and
|
||||
optional keyword arguments.
|
||||
For example, the destroy function takes a single positional string argument
|
||||
(the name of the dataset to destroy) and an optional "defer" keyword boolean
|
||||
argument.
|
||||
When using parentheses to specify the arguments to a Lua function, only
|
||||
positional arguments can be used:
|
||||
.Bd -literal -offset indent
|
||||
zfs.sync.destroy("rpool@snap")
|
||||
.Ed
|
||||
.Pp
|
||||
To use keyword arguments, functions must be called with a single argument that
|
||||
is a Lua table containing entries mapping integers to positional arguments and
|
||||
strings to keyword arguments:
|
||||
.Bd -literal -offset indent
|
||||
zfs.sync.destroy({1="rpool@snap", defer=true})
|
||||
.Ed
|
||||
.Pp
|
||||
The Lua language allows curly braces to be used in place of parenthesis as
|
||||
syntactic sugar for this calling convention:
|
||||
.Bd -literal -offset indent
|
||||
zfs.sync.snapshot{"rpool@snap", defer=true}
|
||||
.Ed
|
||||
.Ss Function Return Values
|
||||
If an API function succeeds, it returns 0.
|
||||
If it fails, it returns an error code and the channel program continues
|
||||
executing.
|
||||
API functions do not generate Fatal Errors except in the case of an
|
||||
unrecoverable internal file system error.
|
||||
.Pp
|
||||
In addition to returning an error code, some functions also return extra
|
||||
details describing what caused the error.
|
||||
This extra description is given as a second return value, and will always be a
|
||||
Lua table, or Nil if no error details were returned.
|
||||
Different keys will exist in the error details table depending on the function
|
||||
and error case.
|
||||
Any such function may be called expecting a single return value:
|
||||
.Bd -literal -offset indent
|
||||
errno = zfs.sync.promote(dataset)
|
||||
.Ed
|
||||
.Pp
|
||||
Or, the error details can be retrieved:
|
||||
.Bd -literal -offset indent
|
||||
errno, details = zfs.sync.promote(dataset)
|
||||
if (errno == EEXIST) then
|
||||
assert(details ~= Nil)
|
||||
list_of_conflicting_snapshots = details
|
||||
end
|
||||
.Ed
|
||||
.Pp
|
||||
The following global aliases for API function error return codes are defined
|
||||
for use in channel programs:
|
||||
.Bd -literal -offset indent
|
||||
EPERM ECHILD ENODEV ENOSPC
|
||||
ENOENT EAGAIN ENOTDIR ESPIPE
|
||||
ESRCH ENOMEM EISDIR EROFS
|
||||
EINTR EACCES EINVAL EMLINK
|
||||
EIO EFAULT ENFILE EPIPE
|
||||
ENXIO ENOTBLK EMFILE EDOM
|
||||
E2BIG EBUSY ENOTTY ERANGE
|
||||
ENOEXEC EEXIST ETXTBSY EDQUOT
|
||||
EBADF EXDEV EFBIG
|
||||
.Ed
|
||||
.Ss API Functions
|
||||
For detailed descriptions of the exact behavior of any zfs administrative
|
||||
operations, see the main
|
||||
.Xr zfs 1
|
||||
manual page.
|
||||
.Bl -tag -width "xx"
|
||||
.It Em zfs.debug(msg)
|
||||
Record a debug message in the zfs_dbgmsg log.
|
||||
A log of these messages can be printed via mdb's "::zfs_dbgmsg" command, or
|
||||
can be monitored live by running:
|
||||
.Bd -literal -offset indent
|
||||
dtrace -n 'zfs-dbgmsg{trace(stringof(arg0))}'
|
||||
.Ed
|
||||
.Pp
|
||||
msg (string)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Debug message to be printed.
|
||||
.Ed
|
||||
.It Em zfs.exists(dataset)
|
||||
Returns true if the given dataset exists, or false if it doesn't.
|
||||
A fatal error will be thrown if the dataset is not in the target pool.
|
||||
That is, in a channel program running on rpool,
|
||||
zfs.exists("rpool/nonexistent_fs") returns false, but
|
||||
zfs.exists("somepool/fs_that_may_exist") will error.
|
||||
.Pp
|
||||
dataset (string)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Dataset to check for existence.
|
||||
Must be in the target pool.
|
||||
.Ed
|
||||
.It Em zfs.get_prop(dataset, property)
|
||||
Returns two values.
|
||||
First, a string, number or table containing the property value for the given
|
||||
dataset.
|
||||
Second, a string containing the source of the property (i.e. the name of the
|
||||
dataset in which it was set or nil if it is readonly).
|
||||
Throws a Lua error if the dataset is invalid or the property doesn't exist.
|
||||
Note that Lua only supports int64 number types whereas ZFS number properties
|
||||
are uint64.
|
||||
This means very large values (like guid) may wrap around and appear negative.
|
||||
.Pp
|
||||
dataset (string)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Filesystem or snapshot path to retrieve properties from.
|
||||
.Ed
|
||||
.Pp
|
||||
property (string)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Name of property to retrieve.
|
||||
All filesystem, snapshot and volume properties are supported except
|
||||
for 'mounted' and 'iscsioptions.'
|
||||
Also supports the 'written@snap' and 'written#bookmark' properties and
|
||||
the '<user|group><quota|used>@id' properties, though the id must be in numeric
|
||||
form.
|
||||
.Ed
|
||||
.El
|
||||
.Bl -tag -width "xx"
|
||||
.It Sy zfs.sync submodule
|
||||
The sync submodule contains functions that modify the on-disk state.
|
||||
They are executed in "syncing context".
|
||||
.Pp
|
||||
The available sync submodule functions are as follows:
|
||||
.Bl -tag -width "xx"
|
||||
.It Em zfs.sync.destroy(dataset, [defer=true|false])
|
||||
Destroy the given dataset.
|
||||
Returns 0 on successful destroy, or a nonzero error code if the dataset could
|
||||
not be destroyed (for example, if the dataset has any active children or
|
||||
clones).
|
||||
.Pp
|
||||
dataset (string)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Filesystem or snapshot to be destroyed.
|
||||
.Ed
|
||||
.Pp
|
||||
[optional] defer (boolean)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Valid only for destroying snapshots.
|
||||
If set to true, and the snapshot has holds or clones, allows the snapshot to be
|
||||
marked for deferred deletion rather than failing.
|
||||
.Ed
|
||||
.It Em zfs.sync.promote(dataset)
|
||||
Promote the given clone to a filesystem.
|
||||
Returns 0 on successful promotion, or a nonzero error code otherwise.
|
||||
If EEXIST is returned, the second return value will be an array of the clone's
|
||||
snapshots whose names collide with snapshots of the parent filesystem.
|
||||
.Pp
|
||||
dataset (string)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Clone to be promoted.
|
||||
.Ed
|
||||
.It Em zfs.sync.rollback(filesystem)
|
||||
Rollback to the previous snapshot for a dataset.
|
||||
Returns 0 on successful rollback, or a nonzero error code otherwise.
|
||||
Rollbacks can be performed on filesystems or zvols, but not on snapshots
|
||||
or mounted datasets.
|
||||
EBUSY is returned in the case where the filesystem is mounted.
|
||||
.Pp
|
||||
filesystem (string)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Filesystem to rollback.
|
||||
.Ed
|
||||
.It Em zfs.sync.snapshot(dataset)
|
||||
Create a snapshot of a filesystem.
|
||||
Returns 0 if the snapshot was successfully created,
|
||||
and a nonzero error code otherwise.
|
||||
.Pp
|
||||
Note: Taking a snapshot will fail on any pool older than legacy version 27.
|
||||
To enable taking snapshots from ZCP scripts, the pool must be upgraded.
|
||||
.Pp
|
||||
dataset (string)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Name of snapshot to create.
|
||||
.Ed
|
||||
.El
|
||||
.It Sy zfs.check submodule
|
||||
For each function in the zfs.sync submodule, there is a corresponding zfs.check
|
||||
function which performs a "dry run" of the same operation.
|
||||
Each takes the same arguments as its zfs.sync counterpart and returns 0 if the
|
||||
operation would succeed, or a non-zero error code if it would fail, along with
|
||||
any other error details.
|
||||
That is, each has the same behavior as the corresponding sync function except
|
||||
for actually executing the requested change.
|
||||
For example,
|
||||
.Em zfs.check.destroy("fs")
|
||||
returns 0 if
|
||||
.Em zfs.sync.destroy("fs")
|
||||
would successfully destroy the dataset.
|
||||
.Pp
|
||||
The available zfs.check functions are:
|
||||
.Bl -tag -width "xx"
|
||||
.It Em zfs.check.destroy(dataset, [defer=true|false])
|
||||
.It Em zfs.check.promote(dataset)
|
||||
.It Em zfs.check.rollback(filesystem)
|
||||
.It Em zfs.check.snapshot(dataset)
|
||||
.El
|
||||
.It Sy zfs.list submodule
|
||||
The zfs.list submodule provides functions for iterating over datasets and
|
||||
properties.
|
||||
Rather than returning tables, these functions act as Lua iterators, and are
|
||||
generally used as follows:
|
||||
.Bd -literal -offset indent
|
||||
for child in zfs.list.children("rpool") do
|
||||
...
|
||||
end
|
||||
.Ed
|
||||
.Pp
|
||||
The available zfs.list functions are:
|
||||
.Bl -tag -width "xx"
|
||||
.It Em zfs.list.clones(snapshot)
|
||||
Iterate through all clones of the given snapshot.
|
||||
.Pp
|
||||
snapshot (string)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Must be a valid snapshot path in the current pool.
|
||||
.Ed
|
||||
.It Em zfs.list.snapshots(dataset)
|
||||
Iterate through all snapshots of the given dataset.
|
||||
Each snapshot is returned as a string containing the full dataset name, e.g.
|
||||
"pool/fs@snap".
|
||||
.Pp
|
||||
dataset (string)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Must be a valid filesystem or volume.
|
||||
.Ed
|
||||
.It Em zfs.list.children(dataset)
|
||||
Iterate through all direct children of the given dataset.
|
||||
Each child is returned as a string containing the full dataset name, e.g.
|
||||
"pool/fs/child".
|
||||
.Pp
|
||||
dataset (string)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Must be a valid filesystem or volume.
|
||||
.Ed
|
||||
.It Em zfs.list.properties(dataset)
|
||||
Iterate through all user properties for the given dataset.
|
||||
.Pp
|
||||
dataset (string)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Must be a valid filesystem, snapshot, or volume.
|
||||
.Ed
|
||||
.It Em zfs.list.system_properties(dataset)
|
||||
Returns an array of strings, the names of the valid system (non-user defined)
|
||||
properties for the given dataset.
|
||||
Throws a Lua error if the dataset is invalid.
|
||||
.Pp
|
||||
dataset (string)
|
||||
.Bd -ragged -compact -offset "xxxx"
|
||||
Must be a valid filesystem, snapshot or volume.
|
||||
.Ed
|
||||
.El
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
.Ss Example 1
|
||||
The following channel program recursively destroys a filesystem and all its
|
||||
snapshots and children in a naive manner.
|
||||
Note that this does not involve any error handling or reporting.
|
||||
.Bd -literal -offset indent
|
||||
function destroy_recursive(root)
|
||||
for child in zfs.list.children(root) do
|
||||
destroy_recursive(child)
|
||||
end
|
||||
for snap in zfs.list.snapshots(root) do
|
||||
zfs.sync.destroy(snap)
|
||||
end
|
||||
zfs.sync.destroy(root)
|
||||
end
|
||||
destroy_recursive("pool/somefs")
|
||||
.Ed
|
||||
.Ss Example 2
|
||||
A more verbose and robust version of the same channel program, which
|
||||
properly detects and reports errors, and also takes the dataset to destroy
|
||||
as a command line argument, would be as follows:
|
||||
.Bd -literal -offset indent
|
||||
succeeded = {}
|
||||
failed = {}
|
||||
|
||||
function destroy_recursive(root)
|
||||
for child in zfs.list.children(root) do
|
||||
destroy_recursive(child)
|
||||
end
|
||||
for snap in zfs.list.snapshots(root) do
|
||||
err = zfs.sync.destroy(snap)
|
||||
if (err ~= 0) then
|
||||
failed[snap] = err
|
||||
else
|
||||
succeeded[snap] = err
|
||||
end
|
||||
end
|
||||
err = zfs.sync.destroy(root)
|
||||
if (err ~= 0) then
|
||||
failed[root] = err
|
||||
else
|
||||
succeeded[root] = err
|
||||
end
|
||||
end
|
||||
|
||||
args = ...
|
||||
argv = args["argv"]
|
||||
|
||||
destroy_recursive(argv[1])
|
||||
|
||||
results = {}
|
||||
results["succeeded"] = succeeded
|
||||
results["failed"] = failed
|
||||
return results
|
||||
.Ed
|
||||
.Ss Example 3
|
||||
The following function performs a forced promote operation by attempting to
|
||||
promote the given clone and destroying any conflicting snapshots.
|
||||
.Bd -literal -offset indent
|
||||
function force_promote(ds)
|
||||
errno, details = zfs.check.promote(ds)
|
||||
if (errno == EEXIST) then
|
||||
assert(details ~= Nil)
|
||||
for i, snap in ipairs(details) do
|
||||
zfs.sync.destroy(ds .. "@" .. snap)
|
||||
end
|
||||
elseif (errno ~= 0) then
|
||||
return errno
|
||||
end
|
||||
return zfs.sync.promote(ds)
|
||||
end
|
||||
.Ed
|
@ -286,6 +286,12 @@
|
||||
.Ar snapshot
|
||||
.Op Ar snapshot Ns | Ns Ar filesystem
|
||||
.Nm
|
||||
.Cm program
|
||||
.Op Fl t Ar timeout
|
||||
.Op Fl m Ar memory_limit
|
||||
.Ar pool script
|
||||
.Op Ar arg1 No ...
|
||||
.Nm
|
||||
.Cm jail
|
||||
.Ar jailid Ns | Ns Ar jailname filesystem
|
||||
.Nm
|
||||
@ -3287,6 +3293,48 @@ Display the path's inode change time as the first column of output.
|
||||
.El
|
||||
.It Xo
|
||||
.Nm
|
||||
.Cm program
|
||||
.Op Fl t Ar timeout
|
||||
.Op Fl m Ar memory_limit
|
||||
.Ar pool script
|
||||
.Op Ar arg1 No ...
|
||||
.Xc
|
||||
.Pp
|
||||
Executes
|
||||
.Ar script
|
||||
as a ZFS channel program on
|
||||
.Ar pool .
|
||||
The ZFS channel
|
||||
program interface allows ZFS administrative operations to be run
|
||||
programmatically via a Lua script.
|
||||
The entire script is executed atomically, with no other administrative
|
||||
operations taking effect concurrently.
|
||||
A library of ZFS calls is made available to channel program scripts.
|
||||
Channel programs may only be run with root privileges.
|
||||
.Pp
|
||||
For full documentation of the ZFS channel program interface, see the manual
|
||||
page for
|
||||
.Xr zfs-program 8 .
|
||||
.Bl -tag -width indent
|
||||
.It Fl t Ar timeout
|
||||
Execution time limit, in milliseconds.
|
||||
If a channel program executes for longer than the provided timeout, it will
|
||||
be stopped and an error will be returned.
|
||||
The default timeout is 1000 ms, and can be set to a maximum of 10000 ms.
|
||||
.It Fl m Ar memory-limit
|
||||
Memory limit, in bytes.
|
||||
If a channel program attempts to allocate more memory than the given limit,
|
||||
it will be stopped and an error returned.
|
||||
The default memory limit is 10 MB, and can be set to a maximum of 100 MB.
|
||||
.Pp
|
||||
All remaining argument strings are passed directly to the channel program as
|
||||
arguments.
|
||||
See
|
||||
.Xr zfs-program 8
|
||||
for more information.
|
||||
.El
|
||||
.It Xo
|
||||
.Nm
|
||||
.Cm jail
|
||||
.Ar jailid filesystem
|
||||
.Xc
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
|
||||
* Copyright 2012 Milan Jurik. All rights reserved.
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
|
||||
@ -51,6 +51,7 @@
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/debug.h>
|
||||
#include <sys/list.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <sys/mnttab.h>
|
||||
@ -111,6 +112,7 @@ static int zfs_do_diff(int argc, char **argv);
|
||||
static int zfs_do_jail(int argc, char **argv);
|
||||
static int zfs_do_unjail(int argc, char **argv);
|
||||
static int zfs_do_bookmark(int argc, char **argv);
|
||||
static int zfs_do_channel_program(int argc, char **argv);
|
||||
|
||||
/*
|
||||
* Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
|
||||
@ -160,6 +162,7 @@ typedef enum {
|
||||
HELP_RELEASE,
|
||||
HELP_DIFF,
|
||||
HELP_BOOKMARK,
|
||||
HELP_CHANNEL_PROGRAM,
|
||||
} zfs_help_t;
|
||||
|
||||
typedef struct zfs_command {
|
||||
@ -187,6 +190,7 @@ static zfs_command_t command_table[] = {
|
||||
{ "promote", zfs_do_promote, HELP_PROMOTE },
|
||||
{ "rename", zfs_do_rename, HELP_RENAME },
|
||||
{ "bookmark", zfs_do_bookmark, HELP_BOOKMARK },
|
||||
{ "program", zfs_do_channel_program, HELP_CHANNEL_PROGRAM },
|
||||
{ NULL },
|
||||
{ "list", zfs_do_list, HELP_LIST },
|
||||
{ NULL },
|
||||
@ -340,6 +344,10 @@ get_usage(zfs_help_t idx)
|
||||
"[snapshot|filesystem]\n"));
|
||||
case HELP_BOOKMARK:
|
||||
return (gettext("\tbookmark <snapshot> <bookmark>\n"));
|
||||
case HELP_CHANNEL_PROGRAM:
|
||||
return (gettext("\tprogram [-t <instruction limit>] "
|
||||
"[-m <memory limit (b)>] <pool> <program file> "
|
||||
"[lua args...]\n"));
|
||||
}
|
||||
|
||||
abort();
|
||||
@ -368,6 +376,18 @@ safe_malloc(size_t size)
|
||||
return (data);
|
||||
}
|
||||
|
||||
void *
|
||||
safe_realloc(void *data, size_t size)
|
||||
{
|
||||
void *newp;
|
||||
if ((newp = realloc(data, size)) == NULL) {
|
||||
free(data);
|
||||
nomem();
|
||||
}
|
||||
|
||||
return (newp);
|
||||
}
|
||||
|
||||
static char *
|
||||
safe_strdup(char *str)
|
||||
{
|
||||
@ -7101,6 +7121,194 @@ zfs_do_bookmark(int argc, char **argv)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_do_channel_program(int argc, char **argv)
|
||||
{
|
||||
int ret, fd;
|
||||
char c;
|
||||
char *progbuf, *filename, *poolname;
|
||||
size_t progsize, progread;
|
||||
nvlist_t *outnvl;
|
||||
uint64_t instrlimit = ZCP_DEFAULT_INSTRLIMIT;
|
||||
uint64_t memlimit = ZCP_DEFAULT_MEMLIMIT;
|
||||
zpool_handle_t *zhp;
|
||||
|
||||
/* check options */
|
||||
while (-1 !=
|
||||
(c = getopt(argc, argv, "t:(instr-limit)m:(memory-limit)"))) {
|
||||
switch (c) {
|
||||
case 't':
|
||||
case 'm': {
|
||||
uint64_t arg;
|
||||
char *endp;
|
||||
|
||||
errno = 0;
|
||||
arg = strtoull(optarg, &endp, 0);
|
||||
if (errno != 0 || *endp != '\0') {
|
||||
(void) fprintf(stderr, gettext(
|
||||
"invalid argument "
|
||||
"'%s': expected integer\n"), optarg);
|
||||
goto usage;
|
||||
}
|
||||
|
||||
if (c == 't') {
|
||||
if (arg > ZCP_MAX_INSTRLIMIT || arg == 0) {
|
||||
(void) fprintf(stderr, gettext(
|
||||
"Invalid instruction limit: "
|
||||
"%s\n"), optarg);
|
||||
return (1);
|
||||
} else {
|
||||
instrlimit = arg;
|
||||
}
|
||||
} else {
|
||||
ASSERT3U(c, ==, 'm');
|
||||
if (arg > ZCP_MAX_MEMLIMIT || arg == 0) {
|
||||
(void) fprintf(stderr, gettext(
|
||||
"Invalid memory limit: "
|
||||
"%s\n"), optarg);
|
||||
return (1);
|
||||
} else {
|
||||
memlimit = arg;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '?':
|
||||
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
|
||||
optopt);
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 2) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("invalid number of arguments\n"));
|
||||
goto usage;
|
||||
}
|
||||
|
||||
poolname = argv[0];
|
||||
filename = argv[1];
|
||||
if (strcmp(filename, "-") == 0) {
|
||||
fd = 0;
|
||||
filename = "standard input";
|
||||
} else if ((fd = open(filename, O_RDONLY)) < 0) {
|
||||
(void) fprintf(stderr, gettext("cannot open '%s': %s\n"),
|
||||
filename, strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
|
||||
if ((zhp = zpool_open(g_zfs, poolname)) == NULL) {
|
||||
(void) fprintf(stderr, gettext("cannot open pool '%s'"),
|
||||
poolname);
|
||||
return (1);
|
||||
}
|
||||
zpool_close(zhp);
|
||||
|
||||
/*
|
||||
* Read in the channel program, expanding the program buffer as
|
||||
* necessary.
|
||||
*/
|
||||
progread = 0;
|
||||
progsize = 1024;
|
||||
progbuf = safe_malloc(progsize);
|
||||
do {
|
||||
ret = read(fd, progbuf + progread, progsize - progread);
|
||||
progread += ret;
|
||||
if (progread == progsize && ret > 0) {
|
||||
progsize *= 2;
|
||||
progbuf = safe_realloc(progbuf, progsize);
|
||||
}
|
||||
} while (ret > 0);
|
||||
|
||||
if (fd != 0)
|
||||
(void) close(fd);
|
||||
if (ret < 0) {
|
||||
free(progbuf);
|
||||
(void) fprintf(stderr,
|
||||
gettext("cannot read '%s': %s\n"),
|
||||
filename, strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
progbuf[progread] = '\0';
|
||||
|
||||
/*
|
||||
* Any remaining arguments are passed as arguments to the lua script as
|
||||
* a string array:
|
||||
* {
|
||||
* "argv" -> [ "arg 1", ... "arg n" ],
|
||||
* }
|
||||
*/
|
||||
nvlist_t *argnvl = fnvlist_alloc();
|
||||
fnvlist_add_string_array(argnvl, ZCP_ARG_CLIARGV, argv + 2, argc - 2);
|
||||
|
||||
ret = lzc_channel_program(poolname, progbuf, instrlimit, memlimit,
|
||||
argnvl, &outnvl);
|
||||
|
||||
if (ret != 0) {
|
||||
/*
|
||||
* On error, report the error message handed back by lua if one
|
||||
* exists. Otherwise, generate an appropriate error message,
|
||||
* falling back on strerror() for an unexpected return code.
|
||||
*/
|
||||
char *errstring = NULL;
|
||||
if (nvlist_exists(outnvl, ZCP_RET_ERROR)) {
|
||||
(void) nvlist_lookup_string(outnvl,
|
||||
ZCP_RET_ERROR, &errstring);
|
||||
if (errstring == NULL)
|
||||
errstring = strerror(ret);
|
||||
} else {
|
||||
switch (ret) {
|
||||
case EINVAL:
|
||||
errstring =
|
||||
"Invalid instruction or memory limit.";
|
||||
break;
|
||||
case ENOMEM:
|
||||
errstring = "Return value too large.";
|
||||
break;
|
||||
case ENOSPC:
|
||||
errstring = "Memory limit exhausted.";
|
||||
break;
|
||||
#ifdef illumos
|
||||
case ETIME:
|
||||
#else
|
||||
case ETIMEDOUT:
|
||||
#endif
|
||||
errstring = "Timed out.";
|
||||
break;
|
||||
case EPERM:
|
||||
errstring = "Permission denied. Channel "
|
||||
"programs must be run as root.";
|
||||
break;
|
||||
default:
|
||||
errstring = strerror(ret);
|
||||
}
|
||||
}
|
||||
(void) fprintf(stderr,
|
||||
gettext("Channel program execution failed:\n%s\n"),
|
||||
errstring);
|
||||
} else {
|
||||
(void) printf("Channel program fully executed ");
|
||||
if (nvlist_empty(outnvl)) {
|
||||
(void) printf("with no return value.\n");
|
||||
} else {
|
||||
(void) printf("with return value:\n");
|
||||
dump_nvlist(outnvl, 4);
|
||||
}
|
||||
}
|
||||
|
||||
free(progbuf);
|
||||
fnvlist_free(outnvl);
|
||||
fnvlist_free(argnvl);
|
||||
return (ret != 0);
|
||||
|
||||
usage:
|
||||
usage(B_FALSE);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012 by Frederik Wessels. All rights reserved.
|
||||
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
* Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
|
||||
@ -705,7 +705,7 @@ zpool_do_labelclear(int argc, char **argv)
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (zpool_read_label(fd, &config) != 0 || config == NULL) {
|
||||
if (zpool_read_label(fd, &config) != 0) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("failed to read label from %s\n"), vdev);
|
||||
return (1);
|
||||
@ -5254,6 +5254,11 @@ get_history_one(zpool_handle_t *zhp, void *data)
|
||||
dump_nvlist(fnvlist_lookup_nvlist(rec,
|
||||
ZPOOL_HIST_OUTPUT_NVL), 8);
|
||||
}
|
||||
if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
|
||||
(void) printf(" errno: %lld\n",
|
||||
fnvlist_lookup_int64(rec,
|
||||
ZPOOL_HIST_ERRNO));
|
||||
}
|
||||
} else {
|
||||
if (!cb->internal)
|
||||
continue;
|
||||
|
@ -25,6 +25,7 @@
|
||||
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||
* Copyright (c) 2014 Integros [integros.com]
|
||||
* Copyright 2017 Joyent, Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -125,6 +126,7 @@
|
||||
#include <errno.h>
|
||||
#include <sys/fs/zfs.h>
|
||||
#include <libnvpair.h>
|
||||
#include <libcmdutils.h>
|
||||
|
||||
static int ztest_fd_data = -1;
|
||||
static int ztest_fd_rand = -1;
|
||||
@ -556,12 +558,13 @@ usage(boolean_t requested)
|
||||
{
|
||||
const ztest_shared_opts_t *zo = &ztest_opts_defaults;
|
||||
|
||||
char nice_vdev_size[10];
|
||||
char nice_gang_bang[10];
|
||||
char nice_vdev_size[NN_NUMBUF_SZ];
|
||||
char nice_gang_bang[NN_NUMBUF_SZ];
|
||||
FILE *fp = requested ? stdout : stderr;
|
||||
|
||||
nicenum(zo->zo_vdev_size, nice_vdev_size);
|
||||
nicenum(zo->zo_metaslab_gang_bang, nice_gang_bang);
|
||||
nicenum(zo->zo_vdev_size, nice_vdev_size, sizeof (nice_vdev_size));
|
||||
nicenum(zo->zo_metaslab_gang_bang, nice_gang_bang,
|
||||
sizeof (nice_gang_bang));
|
||||
|
||||
(void) fprintf(fp, "Usage: %s\n"
|
||||
"\t[-v vdevs (default: %llu)]\n"
|
||||
@ -583,6 +586,8 @@ usage(boolean_t requested)
|
||||
"\t[-F freezeloops (default: %llu)] max loops in spa_freeze()\n"
|
||||
"\t[-P passtime (default: %llu sec)] time per pass\n"
|
||||
"\t[-B alt_ztest (default: <none>)] alternate ztest path\n"
|
||||
"\t[-o variable=value] ... set global variable to an unsigned\n"
|
||||
"\t 32-bit integer value\n"
|
||||
"\t[-h] (print help)\n"
|
||||
"",
|
||||
zo->zo_pool,
|
||||
@ -618,7 +623,7 @@ process_options(int argc, char **argv)
|
||||
bcopy(&ztest_opts_defaults, zo, sizeof (*zo));
|
||||
|
||||
while ((opt = getopt(argc, argv,
|
||||
"v:s:a:m:r:R:d:t:g:i:k:p:f:VET:P:hF:B:")) != EOF) {
|
||||
"v:s:a:m:r:R:d:t:g:i:k:p:f:VET:P:hF:B:o:")) != EOF) {
|
||||
value = 0;
|
||||
switch (opt) {
|
||||
case 'v':
|
||||
@ -705,6 +710,10 @@ process_options(int argc, char **argv)
|
||||
case 'B':
|
||||
(void) strlcpy(altdir, optarg, sizeof (altdir));
|
||||
break;
|
||||
case 'o':
|
||||
if (set_global_var(optarg) != 0)
|
||||
usage(B_FALSE);
|
||||
break;
|
||||
case 'h':
|
||||
usage(B_TRUE);
|
||||
break;
|
||||
@ -1825,13 +1834,14 @@ ztest_get_done(zgd_t *zgd, int error)
|
||||
ztest_object_unlock(zd, object);
|
||||
|
||||
if (error == 0 && zgd->zgd_bp)
|
||||
zil_add_block(zgd->zgd_zilog, zgd->zgd_bp);
|
||||
zil_lwb_add_block(zgd->zgd_lwb, zgd->zgd_bp);
|
||||
|
||||
umem_free(zgd, sizeof (*zgd));
|
||||
}
|
||||
|
||||
static int
|
||||
ztest_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
|
||||
ztest_get_data(void *arg, lr_write_t *lr, char *buf, struct lwb *lwb,
|
||||
zio_t *zio)
|
||||
{
|
||||
ztest_ds_t *zd = arg;
|
||||
objset_t *os = zd->zd_os;
|
||||
@ -1845,6 +1855,10 @@ ztest_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
|
||||
zgd_t *zgd;
|
||||
int error;
|
||||
|
||||
ASSERT3P(lwb, !=, NULL);
|
||||
ASSERT3P(zio, !=, NULL);
|
||||
ASSERT3U(size, !=, 0);
|
||||
|
||||
ztest_object_lock(zd, object, RL_READER);
|
||||
error = dmu_bonus_hold(os, object, FTAG, &db);
|
||||
if (error) {
|
||||
@ -1865,7 +1879,7 @@ ztest_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
|
||||
db = NULL;
|
||||
|
||||
zgd = umem_zalloc(sizeof (*zgd), UMEM_NOFAIL);
|
||||
zgd->zgd_zilog = zd->zd_zilog;
|
||||
zgd->zgd_lwb = lwb;
|
||||
zgd->zgd_private = zd;
|
||||
|
||||
if (buf != NULL) { /* immediate write */
|
||||
@ -3147,10 +3161,10 @@ ztest_vdev_LUN_growth(ztest_ds_t *zd, uint64_t id)
|
||||
old_class_space, new_class_space);
|
||||
|
||||
if (ztest_opts.zo_verbose >= 5) {
|
||||
char oldnumbuf[6], newnumbuf[6];
|
||||
char oldnumbuf[NN_NUMBUF_SZ], newnumbuf[NN_NUMBUF_SZ];
|
||||
|
||||
nicenum(old_class_space, oldnumbuf);
|
||||
nicenum(new_class_space, newnumbuf);
|
||||
nicenum(old_class_space, oldnumbuf, sizeof (oldnumbuf));
|
||||
nicenum(new_class_space, newnumbuf, sizeof (newnumbuf));
|
||||
(void) printf("%s grew from %s to %s\n",
|
||||
spa->spa_name, oldnumbuf, newnumbuf);
|
||||
}
|
||||
@ -6193,7 +6207,7 @@ main(int argc, char **argv)
|
||||
ztest_info_t *zi;
|
||||
ztest_shared_callstate_t *zc;
|
||||
char timebuf[100];
|
||||
char numbuf[6];
|
||||
char numbuf[NN_NUMBUF_SZ];
|
||||
spa_t *spa;
|
||||
char *cmd;
|
||||
boolean_t hasalt;
|
||||
@ -6330,7 +6344,7 @@ main(int argc, char **argv)
|
||||
|
||||
now = MIN(now, zs->zs_proc_stop);
|
||||
print_time(zs->zs_proc_stop - now, timebuf);
|
||||
nicenum(zs->zs_space, numbuf);
|
||||
nicenum(zs->zs_space, numbuf, sizeof (numbuf));
|
||||
|
||||
(void) printf("Pass %3d, %8s, %3llu ENOSPC, "
|
||||
"%4.1f%% of %5s used, %3.0f%% done, %8s to go\n",
|
||||
|
130
cddl/contrib/opensolaris/lib/libcmdutils/common/nicenum.c
Normal file
130
cddl/contrib/opensolaris/lib/libcmdutils/common/nicenum.c
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2017 Jason king
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/debug.h>
|
||||
#include "libcmdutils.h"
|
||||
|
||||
/* The largest suffix that can fit, aka an exabyte (2^60 / 10^18) */
|
||||
#define INDEX_MAX (6)
|
||||
|
||||
/* Verify INDEX_MAX fits */
|
||||
CTASSERT(INDEX_MAX * 10 < sizeof (uint64_t) * 8);
|
||||
|
||||
void
|
||||
nicenum_scale(uint64_t n, size_t units, char *buf, size_t buflen,
|
||||
uint32_t flags)
|
||||
{
|
||||
uint64_t divamt = 1024;
|
||||
uint64_t divisor = 1;
|
||||
int index = 0;
|
||||
int rc = 0;
|
||||
char u;
|
||||
|
||||
if (units == 0)
|
||||
units = 1;
|
||||
|
||||
if (n > 0) {
|
||||
n *= units;
|
||||
if (n < units)
|
||||
goto overflow;
|
||||
}
|
||||
|
||||
if (flags & NN_DIVISOR_1000)
|
||||
divamt = 1000;
|
||||
|
||||
/*
|
||||
* This tries to find the suffix S(n) such that
|
||||
* S(n) <= n < S(n+1), where S(n) = 2^(n*10) | 10^(3*n)
|
||||
* (i.e. 1024/1000, 1,048,576/1,000,000, etc). Stop once S(n)
|
||||
* is the largest prefix supported (i.e. don't bother computing
|
||||
* and checking S(n+1). Since INDEX_MAX should be the largest
|
||||
* suffix that fits (currently an exabyte), S(INDEX_MAX + 1) is
|
||||
* never checked as it would overflow.
|
||||
*/
|
||||
while (index < INDEX_MAX) {
|
||||
uint64_t newdiv = divisor * divamt;
|
||||
|
||||
/* CTASSERT() guarantee these never trip */
|
||||
VERIFY3U(newdiv, >=, divamt);
|
||||
VERIFY3U(newdiv, >=, divisor);
|
||||
|
||||
if (n < newdiv)
|
||||
break;
|
||||
|
||||
divisor = newdiv;
|
||||
index++;
|
||||
}
|
||||
|
||||
u = " KMGTPE"[index];
|
||||
|
||||
if (index == 0) {
|
||||
rc = snprintf(buf, buflen, "%llu", n);
|
||||
} else if (n % divisor == 0) {
|
||||
/*
|
||||
* If this is an even multiple of the base, always display
|
||||
* without any decimal precision.
|
||||
*/
|
||||
rc = snprintf(buf, buflen, "%llu%c", n / divisor, u);
|
||||
} else {
|
||||
/*
|
||||
* We want to choose a precision that reflects the best choice
|
||||
* for fitting in 5 characters. This can get rather tricky
|
||||
* when we have numbers that are very close to an order of
|
||||
* magnitude. For example, when displaying 10239 (which is
|
||||
* really 9.999K), we want only a single place of precision
|
||||
* for 10.0K. We could develop some complex heuristics for
|
||||
* this, but it's much easier just to try each combination
|
||||
* in turn.
|
||||
*/
|
||||
int i;
|
||||
for (i = 2; i >= 0; i--) {
|
||||
if ((rc = snprintf(buf, buflen, "%.*f%c", i,
|
||||
(double)n / divisor, u)) <= 5)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc + 1 > buflen || rc < 0)
|
||||
goto overflow;
|
||||
|
||||
return;
|
||||
|
||||
overflow:
|
||||
/* prefer a more verbose message if possible */
|
||||
if (buflen > 10)
|
||||
(void) strlcpy(buf, "<overflow>", buflen);
|
||||
else
|
||||
(void) strlcpy(buf, "??", buflen);
|
||||
}
|
||||
|
||||
void
|
||||
nicenum(uint64_t num, char *buf, size_t buflen)
|
||||
{
|
||||
nicenum_scale(num, 1, buf, buflen, 0);
|
||||
}
|
235
cddl/contrib/opensolaris/lib/libcmdutils/libcmdutils.h
Normal file
235
cddl/contrib/opensolaris/lib/libcmdutils/libcmdutils.h
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
*
|
||||
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
* or http://www.opensolaris.org/os/licensing.
|
||||
* See the License for the specific language governing permissions
|
||||
* and limitations under the License.
|
||||
*
|
||||
* When distributing Covered Code, include this CDDL HEADER in each
|
||||
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
* If applicable, add the following below this CDDL HEADER, with the
|
||||
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2013 RackTop Systems.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2017 Joyent, Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Declarations for the functions in libcmdutils.
|
||||
*/
|
||||
|
||||
#ifndef _LIBCMDUTILS_H
|
||||
#define _LIBCMDUTILS_H
|
||||
|
||||
#ifdef illumos
|
||||
#if !defined(_LP64) && \
|
||||
!((_FILE_OFFSET_BITS == 64) || defined(_LARGEFILE64_SOURCE))
|
||||
#error "libcmdutils.h can only be used in a largefile compilation environment"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is a private header file. Applications should not directly include
|
||||
* this file.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <libintl.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#ifdef illumos
|
||||
#include <attr.h>
|
||||
#endif
|
||||
#include <sys/avl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <libnvpair.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* extended system attribute support */
|
||||
#define _NOT_SATTR 0
|
||||
#define _RO_SATTR 1
|
||||
#define _RW_SATTR 2
|
||||
|
||||
#define MAXMAPSIZE (1024*1024*8) /* map at most 8MB */
|
||||
#define SMALLFILESIZE (32*1024) /* don't use mmap on little file */
|
||||
|
||||
/* Type used for a node containing a device id and inode number */
|
||||
|
||||
#if defined(_LP64) || (_FILE_OFFSET_BITS == 64)
|
||||
typedef struct tree_node {
|
||||
dev_t node_dev;
|
||||
ino_t node_ino;
|
||||
avl_node_t avl_link;
|
||||
} tree_node_t;
|
||||
#else
|
||||
typedef struct tree_node {
|
||||
dev_t node_dev;
|
||||
ino64_t node_ino;
|
||||
avl_node_t avl_link;
|
||||
} tree_node_t;
|
||||
#endif
|
||||
|
||||
/* extended system attribute support */
|
||||
|
||||
/* Determine if a file is the name of an extended system attribute file */
|
||||
extern int sysattr_type(char *);
|
||||
|
||||
/* Determine if the underlying file system supports system attributes */
|
||||
extern int sysattr_support(char *, int);
|
||||
|
||||
/* Copies the content of the source file to the target file */
|
||||
#if defined(_LP64) || (_FILE_OFFSET_BITS == 64)
|
||||
extern int writefile(int, int, char *, char *, char *, char *,
|
||||
struct stat *, struct stat *);
|
||||
#else
|
||||
extern int writefile(int, int, char *, char *, char *, char *,
|
||||
struct stat64 *, struct stat64 *);
|
||||
#endif
|
||||
|
||||
/* Gets file descriptors of the source and target attribute files */
|
||||
extern int get_attrdirs(int, int, char *, int *, int *);
|
||||
|
||||
/* Move extended attribute and extended system attribute */
|
||||
extern int mv_xattrs(char *, char *, char *, int, int);
|
||||
|
||||
/* Returns non default extended system attribute list */
|
||||
extern nvlist_t *sysattr_list(char *, int, char *);
|
||||
|
||||
|
||||
|
||||
/* avltree */
|
||||
|
||||
/*
|
||||
* Used to compare two nodes. We are attempting to match the 1st
|
||||
* argument (node) against the 2nd argument (a node which
|
||||
* is already in the search tree).
|
||||
*/
|
||||
|
||||
extern int tnode_compare(const void *, const void *);
|
||||
|
||||
/*
|
||||
* Used to add a single node (containing the input device id and
|
||||
* inode number) to the specified search tree. The calling
|
||||
* application must set the tree pointer to NULL before calling
|
||||
* add_tnode() for the first time.
|
||||
*/
|
||||
#if defined(_LP64) || (_FILE_OFFSET_BITS == 64)
|
||||
extern int add_tnode(avl_tree_t **, dev_t, ino_t);
|
||||
#else
|
||||
extern int add_tnode(avl_tree_t **, dev_t, ino64_t);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Used to destroy a whole tree (all nodes) without rebalancing.
|
||||
* The calling application is responsible for setting the tree
|
||||
* pointer to NULL upon return.
|
||||
*/
|
||||
extern void destroy_tree(avl_tree_t *);
|
||||
|
||||
|
||||
|
||||
/* user/group id helpers */
|
||||
|
||||
/*
|
||||
* Used to get the next available user id in given range.
|
||||
*/
|
||||
extern int findnextuid(uid_t, uid_t, uid_t *);
|
||||
|
||||
/*
|
||||
* Used to get the next available group id in given range.
|
||||
*/
|
||||
extern int findnextgid(gid_t, gid_t, gid_t *);
|
||||
|
||||
|
||||
|
||||
/* dynamic string utilities */
|
||||
|
||||
typedef struct custr custr_t;
|
||||
|
||||
/*
|
||||
* Allocate and free a "custr_t" dynamic string object. Returns 0 on success
|
||||
* and -1 otherwise.
|
||||
*/
|
||||
extern int custr_alloc(custr_t **);
|
||||
extern void custr_free(custr_t *);
|
||||
|
||||
/*
|
||||
* Allocate a "custr_t" dynamic string object that operates on a fixed external
|
||||
* buffer.
|
||||
*/
|
||||
extern int custr_alloc_buf(custr_t **, void *, size_t);
|
||||
|
||||
/*
|
||||
* Append a single character, or a NUL-terminated string of characters, to a
|
||||
* dynamic string. Returns 0 on success and -1 otherwise. The dynamic string
|
||||
* will be unmodified if the function returns -1.
|
||||
*/
|
||||
extern int custr_appendc(custr_t *, char);
|
||||
extern int custr_append(custr_t *, const char *);
|
||||
|
||||
/*
|
||||
* Append a format string and arguments as though the contents were being parsed
|
||||
* through snprintf. Returns 0 on success and -1 otherwise. The dynamic string
|
||||
* will be unmodified if the function returns -1.
|
||||
*/
|
||||
extern int custr_append_printf(custr_t *, const char *, ...);
|
||||
extern int custr_append_vprintf(custr_t *, const char *, va_list);
|
||||
|
||||
/*
|
||||
* Determine the length in bytes, not including the NUL terminator, of the
|
||||
* dynamic string.
|
||||
*/
|
||||
extern size_t custr_len(custr_t *);
|
||||
|
||||
/*
|
||||
* Clear the contents of a dynamic string. Does not free the underlying
|
||||
* memory.
|
||||
*/
|
||||
extern void custr_reset(custr_t *);
|
||||
|
||||
/*
|
||||
* Retrieve a const pointer to a NUL-terminated string version of the contents
|
||||
* of the dynamic string. Storage for this string should not be freed, and
|
||||
* the pointer will be invalidated by any mutations to the dynamic string.
|
||||
*/
|
||||
extern const char *custr_cstr(custr_t *str);
|
||||
|
||||
#define NN_DIVISOR_1000 (1U << 0)
|
||||
|
||||
/* Minimum size for the output of nicenum, including NULL */
|
||||
#define NN_NUMBUF_SZ (6)
|
||||
|
||||
void nicenum(uint64_t, char *, size_t);
|
||||
void nicenum_scale(uint64_t, size_t, char *, size_t, uint32_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIBCMDUTILS_H */
|
@ -39,7 +39,8 @@ data contained in each file has information about the layout and
|
||||
sizes of C types, including intrinsic types, enumerations, structures,
|
||||
typedefs, and unions, that are used by the corresponding
|
||||
.Sy ELF
|
||||
object. The
|
||||
object.
|
||||
The
|
||||
.Nm
|
||||
data may also include information about the types of global objects and
|
||||
the return type and arguments of functions in the symbol table.
|
||||
@ -51,41 +52,43 @@ file itself, it may also be referred to as a
|
||||
.Nm
|
||||
.Sy container .
|
||||
.Lp
|
||||
On illumos systems,
|
||||
On
|
||||
.Fx
|
||||
systems,
|
||||
.Nm
|
||||
data is consumed by multiple programs. It can be used by the modular
|
||||
debugger,
|
||||
.Xr mdb 1 ,
|
||||
as well as by
|
||||
.Xr dtrace 1M .
|
||||
data is consumed by
|
||||
.Xr dtrace 1 .
|
||||
Programmatic access to
|
||||
.Nm
|
||||
data can be obtained through
|
||||
.Xr libctf 3LIB .
|
||||
data can be obtained through libctf.
|
||||
.Lp
|
||||
The
|
||||
.Nm
|
||||
file format is broken down into seven different sections. The first
|
||||
section is the
|
||||
file format is broken down into seven different sections.
|
||||
The first section is the
|
||||
.Sy preamble
|
||||
and
|
||||
.Sy header ,
|
||||
which describes the version of the
|
||||
.Nm
|
||||
file, links it has to other
|
||||
file, the links it has to other
|
||||
.Nm
|
||||
files, and the sizes of the other sections. The next section is the
|
||||
files, and the sizes of the other sections.
|
||||
The next section is the
|
||||
.Sy label
|
||||
section,
|
||||
which provides a way of identifying similar groups of
|
||||
.Nm
|
||||
data across multiple files. This is followed by the
|
||||
data across multiple files.
|
||||
This is followed by the
|
||||
.Sy object
|
||||
information section, which describes the type of global
|
||||
symbols. The subsequent section is the
|
||||
information section, which describes the types of global
|
||||
symbols.
|
||||
The subsequent section is the
|
||||
.Sy function
|
||||
information section, which describes the return
|
||||
types and arguments of functions. The next section is the
|
||||
types and arguments of functions.
|
||||
The next section is the
|
||||
.Sy type
|
||||
information section, which describes
|
||||
the format and layout of the C types themselves, and finally the last
|
||||
@ -106,29 +109,35 @@ A
|
||||
file may contain all of the type information that it requires, or it
|
||||
may optionally refer to another
|
||||
.Nm
|
||||
file which holds the remaining types. When a
|
||||
file which holds the remaining types.
|
||||
When a
|
||||
.Nm
|
||||
file refers to another file, it is called the
|
||||
.Sy child
|
||||
and the file it refers to is called the
|
||||
.Sy parent .
|
||||
A given file may only refer to one parent. This process is called
|
||||
A given file may only refer to one parent.
|
||||
This process is called
|
||||
.Em uniquification
|
||||
because it ensures each child only has type information that is
|
||||
unique to it. A common example of this is that most kernel modules in
|
||||
illumos are uniquified against the kernel module
|
||||
unique to it.
|
||||
A common example of this is that most kernel modules in illumos are uniquified
|
||||
against the kernel module
|
||||
.Sy genunix
|
||||
and the type information that comes from the
|
||||
.Sy IP
|
||||
module. This means that a module only has types that are unique to
|
||||
itself and the most common types in the kernel are not duplicated.
|
||||
module.
|
||||
This means that a module only has types that are unique to itself and the most
|
||||
common types in the kernel are not duplicated.
|
||||
.Sh FILE FORMAT
|
||||
This documents version
|
||||
.Em two
|
||||
of the
|
||||
.Nm
|
||||
file format. All applications and tools currently produce and operate on
|
||||
this version.
|
||||
file format.
|
||||
All applications and tools on
|
||||
.Fx
|
||||
currently produce and operate on this version.
|
||||
.Lp
|
||||
The file format can be summarized with the following image, the
|
||||
following sections will cover this in more detail.
|
||||
@ -235,26 +244,31 @@ This
|
||||
.Sy preamble
|
||||
defines the version of the
|
||||
.Nm
|
||||
file which defines the format of the rest of the header. While the
|
||||
header may change in subsequent versions, the preamble will not change
|
||||
file which defines the format of the rest of the header.
|
||||
While the header may change in subsequent versions, the preamble will not change
|
||||
across versions, though the interpretation of its flags may change from
|
||||
version to version. The
|
||||
version to version.
|
||||
The
|
||||
.Em ctp_magic
|
||||
member defines the magic number for the
|
||||
.Nm
|
||||
file format. This must always be
|
||||
file format.
|
||||
This must always be
|
||||
.Li 0xcff1 .
|
||||
If another value is encountered, then the file should not be treated as
|
||||
a
|
||||
.Nm
|
||||
file. The
|
||||
file.
|
||||
The
|
||||
.Em ctp_version
|
||||
member defines the version of the
|
||||
.Nm
|
||||
file. The current version is
|
||||
file.
|
||||
The current version is
|
||||
.Li 2 .
|
||||
It is possible to encounter an unsupported version. In that case,
|
||||
software should not try to parse the format, as it may have changed.
|
||||
It is possible to encounter an unsupported version.
|
||||
In that case, software should not try to parse the format, as it may have
|
||||
changed.
|
||||
Finally, the
|
||||
.Em ctp_flags
|
||||
member describes aspects of the file which modify its interpretation.
|
||||
@ -273,9 +287,10 @@ has been compressed through the
|
||||
.Sy zlib
|
||||
library and its
|
||||
.Sy deflate
|
||||
algorithm. If this flag is not present, then the body has not been
|
||||
compressed and no special action is needed to interpret it. All offsets
|
||||
into the data as described by
|
||||
algorithm.
|
||||
If this flag is not present, then the body has not been compressed and no
|
||||
special action is needed to interpret it.
|
||||
All offsets into the data as described by
|
||||
.Sy header ,
|
||||
always refer to the
|
||||
.Sy uncompressed
|
||||
@ -285,13 +300,13 @@ In version two of the
|
||||
.Nm
|
||||
file format, the
|
||||
.Sy header
|
||||
denotes whether whether or not this
|
||||
denotes whether or not this
|
||||
.Nm
|
||||
file is the child of another
|
||||
.Nm
|
||||
file and also indicates the size of the remaining sections. The
|
||||
structure for the
|
||||
.Sy header ,
|
||||
file and also indicates the size of the remaining sections.
|
||||
The structure for the
|
||||
.Sy header
|
||||
logically contains a copy of the
|
||||
.Sy preamble
|
||||
and the two have a combined size of 36 bytes.
|
||||
@ -315,37 +330,40 @@ the next two members
|
||||
.Em cth_parlablel
|
||||
and
|
||||
.Em cth_parname ,
|
||||
are used to identify the parent. The value of both members are offsets
|
||||
into the
|
||||
are used to identify the parent.
|
||||
The value of both members are offsets into the
|
||||
.Sy string
|
||||
section which point to the start of a null-terminated string. For more
|
||||
information on the encoding of strings, see the subsection on
|
||||
section which point to the start of a null-terminated string.
|
||||
For more information on the encoding of strings, see the subsection on
|
||||
.Sx String Identifiers .
|
||||
If the value of either is zero, then there is no entry for that
|
||||
member. If the member
|
||||
member.
|
||||
If the member
|
||||
.Em cth_parlabel
|
||||
is set, then the
|
||||
.Em ctf_parname
|
||||
member must be set, otherwise it will not be possible to find the
|
||||
parent. If
|
||||
parent.
|
||||
If
|
||||
.Em ctf_parname
|
||||
is set, it is not necessary to define
|
||||
.Em cth_parlabel ,
|
||||
as the parent may not have a label. For more information on labels
|
||||
and their interpretation, see
|
||||
as the parent may not have a label.
|
||||
For more information on labels and their interpretation, see
|
||||
.Sx The Label Section .
|
||||
.Lp
|
||||
The remaining members (excepting
|
||||
.Em cth_strlen )
|
||||
describe the beginning of the corresponding sections. These offsets are
|
||||
relative to the end of the
|
||||
describe the beginning of the corresponding sections.
|
||||
These offsets are relative to the end of the
|
||||
.Sy header .
|
||||
Therefore, something with an offset of 0 is at an offset of thirty-six
|
||||
bytes relative to the start of the
|
||||
.Nm
|
||||
file. The difference between members
|
||||
indicates the size of the section itself. Different offsets have
|
||||
different alignment requirements. The start of the
|
||||
file.
|
||||
The difference between members indicates the size of the section itself.
|
||||
Different offsets have different alignment requirements.
|
||||
The start of the
|
||||
.Em cth_objotoff
|
||||
and
|
||||
.Em cth_funcoff
|
||||
@ -353,13 +371,14 @@ must be two byte aligned, while the sections
|
||||
.Em cth_lbloff
|
||||
and
|
||||
.Em cth_typeoff
|
||||
must be four-byte aligned. The section
|
||||
must be four-byte aligned.
|
||||
The section
|
||||
.Em cth_stroff
|
||||
has no alignment requirements. To calculate the size of a given section,
|
||||
excepting the
|
||||
has no alignment requirements.
|
||||
To calculate the size of a given section, excepting the
|
||||
.Sy string
|
||||
section, one should subtract the offset of the section from the following one. For
|
||||
example, the size of the
|
||||
section, one should subtract the offset of the section from the following one.
|
||||
For example, the size of the
|
||||
.Sy types
|
||||
section can be calculated by subtracting
|
||||
.Em cth_stroff
|
||||
@ -368,8 +387,8 @@ from
|
||||
.Lp
|
||||
Finally, the member
|
||||
.Em cth_strlen
|
||||
describes the length of the string section itself. From it, you can also
|
||||
calculate the size of the entire
|
||||
describes the length of the string section itself.
|
||||
From it, you can also calculate the size of the entire
|
||||
.Nm
|
||||
file by adding together the size of the
|
||||
.Sy ctf_header_t ,
|
||||
@ -380,9 +399,11 @@ and the size of the string section in
|
||||
.Ss Type Identifiers
|
||||
Through the
|
||||
.Nm ctf
|
||||
data, types are referred to by identifiers. A given
|
||||
data, types are referred to by identifiers.
|
||||
A given
|
||||
.Nm
|
||||
file supports up to 32767 (0x7fff) types. The first valid type identifier is 0x1.
|
||||
file supports up to 32767 (0x7fff) types.
|
||||
The first valid type identifier is 0x1.
|
||||
When a given
|
||||
.Nm
|
||||
file is a child, indicated by a non-zero entry for the
|
||||
@ -403,18 +424,20 @@ Other consumers of
|
||||
information may use larger or opaque identifiers.
|
||||
.Ss String Identifiers
|
||||
String identifiers are always encoded as four byte unsigned integers
|
||||
which are an offset into a string table. The
|
||||
which are an offset into a string table.
|
||||
The
|
||||
.Nm
|
||||
format supports two different string tables which have an identifier of
|
||||
zero or one. This identifier is stored in the high-order bit of the
|
||||
unsigned four byte offset. Therefore, the maximum supported offset into
|
||||
one of these tables is 0x7ffffffff.
|
||||
zero or one.
|
||||
This identifier is stored in the high-order bit of the unsigned four byte
|
||||
offset.
|
||||
Therefore, the maximum supported offset into one of these tables is 0x7ffffffff.
|
||||
.Lp
|
||||
Table identifier zero, always refers to the
|
||||
.Sy string
|
||||
section in the CTF file itself. String table identifier one refers to an
|
||||
external string table which is the ELF string table for the ELF symbol
|
||||
table associated with the
|
||||
section in the CTF file itself.
|
||||
String table identifier one refers to an external string table which is the ELF
|
||||
string table for the ELF symbol table associated with the
|
||||
.Nm
|
||||
container.
|
||||
.Ss Type Encoding
|
||||
@ -434,8 +457,8 @@ The length of the variable data
|
||||
.Lp
|
||||
The 16 bits that make up the encoding are broken down such that you have
|
||||
five bits for the kind, one bit for indicating whether or not it is a
|
||||
root type, and 10 bits for the variable length. This is laid out as
|
||||
follows:
|
||||
root type, and 10 bits for the variable length.
|
||||
This is laid out as follows:
|
||||
.Bd -literal -offset indent
|
||||
+--------------------+
|
||||
| kind | root | vlen |
|
||||
@ -443,12 +466,13 @@ follows:
|
||||
15 11 10 9 0
|
||||
.Ed
|
||||
.Lp
|
||||
The current version of the file format defines 14 different kinds. The
|
||||
interpretation of these different kinds will be discussed in the section
|
||||
The current version of the file format defines 14 different kinds.
|
||||
The interpretation of these different kinds will be discussed in the section
|
||||
.Sx The Type Section .
|
||||
If a kind is encountered that is not listed below, then it is not a valid
|
||||
.Nm
|
||||
file. The kinds are defined as follows:
|
||||
file.
|
||||
The kinds are defined as follows:
|
||||
.Bd -literal -offset indent
|
||||
#define CTF_K_UNKNOWN 0
|
||||
#define CTF_K_INTEGER 1
|
||||
@ -467,14 +491,16 @@ file. The kinds are defined as follows:
|
||||
.Ed
|
||||
.Lp
|
||||
Programs directly reference many types; however, other types are referenced
|
||||
indirectly because they are part of some other structure. These types that are
|
||||
referenced directly and used are called
|
||||
indirectly because they are part of some other structure.
|
||||
These types that are referenced directly and used are called
|
||||
.Sy root
|
||||
types. Other types may be used indirectly, for example, a program may reference
|
||||
a structure directly, but not one of its members which has a type. That type is
|
||||
not considered a
|
||||
types.
|
||||
Other types may be used indirectly, for example, a program may reference
|
||||
a structure directly, but not one of its members which has a type.
|
||||
That type is not considered a
|
||||
.Sy root
|
||||
type. If a type is a
|
||||
type.
|
||||
If a type is a
|
||||
.Sy root
|
||||
type, then it will have bit 10 set.
|
||||
.Lp
|
||||
@ -499,16 +525,17 @@ When consuming
|
||||
.Nm
|
||||
data, it is often useful to know whether two different
|
||||
.Nm
|
||||
containers come from the same source base and version. For example, when
|
||||
building illumos, there are many kernel modules that are built against a
|
||||
single collection of source code. A label is encoded into the
|
||||
containers come from the same source base and version.
|
||||
For example, when building illumos, there are many kernel modules that are built
|
||||
against a single collection of source code.
|
||||
A label is encoded into the
|
||||
.Nm
|
||||
files that corresponds with the particular build. This ensures that if
|
||||
files on the system were to become mixed up from multiple releases, that
|
||||
they are not used together by tools, particularly when a child needs to
|
||||
refer to a type in the parent. Because they are linked used the type
|
||||
identifiers, if the wrong parent is used then the wrong type will be
|
||||
encountered.
|
||||
files that corresponds with the particular build.
|
||||
This ensures that if files on the system were to become mixed up from multiple
|
||||
releases, that they are not used together by tools, particularly when a child
|
||||
needs to refer to a type in the parent.
|
||||
Because they are linked using the type identifiers, if the wrong parent is used
|
||||
then the wrong type will be encountered.
|
||||
.Lp
|
||||
Each label is encoded in the file format using the following eight byte
|
||||
structure:
|
||||
@ -530,21 +557,22 @@ section.
|
||||
The type identifier encoded in the member
|
||||
.Em ctl_typeidx
|
||||
refers to the last type identifier that a label refers to in the current
|
||||
file. Labels only refer to types in the current file, if the
|
||||
file.
|
||||
Labels only refer to types in the current file, if the
|
||||
.Nm
|
||||
file is a child, then it will have the same label as its parent;
|
||||
however, its label will only refer to its types, not its parents.
|
||||
however, its label will only refer to its types, not its parent's.
|
||||
.Lp
|
||||
It is also possible, though rather uncommon, for a
|
||||
.Nm
|
||||
file to have multiple labels. Labels are placed one after another, every
|
||||
eight bytes. When multiple labels are present, types may only belong to
|
||||
a single label.
|
||||
file to have multiple labels.
|
||||
Labels are placed one after another, every eight bytes.
|
||||
When multiple labels are present, types may only belong to a single label.
|
||||
.Ss The Object Section
|
||||
The object section provides a mapping from ELF symbols of type
|
||||
.Sy STT_OBJECT
|
||||
in the symbol table to a type identifier. Every entry in this section is
|
||||
a
|
||||
in the symbol table to a type identifier.
|
||||
Every entry in this section is a
|
||||
.Sy uint16_t
|
||||
which contains a type identifier as described in the section
|
||||
.Sx Type Identifiers .
|
||||
@ -555,9 +583,10 @@ To walk the object section, you need to have a corresponding
|
||||
.Sy symbol table
|
||||
in the ELF object that contains the
|
||||
.Nm
|
||||
data. Not every object is included in this section. Specifically, when
|
||||
walking the symbol table. An entry is skipped if it matches any of the
|
||||
following conditions:
|
||||
data.
|
||||
Not every object is included in this section.
|
||||
Specifically, when walking the symbol table, an entry is skipped if it matches
|
||||
any of the following conditions:
|
||||
.Lp
|
||||
.Bl -bullet -offset indent -compact
|
||||
.It
|
||||
@ -628,40 +657,45 @@ walk_symbols(uint16_t *objtoff, Elf_Data *symdata, Elf_Data *strdata,
|
||||
The function section of the
|
||||
.Nm
|
||||
file encodes the types of both the function's arguments and the function's
|
||||
return type. Similar to
|
||||
return value.
|
||||
Similar to
|
||||
.Sx The Object Section ,
|
||||
the function section encodes information for all symbols of type
|
||||
.Sy STT_FUNCTION ,
|
||||
excepting those that fit specific criteria. Unlike with objects, because
|
||||
functions have a variable number of arguments, they start with a type encoding
|
||||
as defined in
|
||||
excepting those that fit specific criteria.
|
||||
Unlike with objects, because functions have a variable number of arguments, they
|
||||
start with a type encoding as defined in
|
||||
.Sx Type Encoding ,
|
||||
which is the size of a
|
||||
.Sy uint16_t .
|
||||
For functions which have no type information available, they are encoded as
|
||||
.Li CTF_TYPE_INFO(CTF_K_UNKNOWN, 0, 0) .
|
||||
Functions with arguments are encoded differently. Here, the variable length is
|
||||
turned into the number of arguments in the function. If a function is a
|
||||
Functions with arguments are encoded differently.
|
||||
Here, the variable length is turned into the number of arguments in the
|
||||
function.
|
||||
If a function is a
|
||||
.Sy varargs
|
||||
type function, then the number of arguments is increased by one. Functions with
|
||||
type information are encoded as:
|
||||
type function, then the number of arguments is increased by one.
|
||||
Functions with type information are encoded as:
|
||||
.Li CTF_TYPE_INFO(CTF_K_FUNCTION, 0, nargs) .
|
||||
.Lp
|
||||
For functions that have no type information, nothing else is encoded, and the
|
||||
next function is encoded. For functions with type information, the next
|
||||
next function is encoded.
|
||||
For functions with type information, the next
|
||||
.Sy uint16_t
|
||||
is encoded with the type identifier of the return type of the function. It is
|
||||
followed by each of the type identifiers of the arguments, if any exist, in the
|
||||
order that they appear in the function. Therefore, argument 0 is the first type
|
||||
identifier and so on. When a function has a final varargs argument, that is
|
||||
encoded with the type identifier of zero.
|
||||
is encoded with the type identifier of the return type of the function.
|
||||
It is followed by each of the type identifiers of the arguments, if any exist,
|
||||
in the order that they appear in the function.
|
||||
Therefore, argument 0 is the first type identifier and so on.
|
||||
When a function has a final varargs argument, that is encoded with the type
|
||||
identifier of zero.
|
||||
.Lp
|
||||
Like
|
||||
.Sx The Object Section ,
|
||||
the function section is encoded in the order of the symbol table. It has
|
||||
similar, but slightly different considerations from objects. While iterating the
|
||||
symbol table, if any of the following conditions are true, then the entry is
|
||||
skipped and no corresponding entry is written:
|
||||
the function section is encoded in the order of the symbol table.
|
||||
It has similar, but slightly different considerations from objects.
|
||||
While iterating the symbol table, if any of the following conditions are true,
|
||||
then the entry is skipped and no corresponding entry is written:
|
||||
.Lp
|
||||
.Bl -bullet -offset indent -compact
|
||||
.It
|
||||
@ -683,10 +717,11 @@ ELF.
|
||||
.Ss The Type Section
|
||||
The type section is the heart of the
|
||||
.Nm
|
||||
data. It encodes all of the information about the types themselves. The base of
|
||||
the type information comes in two forms, a short form and a long form, each of
|
||||
which may be followed by a variable number of arguments. The following
|
||||
definitions describe the short and long forms:
|
||||
data.
|
||||
It encodes all of the information about the types themselves.
|
||||
The base of the type information comes in two forms, a short form and a long
|
||||
form, each of which may be followed by a variable number of arguments.
|
||||
The following definitions describe the short and long forms:
|
||||
.Bd -literal
|
||||
#define CTF_MAX_SIZE 0xfffe /* max size of a type in bytes */
|
||||
#define CTF_LSIZE_SENT 0xffff /* sentinel for ctt_size */
|
||||
@ -720,14 +755,17 @@ Type sizes are stored in
|
||||
.Sy bytes .
|
||||
The basic small form uses a
|
||||
.Sy ushort_t
|
||||
to store the number of bytes. If the number of bytes in a structure would exceed
|
||||
0xfffe, then the alternate form, the
|
||||
to store the number of bytes.
|
||||
If the number of bytes in a structure would exceed 0xfffe, then the alternate
|
||||
form, the
|
||||
.Sy ctf_type_t ,
|
||||
is used instead. To indicate that the larger form is being used, the member
|
||||
is used instead.
|
||||
To indicate that the larger form is being used, the member
|
||||
.Em ctt_size
|
||||
is set to value of
|
||||
.Sy CTF_LSIZE_SENT
|
||||
(0xffff). In general, when going through the type section, consumers use the
|
||||
(0xffff).
|
||||
In general, when going through the type section, consumers use the
|
||||
.Sy ctf_type_t
|
||||
structure, but pay attention to the value of the member
|
||||
.Em ctt_size
|
||||
@ -739,36 +777,43 @@ Not all kinds of types use
|
||||
.Sy ctt_size .
|
||||
Those which do not, will always use the
|
||||
.Sy ctf_stype_t
|
||||
structure. The individual sections for each kind have more information.
|
||||
structure.
|
||||
The individual sections for each kind have more information.
|
||||
.Lp
|
||||
Types are written out in order. Therefore the first entry encountered has a type
|
||||
id of 0x1, or 0x8000 if a child. The member
|
||||
Types are written out in order.
|
||||
Therefore the first entry encountered has a type id of 0x1, or 0x8000 if a
|
||||
child.
|
||||
The member
|
||||
.Em ctt_name
|
||||
is encoded as described in the section
|
||||
.Sx String Identifiers .
|
||||
The string that it points to is the name of the type. If the identifier points
|
||||
to an empty string (one that consists solely of a null terminator) then the type
|
||||
does not have a name, this is common with anonymous structures and unions that
|
||||
only have a typedef to name them, as well as, pointers and qualifiers.
|
||||
The string that it points to is the name of the type.
|
||||
If the identifier points to an empty string (one that consists solely of a null
|
||||
terminator) then the type does not have a name, this is common with anonymous
|
||||
structures and unions that only have a typedef to name them, as well as
|
||||
pointers and qualifiers.
|
||||
.Lp
|
||||
The next member, the
|
||||
.Em ctt_info ,
|
||||
is encoded as described in the section
|
||||
.Sx Type Encoding .
|
||||
The types kind tells us how to interpret the remaining data in the
|
||||
The type's kind tells us how to interpret the remaining data in the
|
||||
.Sy ctf_type_t
|
||||
and any variable length data that may exist. The rest of this section will be
|
||||
broken down into the interpretation of the various kinds.
|
||||
and any variable length data that may exist.
|
||||
The rest of this section will be broken down into the interpretation of the
|
||||
various kinds.
|
||||
.Ss Encoding of Integers
|
||||
Integers, which are of type
|
||||
.Sy CTF_K_INTEGER ,
|
||||
have no variable length arguments. Instead, they are followed by a four byte
|
||||
have no variable length arguments.
|
||||
Instead, they are followed by a four byte
|
||||
.Sy uint_t
|
||||
which describes their encoding. All integers must be encoded with a variable
|
||||
length of zero. The
|
||||
which describes their encoding.
|
||||
All integers must be encoded with a variable length of zero.
|
||||
The
|
||||
.Em ctt_size
|
||||
member describes the length of the integer in bytes. In general, integer sizes
|
||||
will be rounded up to the closest power of two.
|
||||
member describes the length of the integer in bytes.
|
||||
In general, integer sizes will be rounded up to the closest power of two.
|
||||
.Lp
|
||||
The integer encoding contains three different pieces of information:
|
||||
.Bl -bullet -offset indent -compact
|
||||
@ -804,33 +849,37 @@ The following flags are defined for the encoding at this time:
|
||||
.Lp
|
||||
By default, an integer is considered to be unsigned, unless it has the
|
||||
.Sy CTF_INT_SIGNED
|
||||
flag set. If the flag
|
||||
flag set.
|
||||
If the flag
|
||||
.Sy CTF_INT_CHAR
|
||||
is set, that indicates that the integer is of a type that stores character
|
||||
data, for example the intrinsic C type
|
||||
.Sy char
|
||||
would have the
|
||||
.Sy CTF_INT_CHAR
|
||||
flag set. If the flag
|
||||
flag set.
|
||||
If the flag
|
||||
.Sy CTF_INT_BOOL
|
||||
is set, that indicates that the integer represents a boolean type. For example,
|
||||
the intrinsic C type
|
||||
is set, that indicates that the integer represents a boolean type.
|
||||
For example, the intrinsic C type
|
||||
.Sy _Bool
|
||||
would have the
|
||||
.Sy CTF_INT_BOOL
|
||||
flag set. Finally, the flag
|
||||
flag set.
|
||||
Finally, the flag
|
||||
.Sy CTF_INT_VARARGS
|
||||
indicates that the integer is used as part of a variable number of arguments.
|
||||
This encoding is rather uncommon.
|
||||
.Ss Encoding of Floats
|
||||
Floats, which are of type
|
||||
.Sy CTF_K_FLOAT ,
|
||||
are similar to their integer counterparts. They have no variable length
|
||||
arguments and are followed by a four byte encoding which describes the kind of
|
||||
float that exists. The
|
||||
are similar to their integer counterparts.
|
||||
They have no variable length arguments and are followed by a four byte encoding
|
||||
which describes the kind of float that exists.
|
||||
The
|
||||
.Em ctt_size
|
||||
member is the size, in bytes, of the float. The float encoding has three
|
||||
different pieces of information inside of it:
|
||||
member is the size, in bytes, of the float.
|
||||
The float encoding has three different pieces of information inside of it:
|
||||
.Lp
|
||||
.Bl -bullet -offset indent -compact
|
||||
.It
|
||||
@ -855,11 +904,12 @@ This encoding can be expressed through the following macros:
|
||||
(((encoding) << 24) | ((offset) << 16) | (bits))
|
||||
.Ed
|
||||
.Lp
|
||||
Where as the encoding for integers was a series of flags, the encoding for
|
||||
floats maps to a specific kind of float. It is not a flag-based value. The kinds of floats
|
||||
correspond to both their size, and the encoding. This covers all of the basic C
|
||||
intrinsic floating point types. The following are the different kinds of floats
|
||||
represented in the encoding:
|
||||
Where as the encoding for integers is a series of flags, the encoding for
|
||||
floats maps to a specific kind of float.
|
||||
It is not a flag-based value.
|
||||
The kinds of floats correspond to both their size, and the encoding.
|
||||
This covers all of the basic C intrinsic floating point types.
|
||||
The following are the different kinds of floats represented in the encoding:
|
||||
.Bd -literal -offset indent
|
||||
#define CTF_FP_SINGLE 1 /* IEEE 32-bit float encoding */
|
||||
#define CTF_FP_DOUBLE 2 /* IEEE 64-bit float encoding */
|
||||
@ -877,12 +927,14 @@ represented in the encoding:
|
||||
.Ss Encoding of Arrays
|
||||
Arrays, which are of type
|
||||
.Sy CTF_K_ARRAY ,
|
||||
have no variable length arguments. They are followed by a structure which
|
||||
describes the number of elements in the array, the type identifier of the
|
||||
elements in the array, and the type identifier of the index of the array. With
|
||||
arrays, the
|
||||
have no variable length arguments.
|
||||
They are followed by a structure which describes the number of elements in the
|
||||
array, the type identifier of the elements in the array, and the type identifier
|
||||
of the index of the array.
|
||||
With arrays, the
|
||||
.Em ctt_size
|
||||
member is set to zero. The structure that follows an array is defined as:
|
||||
member is set to zero.
|
||||
The structure that follows an array is defined as:
|
||||
.Bd -literal
|
||||
typedef struct ctf_array {
|
||||
ushort_t cta_contents; /* reference to type of array contents */
|
||||
@ -901,14 +953,15 @@ are type identifiers which are encoded as per the section
|
||||
.Sx Type Identifiers .
|
||||
The member
|
||||
.Em cta_nelems
|
||||
is a simple four byte unsigned count of the number of elements. This count may
|
||||
be zero when encountering C99's flexible array members.
|
||||
is a simple four byte unsigned count of the number of elements.
|
||||
This count may be zero when encountering C99's flexible array members.
|
||||
.Ss Encoding of Functions
|
||||
Function types, which are of type
|
||||
.Sy CTF_K_FUNCTION ,
|
||||
use the variable length list to be the number of arguments in the function. When
|
||||
the function has a final member which is a varargs, then the argument count is
|
||||
incremented by one to account for the variable argument. Here, the
|
||||
use the variable length list to be the number of arguments in the function.
|
||||
When the function has a final member which is a varargs, then the argument count
|
||||
is incremented by one to account for the variable argument.
|
||||
Here, the
|
||||
.Em ctt_type
|
||||
member is encoded with the type identifier of the return type of the function.
|
||||
Note that the
|
||||
@ -916,31 +969,40 @@ Note that the
|
||||
member is not used here.
|
||||
.Lp
|
||||
The variable argument list contains the type identifiers for the arguments of
|
||||
the function, if any. Each one is represented by a
|
||||
the function, if any.
|
||||
Each one is represented by a
|
||||
.Sy uint16_t
|
||||
and encoded according to the
|
||||
.Sx Type Identifiers
|
||||
section. If the function's last argument is of type varargs, then it is also
|
||||
written out, but the type identifier is zero. This is included in the count of
|
||||
the function's arguments.
|
||||
section.
|
||||
If the function's last argument is of type varargs, then it is also written out,
|
||||
but the type identifier is zero.
|
||||
This is included in the count of the function's arguments.
|
||||
An extra type identifier may follow the argument and return type identifiers
|
||||
in order to maintain four-byte alignment for the following type definition.
|
||||
Such a type identifier is not included in the argument count and has a value
|
||||
of zero.
|
||||
.Ss Encoding of Structures and Unions
|
||||
Structures and Unions, which are encoded with
|
||||
.Sy CTF_K_STRUCT
|
||||
and
|
||||
.Sy CTF_K_UNION
|
||||
respectively, are very similar constructs in C. The main difference
|
||||
between them is the fact that every member of a structure follows one another,
|
||||
where as in a union, all members share the same memory. They are also very
|
||||
similar in terms of their encoding in
|
||||
respectively, are very similar constructs in C.
|
||||
The main difference between them is the fact that members of a structure
|
||||
follow one another, where as in a union, all members share the same memory.
|
||||
They are also very similar in terms of their encoding in
|
||||
.Nm .
|
||||
The variable length argument for structures and unions represents the number of
|
||||
members that they have. The value of the member
|
||||
members that they have.
|
||||
The value of the member
|
||||
.Em ctt_size
|
||||
is the size of the structure and union. There are two different structures which
|
||||
are used to encode members in the variable list. When the size of a structure or
|
||||
union is greater than or equal to the large member threshold, 8192, then a
|
||||
different structure is used to encode the member, all members are encoded using
|
||||
the same structure. The structure for members is as follows:
|
||||
is the size of the structure and union.
|
||||
There are two different structures which are used to encode members in the
|
||||
variable list.
|
||||
When the size of a structure or union is greater than or equal to the large
|
||||
member threshold, 8192, then a different structure is used to encode the member,
|
||||
all members are encoded using the same structure.
|
||||
The structure for members is as follows:
|
||||
.Bd -literal
|
||||
typedef struct ctf_member {
|
||||
uint_t ctm_name; /* reference to name in string table */
|
||||
@ -961,54 +1023,66 @@ Both the
|
||||
.Em ctm_name
|
||||
and
|
||||
.Em ctlm_name
|
||||
refer to the name of the member. The name is encoded as an offset into the
|
||||
string table as described by the section
|
||||
refer to the name of the member.
|
||||
The name is encoded as an offset into the string table as described by the
|
||||
section
|
||||
.Sx String Identifiers .
|
||||
The members
|
||||
.Sy ctm_type
|
||||
and
|
||||
.Sy ctlm_type
|
||||
both refer to the type of the member. They are encoded as per the section
|
||||
both refer to the type of the member.
|
||||
They are encoded as per the section
|
||||
.Sx Type Identifiers .
|
||||
.Lp
|
||||
The last piece of information that is present is the offset which describes the
|
||||
offset in memory that the member begins at. For unions, this value will always
|
||||
be zero because the start of unions in memory is always zero. For structures,
|
||||
this is the offset in
|
||||
offset in memory at which the member begins.
|
||||
For unions, this value will always be zero because each member of a union has
|
||||
an offset of zero.
|
||||
For structures, this is the offset in
|
||||
.Sy bits
|
||||
that the member begins at. Note that a compiler may lay out a type with padding.
|
||||
at which the member begins.
|
||||
Note that a compiler may lay out a type with padding.
|
||||
This means that the difference in offset between two consecutive members may be
|
||||
larger than the size of the member. When the size of the overall structure is
|
||||
strictly less than 8192 bytes, the normal structure,
|
||||
larger than the size of the member.
|
||||
When the size of the overall structure is strictly less than 8192 bytes, the
|
||||
normal structure,
|
||||
.Sy ctf_member_t ,
|
||||
is used and the offset in bits is stored in the member
|
||||
.Em ctm_offset .
|
||||
However, when the size of the structure is greater than or equal to 8192 bytes,
|
||||
then the number of bits is split into two 32-bit quantities. One member,
|
||||
then the number of bits is split into two 32-bit quantities.
|
||||
One member,
|
||||
.Em ctlm_offsethi ,
|
||||
represents the upper 32 bits of the offset, while the other member,
|
||||
.Em ctlm_offsetlo ,
|
||||
represents the lower 32 bits of the offset. These can be joined together to get
|
||||
a 64-bit sized offset in bits by shifting the member
|
||||
represents the lower 32 bits of the offset.
|
||||
These can be joined together to get a 64-bit sized offset in bits by shifting
|
||||
the member
|
||||
.Em ctlm_offsethi
|
||||
to the left by thirty two and then doing a binary or of
|
||||
.Em ctlm_offsetlo .
|
||||
.Ss Encoding of Enumerations
|
||||
Enumerations, noted by the type
|
||||
.Sy CTF_K_ENUM ,
|
||||
are similar to structures. Enumerations use the variable list to note the number
|
||||
of values that the enumeration contains, which we'll term enumerators. In C, an
|
||||
enumeration is always equivalent to the intrinsic type
|
||||
are similar to structures.
|
||||
Enumerations use the variable list to note the number of values that the
|
||||
enumeration contains, which we'll term enumerators.
|
||||
In C, an enumeration is always equivalent to the intrinsic type
|
||||
.Sy int ,
|
||||
thus the value of the member
|
||||
.Em ctt_size
|
||||
is always the size of an integer which is determined based on the current model.
|
||||
For illumos systems, this will always be 4, as an integer is always defined to
|
||||
For
|
||||
.Fx
|
||||
systems, this will always be 4, as an integer is always defined to
|
||||
be 4 bytes large in both
|
||||
.Sy ILP32
|
||||
and
|
||||
.Sy LP64 ,
|
||||
regardless of the architecture.
|
||||
For further details, see
|
||||
.Xr arch 7 .
|
||||
.Lp
|
||||
The enumerators encoded in an enumeration have the following structure in the
|
||||
variable list:
|
||||
@ -1032,25 +1106,27 @@ Forward references, types of kind
|
||||
.Sy CTF_K_FORWARD ,
|
||||
in a
|
||||
.Nm
|
||||
file refer to types which may not have a definition at all, only a name. If
|
||||
the
|
||||
file refer to types which may not have a definition at all, only a name.
|
||||
If the
|
||||
.Nm
|
||||
file is a child, then it may be that the forward is resolved to an
|
||||
actual type in the parent, otherwise the definition may be in another
|
||||
.Nm
|
||||
container or may not be known at all. The only member of the
|
||||
container or may not be known at all.
|
||||
The only member of the
|
||||
.Sy ctf_type_t
|
||||
that matters for a forward declaration is the
|
||||
.Em ctt_name
|
||||
which points to the name of the forward reference in the string table as
|
||||
described earlier. There is no other information recorded for forward
|
||||
references.
|
||||
described earlier.
|
||||
There is no other information recorded for forward references.
|
||||
.Ss Encoding of Pointers, Typedefs, Volatile, Const, and Restrict
|
||||
Pointers, typedefs, volatile, const, and restrict are all similar in
|
||||
.Nm .
|
||||
They all refer to another type. In the case of typedefs, they provide an
|
||||
alternate name, while volatile, const, and restrict change how the type is
|
||||
interpreted in the C programming language. This covers the
|
||||
They all refer to another type.
|
||||
In the case of typedefs, they provide an alternate name, while volatile, const,
|
||||
and restrict change how the type is interpreted in the C programming language.
|
||||
This covers the
|
||||
.Nm
|
||||
kinds
|
||||
.Sy CTF_K_POINTER ,
|
||||
@ -1066,43 +1142,49 @@ to refer to the base type that they modify.
|
||||
.Ss Encoding of Unknown Types
|
||||
Types with the kind
|
||||
.Sy CTF_K_UNKNOWN
|
||||
are used to indicate gaps in the type identifier space. These entries consume an
|
||||
identifier, but do not define anything. Nothing should refer to these gap
|
||||
identifiers.
|
||||
are used to indicate gaps in the type identifier space.
|
||||
These entries consume an identifier, but do not define anything.
|
||||
Nothing should refer to these gap identifiers.
|
||||
.Ss Dependencies Between Types
|
||||
C types can be imagined as a directed, cyclic, graph. Structures and unions may
|
||||
refer to each other in a way that creates a cyclic dependency. In cases such as
|
||||
these, the entire type section must be read in and processed. Consumers must
|
||||
not assume that every type can be laid out in dependency order; they
|
||||
cannot.
|
||||
C types can be imagined as a directed, cyclic, graph.
|
||||
Structures and unions may refer to each other in a way that creates a cyclic
|
||||
dependency.
|
||||
In cases such as these, the entire type section must be read in and processed.
|
||||
Consumers must not assume that every type can be laid out in dependency order;
|
||||
they cannot.
|
||||
.Ss The String Section
|
||||
The last section of the
|
||||
.Nm
|
||||
file is the
|
||||
.Sy string
|
||||
section. This section encodes all of the strings that appear throughout
|
||||
the other sections. It is laid out as a series of characters followed by
|
||||
a null terminator. Generally, all names are written out in ASCII, as
|
||||
most C compilers do not allow and characters to appear in identifiers
|
||||
outside of a subset of ASCII. However, any extended characters sets
|
||||
should be written out as a series of UTF-8 bytes.
|
||||
section.
|
||||
This section encodes all of the strings that appear throughout the other
|
||||
sections.
|
||||
It is laid out as a series of characters followed by a null terminator.
|
||||
Generally, all names are written out in ASCII, as most C compilers do not allow
|
||||
any characters to appear in identifiers outside of a subset of ASCII.
|
||||
However, any extended characters sets should be written out as a series of UTF-8
|
||||
bytes.
|
||||
.Lp
|
||||
The first entry in the section, at offset zero, is a single null
|
||||
terminator to reference the empty string. Following that, each C string
|
||||
should be written out, including the null terminator. Offsets that refer
|
||||
to something in this section should refer to the first byte which begins
|
||||
a string. Beyond the first byte in the section being the null
|
||||
terminator, the order of strings is unimportant.
|
||||
terminator to reference the empty string.
|
||||
Following that, each C string should be written out, including the null
|
||||
terminator.
|
||||
Offsets that refer to something in this section should refer to the first byte
|
||||
which begins a string.
|
||||
Beyond the first byte in the section being the null terminator, the order of
|
||||
strings is unimportant.
|
||||
.Ss Data Encoding and ELF Considerations
|
||||
.Nm
|
||||
data is generally included in ELF objects which specify information to
|
||||
identify the architecture and endianness of the file. A
|
||||
identify the architecture and endianness of the file.
|
||||
A
|
||||
.Nm
|
||||
container inside such an object must match the endianness of the ELF
|
||||
object. Aside from the question of the endian encoding of data, there
|
||||
should be no other differences between architectures. While many of the
|
||||
types in this document refer to non-fixed size C integral types, they
|
||||
are equivalent in the models
|
||||
container inside such an object must match the endianness of the ELF object.
|
||||
Aside from the question of the endian encoding of data, there should be no other
|
||||
differences between architectures.
|
||||
While many of the types in this document refer to non-fixed size C integral
|
||||
types, they are equivalent in the models
|
||||
.Sy ILP32
|
||||
and
|
||||
.Sy LP64 .
|
||||
@ -1118,15 +1200,16 @@ When placing a
|
||||
container inside of an ELF object, there are certain conventions that are
|
||||
expected for the purposes of tooling being able to find the
|
||||
.Nm
|
||||
data. In particular, a given ELF object should only contain a single
|
||||
data.
|
||||
In particular, a given ELF object should only contain a single
|
||||
.Nm
|
||||
section. Multiple containers should be merged together into a single
|
||||
one.
|
||||
section.
|
||||
Multiple containers should be merged together into a single one.
|
||||
.Lp
|
||||
The
|
||||
.Nm
|
||||
file should be included in its own ELF section. The section's name
|
||||
must be
|
||||
file should be included in its own ELF section.
|
||||
The section's name must be
|
||||
.Ql .SUNW_ctf .
|
||||
The type of the section must be
|
||||
.Sy SHT_PROGBITS .
|
||||
@ -1137,4 +1220,5 @@ alignment must be 4.
|
||||
.Xr elf 3 ,
|
||||
.Xr gelf 3 ,
|
||||
.Xr a.out 5 ,
|
||||
.Xr elf 5
|
||||
.Xr elf 5 ,
|
||||
.Xr arch 7
|
||||
|
@ -434,7 +434,7 @@ dt_dis(const dtrace_difo_t *dp, FILE *fp)
|
||||
ulong_t i = 0;
|
||||
char type[DT_TYPE_NAMELEN];
|
||||
|
||||
(void) fprintf(fp, "\nDIFO 0x%p returns %s\n", (void *)dp,
|
||||
(void) fprintf(fp, "\nDIFO %p returns %s\n", (void *)dp,
|
||||
dt_dis_typestr(&dp->dtdo_rtype, type, sizeof (type)));
|
||||
|
||||
(void) fprintf(fp, "%-3s %-8s %s\n",
|
||||
|
@ -229,10 +229,12 @@ prepare_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf32_t *dep)
|
||||
for (j = 0; j < nrel; j++) {
|
||||
#if defined(__aarch64__)
|
||||
/* XXX */
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
printf("%s:%s(%d): aarch64 not implemented\n",
|
||||
__FUNCTION__, __FILE__, __LINE__);
|
||||
#elif defined(__arm__)
|
||||
/* XXX */
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
printf("%s:%s(%d): arm not implemented\n",
|
||||
__FUNCTION__, __FILE__, __LINE__);
|
||||
#elif defined(__i386) || defined(__amd64)
|
||||
rel->r_offset = s->dofs_offset +
|
||||
dofr[j].dofr_offset;
|
||||
@ -240,7 +242,8 @@ printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
R_386_PC32);
|
||||
#elif defined(__mips__)
|
||||
/* XXX */
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
printf("%s:%s(%d): MIPS not implemented\n",
|
||||
__FUNCTION__, __FILE__, __LINE__);
|
||||
#elif defined(__powerpc__)
|
||||
/*
|
||||
* Add 4 bytes to hit the low half of this 64-bit
|
||||
@ -252,7 +255,8 @@ printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
R_PPC_REL32);
|
||||
#elif defined(__riscv)
|
||||
/* XXX */
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
printf("%s:%s(%d): RISC-V not implemented\n",
|
||||
__FUNCTION__, __FILE__, __LINE__);
|
||||
#else
|
||||
#error unknown ISA
|
||||
#endif
|
||||
@ -802,7 +806,8 @@ static int
|
||||
dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
|
||||
uint32_t *off)
|
||||
{
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
printf("%s:%s(%d): aarch64 not implemented\n", __FUNCTION__, __FILE__,
|
||||
__LINE__);
|
||||
return (0);
|
||||
}
|
||||
#elif defined(__arm__)
|
||||
@ -811,7 +816,8 @@ static int
|
||||
dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
|
||||
uint32_t *off)
|
||||
{
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
printf("%s:%s(%d): arm not implemented\n", __FUNCTION__, __FILE__,
|
||||
__LINE__);
|
||||
return (0);
|
||||
}
|
||||
#elif defined(__mips__)
|
||||
@ -820,7 +826,8 @@ static int
|
||||
dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
|
||||
uint32_t *off)
|
||||
{
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
printf("%s:%s(%d): MIPS not implemented\n", __FUNCTION__, __FILE__,
|
||||
__LINE__);
|
||||
return (0);
|
||||
}
|
||||
#elif defined(__powerpc__)
|
||||
@ -910,7 +917,8 @@ static int
|
||||
dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
|
||||
uint32_t *off)
|
||||
{
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
printf("%s:%s(%d): RISC-V implementation required\n", __FUNCTION__,
|
||||
__FILE__, __LINE__);
|
||||
return (0);
|
||||
}
|
||||
#elif defined(__sparc)
|
||||
|
@ -377,7 +377,7 @@ dt_print_array(ctf_id_t base, ulong_t off, dt_printarg_t *pap)
|
||||
ctf_id_t rtype;
|
||||
|
||||
if (ctf_array_info(ctfp, base, &car) == CTF_ERR) {
|
||||
(void) fprintf(fp, "0x%p", (void *)addr);
|
||||
(void) fprintf(fp, "%p", (void *)addr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -426,7 +426,8 @@ dt_proc_attach(dt_proc_t *dpr, int exec)
|
||||
static void
|
||||
dt_proc_waitrun(dt_proc_t *dpr)
|
||||
{
|
||||
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||
printf("%s:%s(%d): not implemented\n", __FUNCTION__, __FILE__,
|
||||
__LINE__);
|
||||
#ifdef DOODAD
|
||||
struct ps_prochandle *P = dpr->dpr_proc;
|
||||
const lwpstatus_t *psp = &Pstatus(P)->pr_lwp;
|
||||
|
@ -22,7 +22,7 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
|
||||
* Copyright (c) 2013 Martin Matuska. All rights reserved.
|
||||
@ -2166,6 +2166,7 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
|
||||
if (zfs_prop_readonly(prop) &&
|
||||
*source != NULL && (*source)[0] == '\0') {
|
||||
*source = NULL;
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2354,6 +2355,74 @@ zfs_get_clones_nvl(zfs_handle_t *zhp)
|
||||
return (value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Accepts a property and value and checks that the value
|
||||
* matches the one found by the channel program. If they are
|
||||
* not equal, print both of them.
|
||||
*/
|
||||
void
|
||||
zcp_check(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t intval,
|
||||
const char *strval)
|
||||
{
|
||||
if (!zhp->zfs_hdl->libzfs_prop_debug)
|
||||
return;
|
||||
int error;
|
||||
char *poolname = zhp->zpool_hdl->zpool_name;
|
||||
const char *program =
|
||||
"args = ...\n"
|
||||
"ds = args['dataset']\n"
|
||||
"prop = args['property']\n"
|
||||
"value, setpoint = zfs.get_prop(ds, prop)\n"
|
||||
"return {value=value, setpoint=setpoint}\n";
|
||||
nvlist_t *outnvl;
|
||||
nvlist_t *retnvl;
|
||||
nvlist_t *argnvl = fnvlist_alloc();
|
||||
|
||||
fnvlist_add_string(argnvl, "dataset", zhp->zfs_name);
|
||||
fnvlist_add_string(argnvl, "property", zfs_prop_to_name(prop));
|
||||
|
||||
error = lzc_channel_program(poolname, program,
|
||||
10 * 1000 * 1000, 10 * 1024 * 1024, argnvl, &outnvl);
|
||||
|
||||
if (error == 0) {
|
||||
retnvl = fnvlist_lookup_nvlist(outnvl, "return");
|
||||
if (zfs_prop_get_type(prop) == PROP_TYPE_NUMBER) {
|
||||
int64_t ans;
|
||||
error = nvlist_lookup_int64(retnvl, "value", &ans);
|
||||
if (error != 0) {
|
||||
(void) fprintf(stderr, "zcp check error: %u\n",
|
||||
error);
|
||||
return;
|
||||
}
|
||||
if (ans != intval) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: zfs found %lld, but zcp found %lld\n",
|
||||
zfs_prop_to_name(prop),
|
||||
(longlong_t)intval, (longlong_t)ans);
|
||||
}
|
||||
} else {
|
||||
char *str_ans;
|
||||
error = nvlist_lookup_string(retnvl, "value", &str_ans);
|
||||
if (error != 0) {
|
||||
(void) fprintf(stderr, "zcp check error: %u\n",
|
||||
error);
|
||||
return;
|
||||
}
|
||||
if (strcmp(strval, str_ans) != 0) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: zfs found %s, but zcp found %s\n",
|
||||
zfs_prop_to_name(prop),
|
||||
strval, str_ans);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(void) fprintf(stderr,
|
||||
"zcp check failed, channel program error: %u\n", error);
|
||||
}
|
||||
nvlist_free(argnvl);
|
||||
nvlist_free(outnvl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve a property from the given object. If 'literal' is specified, then
|
||||
* numbers are left as exact values. Otherwise, numbers are converted to a
|
||||
@ -2400,6 +2469,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
|
||||
&t) == 0)
|
||||
(void) snprintf(propbuf, proplen, "%llu", val);
|
||||
}
|
||||
zcp_check(zhp, prop, val, NULL);
|
||||
break;
|
||||
|
||||
case ZFS_PROP_MOUNTPOINT:
|
||||
@ -2468,7 +2538,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
|
||||
/* 'legacy' or 'none' */
|
||||
(void) strlcpy(propbuf, str, proplen);
|
||||
}
|
||||
|
||||
zcp_check(zhp, prop, NULL, propbuf);
|
||||
break;
|
||||
|
||||
case ZFS_PROP_ORIGIN:
|
||||
@ -2476,6 +2546,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
|
||||
if (str == NULL)
|
||||
return (-1);
|
||||
(void) strlcpy(propbuf, str, proplen);
|
||||
zcp_check(zhp, prop, NULL, str);
|
||||
break;
|
||||
|
||||
case ZFS_PROP_CLONES:
|
||||
@ -2490,7 +2561,6 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
|
||||
|
||||
if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* If quota or reservation is 0, we translate this into 'none'
|
||||
* (unless literal is set), and indicate that it's the default
|
||||
@ -2509,6 +2579,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
|
||||
else
|
||||
zfs_nicenum(val, propbuf, proplen);
|
||||
}
|
||||
zcp_check(zhp, prop, val, NULL);
|
||||
break;
|
||||
|
||||
case ZFS_PROP_FILESYSTEM_LIMIT:
|
||||
@ -2533,6 +2604,8 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
|
||||
} else {
|
||||
zfs_nicenum(val, propbuf, proplen);
|
||||
}
|
||||
|
||||
zcp_check(zhp, prop, val, NULL);
|
||||
break;
|
||||
|
||||
case ZFS_PROP_REFRATIO:
|
||||
@ -2542,6 +2615,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
|
||||
(void) snprintf(propbuf, proplen, "%llu.%02llux",
|
||||
(u_longlong_t)(val / 100),
|
||||
(u_longlong_t)(val % 100));
|
||||
zcp_check(zhp, prop, val, NULL);
|
||||
break;
|
||||
|
||||
case ZFS_PROP_TYPE:
|
||||
@ -2562,6 +2636,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
|
||||
abort();
|
||||
}
|
||||
(void) snprintf(propbuf, proplen, "%s", str);
|
||||
zcp_check(zhp, prop, NULL, propbuf);
|
||||
break;
|
||||
|
||||
case ZFS_PROP_MOUNTED:
|
||||
@ -2587,6 +2662,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
|
||||
* consumers.
|
||||
*/
|
||||
(void) strlcpy(propbuf, zhp->zfs_name, proplen);
|
||||
zcp_check(zhp, prop, NULL, propbuf);
|
||||
break;
|
||||
|
||||
case ZFS_PROP_MLSLABEL:
|
||||
@ -2640,26 +2716,33 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
|
||||
if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
|
||||
return (-1);
|
||||
(void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
|
||||
zcp_check(zhp, prop, val, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (zfs_prop_get_type(prop)) {
|
||||
case PROP_TYPE_NUMBER:
|
||||
if (get_numeric_property(zhp, prop, src,
|
||||
&source, &val) != 0)
|
||||
&source, &val) != 0) {
|
||||
return (-1);
|
||||
if (literal)
|
||||
}
|
||||
|
||||
if (literal) {
|
||||
(void) snprintf(propbuf, proplen, "%llu",
|
||||
(u_longlong_t)val);
|
||||
else
|
||||
} else {
|
||||
zfs_nicenum(val, propbuf, proplen);
|
||||
}
|
||||
zcp_check(zhp, prop, val, NULL);
|
||||
break;
|
||||
|
||||
case PROP_TYPE_STRING:
|
||||
str = getprop_string(zhp, prop, &source);
|
||||
if (str == NULL)
|
||||
return (-1);
|
||||
|
||||
(void) strlcpy(propbuf, str, proplen);
|
||||
zcp_check(zhp, prop, NULL, str);
|
||||
break;
|
||||
|
||||
case PROP_TYPE_INDEX:
|
||||
@ -2668,7 +2751,9 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
|
||||
return (-1);
|
||||
if (zfs_prop_index_to_string(prop, val, &strval) != 0)
|
||||
return (-1);
|
||||
|
||||
(void) strlcpy(propbuf, strval, proplen);
|
||||
zcp_check(zhp, prop, NULL, strval);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -55,15 +55,6 @@
|
||||
#define ZDIFF_REMOVED '-'
|
||||
#define ZDIFF_RENAMED 'R'
|
||||
|
||||
static boolean_t
|
||||
do_name_cmp(const char *fpath, const char *tpath)
|
||||
{
|
||||
char *fname, *tname;
|
||||
fname = strrchr(fpath, '/') + 1;
|
||||
tname = strrchr(tpath, '/') + 1;
|
||||
return (strcmp(fname, tname) == 0);
|
||||
}
|
||||
|
||||
typedef struct differ_info {
|
||||
zfs_handle_t *zhp;
|
||||
char *fromsnap;
|
||||
@ -262,7 +253,6 @@ static int
|
||||
write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
|
||||
{
|
||||
struct zfs_stat fsb, tsb;
|
||||
boolean_t same_name;
|
||||
mode_t fmode, tmode;
|
||||
char fobjname[MAXPATHLEN], tobjname[MAXPATHLEN];
|
||||
int fobjerr, tobjerr;
|
||||
@ -323,7 +313,6 @@ write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
|
||||
|
||||
if (fmode != tmode && fsb.zs_gen == tsb.zs_gen)
|
||||
tsb.zs_gen++; /* Force a generational difference */
|
||||
same_name = do_name_cmp(fobjname, tobjname);
|
||||
|
||||
/* Simple modification or no change */
|
||||
if (fsb.zs_gen == tsb.zs_gen) {
|
||||
@ -334,7 +323,7 @@ write_inuse_diffs_one(FILE *fp, differ_info_t *di, uint64_t dobj)
|
||||
if (change) {
|
||||
print_link_change(fp, di, change,
|
||||
change > 0 ? fobjname : tobjname, &tsb);
|
||||
} else if (same_name) {
|
||||
} else if (strcmp(fobjname, tobjname) == 0) {
|
||||
print_file(fp, di, ZDIFF_MODIFIED, fobjname, &tsb);
|
||||
} else {
|
||||
print_rename(fp, di, fobjname, tobjname, &tsb);
|
||||
|
@ -79,6 +79,7 @@ struct libzfs_handle {
|
||||
libzfs_fru_t **libzfs_fru_hash;
|
||||
libzfs_fru_t *libzfs_fru_list;
|
||||
char libzfs_chassis_id[256];
|
||||
boolean_t libzfs_prop_debug;
|
||||
};
|
||||
|
||||
#define ZFSSHARE_MISS 0x01 /* Didn't find entry in cache */
|
||||
|
@ -42,6 +42,7 @@
|
||||
* using our derived config, and record the results.
|
||||
*/
|
||||
|
||||
#include <aio.h>
|
||||
#include <ctype.h>
|
||||
#include <devid.h>
|
||||
#include <dirent.h>
|
||||
@ -865,6 +866,7 @@ label_offset(uint64_t size, int l)
|
||||
/*
|
||||
* Given a file descriptor, read the label information and return an nvlist
|
||||
* describing the configuration, if there is one.
|
||||
* Return 0 on success, or -1 on failure
|
||||
*/
|
||||
int
|
||||
zpool_read_label(int fd, nvlist_t **config)
|
||||
@ -877,7 +879,7 @@ zpool_read_label(int fd, nvlist_t **config)
|
||||
*config = NULL;
|
||||
|
||||
if (fstat64(fd, &statbuf) == -1)
|
||||
return (0);
|
||||
return (-1);
|
||||
size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t);
|
||||
|
||||
if ((label = malloc(sizeof (vdev_label_t))) == NULL)
|
||||
@ -911,20 +913,24 @@ zpool_read_label(int fd, nvlist_t **config)
|
||||
|
||||
free(label);
|
||||
*config = NULL;
|
||||
return (0);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a file descriptor, read the label information and return an nvlist
|
||||
* describing the configuration, if there is one.
|
||||
* returns the number of valid labels found
|
||||
* If a label is found, returns it via config. The caller is responsible for
|
||||
* freeing it.
|
||||
*/
|
||||
int
|
||||
zpool_read_all_labels(int fd, nvlist_t **config)
|
||||
{
|
||||
struct stat64 statbuf;
|
||||
struct aiocb aiocbs[VDEV_LABELS];
|
||||
struct aiocb *aiocbps[VDEV_LABELS];
|
||||
int l;
|
||||
vdev_label_t *label;
|
||||
vdev_phys_t *labels;
|
||||
uint64_t state, txg, size;
|
||||
int nlabels = 0;
|
||||
|
||||
@ -934,19 +940,40 @@ zpool_read_all_labels(int fd, nvlist_t **config)
|
||||
return (0);
|
||||
size = P2ALIGN_TYPED(statbuf.st_size, sizeof (vdev_label_t), uint64_t);
|
||||
|
||||
if ((label = malloc(sizeof (vdev_label_t))) == NULL)
|
||||
if ((labels = calloc(VDEV_LABELS, sizeof (vdev_phys_t))) == NULL)
|
||||
return (0);
|
||||
|
||||
memset(aiocbs, 0, sizeof(aiocbs));
|
||||
for (l = 0; l < VDEV_LABELS; l++) {
|
||||
aiocbs[l].aio_fildes = fd;
|
||||
aiocbs[l].aio_offset = label_offset(size, l) + VDEV_SKIP_SIZE;
|
||||
aiocbs[l].aio_buf = &labels[l];
|
||||
aiocbs[l].aio_nbytes = sizeof(vdev_phys_t);
|
||||
aiocbs[l].aio_lio_opcode = LIO_READ;
|
||||
aiocbps[l] = &aiocbs[l];
|
||||
}
|
||||
|
||||
if (lio_listio(LIO_WAIT, aiocbps, VDEV_LABELS, NULL) != 0) {
|
||||
if (errno == EAGAIN || errno == EINTR || errno == EIO) {
|
||||
for (l = 0; l < VDEV_LABELS; l++) {
|
||||
errno = 0;
|
||||
int r = aio_error(&aiocbs[l]);
|
||||
if (r != EINVAL)
|
||||
(void)aio_return(&aiocbs[l]);
|
||||
}
|
||||
}
|
||||
free(labels);
|
||||
return (0);
|
||||
}
|
||||
|
||||
for (l = 0; l < VDEV_LABELS; l++) {
|
||||
nvlist_t *temp = NULL;
|
||||
|
||||
/* TODO: use aio_read so we can read al 4 labels in parallel */
|
||||
if (pread64(fd, label, sizeof (vdev_label_t),
|
||||
label_offset(size, l)) != sizeof (vdev_label_t))
|
||||
if (aio_return(&aiocbs[l]) != sizeof(vdev_phys_t))
|
||||
continue;
|
||||
|
||||
if (nvlist_unpack(label->vl_vdev_phys.vp_nvlist,
|
||||
sizeof (label->vl_vdev_phys.vp_nvlist), &temp, 0) != 0)
|
||||
if (nvlist_unpack(labels[l].vp_nvlist,
|
||||
sizeof (labels[l].vp_nvlist), &temp, 0) != 0)
|
||||
continue;
|
||||
|
||||
if (nvlist_lookup_uint64(temp, ZPOOL_CONFIG_POOL_STATE,
|
||||
@ -969,7 +996,7 @@ zpool_read_all_labels(int fd, nvlist_t **config)
|
||||
nlabels++;
|
||||
}
|
||||
|
||||
free(label);
|
||||
free(labels);
|
||||
return (nlabels);
|
||||
}
|
||||
|
||||
@ -1148,7 +1175,7 @@ zpool_open_func(void *arg)
|
||||
}
|
||||
#endif /* illumos */
|
||||
|
||||
if ((zpool_read_label(fd, &config)) != 0) {
|
||||
if ((zpool_read_label(fd, &config)) != 0 && errno == ENOMEM) {
|
||||
(void) close(fd);
|
||||
(void) no_memory(rn->rn_hdl);
|
||||
return;
|
||||
@ -1649,7 +1676,7 @@ zpool_in_use(libzfs_handle_t *hdl, int fd, pool_state_t *state, char **namestr,
|
||||
|
||||
*inuse = B_FALSE;
|
||||
|
||||
if (zpool_read_label(fd, &config) != 0) {
|
||||
if (zpool_read_label(fd, &config) != 0 && errno == ENOMEM) {
|
||||
(void) no_memory(hdl);
|
||||
return (-1);
|
||||
}
|
||||
|
@ -2295,6 +2295,7 @@ vdev_get_physpaths(nvlist_t *nv, char *physpath, size_t phypath_size,
|
||||
return (ret);
|
||||
}
|
||||
} else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 ||
|
||||
strcmp(type, VDEV_TYPE_RAIDZ) == 0 ||
|
||||
strcmp(type, VDEV_TYPE_REPLACING) == 0 ||
|
||||
(is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) {
|
||||
nvlist_t **child;
|
||||
|
@ -3212,7 +3212,12 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
/*
|
||||
* Determine the name of the origin snapshot, store in zc_string.
|
||||
*/
|
||||
if (drrb->drr_flags & DRR_FLAG_CLONE) {
|
||||
if (originsnap) {
|
||||
(void) strncpy(zc.zc_string, originsnap, sizeof (zc.zc_string));
|
||||
if (flags->verbose)
|
||||
(void) printf("using provided clone origin %s\n",
|
||||
zc.zc_string);
|
||||
} else if (drrb->drr_flags & DRR_FLAG_CLONE) {
|
||||
if (guid_to_name(hdl, zc.zc_value,
|
||||
drrb->drr_fromguid, B_FALSE, zc.zc_string) != 0) {
|
||||
zcmd_free_nvlists(&zc);
|
||||
@ -3223,11 +3228,6 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
|
||||
}
|
||||
if (flags->verbose)
|
||||
(void) printf("found clone origin %s\n", zc.zc_string);
|
||||
} else if (originsnap) {
|
||||
(void) strncpy(zc.zc_string, originsnap, sizeof (zc.zc_string));
|
||||
if (flags->verbose)
|
||||
(void) printf("using provided clone origin %s\n",
|
||||
zc.zc_string);
|
||||
}
|
||||
|
||||
boolean_t resuming = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include <sys/mnttab.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <sys/types.h>
|
||||
#include <libcmdutils.h>
|
||||
|
||||
#include <libzfs.h>
|
||||
#include <libzfs_core.h>
|
||||
@ -579,42 +580,7 @@ zfs_strdup(libzfs_handle_t *hdl, const char *str)
|
||||
void
|
||||
zfs_nicenum(uint64_t num, char *buf, size_t buflen)
|
||||
{
|
||||
uint64_t n = num;
|
||||
int index = 0;
|
||||
char u;
|
||||
|
||||
while (n >= 1024) {
|
||||
n /= 1024;
|
||||
index++;
|
||||
}
|
||||
|
||||
u = " KMGTPE"[index];
|
||||
|
||||
if (index == 0) {
|
||||
(void) snprintf(buf, buflen, "%llu", n);
|
||||
} else if ((num & ((1ULL << 10 * index) - 1)) == 0) {
|
||||
/*
|
||||
* If this is an even multiple of the base, always display
|
||||
* without any decimal precision.
|
||||
*/
|
||||
(void) snprintf(buf, buflen, "%llu%c", n, u);
|
||||
} else {
|
||||
/*
|
||||
* We want to choose a precision that reflects the best choice
|
||||
* for fitting in 5 characters. This can get rather tricky when
|
||||
* we have numbers that are very close to an order of magnitude.
|
||||
* For example, when displaying 10239 (which is really 9.999K),
|
||||
* we want only a single place of precision for 10.0K. We could
|
||||
* develop some complex heuristics for this, but it's much
|
||||
* easier just to try each combination in turn.
|
||||
*/
|
||||
int i;
|
||||
for (i = 2; i >= 0; i--) {
|
||||
if (snprintf(buf, buflen, "%.*f%c", i,
|
||||
(double)num / (1ULL << 10 * index), u) <= 5)
|
||||
break;
|
||||
}
|
||||
}
|
||||
nicenum(num, buf, buflen);
|
||||
}
|
||||
|
||||
void
|
||||
@ -678,6 +644,10 @@ libzfs_init(void)
|
||||
zpool_feature_init();
|
||||
libzfs_mnttab_init(hdl);
|
||||
|
||||
if (getenv("ZFS_PROP_DEBUG") != NULL) {
|
||||
hdl->libzfs_prop_debug = B_TRUE;
|
||||
}
|
||||
|
||||
return (hdl);
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2017 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||
* Copyright (c) 2014 Integros [integros.com]
|
||||
* Copyright 2017 RackTop Systems.
|
||||
@ -160,7 +160,12 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
|
||||
|
||||
if (resultp != NULL) {
|
||||
*resultp = NULL;
|
||||
zc.zc_nvlist_dst_size = MAX(size * 2, 128 * 1024);
|
||||
if (ioc == ZFS_IOC_CHANNEL_PROGRAM) {
|
||||
zc.zc_nvlist_dst_size = fnvlist_lookup_uint64(source,
|
||||
ZCP_ARG_MEMLIMIT);
|
||||
} else {
|
||||
zc.zc_nvlist_dst_size = MAX(size * 2, 128 * 1024);
|
||||
}
|
||||
zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
|
||||
malloc(zc.zc_nvlist_dst_size);
|
||||
#ifdef illumos
|
||||
@ -174,7 +179,15 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
|
||||
}
|
||||
|
||||
while (ioctl(g_fd, ioc, &zc) != 0) {
|
||||
if (errno == ENOMEM && resultp != NULL) {
|
||||
/*
|
||||
* If ioctl exited with ENOMEM, we retry the ioctl after
|
||||
* increasing the size of the destination nvlist.
|
||||
*
|
||||
* Channel programs that exit with ENOMEM ran over the
|
||||
* lua memory sandbox; they should not be retried.
|
||||
*/
|
||||
if (errno == ENOMEM && resultp != NULL &&
|
||||
ioc != ZFS_IOC_CHANNEL_PROGRAM) {
|
||||
free((void *)(uintptr_t)zc.zc_nvlist_dst);
|
||||
zc.zc_nvlist_dst_size *= 2;
|
||||
zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
|
||||
@ -904,3 +917,54 @@ lzc_destroy_bookmarks(nvlist_t *bmarks, nvlist_t **errlist)
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Executes a channel program.
|
||||
*
|
||||
* If this function returns 0 the channel program was successfully loaded and
|
||||
* ran without failing. Note that individual commands the channel program ran
|
||||
* may have failed and the channel program is responsible for reporting such
|
||||
* errors through outnvl if they are important.
|
||||
*
|
||||
* This method may also return:
|
||||
*
|
||||
* EINVAL The program contains syntax errors, or an invalid memory or time
|
||||
* limit was given. No part of the channel program was executed.
|
||||
* If caused by syntax errors, 'outnvl' contains information about the
|
||||
* errors.
|
||||
*
|
||||
* EDOM The program was executed, but encountered a runtime error, such as
|
||||
* calling a function with incorrect arguments, invoking the error()
|
||||
* function directly, failing an assert() command, etc. Some portion
|
||||
* of the channel program may have executed and committed changes.
|
||||
* Information about the failure can be found in 'outnvl'.
|
||||
*
|
||||
* ENOMEM The program fully executed, but the output buffer was not large
|
||||
* enough to store the returned value. No output is returned through
|
||||
* 'outnvl'.
|
||||
*
|
||||
* ENOSPC The program was terminated because it exceeded its memory usage
|
||||
* limit. Some portion of the channel program may have executed and
|
||||
* committed changes to disk. No output is returned through 'outnvl'.
|
||||
*
|
||||
* ETIMEDOUT The program was terminated because it exceeded its Lua instruction
|
||||
* limit. Some portion of the channel program may have executed and
|
||||
* committed changes to disk. No output is returned through 'outnvl'.
|
||||
*/
|
||||
int
|
||||
lzc_channel_program(const char *pool, const char *program, uint64_t instrlimit,
|
||||
uint64_t memlimit, nvlist_t *argnvl, nvlist_t **outnvl)
|
||||
{
|
||||
int error;
|
||||
nvlist_t *args;
|
||||
|
||||
args = fnvlist_alloc();
|
||||
fnvlist_add_string(args, ZCP_ARG_PROGRAM, program);
|
||||
fnvlist_add_nvlist(args, ZCP_ARG_ARGLIST, argnvl);
|
||||
fnvlist_add_uint64(args, ZCP_ARG_INSTRLIMIT, instrlimit);
|
||||
fnvlist_add_uint64(args, ZCP_ARG_MEMLIMIT, memlimit);
|
||||
error = lzc_ioctl(ZFS_IOC_CHANNEL_PROGRAM, pool, args, outnvl);
|
||||
fnvlist_free(args);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
* Copyright 2017 RackTop Systems.
|
||||
*/
|
||||
@ -86,6 +86,9 @@ boolean_t lzc_exists(const char *);
|
||||
int lzc_rollback(const char *, char *, int);
|
||||
int lzc_rollback_to(const char *, const char *);
|
||||
|
||||
int lzc_channel_program(const char *, const char *, uint64_t, uint64_t,
|
||||
nvlist_t *, nvlist_t **);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -738,6 +738,7 @@ vpanic(const char *fmt, va_list adx)
|
||||
char buf[512];
|
||||
(void) vsnprintf(buf, 512, fmt, adx);
|
||||
assfail(buf, NULL, 0);
|
||||
abort(); /* necessary to make vpanic meet noreturn requirements */
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
@ -66,6 +66,7 @@ extern "C" {
|
||||
#include <fsshare.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <setjmp.h>
|
||||
#include <sys/debug.h>
|
||||
#include <sys/note.h>
|
||||
#include <sys/types.h>
|
||||
@ -126,8 +127,8 @@ extern void dprintf_setup(int *argc, char **argv);
|
||||
|
||||
extern void cmn_err(int, const char *, ...);
|
||||
extern void vcmn_err(int, const char *, __va_list);
|
||||
extern void panic(const char *, ...);
|
||||
extern void vpanic(const char *, __va_list);
|
||||
extern void panic(const char *, ...) __NORETURN;
|
||||
extern void vpanic(const char *, __va_list) __NORETURN;
|
||||
|
||||
#define fm_panic panic
|
||||
|
||||
@ -349,6 +350,7 @@ extern void cv_broadcast(kcondvar_t *cv);
|
||||
#define KM_SLEEP UMEM_NOFAIL
|
||||
#define KM_PUSHPAGE KM_SLEEP
|
||||
#define KM_NOSLEEP UMEM_DEFAULT
|
||||
#define KM_NORMALPRI 0 /* not needed with UMEM_DEFAULT */
|
||||
#define KMC_NODEBUG UMC_NODEBUG
|
||||
#define KMC_NOTOUCH 0 /* not needed for userland caches */
|
||||
#define KM_NODEBUG 0
|
||||
@ -579,8 +581,9 @@ extern void kernel_init(int);
|
||||
extern void kernel_fini(void);
|
||||
|
||||
struct spa;
|
||||
extern void nicenum(uint64_t num, char *buf);
|
||||
extern void nicenum(uint64_t num, char *buf, size_t);
|
||||
extern void show_pool_stats(struct spa *);
|
||||
extern int set_global_var(char *arg);
|
||||
|
||||
typedef struct callb_cpr {
|
||||
kmutex_t *cc_lockp;
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@ -31,38 +32,12 @@
|
||||
#include <sys/spa.h>
|
||||
#include <sys/fs/zfs.h>
|
||||
#include <sys/refcount.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
/*
|
||||
* Routines needed by more than one client of libzpool.
|
||||
*/
|
||||
|
||||
void
|
||||
nicenum(uint64_t num, char *buf)
|
||||
{
|
||||
uint64_t n = num;
|
||||
int index = 0;
|
||||
char u;
|
||||
|
||||
while (n >= 1024) {
|
||||
n = (n + (1024 / 2)) / 1024; /* Round up or down */
|
||||
index++;
|
||||
}
|
||||
|
||||
u = " KMGTPE"[index];
|
||||
|
||||
if (index == 0) {
|
||||
(void) sprintf(buf, "%llu", (u_longlong_t)n);
|
||||
} else if (n < 10 && (num & (num - 1)) != 0) {
|
||||
(void) sprintf(buf, "%.2f%c",
|
||||
(double)num / (1ULL << 10 * index), u);
|
||||
} else if (n < 100 && (num & (num - 1)) != 0) {
|
||||
(void) sprintf(buf, "%.1f%c",
|
||||
(double)num / (1ULL << 10 * index), u);
|
||||
} else {
|
||||
(void) sprintf(buf, "%llu%c", (u_longlong_t)n, u);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
|
||||
{
|
||||
@ -95,15 +70,17 @@ show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent)
|
||||
|
||||
sec = MAX(1, vs->vs_timestamp / NANOSEC);
|
||||
|
||||
nicenum(vs->vs_alloc, used);
|
||||
nicenum(vs->vs_space - vs->vs_alloc, avail);
|
||||
nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops);
|
||||
nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops);
|
||||
nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes);
|
||||
nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes);
|
||||
nicenum(vs->vs_read_errors, rerr);
|
||||
nicenum(vs->vs_write_errors, werr);
|
||||
nicenum(vs->vs_checksum_errors, cerr);
|
||||
nicenum(vs->vs_alloc, used, sizeof (used));
|
||||
nicenum(vs->vs_space - vs->vs_alloc, avail, sizeof (avail));
|
||||
nicenum(vs->vs_ops[ZIO_TYPE_READ] / sec, rops, sizeof (rops));
|
||||
nicenum(vs->vs_ops[ZIO_TYPE_WRITE] / sec, wops, sizeof (wops));
|
||||
nicenum(vs->vs_bytes[ZIO_TYPE_READ] / sec, rbytes,
|
||||
sizeof (rbytes));
|
||||
nicenum(vs->vs_bytes[ZIO_TYPE_WRITE] / sec, wbytes,
|
||||
sizeof (wbytes));
|
||||
nicenum(vs->vs_read_errors, rerr, sizeof (rerr));
|
||||
nicenum(vs->vs_write_errors, werr, sizeof (werr));
|
||||
nicenum(vs->vs_checksum_errors, cerr, sizeof (cerr));
|
||||
|
||||
(void) printf("%*s%s%*s%*s%*s %5s %5s %5s %5s %5s %5s %5s\n",
|
||||
indent, "",
|
||||
@ -153,3 +130,58 @@ show_pool_stats(spa_t *spa)
|
||||
|
||||
nvlist_free(config);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets given global variable in libzpool to given unsigned 32-bit value.
|
||||
* arg: "<variable>=<value>"
|
||||
*/
|
||||
int
|
||||
set_global_var(char *arg)
|
||||
{
|
||||
void *zpoolhdl;
|
||||
char *varname = arg, *varval;
|
||||
u_longlong_t val;
|
||||
|
||||
#ifndef _LITTLE_ENDIAN
|
||||
/*
|
||||
* On big endian systems changing a 64-bit variable would set the high
|
||||
* 32 bits instead of the low 32 bits, which could cause unexpected
|
||||
* results.
|
||||
*/
|
||||
fprintf(stderr, "Setting global variables is only supported on "
|
||||
"little-endian systems\n", varname);
|
||||
return (ENOTSUP);
|
||||
#endif
|
||||
if ((varval = strchr(arg, '=')) != NULL) {
|
||||
*varval = '\0';
|
||||
varval++;
|
||||
val = strtoull(varval, NULL, 0);
|
||||
if (val > UINT32_MAX) {
|
||||
fprintf(stderr, "Value for global variable '%s' must "
|
||||
"be a 32-bit unsigned integer\n", varname);
|
||||
return (EOVERFLOW);
|
||||
}
|
||||
} else {
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
zpoolhdl = dlopen("libzpool.so", RTLD_LAZY);
|
||||
if (zpoolhdl != NULL) {
|
||||
uint32_t *var;
|
||||
var = dlsym(zpoolhdl, varname);
|
||||
if (var == NULL) {
|
||||
fprintf(stderr, "Global variable '%s' does not exist "
|
||||
"in libzpool.so\n", varname);
|
||||
return (EINVAL);
|
||||
}
|
||||
*var = (uint32_t)val;
|
||||
|
||||
dlclose(zpoolhdl);
|
||||
} else {
|
||||
fprintf(stderr, "Failed to open libzpool.so to set global "
|
||||
"variable\n");
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
DIRDEPS = \
|
||||
gnu/lib/csu \
|
||||
gnu/lib/libgcc \
|
||||
include \
|
||||
lib/${CSU_DIR} \
|
||||
lib/libc \
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user