Merge branch 'main' of https://github.com/freebsd/freebsd
This commit is contained in:
commit
f4cf3aa68b
@ -1,5 +1,6 @@
|
||||
{
|
||||
"repository.callsign" : "S",
|
||||
"phabricator.uri" : "https://reviews.freebsd.org/",
|
||||
"history.immutable" : true
|
||||
"arc.land.onto.default": "main",
|
||||
"arc.land.onto": ["main"]
|
||||
}
|
||||
|
25
.cirrus.yml
25
.cirrus.yml
@ -1,27 +1,34 @@
|
||||
# $FreeBSD$
|
||||
|
||||
freebsd_instance:
|
||||
# image: freebsd-12-1-stable-amd64
|
||||
# We need a newer image to install llvm11
|
||||
image_family: freebsd-12-1-snap
|
||||
compute_engine_instance:
|
||||
# Image list available via
|
||||
# gcloud compute images list --project freebsd-org-cloud-dev --no-standard-images
|
||||
platform: freebsd
|
||||
image_project: freebsd-org-cloud-dev
|
||||
image: freebsd-13-0-release-amd64
|
||||
cpu: 8
|
||||
memory: 24G
|
||||
disk: 40
|
||||
|
||||
env:
|
||||
CIRRUS_CLONE_DEPTH: 1
|
||||
|
||||
task:
|
||||
only_if: $CIRRUS_BRANCH != 'svn_head'
|
||||
timeout_in: 120m
|
||||
install_script:
|
||||
- pkg install -y qemu42 uefi-edk2-qemu-x86_64 llvm11
|
||||
setup_user_script:
|
||||
- pkg install -y qemu uefi-edk2-qemu-x86_64 llvm12
|
||||
setup_script:
|
||||
- uname -a
|
||||
- df -m
|
||||
- pw useradd user
|
||||
- mkdir -p /usr/obj/$(pwd -P)
|
||||
- chown user:user /usr/obj/$(pwd -P)
|
||||
script:
|
||||
- su user -c "make -j$(sysctl -n hw.ncpu) CROSS_TOOLCHAIN=llvm11 WITHOUT_TOOLCHAIN=yes buildworld buildkernel"
|
||||
- su user -c "make -j$(sysctl -n hw.ncpu) CROSS_TOOLCHAIN=llvm12 WITHOUT_TOOLCHAIN=yes buildworld buildkernel"
|
||||
package_script:
|
||||
- su user -c "make CROSS_TOOLCHAIN=llvm11 WITHOUT_TOOLCHAIN=yes PKG_FORMAT=tar packages"
|
||||
- su user -c "make CROSS_TOOLCHAIN=llvm12 WITHOUT_TOOLCHAIN=yes PKG_FORMAT=tar packages"
|
||||
test_script:
|
||||
- sh tools/boot/ci-qemu-test.sh
|
||||
post_script:
|
||||
- df -m
|
||||
- du -m -s /usr/obj
|
||||
|
9
.github/workflows/cross-bootstrap-tools.yml
vendored
9
.github/workflows/cross-bootstrap-tools.yml
vendored
@ -2,9 +2,9 @@ name: Cross-build Kernel
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
branches: [ main, 'stable/13' ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@ -25,8 +25,7 @@ jobs:
|
||||
pkgs: bmake libarchive-dev
|
||||
- os: macOS-latest
|
||||
compiler: clang-11
|
||||
#cross-bindir: /usr/local/Cellar/llvm/11.0.0/bin # script figures this out automatically
|
||||
pkgs: bmake libarchive llvm@11
|
||||
pkgs: bmake libarchive
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@ -39,7 +38,7 @@ jobs:
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew update --quiet || true
|
||||
brew install ${{ matrix.pkgs }}
|
||||
brew install ${{ matrix.pkgs }} || true
|
||||
- name: create environment
|
||||
run: |
|
||||
echo "GITHUB_WORKSPACE = $GITHUB_WORKSPACE"
|
||||
|
10
.gitignore
vendored
10
.gitignore
vendored
@ -1,3 +1,9 @@
|
||||
*.a
|
||||
*.core
|
||||
*.o
|
||||
*.so
|
||||
*.swp
|
||||
*~
|
||||
_.tinderbox.*
|
||||
_.universe-toolchain
|
||||
_.amd64.*
|
||||
@ -15,5 +21,7 @@ GPATH
|
||||
GRTAGS
|
||||
GTAGS
|
||||
ID
|
||||
cscope.files
|
||||
cscope.in.out
|
||||
cscope.out
|
||||
?cscope.out
|
||||
cscope.po.out
|
||||
|
@ -1,10 +1,9 @@
|
||||
# $FreeBSD$
|
||||
# @(#)COPYRIGHT 8.2 (Berkeley) 3/21/94
|
||||
|
||||
The compilation of software known as FreeBSD is distributed under the
|
||||
following terms:
|
||||
|
||||
Copyright (c) 1992-2020 The FreeBSD Project.
|
||||
Copyright (c) 1992-2021 The FreeBSD Project.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
4
Makefile
4
Makefile
@ -458,8 +458,8 @@ MMAKE= ${MMAKEENV} ${MAKE} \
|
||||
OBJTOP=${MYMAKE:H}/obj \
|
||||
OBJROOT='$${OBJTOP}/' \
|
||||
MAKEOBJDIRPREFIX= \
|
||||
MAN= -DNO_SHARED \
|
||||
-DNO_CPU_CFLAGS -DNO_WERROR \
|
||||
MK_MAN=no -DNO_SHARED \
|
||||
-DNO_CPU_CFLAGS MK_WERROR=no \
|
||||
-DNO_SUBDIR \
|
||||
DESTDIR= PROGNAME=${MYMAKE:T}
|
||||
|
||||
|
122
Makefile.inc1
122
Makefile.inc1
@ -137,9 +137,9 @@ TARGET_ABI= gnueabi
|
||||
.endif
|
||||
.endif
|
||||
MACHINE_ABI?= unknown
|
||||
MACHINE_TRIPLE?=${MACHINE_ARCH:S/amd64/x86_64/:C/[hs]f$//:S/mipsn32/mips64/}-${MACHINE_ABI}-freebsd13.0
|
||||
MACHINE_TRIPLE?=${MACHINE_ARCH:S/amd64/x86_64/:C/[hs]f$//:S/mipsn32/mips64/}-${MACHINE_ABI}-freebsd14.0
|
||||
TARGET_ABI?= unknown
|
||||
TARGET_TRIPLE?= ${TARGET_ARCH:S/amd64/x86_64/:C/[hs]f$//:S/mipsn32/mips64/}-${TARGET_ABI}-freebsd13.0
|
||||
TARGET_TRIPLE?= ${TARGET_ARCH:S/amd64/x86_64/:C/[hs]f$//:S/mipsn32/mips64/}-${TARGET_ABI}-freebsd14.0
|
||||
KNOWN_ARCHES?= aarch64/arm64 \
|
||||
amd64 \
|
||||
armv6/arm \
|
||||
@ -199,7 +199,7 @@ MK_SYSTEM_LINKER= no
|
||||
.if defined(CROSS_TOOLCHAIN_PREFIX)
|
||||
CROSS_BINUTILS_PREFIX?=${CROSS_TOOLCHAIN_PREFIX}
|
||||
.endif
|
||||
XBINUTILS= AS AR LD NM OBJCOPY RANLIB SIZE STRINGS STRIPBIN
|
||||
XBINUTILS= AS AR ELFCTL LD NM OBJCOPY RANLIB SIZE STRINGS STRIPBIN
|
||||
.for BINUTIL in ${XBINUTILS}
|
||||
.if defined(CROSS_BINUTILS_PREFIX) && \
|
||||
exists(${CROSS_BINUTILS_PREFIX}/${${BINUTIL}})
|
||||
@ -540,14 +540,12 @@ OSRELDATE= 0
|
||||
.endif
|
||||
|
||||
# Set VERSION for CTFMERGE to use via the default CTFFLAGS=-L VERSION.
|
||||
.if !defined(_REVISION)
|
||||
_REVISION!= ${MAKE} -C ${SRCDIR}/release MK_AUTO_OBJ=no -V REVISION
|
||||
.export _REVISION
|
||||
.endif
|
||||
.if !defined(_BRANCH)
|
||||
_BRANCH!= ${MAKE} -C ${SRCDIR}/release MK_AUTO_OBJ=no -V BRANCH
|
||||
.export _BRANCH
|
||||
.for _V in BRANCH REVISION
|
||||
.if !defined(_${_V})
|
||||
_${_V}!= eval $$(awk '/^${_V}=/{print}' ${SRCTOP}/sys/conf/newvers.sh); echo $$${_V}
|
||||
.export _${_V}
|
||||
.endif
|
||||
.endfor
|
||||
.if !defined(SRCRELDATE)
|
||||
SRCRELDATE!= awk '/^\#define[[:space:]]*__FreeBSD_version/ { print $$3 }' \
|
||||
${SRCDIR}/sys/sys/param.h
|
||||
@ -559,21 +557,21 @@ VERSION= FreeBSD ${_REVISION}-${_BRANCH:C/-p[0-9]+$//} ${TARGET_ARCH} ${SRCRELDA
|
||||
.endif
|
||||
|
||||
.if !defined(PKG_VERSION)
|
||||
.if ${_BRANCH:MSTABLE*} || ${_BRANCH:MCURRENT*}
|
||||
TIMENOW= %Y%m%d%H%M%S
|
||||
EXTRA_REVISION= .s${TIMENOW:gmtime}
|
||||
_STRTIMENOW= %Y%m%d%H%M%S
|
||||
_TIMENOW= ${_STRTIMENOW:gmtime}
|
||||
.if ${_BRANCH:MCURRENT*} || ${_BRANCH:MSTABLE*} || ${_BRANCH:MPRERELEASE*}
|
||||
_REVISION:= ${_REVISION:R}
|
||||
EXTRA_REVISION= .snap${_TIMENOW}
|
||||
.elif ${_BRANCH:MALPHA*}
|
||||
EXTRA_REVISION= _${_BRANCH:C/-ALPHA/.a/}
|
||||
EXTRA_REVISION= .a${_BRANCH:C/ALPHA([0-9]+).*/\1/}.${_TIMENOW}
|
||||
.elif ${_BRANCH:MBETA*}
|
||||
EXTRA_REVISION= _${_BRANCH:C/-BETA/.b/}
|
||||
EXTRA_REVISION= .b${_BRANCH:C/BETA([0-9]+).*/\1/}.${_TIMENOW}
|
||||
.elif ${_BRANCH:MRC*}
|
||||
EXTRA_REVISION= _${_BRANCH:C/-RC/.r/}
|
||||
.elif ${_BRANCH:MPRERELEASE*}
|
||||
EXTRA_REVISION= _${_BRANCH:C/-PRERELEASE/.p/}
|
||||
EXTRA_REVISION= .rc${_BRANCH:C/RC([0-9]+).*/\1/}.${_TIMENOW}
|
||||
.elif ${_BRANCH:M*-p*}
|
||||
EXTRA_REVISION= _${_BRANCH:C/.*-p([0-9]+$)/\1/}
|
||||
EXTRA_REVISION= p${_BRANCH:C/.*-p([0-9]+$)/\1/}
|
||||
.endif
|
||||
PKG_VERSION:= ${_REVISION}${EXTRA_REVISION}
|
||||
PKG_VERSION:= ${_REVISION}${EXTRA_REVISION:C/[[:space:]]//g}
|
||||
.endif
|
||||
.endif # !defined(PKG_VERSION)
|
||||
|
||||
@ -731,7 +729,7 @@ BSARGS= DESTDIR= \
|
||||
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 \
|
||||
-DNO_CPU_CFLAGS MK_WERROR=no MK_CTF=no \
|
||||
MK_CLANG_EXTRAS=no MK_CLANG_FORMAT=no MK_CLANG_FULL=no \
|
||||
MK_LLDB=no MK_RETPOLINE=no MK_TESTS=no \
|
||||
MK_INCLUDES=yes
|
||||
@ -752,7 +750,7 @@ TMAKE= \
|
||||
BWPHASE=${.TARGET:C,^_,,} \
|
||||
SSP_CFLAGS= \
|
||||
-DNO_LINT \
|
||||
-DNO_CPU_CFLAGS MK_WARNS=no MK_CTF=no \
|
||||
-DNO_CPU_CFLAGS MK_WERROR=no MK_CTF=no \
|
||||
MK_CLANG_EXTRAS=no MK_CLANG_FORMAT=no MK_CLANG_FULL=no \
|
||||
MK_LLDB=no MK_RETPOLINE=no MK_TESTS=no
|
||||
|
||||
@ -780,7 +778,7 @@ KTMAKE= \
|
||||
SSP_CFLAGS= \
|
||||
MK_HTML=no -DNO_LINT MK_MAN=no \
|
||||
-DNO_PIC MK_PROFILE=no -DNO_SHARED \
|
||||
-DNO_CPU_CFLAGS MK_RETPOLINE=no MK_WARNS=no MK_CTF=no
|
||||
-DNO_CPU_CFLAGS MK_RETPOLINE=no MK_WERROR=no MK_CTF=no
|
||||
|
||||
# world stage
|
||||
WMAKEENV= ${CROSSENV} \
|
||||
@ -796,8 +794,8 @@ HMAKE+= PATH=${TMPPATH} METALOG=${METALOG} -DNO_ROOT
|
||||
|
||||
CROSSENV+= CC="${XCC} ${XCFLAGS}" CXX="${XCXX} ${XCXXFLAGS} ${XCFLAGS}" \
|
||||
CPP="${XCPP} ${XCFLAGS}" \
|
||||
AS="${XAS}" AR="${XAR}" LD="${XLD}" LLVM_LINK="${XLLVM_LINK}" \
|
||||
NM=${XNM} OBJCOPY="${XOBJCOPY}" \
|
||||
AS="${XAS}" AR="${XAR}" ELFCTL="${XELFCTL}" LD="${XLD}" \
|
||||
LLVM_LINK="${XLLVM_LINK}" NM=${XNM} OBJCOPY="${XOBJCOPY}" \
|
||||
RANLIB=${XRANLIB} STRINGS=${XSTRINGS} \
|
||||
SIZE="${XSIZE}" STRIPBIN="${XSTRIPBIN}"
|
||||
|
||||
@ -1713,7 +1711,15 @@ buildkernel: .MAKE .PHONY
|
||||
echo "ncpu: $$(${_ncpu_cmd})${.MAKE.JOBS:S/^/, make -j/}"
|
||||
@echo "--------------------------------------------------------------"
|
||||
|
||||
.if !make(packages) && !make(update-packages)
|
||||
NO_INSTALLEXTRAKERNELS?= yes
|
||||
.else
|
||||
# packages/update-packages installs kernels to a staging directory then builds
|
||||
# packages from the result to be installed, typically to other systems. It is
|
||||
# less surprising for these targets to honor KERNCONF if multiple kernels are
|
||||
# specified.
|
||||
NO_INSTALLEXTRAKERNELS?= no
|
||||
.endif
|
||||
|
||||
#
|
||||
# installkernel, etc.
|
||||
@ -1851,7 +1857,7 @@ WSTAGEDIR?= ${OBJTOP}/worldstage
|
||||
KSTAGEDIR?= ${OBJTOP}/kernelstage
|
||||
REPODIR?= ${OBJROOT}repo
|
||||
PKG_FORMAT?= txz
|
||||
PKGSIGNKEY?= # empty
|
||||
PKG_REPO_SIGNING_KEY?= # empty
|
||||
PKG_OUTPUT_DIR?= ${PKG_VERSION}
|
||||
|
||||
.ORDER: stage-packages create-packages
|
||||
@ -1868,17 +1874,26 @@ _pkgbootstrap: .PHONY
|
||||
PKG_ABI!=${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname config ABI
|
||||
.endif
|
||||
|
||||
.if !defined(PKG_VERSION_FROM)
|
||||
.if !defined(PKG_VERSION_FROM) && make(real-update-packages)
|
||||
.if defined(PKG_ABI)
|
||||
.if exists(${REPODIR}/${PKG_ABI})
|
||||
PKG_VERSION_FROM!=/usr/bin/readlink ${REPODIR}/${PKG_ABI}/latest
|
||||
PKG_VERSION_FROM_DIR= ${REPODIR}/${PKG_ABI}/${PKG_VERSION_FROM}
|
||||
.else
|
||||
PKG_VERSION_FROM=
|
||||
PKG_VERSION_FROM_DIR=
|
||||
.endif
|
||||
.endif
|
||||
.endif
|
||||
|
||||
PKGMAKEARGS+= PKG_VERSION=${PKG_VERSION} \
|
||||
NO_INSTALLEXTRAKERNELS=${NO_INSTALLEXTRAKERNELS}
|
||||
|
||||
packages: .PHONY
|
||||
${_+_}${MAKE} -C ${.CURDIR} PKG_VERSION=${PKG_VERSION} real-packages
|
||||
${_+_}${MAKE} -C ${.CURDIR} ${PKGMAKEARGS} real-packages
|
||||
|
||||
update-packages: .PHONY
|
||||
${_+_}${MAKE} -C ${.CURDIR} PKG_VERSION=${PKG_VERSION} real-update-packages
|
||||
${_+_}${MAKE} -C ${.CURDIR} ${PKGMAKEARGS} real-update-packages
|
||||
|
||||
package-pkg: .PHONY
|
||||
rm -rf /tmp/ports.${TARGET} || :
|
||||
@ -1891,8 +1906,11 @@ real-packages: stage-packages create-packages sign-packages .PHONY
|
||||
|
||||
real-update-packages: stage-packages .PHONY
|
||||
${_+_}${MAKE} -C ${.CURDIR} PKG_VERSION=${PKG_VERSION} create-packages
|
||||
.if empty(PKG_VERSION_FROM_DIR)
|
||||
@echo "==> Bootstrapping repository, not checking for new packages"
|
||||
.else
|
||||
@echo "==> Checking for new packages (comparing ${PKG_VERSION} to ${PKG_VERSION_FROM})"
|
||||
@for pkg in ${REPODIR}/${PKG_ABI}/${PKG_VERSION_FROM}/${PKG_NAME_PREFIX}-*; do \
|
||||
@for pkg in ${PKG_VERSION_FROM_DIR}/${PKG_NAME_PREFIX}-*; do \
|
||||
pkgname=$$(pkg query -F $${pkg} '%n' | sed 's/${PKG_NAME_PREFIX}-\(.*\)/\1/') ; \
|
||||
newpkgname=${PKG_NAME_PREFIX}-$${pkgname}-${PKG_VERSION}.${PKG_FORMAT} ; \
|
||||
oldsum=$$(pkg query -F $${pkg} '%X') ; \
|
||||
@ -1908,6 +1926,7 @@ real-update-packages: stage-packages .PHONY
|
||||
echo "==> New package $${newpkgname}" ; \
|
||||
fi ; \
|
||||
done
|
||||
.endif
|
||||
${_+_}@cd ${.CURDIR}; \
|
||||
${MAKE} -f Makefile.inc1 PKG_VERSION=${PKG_VERSION} sign-packages
|
||||
|
||||
@ -2064,7 +2083,7 @@ sign-packages: _pkgbootstrap .PHONY
|
||||
-m ${WSTAGEDIR}/meta \
|
||||
-o ${REPODIR}/$$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname config ABI)/${PKG_VERSION} \
|
||||
${REPODIR}/$$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname config ABI)/${PKG_VERSION} \
|
||||
${PKGSIGNKEY} ; \
|
||||
${PKG_REPO_SIGNING_KEY} ; \
|
||||
cd ${REPODIR}/$$(${PKG_CMD} -o ABI_FILE=${WSTAGEDIR}/usr/bin/uname config ABI); \
|
||||
ln -s ${PKG_OUTPUT_DIR} latest
|
||||
|
||||
@ -2190,9 +2209,9 @@ ${_bt}-usr.sbin/config: ${_bt}-lib/libnv ${_bt}-lib/libsbuf
|
||||
_strfile= usr.bin/fortune/strfile
|
||||
.endif
|
||||
|
||||
.if ${MK_VT} != "no"
|
||||
# vtfontcvt is used to build font files for loader and to generate
|
||||
# C source for loader built in font (8x16.c).
|
||||
_vtfontcvt= usr.bin/vtfontcvt
|
||||
.endif
|
||||
|
||||
# If we are not building the bootstrap because BOOTSTRAPPING is sufficient
|
||||
# we symlink the host version to $WORLDTMP instead. By doing this we can also
|
||||
@ -2280,13 +2299,22 @@ _bootstrap_tools_links+=crunchgen
|
||||
# Note: kbdcontrol can not be bootstrapped on non-FreeBSD systems
|
||||
.if !defined(CROSSBUILD_HOST)
|
||||
.if (${BOOTSTRAPPING} < 1003501 || \
|
||||
(${BOOTSTRAPPING} >= 1100000 && ${BOOTSTRAPPING} < 1100103))
|
||||
(${BOOTSTRAPPING} >= 1100000 && ${BOOTSTRAPPING} < 1100103) || \
|
||||
(!exists(/usr/sbin/kbdcontrol)))
|
||||
_kbdcontrol= usr.sbin/kbdcontrol
|
||||
.else
|
||||
_bootstrap_tools_links+=kbdcontrol
|
||||
.endif
|
||||
.endif
|
||||
|
||||
# 1300102: VHDX support
|
||||
.if ${BOOTSTRAPPING} < 1201520 || \
|
||||
(${BOOTSTRAPPING} > 1300000 && ${BOOTSTRAPPING} < 1300102)
|
||||
_mkimg= usr.bin/mkimg
|
||||
.else
|
||||
_bootstrap_tools_links+=mkimg
|
||||
.endif
|
||||
|
||||
_yacc= usr.bin/yacc
|
||||
|
||||
.if ${MK_BSNMP} != "no"
|
||||
@ -2462,6 +2490,7 @@ bootstrap-tools: ${_bt}-links .PHONY
|
||||
${_flua} \
|
||||
${_crunchide} \
|
||||
${_crunchgen} \
|
||||
${_mkimg} \
|
||||
${_nmtree} \
|
||||
${_vtfontcvt} \
|
||||
${_localedef} \
|
||||
@ -2524,7 +2553,6 @@ _bt_clean= ${CLEANDIR}
|
||||
${LOCAL_TOOL_DIRS} \
|
||||
${_jevents} \
|
||||
lib/ncurses/ncurses \
|
||||
lib/ncurses/ncursesw \
|
||||
${_rescue} \
|
||||
${_share} \
|
||||
usr.bin/awk \
|
||||
@ -2572,6 +2600,7 @@ _dtrace_tools= cddl/lib/libctf cddl/lib/libspl cddl/usr.bin/ctfconvert \
|
||||
.if ${MK_ELFTOOLCHAIN_BOOTSTRAP} != "no"
|
||||
_elftctools= lib/libelftc \
|
||||
lib/libpe \
|
||||
usr.bin/elfctl \
|
||||
usr.bin/objcopy \
|
||||
usr.bin/nm \
|
||||
usr.bin/size \
|
||||
@ -2585,6 +2614,7 @@ _elftctools+= usr.bin/addr2line
|
||||
# the target (for at least crunchide).
|
||||
_elftctools= lib/libelftc \
|
||||
lib/libpe \
|
||||
usr.bin/elfctl \
|
||||
usr.bin/objcopy
|
||||
.endif
|
||||
|
||||
@ -2740,7 +2770,7 @@ NXBMAKEARGS+= \
|
||||
MK_SENDMAIL=no \
|
||||
MK_SVNLITE=no \
|
||||
MK_TESTS=no \
|
||||
MK_WARNS=no \
|
||||
MK_WERROR=no \
|
||||
MK_ZFS=no
|
||||
|
||||
.if make(native-xtools*) && \
|
||||
@ -2840,7 +2870,7 @@ _prereq_libs+= lib/libssp_nonshared
|
||||
_startup_libs= lib/csu
|
||||
_startup_libs+= lib/libc
|
||||
_startup_libs+= lib/libc_nonshared
|
||||
.if ${MK_LIBCPLUSPLUS} != "no"
|
||||
.if ${MK_CXX} != "no"
|
||||
_startup_libs+= lib/libcxxrt
|
||||
.endif
|
||||
|
||||
@ -2849,7 +2879,7 @@ _startup_libs+= lib/libgcc_eh lib/libgcc_s
|
||||
|
||||
lib/libgcc_s__L: lib/libc__L
|
||||
lib/libgcc_s__L: lib/libc_nonshared__L
|
||||
.if ${MK_LIBCPLUSPLUS} != "no"
|
||||
.if ${MK_CXX} != "no"
|
||||
lib/libcxxrt__L: lib/libgcc_s__L
|
||||
.endif
|
||||
|
||||
@ -2870,8 +2900,8 @@ _prebuild_libs= ${_kerberos5_lib_libasn1} \
|
||||
lib/libkiconv lib/libkvm lib/liblzma lib/libmd lib/libnv \
|
||||
lib/libzstd \
|
||||
${_lib_casper} \
|
||||
lib/ncurses/ncurses lib/ncurses/ncursesw \
|
||||
lib/libopie lib/libpam/libpam ${_lib_libthr} \
|
||||
lib/ncurses/ncurses \
|
||||
lib/libopie lib/libpam/libpam lib/libthr \
|
||||
${_lib_libradius} lib/libsbuf lib/libtacplus \
|
||||
lib/libgeom \
|
||||
${_cddl_lib_libumem} ${_cddl_lib_libnvpair} \
|
||||
@ -2891,24 +2921,20 @@ _prebuild_libs= ${_kerberos5_lib_libasn1} \
|
||||
|
||||
.if ${MK_DIALOG} != "no"
|
||||
_prebuild_libs+= gnu/lib/libdialog
|
||||
gnu/lib/libdialog__L: lib/msun__L lib/ncurses/ncursesw__L
|
||||
gnu/lib/libdialog__L: lib/msun__L lib/ncurses/ncurses__L
|
||||
.endif
|
||||
|
||||
.if ${MK_GOOGLETEST} != "no"
|
||||
_prebuild_libs+= lib/libregex
|
||||
.endif
|
||||
|
||||
.if ${MK_LIBCPLUSPLUS} != "no"
|
||||
.if ${MK_CXX} != "no"
|
||||
_prebuild_libs+= lib/libc++
|
||||
.endif
|
||||
|
||||
lib/libgeom__L: lib/libexpat__L lib/libsbuf__L
|
||||
lib/libkvm__L: lib/libelf__L
|
||||
|
||||
.if ${MK_LIBTHR} != "no"
|
||||
_lib_libthr= lib/libthr
|
||||
.endif
|
||||
|
||||
.if ${MK_RADIUS_SUPPORT} != "no"
|
||||
_lib_libradius= lib/libradius
|
||||
.endif
|
||||
@ -3066,7 +3092,7 @@ lib/libradius__L: lib/libmd__L
|
||||
|
||||
lib/libproc__L: \
|
||||
${_cddl_lib_libctf:D${_cddl_lib_libctf}__L} lib/libelf__L lib/librtld_db__L lib/libutil__L
|
||||
.if ${MK_CXX} != "no" && ${MK_LIBCPLUSPLUS} != "no"
|
||||
.if ${MK_CXX} != "no"
|
||||
lib/libproc__L: lib/libcxxrt__L
|
||||
.endif
|
||||
|
||||
@ -3359,7 +3385,7 @@ XDEV_CPUTYPE?=${TARGET_CPUTYPE}
|
||||
|
||||
NOFUN=-DNO_FSCHG MK_HTML=no -DNO_LINT \
|
||||
MK_MAN=no MK_NLS=no MK_PROFILE=no \
|
||||
MK_KERBEROS=no MK_RESCUE=no MK_TESTS=no MK_WARNS=no \
|
||||
MK_KERBEROS=no MK_RESCUE=no MK_TESTS=no MK_WERROR=no \
|
||||
TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \
|
||||
CPUTYPE=${XDEV_CPUTYPE}
|
||||
|
||||
|
@ -45,7 +45,7 @@ _LC_LIBDIRS.${MK_KERBEROS:tl}+= kerberos5/lib
|
||||
|
||||
_LC_INCDIRS= \
|
||||
include \
|
||||
lib/ncurses/ncursesw \
|
||||
lib/ncurses/ncurses \
|
||||
${_LC_LIBDIRS.yes}
|
||||
|
||||
.if ${MK_FILE} != "no"
|
||||
@ -94,7 +94,7 @@ build${libcompat}: .PHONY
|
||||
DIRPRFX=${_dir}/ ${_t}
|
||||
.endfor
|
||||
.endfor
|
||||
.for _dir in lib/ncurses/ncurses lib/ncurses/ncursesw ${_libmagic} ${_jevents}
|
||||
.for _dir in lib/ncurses/ncurses ${_libmagic} ${_jevents}
|
||||
.for _t in ${_obj} build-tools
|
||||
${_+_}cd ${.CURDIR}/${_dir}; \
|
||||
WORLDTMP=${WORLDTMP} \
|
||||
@ -104,7 +104,7 @@ build${libcompat}: .PHONY
|
||||
OBJROOT='$${OBJTOP}/' \
|
||||
MAKEOBJDIRPREFIX= \
|
||||
DIRPRFX=${_dir}/ -DNO_LINT -DNO_CPU_CFLAGS \
|
||||
MK_CTF=no MK_RETPOLINE=no MK_WARNS=no \
|
||||
MK_CTF=no MK_RETPOLINE=no MK_WERROR=no \
|
||||
${_t}
|
||||
.endfor
|
||||
.endfor
|
||||
|
3355
ObsoleteFiles.inc
3355
ObsoleteFiles.inc
File diff suppressed because it is too large
Load Diff
82
README
82
README
@ -1,82 +0,0 @@
|
||||
This repository is being converted from Subversion to Git.
|
||||
|
||||
This is the top level of the FreeBSD source directory. This file
|
||||
was last revised on:
|
||||
$FreeBSD$
|
||||
|
||||
FreeBSD is an operating system used to power modern servers,
|
||||
desktops, and embedded platforms. A large community has
|
||||
continually developed it for more than thirty years. Its
|
||||
advanced networking, security, and storage features have
|
||||
made FreeBSD the platform of choice for many of the
|
||||
busiest web sites and most pervasive embedded networking
|
||||
and storage devices.
|
||||
|
||||
For copyright information, please see the file COPYRIGHT in this
|
||||
directory. Additional copyright information also exists for some
|
||||
sources in this tree - please see the specific source directories for
|
||||
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), config(8),
|
||||
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html, and
|
||||
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig.html
|
||||
for more information, including setting make(1) variables.
|
||||
|
||||
Source Roadmap:
|
||||
---------------
|
||||
|
||||
bin System/user commands.
|
||||
|
||||
cddl Various commands and libraries under the Common Development
|
||||
and Distribution License.
|
||||
|
||||
contrib Packages contributed by 3rd parties.
|
||||
|
||||
crypto Cryptography stuff (see crypto/README).
|
||||
|
||||
etc Template files for /etc.
|
||||
|
||||
gnu Various commands and libraries under the GNU Public License.
|
||||
Please see gnu/COPYING* for more information.
|
||||
|
||||
include System include files.
|
||||
|
||||
kerberos5 Kerberos5 (Heimdal) package.
|
||||
|
||||
lib System libraries.
|
||||
|
||||
libexec System daemons.
|
||||
|
||||
release Release building Makefile & associated tools.
|
||||
|
||||
rescue Build system for statically linked /rescue utilities.
|
||||
|
||||
sbin System commands.
|
||||
|
||||
secure Cryptographic libraries and commands.
|
||||
|
||||
share Shared resources.
|
||||
|
||||
stand Boot loader sources.
|
||||
|
||||
sys Kernel sources.
|
||||
|
||||
sys/<arch>/conf Kernel configuration files. GENERIC is the configuration
|
||||
used in release builds. NOTES contains documentation of
|
||||
all possible entries.
|
||||
|
||||
tests Regression tests which can be run by Kyua. See tests/README
|
||||
for additional information.
|
||||
|
||||
tools Utilities for regression testing and miscellaneous tasks.
|
||||
|
||||
usr.bin User commands.
|
||||
|
||||
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/current-stable.html
|
108
README.md
108
README.md
@ -1,84 +1,42 @@
|
||||
This repository is being converted from Subversion to Git.
|
||||
|
||||
FreeBSD Source:
|
||||
---------------
|
||||
This is the top level of the FreeBSD source directory. This file
|
||||
was last revised on:
|
||||
$FreeBSD$
|
||||
This is the top level of the FreeBSD source directory.
|
||||
|
||||
FreeBSD is an operating system used to power modern servers,
|
||||
desktops, and embedded platforms. A large community has
|
||||
continually developed it for more than thirty years. Its
|
||||
advanced networking, security, and storage features have
|
||||
made FreeBSD the platform of choice for many of the
|
||||
busiest web sites and most pervasive embedded networking
|
||||
and storage devices.
|
||||
FreeBSD is an operating system used to power modern servers, desktops, and embedded platforms.
|
||||
A large community has continually developed it for more than thirty years.
|
||||
Its advanced networking, security, and storage features have made FreeBSD the platform of choice for many of the busiest web sites and most pervasive embedded networking and storage devices.
|
||||
|
||||
For copyright information, please see the file COPYRIGHT in this
|
||||
directory. Additional copyright information also exists for some
|
||||
sources in this tree - please see the specific source directories for
|
||||
more information.
|
||||
For copyright information, please see [the file COPYRIGHT](COPYRIGHT) in this directory.
|
||||
Additional copyright information also exists for some sources in this tree - please see the specific source directories for 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), config(8),
|
||||
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html, and
|
||||
https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig.html
|
||||
for more information, including setting make(1) variables.
|
||||
The Makefile in this directory supports a number of targets for building components (or all) of the FreeBSD source tree.
|
||||
See build(7), config(8), [FreeBSD handbook on building userland](https://docs.freebsd.org/en/books/handbook/cutting-edge/#makeworld), and [Handbook for kernels](https://docs.freebsd.org/en/books/handbook/kernelconfig/) for more information, including setting make(1) variables.
|
||||
|
||||
Source Roadmap:
|
||||
---------------
|
||||
```
|
||||
bin System/user commands.
|
||||
| Directory | Description |
|
||||
| --------- | ----------- |
|
||||
| bin | System/user commands. |
|
||||
| cddl | Various commands and libraries under the Common Development and Distribution License. |
|
||||
| contrib | Packages contributed by 3rd parties. |
|
||||
| crypto | Cryptography stuff (see [crypto/README](crypto/README)). |
|
||||
| etc | Template files for /etc. |
|
||||
| gnu | Various commands and libraries under the GNU Public License. Please see [gnu/COPYING](gnu/COPYING) and [gnu/COPYING.LIB](gnu/COPYING.LIB) for more information. |
|
||||
| include | System include files. |
|
||||
| kerberos5 | Kerberos5 (Heimdal) package. |
|
||||
| lib | System libraries. |
|
||||
| libexec | System daemons. |
|
||||
| release | Release building Makefile & associated tools. |
|
||||
| rescue | Build system for statically linked /rescue utilities. |
|
||||
| sbin | System commands. |
|
||||
| secure | Cryptographic libraries and commands. |
|
||||
| share | Shared resources. |
|
||||
| stand | Boot loader sources. |
|
||||
| sys | Kernel sources. |
|
||||
| sys/`arch`/conf | Kernel configuration files. GENERIC is the configuration used in release builds. NOTES contains documentation of all possible entries. |
|
||||
| tests | Regression tests which can be run by Kyua. See [tests/README](tests/README) for additional information. |
|
||||
| tools | Utilities for regression testing and miscellaneous tasks. |
|
||||
| usr.bin | User commands. |
|
||||
| usr.sbin | System administration commands. |
|
||||
|
||||
cddl Various commands and libraries under the Common Development
|
||||
and Distribution License.
|
||||
|
||||
contrib Packages contributed by 3rd parties.
|
||||
|
||||
crypto Cryptography stuff (see crypto/README).
|
||||
|
||||
etc Template files for /etc.
|
||||
|
||||
gnu Various commands and libraries under the GNU Public License.
|
||||
Please see gnu/COPYING* for more information.
|
||||
|
||||
include System include files.
|
||||
|
||||
kerberos5 Kerberos5 (Heimdal) package.
|
||||
|
||||
lib System libraries.
|
||||
|
||||
libexec System daemons.
|
||||
|
||||
release Release building Makefile & associated tools.
|
||||
|
||||
rescue Build system for statically linked /rescue utilities.
|
||||
|
||||
sbin System commands.
|
||||
|
||||
secure Cryptographic libraries and commands.
|
||||
|
||||
share Shared resources.
|
||||
|
||||
stand Boot loader sources.
|
||||
|
||||
sys Kernel sources.
|
||||
|
||||
sys/<arch>/conf Kernel configuration files. GENERIC is the configuration
|
||||
used in release builds. NOTES contains documentation of
|
||||
all possible entries.
|
||||
|
||||
tests Regression tests which can be run by Kyua. See tests/README
|
||||
for additional information.
|
||||
|
||||
tools Utilities for regression testing and miscellaneous tasks.
|
||||
|
||||
usr.bin User commands.
|
||||
|
||||
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/current-stable.html
|
||||
For information on synchronizing your source tree with one or more of the FreeBSD Project's development branches, please see [FreeBSD Handbook](https://docs.freebsd.org/en/books/handbook/cutting-edge/#current-stable).
|
||||
|
280
RELNOTES
280
RELNOTES
@ -1,4 +1,4 @@
|
||||
Release notes for FreeBSD 13.0.
|
||||
Release notes for FreeBSD 14.0.
|
||||
|
||||
This file describes new user-visible features, changes and updates relevant to
|
||||
users of binary FreeBSD releases. Each entry should describe the change in no
|
||||
@ -10,280 +10,6 @@ newline. Entries should be separated by a newline.
|
||||
|
||||
Changes to this file should not be MFCed.
|
||||
|
||||
r368667:
|
||||
GDB 6.1.1 was removed. Users of crashinfo(8) should install the
|
||||
gdb package or devel/gdb port.
|
||||
|
||||
r368559:
|
||||
The hme(4) driver was removed.
|
||||
|
||||
r367660:
|
||||
Fixes the case where gssd will not startup because /usr is a separate
|
||||
local file system that is not yet mounted. It does not fix the case
|
||||
where /usr is a separately mounted remote file system (such as NFS).
|
||||
This latter case can be fixed by adding mountcritremote to the
|
||||
REQUIRED line. Unfortunately doing so implies that all Kerberized
|
||||
NFS mounts in /etc/fstab will need the "late" mount option.
|
||||
This was not done, since the requirement for "late" would introduce
|
||||
a POLA violation.
|
||||
|
||||
r367423:
|
||||
This commit added a new startup scripts variable called
|
||||
nfsv4_server_only which uses the -R option on mountd added by r367026.
|
||||
When nfsv4_server_only is set to "YES" in /etc/rc.conf, the NFS server
|
||||
only handles NFSv4 and does not register with rpcbind. As such, rpcbind
|
||||
does not need to be running. Useful for sites which consider rpcbind a
|
||||
security issue.
|
||||
|
||||
r366267:
|
||||
Kernel option ACPI_DMAR was renamed to IOMMU. amd64's IOMMU subsystem
|
||||
was split out from amd64 DMAR support and is now generic, i.e., it can
|
||||
be used by all architectures.
|
||||
|
||||
r364896:
|
||||
A series of commits ending with r364896 added NFS over TLS
|
||||
to the kernel. This is believed to be compatible with
|
||||
the Internet Draft titled "Towards Remote Procedure Call Encryption
|
||||
By Default" (expected to soon become an RFC).
|
||||
The mount_nfs(8) and exports(5) man pages describe the mount and
|
||||
export option(s) related to NFS over TLS.
|
||||
For NFS over TLS to work, the rpctlscd(8) { client } or rpctlssd(8)
|
||||
{ server } must be running on a kernel built with "options KERN_TLS"
|
||||
on an architecture where PMAP_HAS_DMAP != 0.
|
||||
|
||||
r364725:
|
||||
Changes to one obscure devd event generated on resume need to
|
||||
be documented. The old form will still be generated in 13, but not
|
||||
in 14.
|
||||
|
||||
r363679:
|
||||
Applications using regex(3), e.g. sed/grep, will no longer accept
|
||||
redundant escapes for most ordinary characters.
|
||||
|
||||
r363253:
|
||||
SCTP support has been removed from GENERIC kernel configurations.
|
||||
The SCTP stack is now built as sctp.ko and can be dynamically loaded.
|
||||
|
||||
r363233:
|
||||
Merge sendmail 8.16.1: See contrib/sendmail/RELEASE_NOTES for details.
|
||||
|
||||
r363180:
|
||||
The safexcel(4) crypto offload driver has been added.
|
||||
|
||||
r363084:
|
||||
nc(1) now implements SCTP mode, enabled by specifying the --sctp option.
|
||||
|
||||
r362681:
|
||||
A new implementation of bc and dc has been imported. It offers
|
||||
better standards compliance, performance, localization and comes
|
||||
with extensive test cases that are optionally installed.
|
||||
Use WITHOUT_GH_BC=yes to build and install the world with the
|
||||
previous version instead of the new one, if required.
|
||||
|
||||
r362158, r362163:
|
||||
struct export_args has changed so that the "user" specified for
|
||||
the -maproot and -mapall exports(5) options may be in more than
|
||||
16 groups.
|
||||
|
||||
r361884:
|
||||
sed(1) has learned about hex escapes (e.g. \x27) and will now do the
|
||||
right thing with them, removing the need for printf magic or obnoxious
|
||||
escaping in many scenarios.
|
||||
|
||||
r361238, r361798, r361799:
|
||||
ZFS will now unconditionally reject read(2) of a directory with EISDIR.
|
||||
Additionally, read(2) of a directory is now rejected with EISDIR by
|
||||
default and may be re-enabled for non-ZFS filesystems that allow it with
|
||||
the sysctl(8) MIB 'security.bsd.allow_read_dir'.
|
||||
|
||||
Aliases for grep to default to '-d skip' may be desired if commonly
|
||||
non-recursively grepping a list that includes directories and the
|
||||
possibility of EISDIR errors in stderr is not tolerable. Example
|
||||
aliases, commented out, have been installed in /root/.cshrc and
|
||||
/root/.shrc.
|
||||
|
||||
r361066:
|
||||
Add exec.prepare and exec.release hooks for jail(8) and jail.conf(5).
|
||||
exec.prepare runs before mounts, so can be used to populate new jails.
|
||||
exec.release runs after unmounts, so can be used to remove ephemeral
|
||||
jails.
|
||||
|
||||
r360920,r360923,r360924,r360927,r360928,r360931,r360933,r360936:
|
||||
Remove support for ARC4, Blowfish, Cast, DES, Triple DES, MD5,
|
||||
MD5-KPDK, MD5-HMAC, SHA1-KPDK, and Skipjack algorithms from
|
||||
76681661be28
|
||||
Remove support for asymmetric cryptographic operations from
|
||||
the kernel open cryptographic framework (OCF).
|
||||
|
||||
r360562:
|
||||
Remove support for ARC4, Blowfish, Cast, DES, Triple DES,
|
||||
MD5-HMAC, and Skipjack algorithms from /dev/crypto.
|
||||
|
||||
r360557:
|
||||
Remove support for DES, Triple DES, Blowfish, Cast, and
|
||||
Camellia ciphers from IPsec(4). Remove support for MD5-HMAC,
|
||||
Keyed MD5, Keyed SHA1, and RIPEMD160-HMAC from IPsec(4).
|
||||
|
||||
r359945:
|
||||
Remove support for Triple DES, Blowfish, and MD5 HMAC from
|
||||
geli(4).
|
||||
|
||||
r359786-r359787:
|
||||
Remove support for DES, Triple DES, and RC4 from in-kernel GSS
|
||||
authentication.
|
||||
|
||||
r357627:
|
||||
remove elf2aout.
|
||||
|
||||
r357560-r357565:
|
||||
init(8), service(8), and cron(8) will now adopt user/class environment
|
||||
variables (excluding PATH, by default, which will be overwritten) by
|
||||
default. Notably, environment variables for all cron jobs and rc
|
||||
services can now be set via login.conf(5).
|
||||
|
||||
r357455:
|
||||
sparc64 has been removed from FreeBSD.
|
||||
|
||||
r355677:
|
||||
Adds support for NFSv4.2 (RFC-7862) and Extended Attributes
|
||||
(RFC-8276) to the NFS client and server.
|
||||
NFSv4.2 is comprised of several optional features that can be supported
|
||||
in addition to NFSv4.1. This patch adds the following optional features:
|
||||
- posix_fadvise(POSIX_FADV_WILLNEED/POSIX_FADV_DONTNEED)
|
||||
- posix_fallocate()
|
||||
- intra server file range copying via the copy_file_range(2) syscall
|
||||
--> Avoiding data tranfer over the wire to/from the NFS client.
|
||||
- lseek(SEEK_DATA/SEEK_HOLE)
|
||||
- Extended attribute syscalls for "user" namespace attributes as defined
|
||||
by RFC-8276.
|
||||
|
||||
For the client, NFSv4.2 is only used if the mount command line option
|
||||
minorversion=2 is specified.
|
||||
For the server, two new sysctls called vfs.nfsd.server_min_minorversion4
|
||||
and vfs.nfsd.server_max_minorversion4 have been added that allow
|
||||
sysadmins to limit the minor versions of NFSv4 supported by the nfsd
|
||||
server.
|
||||
Setting vfs.nfsd.server_max_minorversion4 to 0 or 1 will disable NFSv4.2
|
||||
on the server.
|
||||
|
||||
r356263:
|
||||
armv5 support has been removed from FreeBSD.
|
||||
|
||||
r354517:
|
||||
iwm(4) now supports most Intel 9260, 9460 and 9560 Wi-Fi devices.
|
||||
|
||||
r354269:
|
||||
sqlite3 is updated to sqlite3-3.30.1.
|
||||
|
||||
r352668:
|
||||
cron(8) now supports the -n (suppress mail on succesful run) and -q
|
||||
(suppress logging of command execution) options in the crontab format.
|
||||
See the crontab(5) manpage for details.
|
||||
|
||||
r352304:
|
||||
ntpd is no longer by default locked in memory. rlimit memlock 32
|
||||
or rlimit memlock 0 can be used to restore this behaviour.
|
||||
|
||||
r351863:
|
||||
rc.subr(8) now honors ${name}_env in all rc(8) scripts. Previously,
|
||||
environment variables set by a user via ${name}_env were ignored
|
||||
if the service defined a custom *_cmd variable to control the behavior
|
||||
of the run_rc_command function, e.g., start_cmd, instead of relying on
|
||||
the variables like command and command_args,
|
||||
|
||||
r351770,r352920,r352922,r352923:
|
||||
dd(1) now supports conv=fsync, conv=fdatasync, oflag=fsync, oflag=sync,
|
||||
and iflag=fullblock flags, compatible with illumos and GNU.
|
||||
|
||||
r351522:
|
||||
Add kernel-side support for in-kernel Transport Layer Security
|
||||
(KTLS). KTLS permits using sendfile(2) over sockets using
|
||||
TLS.
|
||||
|
||||
r351397:
|
||||
WPA is updated from 2.8 to 2.9.
|
||||
|
||||
r351361:
|
||||
Add probes for lockmgr(9) to the lockstat DTrace provider, add
|
||||
corresponding lockstat(1) events, and document the new probes in
|
||||
dtrace_lockstat.4.
|
||||
|
||||
r351356:
|
||||
Intel RST is a new 'feature' that remaps NVMe devices from
|
||||
their normal location to part of the AHCI bar space. This
|
||||
will eliminate the need to set the BIOS SATA setting from RST
|
||||
to AHCI causing the nvme drive to be erased before FreeBSD
|
||||
will see the nvme drive. FreeBSD will now be able to see the
|
||||
nvme drive now in the default config.
|
||||
|
||||
r351201, r351372:
|
||||
Add a vop_stdioctl() call, so that file systems that do not support
|
||||
holes will have a trivial implementation of lseek(SEEK_DATA/SEEK_HOLE).
|
||||
The algorithm appears to be compatible with the POSIX draft and
|
||||
the implementation in Linux for the case of a file system that
|
||||
does not support holes. Prior to this patch, lseek(2) would reply
|
||||
-1 with errno set to ENOTTY for SEEK_DATA/SEEK_HOLE on files in
|
||||
file systems that do not support holes.
|
||||
r351372 maps ENOTTY to EINVAL for lseek(SEEK_DATA/SEEK_HOLE) for
|
||||
any other cases, such as a ENOTTY return from vn_bmap_seekhole().
|
||||
|
||||
r350665:
|
||||
The fuse driver has been renamed to fusefs(5) and been substantially
|
||||
rewritten. The new driver includes many bug fixes and performance
|
||||
enhancements, as well as the following user-visible features:
|
||||
* Optional kernel-side permissions checks (-o default_permissions)
|
||||
* mknod(2), socket(2), and pipe(2) support
|
||||
* server side locking with fcntl(2)
|
||||
* FUSE operations are now interruptible when mounted with -o intr
|
||||
* server side handling of UTIME_NOW during utimensat(2)
|
||||
* mount options may be updated with "mount -u"
|
||||
* fusefs file system may now be exported over NFS
|
||||
* RLIMIT_FSIZE support
|
||||
* support for fuse file systems using protocols as old as 7.4
|
||||
|
||||
FUSE file system developers should also take note of the following new
|
||||
features:
|
||||
* The protocol level has been raised from 7.8 to 7.23
|
||||
* kqueue support on /dev/fuse
|
||||
* server-initiated cache invalidation via FUSE_NOTIFY_REPLY
|
||||
|
||||
r350471:
|
||||
gnop(8) can now configure a delay to be applied to read and write
|
||||
request delays. See the -d, -q and -x parameters.
|
||||
|
||||
r350315, r350316:
|
||||
Adds a Linux compatible copy_file_range(2) syscall.
|
||||
|
||||
r350307:
|
||||
libcap_random(3) has been removed. Applications can use native
|
||||
APIs to get random data in capability mode.
|
||||
|
||||
r349529,r349530:
|
||||
Add support for using unmapped mbufs with sendfile(2).
|
||||
|
||||
r349352:
|
||||
nand(4) and related components have been removed.
|
||||
|
||||
r349349:
|
||||
The UEFI loader now supports HTTP boot.
|
||||
|
||||
r349335:
|
||||
bhyve(8) now implements a High Definition Audio (HDA) driver, allowing
|
||||
guests to play to and record audio data from the host.
|
||||
|
||||
r349286:
|
||||
swapon(8) can now erase a swap device immediately before enabling it,
|
||||
similar to newfs(8)'s -E option. This behaviour can be specified by
|
||||
adding -E to swapon(8)'s command-line parameters, or by adding the
|
||||
"trimonce" option to a swap device's /etc/fstab entry.
|
||||
|
||||
r347908-r347923:
|
||||
The following network drivers have been removed: bm(4), cs(4), de(4),
|
||||
ed(4), ep(4), ex(4), fe(4), pcn(4), sf(4), sn(4), tl(4), tx(4), txp(4),
|
||||
vx(4), wb(4), xe(4).
|
||||
|
||||
r347532:
|
||||
Wired page accounting has been split into kernel wirings and user
|
||||
wirings (e.g., by mlock(2)). Kernel wirings no long count towards
|
||||
the global limit, which is renamed to vm.max_user_wired. bhyve -S
|
||||
allocates user-wired memory and is now subject to that limit.
|
||||
|
||||
$FreeBSD$
|
||||
|
81
UPDATING
81
UPDATING
@ -1,4 +1,4 @@
|
||||
Updating Information for FreeBSD current users.
|
||||
Updating Information for FreeBSD current users.
|
||||
|
||||
This file is maintained and copyrighted by M. Warner Losh <imp@freebsd.org>.
|
||||
See end of file for further details. For commonly done items, please see the
|
||||
@ -6,13 +6,14 @@ 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/makeworld.html
|
||||
https://docs.freebsd.org/en/books/handbook/cutting-edge/#makeworld
|
||||
|
||||
Items affecting the ports and packages system can be found in
|
||||
/usr/ports/UPDATING. Please read that file before running portupgrade.
|
||||
/usr/ports/UPDATING. Please read that file before updating system packages
|
||||
and/or ports.
|
||||
|
||||
NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW:
|
||||
FreeBSD 13.x has many debugging features turned on, in both the kernel
|
||||
NOTE TO PEOPLE WHO THINK THAT FreeBSD 14.x IS SLOW:
|
||||
FreeBSD 14.x has many debugging features turned on, in both the kernel
|
||||
and userland. These features attempt to detect incorrect use of
|
||||
system primitives, and encourage loud failure through extra sanity
|
||||
checking and fail stop semantics. They also substantially impact
|
||||
@ -26,6 +27,75 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW:
|
||||
world, or to merely disable the most expensive debugging functionality
|
||||
at runtime, run "ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
||||
|
||||
20210525:
|
||||
Commits 17accc08ae15 and de102f870501 add new files to LinuxKPI
|
||||
which break drm-kmod. In addition various other additions where
|
||||
comitted. Bump __FreeBSD_version to 1400015 to be able to detect this.
|
||||
|
||||
20210513:
|
||||
Commit ca179c4d74f2 changed the package in which the OpenSSL
|
||||
libraries and utilities are packaged.
|
||||
It is recommended for pkgbase user to do:
|
||||
pkg install -f FreeBSD-openssl
|
||||
before pkg upgrade otherwise some dependencies might not be met
|
||||
and pkg will stop working as libssl will not be present anymore
|
||||
on the system.
|
||||
|
||||
20210426:
|
||||
Commit 875977314881 changed the internal KAPI between
|
||||
the nfsd and nfscommon modules. As such these modules
|
||||
need to be rebuilt from sources.
|
||||
Without this patch in your NFSv4.1/4.2 server, enabling
|
||||
delegations by setting vfs.nfsd.issue_delegations non-zero
|
||||
is not recommended.
|
||||
|
||||
20210411:
|
||||
Commit 7763814fc9c2 changed the internal KAPI between
|
||||
the krpc and NFS. As such, the krpc, nfscommon and
|
||||
nfscl modules must all be rebuilt from sources.
|
||||
Without this patch, NFSv4.1/4.2 mounts should not
|
||||
be done with the nfscbd(8) daemon running, to avoid
|
||||
needing a working back channel for server->client RPCs.
|
||||
|
||||
20210330:
|
||||
Commit 01ae8969a9ee fixed the NFSv4.1/4.2 server so that it
|
||||
handles binding of the back channel as required by RFC5661.
|
||||
Until this patch is in your server, avoid use of the "nconnects"
|
||||
mount option for Linux NFSv4.1/4.2 mounts.
|
||||
|
||||
20210225:
|
||||
For 64-bit architectures the base system is now built with Position
|
||||
Independent Executable (PIE) support enabled by default. It may be
|
||||
disabled using the WITHOUT_PIE knob. A clean build is required.
|
||||
|
||||
20210128:
|
||||
Various LinuxKPI functionality was added which conflicts with DRM.
|
||||
Please update your drm-kmod port to after the __FreeBSD_verison 1400003
|
||||
update.
|
||||
|
||||
20210108:
|
||||
PC Card attachments for all devices have been removed. In the case of
|
||||
wi and cmx, the entire drivers were removed because they were only
|
||||
PC Card devices. FreeBSD_version 1300134 should be used for this
|
||||
since it was bumped so recently.
|
||||
|
||||
20210107:
|
||||
Transport-independent parts of HID support have been split off the USB
|
||||
code in to separate subsystem. Kernel configs which include one of
|
||||
ums, ukbd, uhid, atp, wsp, wmt, uaudio, ugold or ucycom drivers should
|
||||
be updated with adding of "device hid" line.
|
||||
|
||||
20210105:
|
||||
ncurses installation has been modified to only keep the widechar
|
||||
enabled version. Incremental build is broken for that change, so it
|
||||
requires a clean build.
|
||||
|
||||
20201223:
|
||||
The FreeBSD project has migrated from Subversion to Git. Temporary
|
||||
instructions can be found at
|
||||
https://github.com/bsdimp/freebsd-git-docs/blob/main/src-cvt.md
|
||||
and other documents in that repo.
|
||||
|
||||
20201216:
|
||||
The services database has been updated to cover more of the basic
|
||||
services expected in a modern system. The database is big enough
|
||||
@ -44,6 +114,7 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW:
|
||||
Default value of net.add_addr_allfibs has been changed to 0.
|
||||
If you have multi-fib configuration and rely on existence of all
|
||||
interface routes in every fib, you need to set the above sysctl to 1.
|
||||
|
||||
20201030:
|
||||
The internal pre-processor in the calendar(1) program has been
|
||||
extended to support more C pre-processor commands (e.g. #ifdef, #else,
|
||||
|
@ -15,4 +15,14 @@ CFLAGS+=-DBOOTSTRAP_CAT
|
||||
HAS_TESTS=
|
||||
SUBDIR.${MK_TESTS}+= tests
|
||||
|
||||
# Temporary disable building cat with Casper.
|
||||
#.if ${MK_CASPER} != "no" && !defined(RESCUE) && !defined(BOOTSTRAPPING)
|
||||
#LIBADD+= casper
|
||||
#LIBADD+= cap_fileargs
|
||||
#LIBADD+= cap_net
|
||||
#CFLAGS+=-DWITH_CASPER
|
||||
#.endif
|
||||
# Depend on Makefile to rebiuld when WITH_CASPER changes
|
||||
cat.o: Makefile
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
109
bin/cat/cat.c
109
bin/cat/cat.c
@ -48,6 +48,7 @@ static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95";
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#ifndef NO_UDOM_SUPPORT
|
||||
@ -56,6 +57,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include <capsicum_helpers.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
@ -68,16 +70,25 @@ __FBSDID("$FreeBSD$");
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
|
||||
#include <libcasper.h>
|
||||
#include <casper/cap_fileargs.h>
|
||||
#include <casper/cap_net.h>
|
||||
|
||||
static int bflag, eflag, lflag, nflag, sflag, tflag, vflag;
|
||||
static int rval;
|
||||
static const char *filename;
|
||||
static fileargs_t *fa;
|
||||
|
||||
static void usage(void) __dead2;
|
||||
static void scanfiles(char *argv[], int cooked);
|
||||
#ifndef BOOTSTRAP_CAT
|
||||
static void cook_cat(FILE *);
|
||||
#endif
|
||||
static void raw_cat(int);
|
||||
|
||||
#ifndef NO_UDOM_SUPPORT
|
||||
static cap_channel_t *capnet;
|
||||
|
||||
static int udom_open(const char *path, int flags);
|
||||
#endif
|
||||
|
||||
@ -110,6 +121,53 @@ static int udom_open(const char *path, int flags);
|
||||
#define SUPPORTED_FLAGS "belnstuv"
|
||||
#endif
|
||||
|
||||
#ifndef NO_UDOM_SUPPORT
|
||||
static void
|
||||
init_casper_net(cap_channel_t *casper)
|
||||
{
|
||||
cap_net_limit_t *limit;
|
||||
int familylimit;
|
||||
|
||||
capnet = cap_service_open(casper, "system.net");
|
||||
if (capnet == NULL)
|
||||
err(EXIT_FAILURE, "unable to create network service");
|
||||
|
||||
limit = cap_net_limit_init(capnet, CAPNET_NAME2ADDR |
|
||||
CAPNET_CONNECTDNS);
|
||||
if (limit == NULL)
|
||||
err(EXIT_FAILURE, "unable to create limits");
|
||||
|
||||
familylimit = AF_LOCAL;
|
||||
cap_net_limit_name2addr_family(limit, &familylimit, 1);
|
||||
|
||||
if (cap_net_limit(limit) < 0)
|
||||
err(EXIT_FAILURE, "unable to apply limits");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
init_casper(int argc, char *argv[])
|
||||
{
|
||||
cap_channel_t *casper;
|
||||
cap_rights_t rights;
|
||||
|
||||
casper = cap_init();
|
||||
if (casper == NULL)
|
||||
err(EXIT_FAILURE, "unable to create Casper");
|
||||
|
||||
fa = fileargs_cinit(casper, argc, argv, O_RDONLY, 0,
|
||||
cap_rights_init(&rights, CAP_READ | CAP_FSTAT | CAP_FCNTL),
|
||||
FA_OPEN | FA_REALPATH);
|
||||
if (fa == NULL)
|
||||
err(EXIT_FAILURE, "unable to create fileargs");
|
||||
|
||||
#ifndef NO_UDOM_SUPPORT
|
||||
init_casper_net(casper);
|
||||
#endif
|
||||
|
||||
cap_close(casper);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
@ -148,6 +206,7 @@ main(int argc, char *argv[])
|
||||
usage();
|
||||
}
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
|
||||
if (lflag) {
|
||||
stdout_lock.l_len = 0;
|
||||
@ -158,6 +217,13 @@ main(int argc, char *argv[])
|
||||
err(EXIT_FAILURE, "stdout");
|
||||
}
|
||||
|
||||
init_casper(argc, argv);
|
||||
|
||||
caph_cache_catpages();
|
||||
|
||||
if (caph_enter_casper() < 0)
|
||||
err(EXIT_FAILURE, "capsicum");
|
||||
|
||||
if (bflag || eflag || nflag || sflag || tflag || vflag)
|
||||
scanfiles(argv, 1);
|
||||
else
|
||||
@ -178,11 +244,13 @@ usage(void)
|
||||
}
|
||||
|
||||
static void
|
||||
scanfiles(char *argv[], int cooked)
|
||||
scanfiles(char *argv[], int cooked __unused)
|
||||
{
|
||||
int fd, i;
|
||||
char *path;
|
||||
#ifndef BOOTSTRAP_CAT
|
||||
FILE *fp;
|
||||
#endif
|
||||
|
||||
i = 0;
|
||||
fd = -1;
|
||||
@ -192,7 +260,7 @@ scanfiles(char *argv[], int cooked)
|
||||
fd = STDIN_FILENO;
|
||||
} else {
|
||||
filename = path;
|
||||
fd = open(path, O_RDONLY);
|
||||
fd = fileargs_open(fa, path);
|
||||
#ifndef NO_UDOM_SUPPORT
|
||||
if (fd < 0 && errno == EOPNOTSUPP)
|
||||
fd = udom_open(path, O_RDONLY);
|
||||
@ -360,33 +428,48 @@ udom_open(const char *path, int flags)
|
||||
{
|
||||
struct addrinfo hints, *res, *res0;
|
||||
char rpath[PATH_MAX];
|
||||
int fd = -1;
|
||||
int error;
|
||||
int error, fd, serrno;
|
||||
cap_rights_t rights;
|
||||
|
||||
/*
|
||||
* Construct the unix domain socket address and attempt to connect.
|
||||
*/
|
||||
bzero(&hints, sizeof(hints));
|
||||
hints.ai_family = AF_LOCAL;
|
||||
if (realpath(path, rpath) == NULL)
|
||||
fd = -1;
|
||||
|
||||
if (fileargs_realpath(fa, path, rpath) == NULL)
|
||||
return (-1);
|
||||
error = getaddrinfo(rpath, NULL, &hints, &res0);
|
||||
|
||||
error = cap_getaddrinfo(capnet, rpath, NULL, &hints, &res0);
|
||||
if (error) {
|
||||
warn("%s", gai_strerror(error));
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
cap_rights_init(&rights, CAP_CONNECT, CAP_READ, CAP_WRITE,
|
||||
CAP_SHUTDOWN, CAP_FSTAT, CAP_FCNTL);
|
||||
for (res = res0; res != NULL; res = res->ai_next) {
|
||||
fd = socket(res->ai_family, res->ai_socktype,
|
||||
res->ai_protocol);
|
||||
if (fd < 0) {
|
||||
serrno = errno;
|
||||
freeaddrinfo(res0);
|
||||
errno = serrno;
|
||||
return (-1);
|
||||
}
|
||||
error = connect(fd, res->ai_addr, res->ai_addrlen);
|
||||
if (caph_rights_limit(fd, &rights) < 0) {
|
||||
serrno = errno;
|
||||
close(fd);
|
||||
freeaddrinfo(res0);
|
||||
errno = serrno;
|
||||
return (-1);
|
||||
}
|
||||
error = cap_connect(capnet, fd, res->ai_addr, res->ai_addrlen);
|
||||
if (error == 0)
|
||||
break;
|
||||
else {
|
||||
serrno = errno;
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
@ -399,16 +482,28 @@ udom_open(const char *path, int flags)
|
||||
if (fd >= 0) {
|
||||
switch(flags & O_ACCMODE) {
|
||||
case O_RDONLY:
|
||||
cap_rights_clear(&rights, CAP_WRITE);
|
||||
if (shutdown(fd, SHUT_WR) == -1)
|
||||
warn(NULL);
|
||||
break;
|
||||
case O_WRONLY:
|
||||
cap_rights_clear(&rights, CAP_READ);
|
||||
if (shutdown(fd, SHUT_RD) == -1)
|
||||
warn(NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cap_rights_clear(&rights, CAP_CONNECT, CAP_SHUTDOWN);
|
||||
if (caph_rights_limit(fd, &rights) < 0) {
|
||||
serrno = errno;
|
||||
close(fd);
|
||||
errno = serrno;
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
errno = serrno;
|
||||
}
|
||||
return (fd);
|
||||
}
|
||||
|
@ -74,11 +74,10 @@ __FBSDID("$FreeBSD$");
|
||||
*/
|
||||
#define BUFSIZE_SMALL (MAXPHYS)
|
||||
|
||||
static int
|
||||
static ssize_t
|
||||
copy_fallback(int from_fd, int to_fd, char *buf, size_t bufsize)
|
||||
{
|
||||
int rcount;
|
||||
ssize_t wresid, wcount = 0;
|
||||
ssize_t rcount, wresid, wcount = 0;
|
||||
char *bufp;
|
||||
|
||||
rcount = read(from_fd, buf, bufsize);
|
||||
@ -100,10 +99,10 @@ copy_file(const FTSENT *entp, int dne)
|
||||
static char *buf = NULL;
|
||||
static size_t bufsize;
|
||||
struct stat *fs;
|
||||
ssize_t wcount;
|
||||
ssize_t rcount, wcount;
|
||||
size_t wresid;
|
||||
off_t wtotal;
|
||||
int ch, checkch, from_fd, rcount, rval, to_fd;
|
||||
int ch, checkch, from_fd, rval, to_fd;
|
||||
char *bufp;
|
||||
#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
|
||||
char *p;
|
||||
@ -236,7 +235,7 @@ copy_file(const FTSENT *entp, int dne)
|
||||
do {
|
||||
if (use_copy_file_range) {
|
||||
rcount = copy_file_range(from_fd, NULL,
|
||||
to_fd, NULL, bufsize, 0);
|
||||
to_fd, NULL, SSIZE_MAX, 0);
|
||||
if (rcount < 0 && errno == EINVAL) {
|
||||
/* Prob a non-seekable FD */
|
||||
use_copy_file_range = 0;
|
||||
|
@ -220,8 +220,7 @@ Mounted on
|
||||
.Ed
|
||||
.Pp
|
||||
Show human readable information for the file system containing the file
|
||||
.Pa /etc/rc.conf
|
||||
:
|
||||
.Pa /etc/rc.conf :
|
||||
.Bd -literal -offset indent
|
||||
$ df -h /etc/rc.conf
|
||||
Filesystem Size Used Avail Capacity Mounted on
|
||||
|
12
bin/ed/ed.1
12
bin/ed/ed.1
@ -1,5 +1,5 @@
|
||||
.\" $FreeBSD$
|
||||
.Dd November 3, 2018
|
||||
.Dd April 9, 2021
|
||||
.Dt ED 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -961,6 +961,16 @@ USD:12-13
|
||||
.%O Addison-Wesley
|
||||
.%D 1981
|
||||
.Re
|
||||
.Rs
|
||||
.\" 4.4BSD USD:9
|
||||
.%A B. W. Kernighan
|
||||
.%T A Tutorial Introduction to the UNIX Text Editor
|
||||
.Re
|
||||
.Rs
|
||||
.\" 4.4BSD USD:10
|
||||
.%A B. W. Kernighan
|
||||
.%T Advanced Editing on UNIX
|
||||
.Re
|
||||
.Sh LIMITATIONS
|
||||
The
|
||||
.Nm
|
||||
|
115
bin/ls/ls.c
115
bin/ls/ls.c
@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mac.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
@ -88,12 +89,12 @@ __FBSDID("$FreeBSD$");
|
||||
*/
|
||||
#define MAKENINES(n) \
|
||||
do { \
|
||||
intmax_t i; \
|
||||
intmax_t __i; \
|
||||
\
|
||||
/* Use a loop as all values of n are small. */ \
|
||||
for (i = 1; n > 0; i *= 10) \
|
||||
for (__i = 1; n > 0; __i *= 10) \
|
||||
n--; \
|
||||
n = i - 1; \
|
||||
n = __i - 1; \
|
||||
} while(0)
|
||||
|
||||
static void display(const FTSENT *, FTSENT *, int);
|
||||
@ -715,88 +716,58 @@ display(const FTSENT *p, FTSENT *list, int options)
|
||||
char *flags, *labelstr = NULL;
|
||||
char ngroup[STRBUF_SIZEOF(uid_t) + 1];
|
||||
char nuser[STRBUF_SIZEOF(gid_t) + 1];
|
||||
u_long width[9];
|
||||
int i;
|
||||
|
||||
needstats = f_inode || f_longform || f_size;
|
||||
flen = 0;
|
||||
btotal = 0;
|
||||
initmax = getenv("LS_COLWIDTHS");
|
||||
/* Fields match -lios order. New ones should be added at the end. */
|
||||
maxlabelstr = maxblock = maxlen = maxnlink = 0;
|
||||
maxuser = maxgroup = maxflags = maxsize = 0;
|
||||
maxinode = 0;
|
||||
if (initmax != NULL && *initmax != '\0') {
|
||||
char *initmax2, *jinitmax;
|
||||
int ninitmax;
|
||||
|
||||
/* Fill-in "::" as "0:0:0" for the sake of scanf. */
|
||||
jinitmax = malloc(strlen(initmax) * 2 + 2);
|
||||
if (jinitmax == NULL)
|
||||
err(1, "malloc");
|
||||
initmax2 = jinitmax;
|
||||
if (*initmax == ':')
|
||||
strcpy(initmax2, "0:"), initmax2 += 2;
|
||||
else
|
||||
*initmax2++ = *initmax, *initmax2 = '\0';
|
||||
for (initmax++; *initmax != '\0'; initmax++) {
|
||||
if (initmax[-1] == ':' && initmax[0] == ':') {
|
||||
*initmax2++ = '0';
|
||||
*initmax2++ = initmax[0];
|
||||
initmax2[1] = '\0';
|
||||
#define LS_COLWIDTHS_FIELDS 9
|
||||
initmax = getenv("LS_COLWIDTHS");
|
||||
|
||||
for (i = 0 ; i < LS_COLWIDTHS_FIELDS; i++)
|
||||
width[i] = 0;
|
||||
|
||||
if (initmax != NULL) {
|
||||
char *endp;
|
||||
|
||||
for (i = 0; i < LS_COLWIDTHS_FIELDS && *initmax != '\0'; i++) {
|
||||
if (*initmax == ':') {
|
||||
width[i] = 0;
|
||||
} else {
|
||||
*initmax2++ = initmax[0];
|
||||
initmax2[1] = '\0';
|
||||
width[i] = strtoul(initmax, &endp, 10);
|
||||
initmax = endp;
|
||||
while (isspace(*initmax))
|
||||
initmax++;
|
||||
if (*initmax != ':')
|
||||
break;
|
||||
initmax++;
|
||||
}
|
||||
}
|
||||
if (initmax2[-1] == ':')
|
||||
strcpy(initmax2, "0");
|
||||
|
||||
ninitmax = sscanf(jinitmax,
|
||||
" %ju : %ld : %lu : %u : %u : %i : %jd : %lu : %lu ",
|
||||
&maxinode, &maxblock, &maxnlink, &maxuser,
|
||||
&maxgroup, &maxflags, &maxsize, &maxlen, &maxlabelstr);
|
||||
f_notabs = 1;
|
||||
switch (ninitmax) {
|
||||
case 0:
|
||||
maxinode = 0;
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
maxblock = 0;
|
||||
/* FALLTHROUGH */
|
||||
case 2:
|
||||
maxnlink = 0;
|
||||
/* FALLTHROUGH */
|
||||
case 3:
|
||||
maxuser = 0;
|
||||
/* FALLTHROUGH */
|
||||
case 4:
|
||||
maxgroup = 0;
|
||||
/* FALLTHROUGH */
|
||||
case 5:
|
||||
maxflags = 0;
|
||||
/* FALLTHROUGH */
|
||||
case 6:
|
||||
maxsize = 0;
|
||||
/* FALLTHROUGH */
|
||||
case 7:
|
||||
maxlen = 0;
|
||||
/* FALLTHROUGH */
|
||||
case 8:
|
||||
maxlabelstr = 0;
|
||||
/* FALLTHROUGH */
|
||||
if (i < LS_COLWIDTHS_FIELDS)
|
||||
#ifdef COLORLS
|
||||
if (!f_color)
|
||||
#endif
|
||||
f_notabs = 0;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
MAKENINES(maxinode);
|
||||
MAKENINES(maxblock);
|
||||
MAKENINES(maxnlink);
|
||||
MAKENINES(maxsize);
|
||||
free(jinitmax);
|
||||
}
|
||||
|
||||
/* Fields match -lios order. New ones should be added at the end. */
|
||||
maxinode = width[0];
|
||||
maxblock = width[1];
|
||||
maxnlink = width[2];
|
||||
maxuser = width[3];
|
||||
maxgroup = width[4];
|
||||
maxflags = width[5];
|
||||
maxsize = width[6];
|
||||
maxlen = width[7];
|
||||
maxlabelstr = width[8];
|
||||
|
||||
MAKENINES(maxinode);
|
||||
MAKENINES(maxblock);
|
||||
MAKENINES(maxnlink);
|
||||
MAKENINES(maxsize);
|
||||
|
||||
d.s_size = 0;
|
||||
sizelen = 0;
|
||||
flags = NULL;
|
||||
|
@ -9,7 +9,7 @@ jail_name_to_jid()
|
||||
|
||||
base=pgrep_j_test
|
||||
|
||||
if [ `id -u` -ne 0 ]; then
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "1..0 # skip Test needs uid 0."
|
||||
exit 0
|
||||
fi
|
||||
@ -28,12 +28,12 @@ jail -c path=/ name=${base}_1_2 ip4.addr=127.0.0.1 \
|
||||
command=daemon -p ${PWD}/${base}_1_2.pid $sleep $sleep_amount &
|
||||
sleep 0.5
|
||||
|
||||
for i in `seq 1 10`; do
|
||||
for i in $(seq 1 10); do
|
||||
jid1=$(jail_name_to_jid ${base}_1_1)
|
||||
jid2=$(jail_name_to_jid ${base}_1_2)
|
||||
jid="${jid1},${jid2}"
|
||||
case "$jid" in
|
||||
[0-9]+,[0-9]+)
|
||||
[0-9]*,[0-9]*)
|
||||
break
|
||||
;;
|
||||
esac
|
||||
@ -43,14 +43,14 @@ sleep 0.5
|
||||
|
||||
pid1="$(pgrep -f -x -j "$jid" "$sleep $sleep_amount" | sort)"
|
||||
pid2=$(printf "%s\n%s" "$(cat ${PWD}/${base}_1_1.pid)" \
|
||||
$(cat ${PWD}/${base}_1_2.pid) | sort)
|
||||
"$(cat ${PWD}/${base}_1_2.pid)" | sort)
|
||||
if [ "$pid1" = "$pid2" ]; then
|
||||
echo "ok 1 - $name"
|
||||
else
|
||||
echo "not ok 1 - $name # pgrep output: '$(echo $pid1)', pidfile output: '$(echo $pid2)'"
|
||||
echo "not ok 1 - $name # pgrep output: '$pid1', pidfile output: '$pid2'"
|
||||
fi
|
||||
[ -f ${PWD}/${base}_1_1.pid ] && kill $(cat ${PWD}/${base}_1_1.pid)
|
||||
[ -f ${PWD}/${base}_1_2.pid ] && kill $(cat ${PWD}/${base}_1_2.pid)
|
||||
[ -f ${PWD}/${base}_1_1.pid ] && kill "$(cat ${PWD}/${base}_1_1.pid)"
|
||||
[ -f ${PWD}/${base}_1_2.pid ] && kill "$(cat ${PWD}/${base}_1_2.pid)"
|
||||
wait
|
||||
|
||||
name="pgrep -j any"
|
||||
@ -64,14 +64,14 @@ jail -c path=/ name=${base}_2_2 ip4.addr=127.0.0.1 \
|
||||
sleep 2
|
||||
pid1="$(pgrep -f -x -j any "$sleep $sleep_amount" | sort)"
|
||||
pid2=$(printf "%s\n%s" "$(cat ${PWD}/${base}_2_1.pid)" \
|
||||
$(cat ${PWD}/${base}_2_2.pid) | sort)
|
||||
"$(cat ${PWD}/${base}_2_2.pid)" | sort)
|
||||
if [ "$pid1" = "$pid2" ]; then
|
||||
echo "ok 2 - $name"
|
||||
else
|
||||
echo "not ok 2 - $name # pgrep output: '$(echo $pid1)', pidfile output: '$(echo $pid2)'"
|
||||
echo "not ok 2 - $name # pgrep output: '$pid1', pidfile output: '$pid2'"
|
||||
fi
|
||||
[ -f ${PWD}/${base}_2_1.pid ] && kill $(cat ${PWD}/${base}_2_1.pid)
|
||||
[ -f ${PWD}/${base}_2_2.pid ] && kill $(cat ${PWD}/${base}_2_2.pid)
|
||||
[ -f ${PWD}/${base}_2_1.pid ] && kill "$(cat ${PWD}/${base}_2_1.pid)"
|
||||
[ -f ${PWD}/${base}_2_2.pid ] && kill "$(cat ${PWD}/${base}_2_2.pid)"
|
||||
wait
|
||||
|
||||
name="pgrep -j none"
|
||||
@ -84,10 +84,10 @@ pid="$(pgrep -f -x -j none "$sleep $sleep_amount")"
|
||||
if [ "$pid" = "$(cat ${PWD}/${base}_3_1.pid)" ]; then
|
||||
echo "ok 3 - $name"
|
||||
else
|
||||
echo "not ok 3 - $name # pgrep output: '$(echo $pid1)', pidfile output: '$(echo $pid2)'"
|
||||
echo "not ok 3 - $name # pgrep output: '$pid1', pidfile output: '$pid2'"
|
||||
fi
|
||||
[ -f ${PWD}/${base}_3_1.pid ] && kill $(cat $PWD/${base}_3_1.pid)
|
||||
[ -f ${PWD}/${base}_3_2.pid ] && kill $(cat $PWD/${base}_3_2.pid)
|
||||
[ -f ${PWD}/${base}_3_1.pid ] && kill "$(cat $PWD/${base}_3_1.pid)"
|
||||
[ -f ${PWD}/${base}_3_2.pid ] && kill "$(cat $PWD/${base}_3_2.pid)"
|
||||
wait
|
||||
|
||||
# test 4 is like test 1 except with jname instead of jid.
|
||||
@ -104,14 +104,14 @@ sleep 0.5
|
||||
jname="${base}_4_1,${base}_4_2"
|
||||
pid1="$(pgrep -f -x -j "$jname" "$sleep $sleep_amount" | sort)"
|
||||
pid2=$(printf "%s\n%s" "$(cat ${PWD}/${base}_4_1.pid)" \
|
||||
$(cat ${PWD}/${base}_4_2.pid) | sort)
|
||||
"$(cat ${PWD}/${base}_4_2.pid)" | sort)
|
||||
if [ "$pid1" = "$pid2" ]; then
|
||||
echo "ok 4 - $name"
|
||||
else
|
||||
echo "not ok 4 - $name # pgrep output: '$(echo $pid1)', pidfile output: '$(echo $pid2)'"
|
||||
fi
|
||||
[ -f ${PWD}/${base}_4_1.pid ] && kill $(cat ${PWD}/${base}_4_1.pid)
|
||||
[ -f ${PWD}/${base}_4_2.pid ] && kill $(cat ${PWD}/${base}_4_2.pid)
|
||||
[ -f ${PWD}/${base}_4_1.pid ] && kill "$(cat ${PWD}/${base}_4_1.pid)"
|
||||
[ -f ${PWD}/${base}_4_2.pid ] && kill "$(cat ${PWD}/${base}_4_2.pid)"
|
||||
wait
|
||||
|
||||
rm -f $sleep
|
||||
|
@ -9,7 +9,7 @@ jail_name_to_jid()
|
||||
|
||||
base=pkill_j_test
|
||||
|
||||
if [ `id -u` -ne 0 ]; then
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "1..0 # skip Test needs uid 0."
|
||||
exit 0
|
||||
fi
|
||||
@ -29,28 +29,31 @@ jail -c path=/ name=${base}_1_2 ip4.addr=127.0.0.1 \
|
||||
|
||||
$sleep $sleep_amount &
|
||||
|
||||
for i in `seq 1 10`; do
|
||||
for i in $(seq 1 10); do
|
||||
jid1=$(jail_name_to_jid ${base}_1_1)
|
||||
jid2=$(jail_name_to_jid ${base}_1_2)
|
||||
jid="${jid1},${jid2}"
|
||||
case "$jid" in
|
||||
[0-9]+,[0-9]+)
|
||||
[0-9]*,[0-9]*)
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Did not match: '${jid}'" >&2
|
||||
;;
|
||||
esac
|
||||
sleep 0.1
|
||||
done
|
||||
sleep 0.5
|
||||
|
||||
if pkill -f -j "$jid" $sleep && sleep 0.5 &&
|
||||
! -f ${PWD}/${base}_1_1.pid &&
|
||||
! -f ${PWD}/${base}_1_2.pid ; then
|
||||
! test -f "${PWD}/${base}_1_1.pid" &&
|
||||
! test -f "${PWD}/${base}_1_2.pid" ; then
|
||||
echo "ok 1 - $name"
|
||||
else
|
||||
echo "not ok 1 - $name"
|
||||
fi 2>/dev/null
|
||||
[ -f ${PWD}/${base}_1_1.pid ] && kill $(cat ${PWD}/${base}_1_1.pid)
|
||||
[ -f ${PWD}/${base}_1_2.pid ] && kill $(cat ${PWD}/${base}_1_2.pid)
|
||||
[ -f ${PWD}/${base}_1_1.pid ] && kill "$(cat ${PWD}/${base}_1_1.pid)"
|
||||
[ -f ${PWD}/${base}_1_2.pid ] && kill "$(cat ${PWD}/${base}_1_2.pid)"
|
||||
wait
|
||||
|
||||
name="pkill -j any"
|
||||
@ -65,14 +68,14 @@ $sleep $sleep_amount &
|
||||
chpid3=$!
|
||||
sleep 0.5
|
||||
if pkill -f -j any $sleep && sleep 0.5 &&
|
||||
[ ! -f ${PWD}/${base}_2_1.pid -a
|
||||
! -f ${PWD}/${base}_2_2.pid ] && kill $chpid3; then
|
||||
! test -f ${PWD}/${base}_2_1.pid &&
|
||||
! test -f ${PWD}/${base}_2_2.pid && kill $chpid3; then
|
||||
echo "ok 2 - $name"
|
||||
else
|
||||
echo "not ok 2 - $name"
|
||||
fi 2>/dev/null
|
||||
[ -f ${PWD}/${base}_2_1.pid ] && kill $(cat ${PWD}/${base}_2_1.pid)
|
||||
[ -f ${PWD}/${base}_2_2.pid ] && kill $(cat ${PWD}/${base}_2_2.pid)
|
||||
[ -f ${PWD}/${base}_2_1.pid ] && kill "$(cat ${PWD}/${base}_2_1.pid)"
|
||||
[ -f ${PWD}/${base}_2_2.pid ] && kill "$(cat ${PWD}/${base}_2_2.pid)"
|
||||
wait
|
||||
|
||||
name="pkill -j none"
|
||||
@ -88,8 +91,8 @@ else
|
||||
ls ${PWD}/*.pid
|
||||
echo "not ok 3 - $name"
|
||||
fi 2>/dev/null
|
||||
[ -f ${PWD}/${base}_3_1.pid ] && kill $(cat ${base}_3_1.pid)
|
||||
[ -f ${PWD}/${base}_3_2.pid ] && kill $(cat ${base}_3_2.pid)
|
||||
[ -f ${PWD}/${base}_3_1.pid ] && kill "$(cat ${base}_3_1.pid)"
|
||||
[ -f ${PWD}/${base}_3_2.pid ] && kill "$(cat ${base}_3_2.pid)"
|
||||
wait
|
||||
|
||||
# test 4 is like test 1 except with jname instead of jid.
|
||||
@ -107,14 +110,14 @@ sleep 0.5
|
||||
|
||||
jname="${base}_4_1,${base}_4_2"
|
||||
if pkill -f -j "$jname" $sleep && sleep 0.5 &&
|
||||
! -f ${PWD}/${base}_4_1.pid &&
|
||||
! -f ${PWD}/${base}_4_2.pid ; then
|
||||
! test -f ${PWD}/${base}_4_1.pid &&
|
||||
! test -f ${PWD}/${base}_4_2.pid ; then
|
||||
echo "ok 4 - $name"
|
||||
else
|
||||
echo "not ok 4 - $name"
|
||||
fi 2>/dev/null
|
||||
[ -f ${PWD}/${base}_4_1.pid ] && kill $(cat ${PWD}/${base}_4_1.pid)
|
||||
[ -f ${PWD}/${base}_4_2.pid ] && kill $(cat ${PWD}/${base}_4_2.pid)
|
||||
[ -f ${PWD}/${base}_4_1.pid ] && kill "$(cat ${PWD}/${base}_4_1.pid)"
|
||||
[ -f ${PWD}/${base}_4_2.pid ] && kill "$(cat ${PWD}/${base}_4_2.pid)"
|
||||
wait
|
||||
|
||||
rm -f $sleep
|
||||
|
@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 5, 2020
|
||||
.Dd January 21, 2021
|
||||
.Dt PWAIT 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -145,6 +145,10 @@ is not a substitute for the
|
||||
.Xr wait 1
|
||||
builtin
|
||||
as it will not clean up any zombies or state in the parent process.
|
||||
.Pp
|
||||
To avoid deadlock,
|
||||
.Nm
|
||||
will ignore its own pid, if it is provided as a process id to wait for.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
|
@ -146,6 +146,10 @@ main(int argc, char *argv[])
|
||||
warnx("%s: bad process id", s);
|
||||
continue;
|
||||
}
|
||||
if (pid == getpid()) {
|
||||
warnx("%s: skipping my own pid", s);
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < nleft; i++) {
|
||||
if (e[i].ident == (uintptr_t)pid) {
|
||||
break;
|
||||
|
@ -39,6 +39,9 @@ static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <paths.h>
|
||||
#include <stdio.h>
|
||||
@ -72,6 +75,67 @@ static FILE *el_in, *el_out;
|
||||
static char *fc_replace(const char *, char *, char *);
|
||||
static int not_fcnumber(const char *);
|
||||
static int str_to_event(const char *, int);
|
||||
static int comparator(const void *, const void *, void *);
|
||||
static char **sh_matches(const char *, int, int);
|
||||
static unsigned char sh_complete(EditLine *, int);
|
||||
|
||||
static const char *
|
||||
get_histfile(void)
|
||||
{
|
||||
const char *histfile;
|
||||
|
||||
/* don't try to save if the history size is 0 */
|
||||
if (hist == NULL || histsizeval() == 0)
|
||||
return (NULL);
|
||||
histfile = expandstr("${HISTFILE-${HOME-}/.sh_history}");
|
||||
|
||||
if (histfile[0] == '\0')
|
||||
return (NULL);
|
||||
return (histfile);
|
||||
}
|
||||
|
||||
void
|
||||
histsave(void)
|
||||
{
|
||||
HistEvent he;
|
||||
char *histtmpname = NULL;
|
||||
const char *histfile;
|
||||
int fd;
|
||||
FILE *f;
|
||||
|
||||
if ((histfile = get_histfile()) == NULL)
|
||||
return;
|
||||
INTOFF;
|
||||
asprintf(&histtmpname, "%s.XXXXXXXXXX", histfile);
|
||||
if (histtmpname == NULL) {
|
||||
INTON;
|
||||
return;
|
||||
}
|
||||
fd = mkstemp(histtmpname);
|
||||
if (fd == -1 || (f = fdopen(fd, "w")) == NULL) {
|
||||
free(histtmpname);
|
||||
INTON;
|
||||
return;
|
||||
}
|
||||
if (history(hist, &he, H_SAVE_FP, f) < 1 ||
|
||||
rename(histtmpname, histfile) == -1)
|
||||
unlink(histtmpname);
|
||||
fclose(f);
|
||||
free(histtmpname);
|
||||
INTON;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
histload(void)
|
||||
{
|
||||
const char *histfile;
|
||||
HistEvent he;
|
||||
|
||||
if ((histfile = get_histfile()) == NULL)
|
||||
return;
|
||||
history(hist, &he, H_LOAD, histfile);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set history and editing status. Called whenever the status may
|
||||
@ -122,7 +186,7 @@ histedit(void)
|
||||
el_set(el, EL_PROMPT, getprompt);
|
||||
el_set(el, EL_ADDFN, "sh-complete",
|
||||
"Filename completion",
|
||||
_el_fn_complete);
|
||||
sh_complete);
|
||||
} else {
|
||||
bad:
|
||||
out2fmt_flush("sh: can't initialize editing\n");
|
||||
@ -137,8 +201,10 @@ bad:
|
||||
if (el) {
|
||||
if (Vflag)
|
||||
el_set(el, EL_EDITOR, "vi");
|
||||
else if (Eflag)
|
||||
else if (Eflag) {
|
||||
el_set(el, EL_EDITOR, "emacs");
|
||||
el_set(el, EL_BIND, "^R", "em-inc-search-prev", NULL);
|
||||
}
|
||||
el_set(el, EL_BIND, "^I", "sh-complete", NULL);
|
||||
el_source(el, NULL);
|
||||
}
|
||||
@ -519,3 +585,124 @@ bindcmd(int argc __unused, char **argv __unused)
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Comparator function for qsort(). The use of curpos here is to skip
|
||||
* characters that we already know to compare equal (common prefix).
|
||||
*/
|
||||
static int
|
||||
comparator(const void *a, const void *b, void *thunk)
|
||||
{
|
||||
size_t curpos = (intptr_t)thunk;
|
||||
return (strcmp(*(char *const *)a + curpos,
|
||||
*(char *const *)b + curpos));
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is passed to libedit's fn_complete2(). The library will
|
||||
* use it instead of its standard function that finds matching files in
|
||||
* current directory. If we're at the start of the line, we want to look
|
||||
* for available commands from all paths in $PATH.
|
||||
*/
|
||||
static char
|
||||
**sh_matches(const char *text, int start, int end)
|
||||
{
|
||||
char *free_path = NULL, *path;
|
||||
const char *dirname;
|
||||
char **matches = NULL;
|
||||
size_t i = 0, size = 16, j, k;
|
||||
size_t curpos = end - start;
|
||||
|
||||
if (start > 0 || memchr("/.~", text[0], 3) != NULL)
|
||||
return (NULL);
|
||||
if ((free_path = path = strdup(pathval())) == NULL)
|
||||
goto out;
|
||||
if ((matches = malloc(size * sizeof(matches[0]))) == NULL)
|
||||
goto out;
|
||||
while ((dirname = strsep(&path, ":")) != NULL) {
|
||||
struct dirent *entry;
|
||||
DIR *dir;
|
||||
int dfd;
|
||||
|
||||
dir = opendir(dirname[0] == '\0' ? "." : dirname);
|
||||
if (dir == NULL)
|
||||
continue;
|
||||
if ((dfd = dirfd(dir)) == -1) {
|
||||
closedir(dir);
|
||||
continue;
|
||||
}
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
struct stat statb;
|
||||
char **rmatches;
|
||||
|
||||
if (strncmp(entry->d_name, text, curpos) != 0)
|
||||
continue;
|
||||
if (entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK) {
|
||||
if (fstatat(dfd, entry->d_name, &statb, 0) == -1)
|
||||
continue;
|
||||
if (!S_ISREG(statb.st_mode))
|
||||
continue;
|
||||
} else if (entry->d_type != DT_REG)
|
||||
continue;
|
||||
matches[++i] = strdup(entry->d_name);
|
||||
if (i < size - 1)
|
||||
continue;
|
||||
size *= 2;
|
||||
rmatches = reallocarray(matches, size, sizeof(matches[0]));
|
||||
if (rmatches == NULL) {
|
||||
closedir(dir);
|
||||
goto out;
|
||||
}
|
||||
matches = rmatches;
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
out:
|
||||
free(free_path);
|
||||
/*
|
||||
* matches[0] is special: it's not a real matching file name but a common
|
||||
* prefix for all matching names. It can't be null, unlike any other
|
||||
* element of the array. When strings matches[0] and matches[1] compare
|
||||
* equal and matches[2] is null that means to libedit that there is only
|
||||
* a single match. It will then replace user input with possibly escaped
|
||||
* string in matches[0] which is the reason to copy the full name of the
|
||||
* only match.
|
||||
*/
|
||||
if (i == 0) {
|
||||
free(matches);
|
||||
return (NULL);
|
||||
} else if (i == 1) {
|
||||
matches[0] = strdup(matches[1]);
|
||||
matches[2] = NULL;
|
||||
if (matches[0] != NULL)
|
||||
return (matches);
|
||||
} else
|
||||
matches[0] = strdup(text);
|
||||
if (matches[0] == NULL) {
|
||||
for (j = 1; j <= i; j++)
|
||||
free(matches[j]);
|
||||
free(matches);
|
||||
return (NULL);
|
||||
}
|
||||
qsort_s(matches + 1, i, sizeof(matches[0]), comparator,
|
||||
(void *)(intptr_t)curpos);
|
||||
for (j = 1, k = 2; k <= i; k++)
|
||||
if (strcmp(matches[j] + curpos, matches[k] + curpos) == 0)
|
||||
free(matches[k]);
|
||||
else
|
||||
matches[++j] = matches[k];
|
||||
matches[j + 1] = NULL;
|
||||
return (matches);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is passed to el_set(el, EL_ADDFN, ...) so that it's possible to
|
||||
* bind a key (tab by default) to execute the function.
|
||||
*/
|
||||
unsigned char
|
||||
sh_complete(EditLine *sel, int ch __unused)
|
||||
{
|
||||
return (unsigned char)fn_complete2(sel, NULL, sh_matches,
|
||||
L" \t\n\"\\'`@$><=;|&{(", NULL, NULL, (size_t)100,
|
||||
NULL, &((int) {0}), NULL, NULL, FN_QUOTE_MATCH);
|
||||
}
|
||||
|
@ -928,7 +928,12 @@ forkshell(struct job *jp, union node *n, int mode)
|
||||
pgrp = jp->ps[0].pid;
|
||||
if (setpgid(0, pgrp) == 0 && mode == FORK_FG &&
|
||||
ttyfd >= 0) {
|
||||
/*** this causes superfluous TIOCSPGRPS ***/
|
||||
/*
|
||||
* Each process in a pipeline must have the tty
|
||||
* pgrp set before running its code.
|
||||
* Only for pipelines of three or more processes
|
||||
* could this be reduced to two calls.
|
||||
*/
|
||||
if (tcsetpgrp(ttyfd, pgrp) < 0)
|
||||
error("tcsetpgrp failed, errno=%d", errno);
|
||||
}
|
||||
|
@ -75,6 +75,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include "cd.h"
|
||||
#include "redir.h"
|
||||
#include "builtins.h"
|
||||
#ifndef NO_HISTORY
|
||||
#include "myhistedit.h"
|
||||
#endif
|
||||
|
||||
int rootpid;
|
||||
int rootshell;
|
||||
@ -157,6 +160,10 @@ state2:
|
||||
read_profile(shinit);
|
||||
}
|
||||
}
|
||||
#ifndef NO_HISTORY
|
||||
if (iflag)
|
||||
histload();
|
||||
#endif
|
||||
state3:
|
||||
state = 4;
|
||||
popstackmark(&smark2);
|
||||
|
@ -227,7 +227,10 @@ popstackmark(struct stackmark *mark)
|
||||
}
|
||||
stacknxt = mark->stacknxt;
|
||||
stacknleft = mark->stacknleft;
|
||||
sstrend = stacknxt + stacknleft;
|
||||
if (stacknleft != 0)
|
||||
sstrend = stacknxt + stacknleft;
|
||||
else
|
||||
sstrend = stacknxt;
|
||||
INTON;
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,10 @@ extern History *hist;
|
||||
extern EditLine *el;
|
||||
extern int displayhist;
|
||||
|
||||
#include <filecomplete.h>
|
||||
|
||||
void histedit(void);
|
||||
void sethistsize(const char *);
|
||||
void setterm(const char *);
|
||||
|
||||
void histload(void);
|
||||
void histsave(void);
|
||||
|
11
bin/sh/sh.1
11
bin/sh/sh.1
@ -32,7 +32,7 @@
|
||||
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 6, 2020
|
||||
.Dd May 10, 2021
|
||||
.Dt SH 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -1351,6 +1351,15 @@ If not set, the default editor is
|
||||
The default editor used with the
|
||||
.Ic fc
|
||||
built-in.
|
||||
.It Va HISTFILE
|
||||
File used for persistent history storage.
|
||||
If unset
|
||||
.Pa ~/.sh_history
|
||||
will be used.
|
||||
If set but empty or
|
||||
.Va HISTSIZE
|
||||
is set to 0
|
||||
the shell will not load and save the history.
|
||||
.It Va HISTSIZE
|
||||
The number of previous commands that are accessible.
|
||||
.It Va HOME
|
||||
|
@ -73,7 +73,7 @@ static void
|
||||
shtree(union node *n, int ind, char *pfx, FILE *fp)
|
||||
{
|
||||
struct nodelist *lp;
|
||||
char *s;
|
||||
const char *s;
|
||||
|
||||
if (n == NULL)
|
||||
return;
|
||||
@ -125,7 +125,7 @@ shcmd(union node *cmd, FILE *fp)
|
||||
{
|
||||
union node *np;
|
||||
int first;
|
||||
char *s;
|
||||
const char *s;
|
||||
int dftfd;
|
||||
|
||||
first = 1;
|
||||
@ -274,8 +274,7 @@ indent(int amount, char *pfx, FILE *fp)
|
||||
*/
|
||||
|
||||
|
||||
FILE *tracefile;
|
||||
|
||||
static FILE *tracefile;
|
||||
#if DEBUG >= 2
|
||||
int debug = 1;
|
||||
#else
|
||||
|
@ -39,4 +39,6 @@ void trargs(char **);
|
||||
void trputc(int);
|
||||
void trputs(const char *);
|
||||
void opentrace(void);
|
||||
|
||||
extern int debug;
|
||||
#endif
|
||||
|
@ -63,6 +63,7 @@ ${PACKAGE}FILES+= shellproc3.0
|
||||
${PACKAGE}FILES+= shellproc4.0
|
||||
${PACKAGE}FILES+= shellproc5.0
|
||||
${PACKAGE}FILES+= shellproc6.0
|
||||
${PACKAGE}FILES+= shellproc7.0
|
||||
${PACKAGE}FILES+= subshell1.0 subshell1.0.stdout
|
||||
${PACKAGE}FILES+= subshell2.0
|
||||
${PACKAGE}FILES+= subshell3.0
|
||||
|
10
bin/sh/tests/execution/shellproc7.0
Normal file
10
bin/sh/tests/execution/shellproc7.0
Normal file
@ -0,0 +1,10 @@
|
||||
# $FreeBSD$
|
||||
# Non-POSIX trickery that is widely supported,
|
||||
# used by https://justine.lol/ape.html
|
||||
|
||||
T=`mktemp -d "${TMPDIR:-/tmp}/sh-test.XXXXXXXX"` || exit
|
||||
trap 'rm -rf "${T}"' 0
|
||||
printf "MZqFpD='\n\0'\n#'\"\necho this is a test\n" >"$T/testshellproc"
|
||||
chmod 755 "$T/testshellproc"
|
||||
PATH=$T:$PATH
|
||||
[ "`testshellproc`" = "this is a test" ]
|
@ -274,12 +274,8 @@ setsignal(int signo)
|
||||
break;
|
||||
case SIGQUIT:
|
||||
#ifdef DEBUG
|
||||
{
|
||||
extern int debug;
|
||||
|
||||
if (debug)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
action = S_CATCH;
|
||||
break;
|
||||
@ -539,6 +535,9 @@ exitshell_savedstatus(void)
|
||||
flushall();
|
||||
#if JOBS
|
||||
setjobctl(0);
|
||||
#endif
|
||||
#ifndef NO_HISTORY
|
||||
histsave();
|
||||
#endif
|
||||
}
|
||||
if (sig != 0 && sig != SIGSTOP && sig != SIGTSTP && sig != SIGTTIN &&
|
||||
|
@ -32,7 +32,7 @@
|
||||
.\" @(#)sleep.1 8.3 (Berkeley) 4/18/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd April 18, 1994
|
||||
.Dd December 31, 2020
|
||||
.Dt SLEEP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -65,8 +65,8 @@ The
|
||||
command allows and honors a non-integer number of seconds to sleep
|
||||
in any form acceptable by
|
||||
.Xr strtod 3 .
|
||||
This is a non-portable extension, and its use will nearly guarantee that
|
||||
a shell script will not execute properly on another system.
|
||||
This is a non-portable extension, but is also implemented in GNU sh-utils
|
||||
since version 2.0a (released in 2002).
|
||||
.Sh EXIT STATUS
|
||||
.Ex -std
|
||||
.Sh EXAMPLES
|
||||
|
@ -42,12 +42,10 @@ static char sccsid[] = "@(#)sleep.c 8.3 (Berkeley) 4/2/94";
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <capsicum_helpers.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "stty.h"
|
||||
@ -85,7 +86,7 @@ gread(struct termios *tp, char *s)
|
||||
if (!(ep = strchr(p, '=')))
|
||||
gerr(p);
|
||||
*ep++ = '\0';
|
||||
(void)sscanf(ep, "%lx", (u_long *)&tmp);
|
||||
tmp = strtoul(ep, NULL, 0x10);
|
||||
|
||||
#define CHK(s) (*p == s[0] && !strcmp(p, s))
|
||||
if (CHK("cflag")) {
|
||||
@ -97,7 +98,7 @@ gread(struct termios *tp, char *s)
|
||||
continue;
|
||||
}
|
||||
if (CHK("ispeed")) {
|
||||
(void)sscanf(ep, "%ld", &tmp);
|
||||
tmp = strtoul(ep, NULL, 10);
|
||||
tp->c_ispeed = tmp;
|
||||
continue;
|
||||
}
|
||||
@ -110,14 +111,14 @@ gread(struct termios *tp, char *s)
|
||||
continue;
|
||||
}
|
||||
if (CHK("ospeed")) {
|
||||
(void)sscanf(ep, "%ld", &tmp);
|
||||
tmp = strtoul(ep, NULL, 10);
|
||||
tp->c_ospeed = tmp;
|
||||
continue;
|
||||
}
|
||||
for (cp = cchars1; cp->name != NULL; ++cp)
|
||||
if (CHK(cp->name)) {
|
||||
if (cp->sub == VMIN || cp->sub == VTIME)
|
||||
(void)sscanf(ep, "%ld", &tmp);
|
||||
tmp = strtoul(ep, NULL, 10);
|
||||
tp->c_cc[cp->sub] = tmp;
|
||||
break;
|
||||
}
|
||||
|
@ -24,9 +24,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
@ -3,7 +3,7 @@
|
||||
.include <src.opts.mk>
|
||||
|
||||
SUBDIR= lib .WAIT \
|
||||
sbin usr.bin usr.sbin
|
||||
sbin share usr.bin usr.sbin
|
||||
|
||||
SUBDIR.${MK_TESTS}+= tests
|
||||
|
||||
|
@ -1,115 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* 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 AUTHORS 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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <libgeom.h>
|
||||
#include <devid.h>
|
||||
|
||||
int
|
||||
devid_str_decode(char *devidstr, ddi_devid_t *retdevid, char **retminor_name)
|
||||
{
|
||||
|
||||
if (strlcpy(retdevid->devid, devidstr, sizeof(retdevid->devid)) >=
|
||||
sizeof(retdevid->devid)) {
|
||||
return (EINVAL);
|
||||
}
|
||||
*retminor_name = strdup("");
|
||||
if (*retminor_name == NULL)
|
||||
return (ENOMEM);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
devid_deviceid_to_nmlist(char *search_path, ddi_devid_t devid, char *minor_name,
|
||||
devid_nmlist_t **retlist)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
char *dst;
|
||||
|
||||
if (g_get_name(devid.devid, path, sizeof(path)) == -1)
|
||||
return (errno);
|
||||
*retlist = malloc(sizeof(**retlist));
|
||||
if (*retlist == NULL)
|
||||
return (ENOMEM);
|
||||
if (strlcpy((*retlist)[0].devname, path,
|
||||
sizeof((*retlist)[0].devname)) >= sizeof((*retlist)[0].devname)) {
|
||||
free(*retlist);
|
||||
return (ENAMETOOLONG);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
devid_str_free(char *str)
|
||||
{
|
||||
|
||||
free(str);
|
||||
}
|
||||
|
||||
void
|
||||
devid_free(ddi_devid_t devid)
|
||||
{
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
void
|
||||
devid_free_nmlist(devid_nmlist_t *list)
|
||||
{
|
||||
|
||||
free(list);
|
||||
}
|
||||
|
||||
int
|
||||
devid_get(int fd, ddi_devid_t *retdevid)
|
||||
{
|
||||
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
int
|
||||
devid_get_minor_name(int fd, char **retminor_name)
|
||||
{
|
||||
|
||||
*retminor_name = strdup("");
|
||||
if (*retminor_name == NULL)
|
||||
return (ENOMEM);
|
||||
return (0);
|
||||
}
|
||||
|
||||
char *
|
||||
devid_str_encode(ddi_devid_t devid, char *minor_name)
|
||||
{
|
||||
|
||||
return (strdup(devid.devid));
|
||||
}
|
@ -1,262 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* 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 AUTHORS 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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fsshare.h>
|
||||
#include <libutil.h>
|
||||
#include <pathnames.h> /* _PATH_MOUNTDPID */
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define FILE_HEADER "# !!! DO NOT EDIT THIS FILE MANUALLY !!!\n\n"
|
||||
#define OPTSSIZE 1024
|
||||
#define MAXLINESIZE (PATH_MAX + OPTSSIZE)
|
||||
|
||||
static void
|
||||
restart_mountd(void)
|
||||
{
|
||||
struct pidfh *pfh;
|
||||
pid_t mountdpid;
|
||||
|
||||
pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &mountdpid);
|
||||
if (pfh != NULL) {
|
||||
/* Mountd is not running. */
|
||||
pidfile_remove(pfh);
|
||||
return;
|
||||
}
|
||||
if (errno != EEXIST) {
|
||||
/* Cannot open pidfile for some reason. */
|
||||
return;
|
||||
}
|
||||
/* We have mountd(8) PID in mountdpid varible. */
|
||||
kill(mountdpid, SIGHUP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read one line from a file. Skip comments, empty lines and a line with a
|
||||
* mountpoint specified in the 'skip' argument.
|
||||
*/
|
||||
static char *
|
||||
zgetline(FILE *fd, const char *skip)
|
||||
{
|
||||
static char line[MAXLINESIZE];
|
||||
size_t len, skiplen;
|
||||
char *s, last;
|
||||
|
||||
if (skip != NULL)
|
||||
skiplen = strlen(skip);
|
||||
for (;;) {
|
||||
s = fgets(line, sizeof(line), fd);
|
||||
if (s == NULL)
|
||||
return (NULL);
|
||||
/* Skip empty lines and comments. */
|
||||
if (line[0] == '\n' || line[0] == '#')
|
||||
continue;
|
||||
len = strlen(line);
|
||||
if (line[len - 1] == '\n')
|
||||
line[len - 1] = '\0';
|
||||
last = line[skiplen];
|
||||
/* Skip the given mountpoint. */
|
||||
if (skip != NULL && strncmp(skip, line, skiplen) == 0 &&
|
||||
(last == '\t' || last == ' ' || last == '\0')) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (line);
|
||||
}
|
||||
|
||||
/*
|
||||
* Function translate options to a format acceptable by exports(5), eg.
|
||||
*
|
||||
* -ro -network=192.168.0.0 -mask=255.255.255.0 -maproot=0 freefall.freebsd.org 69.147.83.54
|
||||
*
|
||||
* Accepted input formats:
|
||||
*
|
||||
* ro,network=192.168.0.0,mask=255.255.255.0,maproot=0,freefall.freebsd.org
|
||||
* ro network=192.168.0.0 mask=255.255.255.0 maproot=0 freefall.freebsd.org
|
||||
* -ro,-network=192.168.0.0,-mask=255.255.255.0,-maproot=0,freefall.freebsd.org
|
||||
* -ro -network=192.168.0.0 -mask=255.255.255.0 -maproot=0 freefall.freebsd.org
|
||||
*
|
||||
* Recognized keywords:
|
||||
*
|
||||
* ro, maproot, mapall, mask, network, sec, alldirs, public, webnfs, index, quiet
|
||||
*
|
||||
*/
|
||||
static const char *known_opts[] = { "ro", "maproot", "mapall", "mask",
|
||||
"network", "sec", "alldirs", "public", "webnfs", "index", "quiet", NULL };
|
||||
static char *
|
||||
translate_opts(const char *shareopts)
|
||||
{
|
||||
static char newopts[OPTSSIZE];
|
||||
char oldopts[OPTSSIZE];
|
||||
char *o, *s = NULL;
|
||||
unsigned int i;
|
||||
size_t len;
|
||||
|
||||
strlcpy(oldopts, shareopts, sizeof(oldopts));
|
||||
newopts[0] = '\0';
|
||||
s = oldopts;
|
||||
while ((o = strsep(&s, "-, ")) != NULL) {
|
||||
if (o[0] == '\0')
|
||||
continue;
|
||||
for (i = 0; known_opts[i] != NULL; i++) {
|
||||
len = strlen(known_opts[i]);
|
||||
if (strncmp(known_opts[i], o, len) == 0 &&
|
||||
(o[len] == '\0' || o[len] == '=')) {
|
||||
strlcat(newopts, "-", sizeof(newopts));
|
||||
break;
|
||||
}
|
||||
}
|
||||
strlcat(newopts, o, sizeof(newopts));
|
||||
strlcat(newopts, " ", sizeof(newopts));
|
||||
}
|
||||
return (newopts);
|
||||
}
|
||||
|
||||
static int
|
||||
fsshare_main(const char *file, const char *mountpoint, const char *shareopts,
|
||||
int share)
|
||||
{
|
||||
char tmpfile[PATH_MAX];
|
||||
char *line;
|
||||
FILE *newfd, *oldfd;
|
||||
int fd, error;
|
||||
|
||||
newfd = oldfd = NULL;
|
||||
error = 0;
|
||||
|
||||
/*
|
||||
* Create temporary file in the same directory, so we can atomically
|
||||
* rename it.
|
||||
*/
|
||||
if (strlcpy(tmpfile, file, sizeof(tmpfile)) >= sizeof(tmpfile))
|
||||
return (ENAMETOOLONG);
|
||||
if (strlcat(tmpfile, ".XXXXXXXX", sizeof(tmpfile)) >= sizeof(tmpfile))
|
||||
return (ENAMETOOLONG);
|
||||
fd = mkstemp(tmpfile);
|
||||
if (fd == -1)
|
||||
return (errno);
|
||||
/*
|
||||
* File name is random, so we don't really need file lock now, but it
|
||||
* will be needed after rename(2).
|
||||
*/
|
||||
error = flock(fd, LOCK_EX);
|
||||
assert(error == 0 || (error == -1 && errno == EOPNOTSUPP));
|
||||
newfd = fdopen(fd, "r+");
|
||||
assert(newfd != NULL);
|
||||
/* Open old exports file. */
|
||||
oldfd = fopen(file, "r");
|
||||
if (oldfd == NULL) {
|
||||
if (share) {
|
||||
if (errno != ENOENT) {
|
||||
error = errno;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* If there is no exports file, ignore the error. */
|
||||
if (errno == ENOENT)
|
||||
errno = 0;
|
||||
error = errno;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
error = flock(fileno(oldfd), LOCK_EX);
|
||||
assert(error == 0 || (error == -1 && errno == EOPNOTSUPP));
|
||||
error = 0;
|
||||
}
|
||||
|
||||
/* Place big, fat warning at the begining of the file. */
|
||||
fprintf(newfd, "%s", FILE_HEADER);
|
||||
while (oldfd != NULL && (line = zgetline(oldfd, mountpoint)) != NULL)
|
||||
fprintf(newfd, "%s\n", line);
|
||||
if (oldfd != NULL && ferror(oldfd) != 0) {
|
||||
error = ferror(oldfd);
|
||||
goto out;
|
||||
}
|
||||
if (ferror(newfd) != 0) {
|
||||
error = ferror(newfd);
|
||||
goto out;
|
||||
}
|
||||
if (share) {
|
||||
fprintf(newfd, "%s\t%s\n", mountpoint,
|
||||
translate_opts(shareopts));
|
||||
}
|
||||
|
||||
out:
|
||||
if (error != 0)
|
||||
unlink(tmpfile);
|
||||
else {
|
||||
if (rename(tmpfile, file) == -1) {
|
||||
error = errno;
|
||||
unlink(tmpfile);
|
||||
} else {
|
||||
fflush(newfd);
|
||||
/*
|
||||
* Send SIGHUP to mountd, but unlock exports file later.
|
||||
*/
|
||||
restart_mountd();
|
||||
}
|
||||
}
|
||||
if (oldfd != NULL) {
|
||||
flock(fileno(oldfd), LOCK_UN);
|
||||
fclose(oldfd);
|
||||
}
|
||||
if (newfd != NULL) {
|
||||
flock(fileno(newfd), LOCK_UN);
|
||||
fclose(newfd);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the given mountpoint to the given exports file.
|
||||
*/
|
||||
int
|
||||
fsshare(const char *file, const char *mountpoint, const char *shareopts)
|
||||
{
|
||||
|
||||
return (fsshare_main(file, mountpoint, shareopts, 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the given mountpoint from the given exports file.
|
||||
*/
|
||||
int
|
||||
fsunshare(const char *file, const char *mountpoint)
|
||||
{
|
||||
|
||||
return (fsshare_main(file, mountpoint, NULL, 0));
|
||||
}
|
@ -1,215 +0,0 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* The contents of this file are subject to the terms of the
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (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
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/* Copyright (c) 1988 AT&T */
|
||||
/* All Rights Reserved */
|
||||
|
||||
/*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "@(#)mkdirp.c 1.15 06/01/04 SMI"
|
||||
|
||||
/*
|
||||
* Creates directory and it's parents if the parents do not
|
||||
* exist yet.
|
||||
*
|
||||
* Returns -1 if fails for reasons other than non-existing
|
||||
* parents.
|
||||
* Does NOT simplify pathnames with . or .. in them.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <libgen.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static char *simplify(const char *str);
|
||||
|
||||
int
|
||||
mkdirp(const char *d, mode_t mode)
|
||||
{
|
||||
char *endptr, *ptr, *slash, *str;
|
||||
|
||||
str = simplify(d);
|
||||
|
||||
/* If space couldn't be allocated for the simplified names, return. */
|
||||
|
||||
if (str == NULL)
|
||||
return (-1);
|
||||
|
||||
/* Try to make the directory */
|
||||
|
||||
if (mkdir(str, mode) == 0) {
|
||||
free(str);
|
||||
return (0);
|
||||
}
|
||||
if (errno != ENOENT) {
|
||||
free(str);
|
||||
return (-1);
|
||||
}
|
||||
endptr = strrchr(str, '\0');
|
||||
slash = strrchr(str, '/');
|
||||
|
||||
/* Search upward for the non-existing parent */
|
||||
|
||||
while (slash != NULL) {
|
||||
|
||||
ptr = slash;
|
||||
*ptr = '\0';
|
||||
|
||||
/* If reached an existing parent, break */
|
||||
|
||||
if (access(str, F_OK) == 0)
|
||||
break;
|
||||
|
||||
/* If non-existing parent */
|
||||
|
||||
else {
|
||||
slash = strrchr(str, '/');
|
||||
|
||||
/* If under / or current directory, make it. */
|
||||
|
||||
if (slash == NULL || slash == str) {
|
||||
if (mkdir(str, mode) != 0 && errno != EEXIST) {
|
||||
free(str);
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create directories starting from upmost non-existing parent */
|
||||
|
||||
while ((ptr = strchr(str, '\0')) != endptr) {
|
||||
*ptr = '/';
|
||||
if (mkdir(str, mode) != 0 && errno != EEXIST) {
|
||||
/*
|
||||
* If the mkdir fails because str already
|
||||
* exists (EEXIST), then str has the form
|
||||
* "existing-dir/..", and this is really
|
||||
* ok. (Remember, this loop is creating the
|
||||
* portion of the path that didn't exist)
|
||||
*/
|
||||
free(str);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
free(str);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* simplify - given a pathname, simplify that path by removing
|
||||
* duplicate contiguous slashes.
|
||||
*
|
||||
* A simplified copy of the argument is returned to the
|
||||
* caller, or NULL is returned on error.
|
||||
*
|
||||
* The caller should handle error reporting based upon the
|
||||
* returned vlaue, and should free the returned value,
|
||||
* when appropriate.
|
||||
*/
|
||||
|
||||
static char *
|
||||
simplify(const char *str)
|
||||
{
|
||||
int i;
|
||||
size_t mbPathlen; /* length of multi-byte path */
|
||||
size_t wcPathlen; /* length of wide-character path */
|
||||
wchar_t *wptr; /* scratch pointer */
|
||||
wchar_t *wcPath; /* wide-character version of the path */
|
||||
char *mbPath; /* The copy fo the path to be returned */
|
||||
|
||||
/*
|
||||
* bail out if there is nothing there.
|
||||
*/
|
||||
|
||||
if (!str)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Get a copy of the argument.
|
||||
*/
|
||||
|
||||
if ((mbPath = strdup(str)) == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* convert the multi-byte version of the path to a
|
||||
* wide-character rendering, for doing our figuring.
|
||||
*/
|
||||
|
||||
mbPathlen = strlen(mbPath);
|
||||
|
||||
if ((wcPath = calloc(sizeof (wchar_t), mbPathlen+1)) == NULL) {
|
||||
free(mbPath);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((wcPathlen = mbstowcs(wcPath, mbPath, mbPathlen)) == (size_t)-1) {
|
||||
free(mbPath);
|
||||
free(wcPath);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove duplicate slashes first ("//../" -> "/")
|
||||
*/
|
||||
|
||||
for (wptr = wcPath, i = 0; i < wcPathlen; i++) {
|
||||
*wptr++ = wcPath[i];
|
||||
|
||||
if (wcPath[i] == '/') {
|
||||
i++;
|
||||
|
||||
while (wcPath[i] == '/') {
|
||||
i++;
|
||||
}
|
||||
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
*wptr = '\0';
|
||||
|
||||
/*
|
||||
* now convert back to the multi-byte format.
|
||||
*/
|
||||
|
||||
if (wcstombs(mbPath, wcPath, mbPathlen) == (size_t)-1) {
|
||||
free(mbPath);
|
||||
free(wcPath);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
free(wcPath);
|
||||
return (mbPath);
|
||||
}
|
@ -1,216 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* 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 AUTHORS 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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file implements Solaris compatible getmntany() and hasmntopt()
|
||||
* functions.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <sys/mnttab.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *
|
||||
mntopt(char **p)
|
||||
{
|
||||
char *cp = *p;
|
||||
char *retstr;
|
||||
|
||||
while (*cp && isspace(*cp))
|
||||
cp++;
|
||||
|
||||
retstr = cp;
|
||||
while (*cp && *cp != ',')
|
||||
cp++;
|
||||
|
||||
if (*cp) {
|
||||
*cp = '\0';
|
||||
cp++;
|
||||
}
|
||||
|
||||
*p = cp;
|
||||
return (retstr);
|
||||
}
|
||||
|
||||
char *
|
||||
hasmntopt(struct mnttab *mnt, char *opt)
|
||||
{
|
||||
char tmpopts[MNT_LINE_MAX];
|
||||
char *f, *opts = tmpopts;
|
||||
|
||||
if (mnt->mnt_mntopts == NULL)
|
||||
return (NULL);
|
||||
(void) strcpy(opts, mnt->mnt_mntopts);
|
||||
f = mntopt(&opts);
|
||||
for (; *f; f = mntopt(&opts)) {
|
||||
if (strncmp(opt, f, strlen(opt)) == 0)
|
||||
return (f - tmpopts + mnt->mnt_mntopts);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
optadd(char *mntopts, size_t size, const char *opt)
|
||||
{
|
||||
|
||||
if (mntopts[0] != '\0')
|
||||
strlcat(mntopts, ",", size);
|
||||
strlcat(mntopts, opt, size);
|
||||
}
|
||||
|
||||
void
|
||||
statfs2mnttab(struct statfs *sfs, struct mnttab *mp)
|
||||
{
|
||||
static char mntopts[MNTMAXSTR];
|
||||
long flags;
|
||||
|
||||
mntopts[0] = '\0';
|
||||
|
||||
flags = sfs->f_flags;
|
||||
#define OPTADD(opt) optadd(mntopts, sizeof(mntopts), (opt))
|
||||
if (flags & MNT_RDONLY)
|
||||
OPTADD(MNTOPT_RO);
|
||||
else
|
||||
OPTADD(MNTOPT_RW);
|
||||
if (flags & MNT_NOSUID)
|
||||
OPTADD(MNTOPT_NOSUID);
|
||||
else
|
||||
OPTADD(MNTOPT_SETUID);
|
||||
if (flags & MNT_UPDATE)
|
||||
OPTADD(MNTOPT_REMOUNT);
|
||||
if (flags & MNT_NOATIME)
|
||||
OPTADD(MNTOPT_NOATIME);
|
||||
else
|
||||
OPTADD(MNTOPT_ATIME);
|
||||
OPTADD(MNTOPT_NOXATTR);
|
||||
if (flags & MNT_NOEXEC)
|
||||
OPTADD(MNTOPT_NOEXEC);
|
||||
else
|
||||
OPTADD(MNTOPT_EXEC);
|
||||
#undef OPTADD
|
||||
mp->mnt_special = sfs->f_mntfromname;
|
||||
mp->mnt_mountp = sfs->f_mntonname;
|
||||
mp->mnt_fstype = sfs->f_fstypename;
|
||||
mp->mnt_mntopts = mntopts;
|
||||
}
|
||||
|
||||
static struct statfs *gsfs = NULL;
|
||||
static int allfs = 0;
|
||||
|
||||
static int
|
||||
statfs_init(void)
|
||||
{
|
||||
struct statfs *sfs;
|
||||
int error;
|
||||
|
||||
if (gsfs != NULL) {
|
||||
free(gsfs);
|
||||
gsfs = NULL;
|
||||
}
|
||||
allfs = getfsstat(NULL, 0, MNT_WAIT);
|
||||
if (allfs == -1)
|
||||
goto fail;
|
||||
gsfs = malloc(sizeof(gsfs[0]) * allfs * 2);
|
||||
if (gsfs == NULL)
|
||||
goto fail;
|
||||
allfs = getfsstat(gsfs, (long)(sizeof(gsfs[0]) * allfs * 2),
|
||||
MNT_WAIT);
|
||||
if (allfs == -1)
|
||||
goto fail;
|
||||
sfs = realloc(gsfs, allfs * sizeof(gsfs[0]));
|
||||
if (sfs != NULL)
|
||||
gsfs = sfs;
|
||||
return (0);
|
||||
fail:
|
||||
error = errno;
|
||||
if (gsfs != NULL)
|
||||
free(gsfs);
|
||||
gsfs = NULL;
|
||||
allfs = 0;
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
getmntany(FILE *fd __unused, struct mnttab *mgetp, struct mnttab *mrefp)
|
||||
{
|
||||
struct statfs *sfs;
|
||||
int i, error;
|
||||
|
||||
error = statfs_init();
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
for (i = 0; i < allfs; i++) {
|
||||
if (mrefp->mnt_special != NULL &&
|
||||
strcmp(mrefp->mnt_special, gsfs[i].f_mntfromname) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (mrefp->mnt_mountp != NULL &&
|
||||
strcmp(mrefp->mnt_mountp, gsfs[i].f_mntonname) != 0) {
|
||||
continue;
|
||||
}
|
||||
if (mrefp->mnt_fstype != NULL &&
|
||||
strcmp(mrefp->mnt_fstype, gsfs[i].f_fstypename) != 0) {
|
||||
continue;
|
||||
}
|
||||
statfs2mnttab(&gsfs[i], mgetp);
|
||||
return (0);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
getmntent(FILE *fp, struct mnttab *mp)
|
||||
{
|
||||
struct statfs *sfs;
|
||||
int error, nfs;
|
||||
|
||||
nfs = (int)lseek(fileno(fp), 0, SEEK_CUR);
|
||||
if (nfs == -1)
|
||||
return (errno);
|
||||
/* If nfs is 0, we want to refresh out cache. */
|
||||
if (nfs == 0 || gsfs == NULL) {
|
||||
error = statfs_init();
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
if (nfs >= allfs)
|
||||
return (-1);
|
||||
statfs2mnttab(&gsfs[nfs], mp);
|
||||
if (lseek(fileno(fp), 1, SEEK_CUR) == -1)
|
||||
return (errno);
|
||||
return (0);
|
||||
}
|
@ -1,428 +0,0 @@
|
||||
/*
|
||||
* 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 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include "thread_pool_impl.h"
|
||||
|
||||
typedef void (*_Voidfp)(void*); /* pointer to extern "C" function */
|
||||
|
||||
static void
|
||||
delete_pool(tpool_t *tpool)
|
||||
{
|
||||
tpool_job_t *job;
|
||||
|
||||
/*
|
||||
* There should be no pending jobs, but just in case...
|
||||
*/
|
||||
for (job = tpool->tp_head; job != NULL; job = tpool->tp_head) {
|
||||
tpool->tp_head = job->tpj_next;
|
||||
free(job);
|
||||
}
|
||||
(void) pthread_attr_destroy(&tpool->tp_attr);
|
||||
free(tpool);
|
||||
}
|
||||
|
||||
/*
|
||||
* Worker thread is terminating.
|
||||
*/
|
||||
static void
|
||||
worker_cleanup(void *arg)
|
||||
{
|
||||
tpool_t *tpool = arg;
|
||||
|
||||
if (--tpool->tp_current == 0 &&
|
||||
(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))) {
|
||||
if (tpool->tp_flags & TP_ABANDON) {
|
||||
pthread_mutex_unlock(&tpool->tp_mutex);
|
||||
delete_pool(tpool);
|
||||
return;
|
||||
}
|
||||
if (tpool->tp_flags & TP_DESTROY)
|
||||
(void) pthread_cond_broadcast(&tpool->tp_busycv);
|
||||
}
|
||||
pthread_mutex_unlock(&tpool->tp_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_waiters(tpool_t *tpool)
|
||||
{
|
||||
if (tpool->tp_head == NULL && tpool->tp_active == NULL) {
|
||||
tpool->tp_flags &= ~TP_WAIT;
|
||||
(void) pthread_cond_broadcast(&tpool->tp_waitcv);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by a worker thread on return from a tpool_dispatch()d job.
|
||||
*/
|
||||
static void
|
||||
job_cleanup(void *arg)
|
||||
{
|
||||
tpool_t *tpool = arg;
|
||||
pthread_t my_tid = pthread_self();
|
||||
tpool_active_t *activep;
|
||||
tpool_active_t **activepp;
|
||||
|
||||
pthread_mutex_lock(&tpool->tp_mutex);
|
||||
/* CSTYLED */
|
||||
for (activepp = &tpool->tp_active;; activepp = &activep->tpa_next) {
|
||||
activep = *activepp;
|
||||
if (activep->tpa_tid == my_tid) {
|
||||
*activepp = activep->tpa_next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tpool->tp_flags & TP_WAIT)
|
||||
notify_waiters(tpool);
|
||||
}
|
||||
|
||||
static void *
|
||||
tpool_worker(void *arg)
|
||||
{
|
||||
tpool_t *tpool = (tpool_t *)arg;
|
||||
int elapsed;
|
||||
tpool_job_t *job;
|
||||
void (*func)(void *);
|
||||
tpool_active_t active;
|
||||
sigset_t maskset;
|
||||
|
||||
pthread_mutex_lock(&tpool->tp_mutex);
|
||||
pthread_cleanup_push(worker_cleanup, tpool);
|
||||
|
||||
/*
|
||||
* This is the worker's main loop.
|
||||
* It will only be left if a timeout or an error has occured.
|
||||
*/
|
||||
active.tpa_tid = pthread_self();
|
||||
for (;;) {
|
||||
elapsed = 0;
|
||||
tpool->tp_idle++;
|
||||
if (tpool->tp_flags & TP_WAIT)
|
||||
notify_waiters(tpool);
|
||||
while ((tpool->tp_head == NULL ||
|
||||
(tpool->tp_flags & TP_SUSPEND)) &&
|
||||
!(tpool->tp_flags & (TP_DESTROY | TP_ABANDON))) {
|
||||
if (tpool->tp_current <= tpool->tp_minimum ||
|
||||
tpool->tp_linger == 0) {
|
||||
(void) pthread_cond_wait(&tpool->tp_workcv,
|
||||
&tpool->tp_mutex);
|
||||
} else {
|
||||
struct timespec timeout;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &timeout);
|
||||
timeout.tv_sec += tpool->tp_linger;
|
||||
if (pthread_cond_timedwait(&tpool->tp_workcv,
|
||||
&tpool->tp_mutex, &timeout) != 0) {
|
||||
elapsed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
tpool->tp_idle--;
|
||||
if (tpool->tp_flags & TP_DESTROY)
|
||||
break;
|
||||
if (tpool->tp_flags & TP_ABANDON) {
|
||||
/* can't abandon a suspended pool */
|
||||
if (tpool->tp_flags & TP_SUSPEND) {
|
||||
tpool->tp_flags &= ~TP_SUSPEND;
|
||||
(void) pthread_cond_broadcast(&tpool->tp_workcv);
|
||||
}
|
||||
if (tpool->tp_head == NULL)
|
||||
break;
|
||||
}
|
||||
if ((job = tpool->tp_head) != NULL &&
|
||||
!(tpool->tp_flags & TP_SUSPEND)) {
|
||||
elapsed = 0;
|
||||
func = job->tpj_func;
|
||||
arg = job->tpj_arg;
|
||||
tpool->tp_head = job->tpj_next;
|
||||
if (job == tpool->tp_tail)
|
||||
tpool->tp_tail = NULL;
|
||||
tpool->tp_njobs--;
|
||||
active.tpa_next = tpool->tp_active;
|
||||
tpool->tp_active = &active;
|
||||
pthread_mutex_unlock(&tpool->tp_mutex);
|
||||
pthread_cleanup_push(job_cleanup, tpool);
|
||||
free(job);
|
||||
/*
|
||||
* Call the specified function.
|
||||
*/
|
||||
func(arg);
|
||||
/*
|
||||
* We don't know what this thread has been doing,
|
||||
* so we reset its signal mask and cancellation
|
||||
* state back to the initial values.
|
||||
*/
|
||||
sigfillset(&maskset);
|
||||
(void) pthread_sigmask(SIG_SETMASK, &maskset, NULL);
|
||||
(void) pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,
|
||||
NULL);
|
||||
(void) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,
|
||||
NULL);
|
||||
pthread_cleanup_pop(1);
|
||||
}
|
||||
if (elapsed && tpool->tp_current > tpool->tp_minimum) {
|
||||
/*
|
||||
* We timed out and there is no work to be done
|
||||
* and the number of workers exceeds the minimum.
|
||||
* Exit now to reduce the size of the pool.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
pthread_cleanup_pop(1);
|
||||
return (arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a worker thread, with all signals blocked.
|
||||
*/
|
||||
static int
|
||||
create_worker(tpool_t *tpool)
|
||||
{
|
||||
sigset_t maskset, oset;
|
||||
pthread_t thread;
|
||||
int error;
|
||||
|
||||
sigfillset(&maskset);
|
||||
(void) pthread_sigmask(SIG_SETMASK, &maskset, &oset);
|
||||
error = pthread_create(&thread, &tpool->tp_attr, tpool_worker, tpool);
|
||||
(void) pthread_sigmask(SIG_SETMASK, &oset, NULL);
|
||||
return (error);
|
||||
}
|
||||
|
||||
tpool_t *
|
||||
tpool_create(uint_t min_threads, uint_t max_threads, uint_t linger,
|
||||
pthread_attr_t *attr)
|
||||
{
|
||||
tpool_t *tpool;
|
||||
int error;
|
||||
|
||||
if (min_threads > max_threads || max_threads < 1) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
tpool = calloc(1, sizeof (*tpool));
|
||||
if (tpool == NULL) {
|
||||
errno = ENOMEM;
|
||||
return (NULL);
|
||||
}
|
||||
(void) pthread_mutex_init(&tpool->tp_mutex, NULL);
|
||||
(void) pthread_cond_init(&tpool->tp_busycv, NULL);
|
||||
(void) pthread_cond_init(&tpool->tp_workcv, NULL);
|
||||
(void) pthread_cond_init(&tpool->tp_waitcv, NULL);
|
||||
tpool->tp_minimum = min_threads;
|
||||
tpool->tp_maximum = max_threads;
|
||||
tpool->tp_linger = linger;
|
||||
|
||||
/* make all pool threads be detached daemon threads */
|
||||
(void) pthread_attr_init(&tpool->tp_attr);
|
||||
(void) pthread_attr_setdetachstate(&tpool->tp_attr,
|
||||
PTHREAD_CREATE_DETACHED);
|
||||
|
||||
return (tpool);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatch a work request to the thread pool.
|
||||
* If there are idle workers, awaken one.
|
||||
* Else, if the maximum number of workers has
|
||||
* not been reached, spawn a new worker thread.
|
||||
* Else just return with the job added to the queue.
|
||||
*/
|
||||
int
|
||||
tpool_dispatch(tpool_t *tpool, void (*func)(void *), void *arg)
|
||||
{
|
||||
tpool_job_t *job;
|
||||
|
||||
if ((job = calloc(1, sizeof (*job))) == NULL)
|
||||
return (-1);
|
||||
job->tpj_next = NULL;
|
||||
job->tpj_func = func;
|
||||
job->tpj_arg = arg;
|
||||
|
||||
pthread_mutex_lock(&tpool->tp_mutex);
|
||||
|
||||
if (tpool->tp_head == NULL)
|
||||
tpool->tp_head = job;
|
||||
else
|
||||
tpool->tp_tail->tpj_next = job;
|
||||
tpool->tp_tail = job;
|
||||
tpool->tp_njobs++;
|
||||
|
||||
if (!(tpool->tp_flags & TP_SUSPEND)) {
|
||||
if (tpool->tp_idle > 0)
|
||||
(void) pthread_cond_signal(&tpool->tp_workcv);
|
||||
else if (tpool->tp_current < tpool->tp_maximum &&
|
||||
create_worker(tpool) == 0)
|
||||
tpool->tp_current++;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&tpool->tp_mutex);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Assumes: by the time tpool_destroy() is called no one will use this
|
||||
* thread pool in any way and no one will try to dispatch entries to it.
|
||||
* Calling tpool_destroy() from a job in the pool will cause deadlock.
|
||||
*/
|
||||
void
|
||||
tpool_destroy(tpool_t *tpool)
|
||||
{
|
||||
tpool_active_t *activep;
|
||||
|
||||
pthread_mutex_lock(&tpool->tp_mutex);
|
||||
pthread_cleanup_push((_Voidfp)pthread_mutex_unlock, &tpool->tp_mutex);
|
||||
|
||||
/* mark the pool as being destroyed; wakeup idle workers */
|
||||
tpool->tp_flags |= TP_DESTROY;
|
||||
tpool->tp_flags &= ~TP_SUSPEND;
|
||||
(void) pthread_cond_broadcast(&tpool->tp_workcv);
|
||||
|
||||
/* cancel all active workers */
|
||||
for (activep = tpool->tp_active; activep; activep = activep->tpa_next)
|
||||
(void) pthread_cancel(activep->tpa_tid);
|
||||
|
||||
/* wait for all active workers to finish */
|
||||
while (tpool->tp_active != NULL) {
|
||||
tpool->tp_flags |= TP_WAIT;
|
||||
(void) pthread_cond_wait(&tpool->tp_waitcv, &tpool->tp_mutex);
|
||||
}
|
||||
|
||||
/* the last worker to terminate will wake us up */
|
||||
while (tpool->tp_current != 0)
|
||||
(void) pthread_cond_wait(&tpool->tp_busycv, &tpool->tp_mutex);
|
||||
|
||||
pthread_cleanup_pop(1); /* pthread_mutex_unlock(&tpool->tp_mutex); */
|
||||
delete_pool(tpool);
|
||||
}
|
||||
|
||||
/*
|
||||
* Like tpool_destroy(), but don't cancel workers or wait for them to finish.
|
||||
* The last worker to terminate will delete the pool.
|
||||
*/
|
||||
void
|
||||
tpool_abandon(tpool_t *tpool)
|
||||
{
|
||||
|
||||
pthread_mutex_lock(&tpool->tp_mutex);
|
||||
if (tpool->tp_current == 0) {
|
||||
/* no workers, just delete the pool */
|
||||
pthread_mutex_unlock(&tpool->tp_mutex);
|
||||
delete_pool(tpool);
|
||||
} else {
|
||||
/* wake up all workers, last one will delete the pool */
|
||||
tpool->tp_flags |= TP_ABANDON;
|
||||
tpool->tp_flags &= ~TP_SUSPEND;
|
||||
(void) pthread_cond_broadcast(&tpool->tp_workcv);
|
||||
pthread_mutex_unlock(&tpool->tp_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for all jobs to complete.
|
||||
* Calling tpool_wait() from a job in the pool will cause deadlock.
|
||||
*/
|
||||
void
|
||||
tpool_wait(tpool_t *tpool)
|
||||
{
|
||||
|
||||
pthread_mutex_lock(&tpool->tp_mutex);
|
||||
pthread_cleanup_push((_Voidfp)pthread_mutex_unlock, &tpool->tp_mutex);
|
||||
while (tpool->tp_head != NULL || tpool->tp_active != NULL) {
|
||||
tpool->tp_flags |= TP_WAIT;
|
||||
(void) pthread_cond_wait(&tpool->tp_waitcv, &tpool->tp_mutex);
|
||||
}
|
||||
pthread_cleanup_pop(1); /* pthread_mutex_unlock(&tpool->tp_mutex); */
|
||||
}
|
||||
|
||||
void
|
||||
tpool_suspend(tpool_t *tpool)
|
||||
{
|
||||
|
||||
pthread_mutex_lock(&tpool->tp_mutex);
|
||||
tpool->tp_flags |= TP_SUSPEND;
|
||||
pthread_mutex_unlock(&tpool->tp_mutex);
|
||||
}
|
||||
|
||||
int
|
||||
tpool_suspended(tpool_t *tpool)
|
||||
{
|
||||
int suspended;
|
||||
|
||||
pthread_mutex_lock(&tpool->tp_mutex);
|
||||
suspended = (tpool->tp_flags & TP_SUSPEND) != 0;
|
||||
pthread_mutex_unlock(&tpool->tp_mutex);
|
||||
|
||||
return (suspended);
|
||||
}
|
||||
|
||||
void
|
||||
tpool_resume(tpool_t *tpool)
|
||||
{
|
||||
int excess;
|
||||
|
||||
pthread_mutex_lock(&tpool->tp_mutex);
|
||||
if (!(tpool->tp_flags & TP_SUSPEND)) {
|
||||
pthread_mutex_unlock(&tpool->tp_mutex);
|
||||
return;
|
||||
}
|
||||
tpool->tp_flags &= ~TP_SUSPEND;
|
||||
(void) pthread_cond_broadcast(&tpool->tp_workcv);
|
||||
excess = tpool->tp_njobs - tpool->tp_idle;
|
||||
while (excess-- > 0 && tpool->tp_current < tpool->tp_maximum) {
|
||||
if (create_worker(tpool) != 0)
|
||||
break; /* pthread_create() failed */
|
||||
tpool->tp_current++;
|
||||
}
|
||||
pthread_mutex_unlock(&tpool->tp_mutex);
|
||||
}
|
||||
|
||||
int
|
||||
tpool_member(tpool_t *tpool)
|
||||
{
|
||||
pthread_t my_tid = pthread_self();
|
||||
tpool_active_t *activep;
|
||||
|
||||
pthread_mutex_lock(&tpool->tp_mutex);
|
||||
for (activep = tpool->tp_active; activep; activep = activep->tpa_next) {
|
||||
if (activep->tpa_tid == my_tid) {
|
||||
pthread_mutex_unlock(&tpool->tp_mutex);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&tpool->tp_mutex);
|
||||
return (0);
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* 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 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _THREAD_POOL_IMPL_H
|
||||
#define _THREAD_POOL_IMPL_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <thread_pool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Thread pool implementation definitions.
|
||||
* See <thread_pool.h> for interface declarations.
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIFO queued job
|
||||
*/
|
||||
typedef struct tpool_job tpool_job_t;
|
||||
struct tpool_job {
|
||||
tpool_job_t *tpj_next; /* list of jobs */
|
||||
void (*tpj_func)(void *); /* function to call */
|
||||
void *tpj_arg; /* its argument */
|
||||
};
|
||||
|
||||
/*
|
||||
* List of active threads, linked through their stacks.
|
||||
*/
|
||||
typedef struct tpool_active tpool_active_t;
|
||||
struct tpool_active {
|
||||
tpool_active_t *tpa_next; /* list of active threads */
|
||||
pthread_t tpa_tid; /* active thread id */
|
||||
};
|
||||
|
||||
/*
|
||||
* The thread pool.
|
||||
*/
|
||||
struct tpool {
|
||||
tpool_t *tp_forw; /* circular list of all thread pools */
|
||||
tpool_t *tp_back;
|
||||
mutex_t tp_mutex; /* protects the pool data */
|
||||
cond_t tp_busycv; /* synchronization in tpool_dispatch */
|
||||
cond_t tp_workcv; /* synchronization with workers */
|
||||
cond_t tp_waitcv; /* synchronization in tpool_wait() */
|
||||
tpool_active_t *tp_active; /* threads performing work */
|
||||
tpool_job_t *tp_head; /* FIFO job queue */
|
||||
tpool_job_t *tp_tail;
|
||||
pthread_attr_t tp_attr; /* attributes of the workers */
|
||||
int tp_flags; /* see below */
|
||||
uint_t tp_linger; /* seconds before idle workers exit */
|
||||
int tp_njobs; /* number of jobs in job queue */
|
||||
int tp_minimum; /* minimum number of worker threads */
|
||||
int tp_maximum; /* maximum number of worker threads */
|
||||
int tp_current; /* current number of worker threads */
|
||||
int tp_idle; /* number of idle workers */
|
||||
};
|
||||
|
||||
/* tp_flags */
|
||||
#define TP_WAIT 0x01 /* waiting in tpool_wait() */
|
||||
#define TP_SUSPEND 0x02 /* pool is being suspended */
|
||||
#define TP_DESTROY 0x04 /* pool is being destroyed */
|
||||
#define TP_ABANDON 0x08 /* pool is abandoned (auto-destroy) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _THREAD_POOL_IMPL_H */
|
@ -1,106 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* 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 AUTHORS 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 AUTHORS 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file implements Solaris compatible zmount() function.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <mnttab.h>
|
||||
|
||||
static void
|
||||
build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val,
|
||||
size_t len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (*iovlen < 0)
|
||||
return;
|
||||
i = *iovlen;
|
||||
*iov = realloc(*iov, sizeof(**iov) * (i + 2));
|
||||
if (*iov == NULL) {
|
||||
*iovlen = -1;
|
||||
return;
|
||||
}
|
||||
(*iov)[i].iov_base = strdup(name);
|
||||
(*iov)[i].iov_len = strlen(name) + 1;
|
||||
i++;
|
||||
(*iov)[i].iov_base = val;
|
||||
if (len == (size_t)-1) {
|
||||
if (val != NULL)
|
||||
len = strlen(val) + 1;
|
||||
else
|
||||
len = 0;
|
||||
}
|
||||
(*iov)[i].iov_len = (int)len;
|
||||
*iovlen = ++i;
|
||||
}
|
||||
|
||||
int
|
||||
zmount(const char *spec, const char *dir, int mflag, char *fstype,
|
||||
char *dataptr, int datalen, char *optptr, int optlen)
|
||||
{
|
||||
struct iovec *iov;
|
||||
char *optstr, *os, *p, *tofree;
|
||||
int iovlen, rv;
|
||||
|
||||
assert(spec != NULL);
|
||||
assert(dir != NULL);
|
||||
assert(mflag == 0 || mflag == MS_RDONLY);
|
||||
assert(fstype != NULL);
|
||||
assert(strcmp(fstype, MNTTYPE_ZFS) == 0);
|
||||
assert(dataptr == NULL);
|
||||
assert(datalen == 0);
|
||||
assert(optptr != NULL);
|
||||
assert(optlen > 0);
|
||||
|
||||
tofree = optstr = strdup(optptr);
|
||||
assert(optstr != NULL);
|
||||
|
||||
iov = NULL;
|
||||
iovlen = 0;
|
||||
if (mflag & MS_RDONLY)
|
||||
build_iovec(&iov, &iovlen, "ro", NULL, 0);
|
||||
build_iovec(&iov, &iovlen, "fstype", fstype, (size_t)-1);
|
||||
build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, dir),
|
||||
(size_t)-1);
|
||||
build_iovec(&iov, &iovlen, "from", __DECONST(char *, spec), (size_t)-1);
|
||||
while ((p = strsep(&optstr, ",/")) != NULL)
|
||||
build_iovec(&iov, &iovlen, p, NULL, (size_t)-1);
|
||||
rv = nmount(iov, iovlen, 0);
|
||||
free(tofree);
|
||||
return (rv);
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* 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 AUTHORS 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 AUTHORS 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$
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/zone.h>
|
||||
|
||||
zoneid_t
|
||||
getzoneid(void)
|
||||
{
|
||||
size_t size;
|
||||
int jailid;
|
||||
|
||||
/* Information that we are in jail or not is enough for our needs. */
|
||||
size = sizeof(jailid);
|
||||
if (sysctlbyname("security.jail.jailed", &jailid, &size, NULL, 0) == -1)
|
||||
assert(!"No security.jail.jailed sysctl!");
|
||||
return ((zoneid_t)jailid);
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 25, 2020
|
||||
.Dd April 2, 2021
|
||||
.Dt DTRACE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -602,8 +602,12 @@ Number of default stack frames for
|
||||
.It Sy jstackstrsize Ns = Ns Ar scalar
|
||||
Default string space size for
|
||||
.Fn jstack .
|
||||
.It Sy libdir Ns = Ns Ar path
|
||||
Add a directory to the system library path.
|
||||
.It Sy nspec Ns = Ns Ar scalar
|
||||
Number of speculations.
|
||||
.It Sy nolibs
|
||||
Do not load D system libraries.
|
||||
.It Sy quiet
|
||||
Set quiet mode.
|
||||
Same as the
|
||||
@ -627,6 +631,10 @@ output.
|
||||
Rate of status checking.
|
||||
.It Sy switchrate Ns = Ns Ar time
|
||||
Rate of buffer switching.
|
||||
.It Sy syslibdir Ns = Ns Ar path
|
||||
Path to system libraries.
|
||||
Defaults to
|
||||
.Pa /usr/lib/dtrace .
|
||||
.It Sy ustackframes Ns = Ns Ar scalar
|
||||
Maximum number of userspace stack frames to unwind when executing the
|
||||
.Fn ustack
|
||||
|
@ -35,11 +35,11 @@ BEGIN
|
||||
this->b = -2;
|
||||
|
||||
system("echo %s %d %d", "foo", this->a, this->b);
|
||||
system("ping -q -c 1 localhost 2>/dev/null | grep -v '^round-trip '");
|
||||
system("ping -q -c 1 127.0.0.1 2>/dev/null | grep -v '^round-trip '");
|
||||
system("echo %d", ++this->a);
|
||||
system("ping -q -c 1 localhost 2>/dev/null | grep -v '^round-trip '");
|
||||
system("ping -4 -q -c 1 127.0.0.1 2>/dev/null | grep -v '^round-trip '");
|
||||
system("echo %d", ++this->a);
|
||||
system("ping -q -c 1 localhost 2>/dev/null | grep -v '^round-trip '");
|
||||
system("ping -4 -q -c 1 127.0.0.1 2>/dev/null | grep -v '^round-trip '");
|
||||
system("echo %d", ++this->a);
|
||||
exit(0);
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ f2(f func, int i)
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
main(void)
|
||||
{
|
||||
f2(f1, 3);
|
||||
|
||||
|
@ -66,7 +66,7 @@ fN2(f func, char *a, int i __unused)
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
main(void)
|
||||
{
|
||||
/*
|
||||
* Avoid length of 1, 2, 4, or 8 bytes so DTrace will treat the data as
|
||||
|
@ -33,8 +33,7 @@
|
||||
* leading underscores.
|
||||
*/
|
||||
|
||||
#pragma weak _go = go
|
||||
|
||||
extern int _go(int);
|
||||
int go(int);
|
||||
|
||||
int
|
||||
@ -57,3 +56,5 @@ main(void)
|
||||
for (;;)
|
||||
getpid();
|
||||
}
|
||||
|
||||
#pragma weak _go = go
|
||||
|
@ -33,14 +33,14 @@
|
||||
* leading underscores.
|
||||
*/
|
||||
|
||||
extern int _go(int);
|
||||
|
||||
static int __unused
|
||||
go(int a)
|
||||
{
|
||||
return (a + 1);
|
||||
}
|
||||
|
||||
#pragma weak _go = go
|
||||
|
||||
static void
|
||||
handle(int sig __unused)
|
||||
{
|
||||
@ -55,3 +55,5 @@ main(void)
|
||||
for (;;)
|
||||
getpid();
|
||||
}
|
||||
|
||||
#pragma weak _go = go
|
||||
|
@ -133,7 +133,8 @@ ctf_lookup_by_name(ctf_file_t *fp, const char *name)
|
||||
|
||||
for (lp = fp->ctf_lookups; lp->ctl_prefix != NULL; lp++) {
|
||||
if (lp->ctl_prefix[0] == '\0' ||
|
||||
strncmp(p, lp->ctl_prefix, (size_t)(q - p)) == 0) {
|
||||
((size_t)(q - p) >= lp->ctl_len && strncmp(p,
|
||||
lp->ctl_prefix, (size_t)(q - p)) == 0)) {
|
||||
for (p += lp->ctl_len; isspace(*p); p++)
|
||||
continue; /* skip prefix and next ws */
|
||||
|
||||
|
@ -717,7 +717,7 @@ extern dt_pcb_t *yypcb; /* pointer to current parser control block */
|
||||
extern char yyintprefix; /* int token prefix for macros (+/-) */
|
||||
extern char yyintsuffix[4]; /* int token suffix ([uUlL]*) */
|
||||
extern int yyintdecimal; /* int token is decimal (1) or octal/hex (0) */
|
||||
extern char yytext[]; /* lex input buffer */
|
||||
extern char *yytext; /* lex input buffer */
|
||||
extern int yylineno; /* lex line number */
|
||||
extern int yydebug; /* lex debugging */
|
||||
extern dt_node_t *yypragma; /* lex token list for control lines */
|
||||
|
@ -51,16 +51,17 @@
|
||||
/*
|
||||
* Define YY_INPUT for flex since input() can't be re-defined.
|
||||
*/
|
||||
#define YY_INPUT(buf,result,max_size) \
|
||||
if (yypcb->pcb_fileptr != NULL) { \
|
||||
if (((result = fread(buf, 1, max_size, yypcb->pcb_fileptr)) == 0) \
|
||||
&& ferror(yypcb->pcb_fileptr)) \
|
||||
#define YY_INPUT(buf, result, max_size) \
|
||||
if (yypcb->pcb_fileptr != NULL) { \
|
||||
if (((result = fread(buf, 1, max_size, yypcb->pcb_fileptr)) == \
|
||||
0) && ferror(yypcb->pcb_fileptr)) \
|
||||
longjmp(yypcb->pcb_jmpbuf, EDT_FIO); \
|
||||
} else { \
|
||||
int n; \
|
||||
for (n = 0; n < max_size && \
|
||||
yypcb->pcb_strptr < yypcb->pcb_string + yypcb->pcb_strlen; n++) \
|
||||
buf[n] = *yypcb->pcb_strptr++; \
|
||||
} else { \
|
||||
int n; \
|
||||
for (n = 0; n < max_size && \
|
||||
yypcb->pcb_strptr < yypcb->pcb_string + yypcb->pcb_strlen; \
|
||||
n++) \
|
||||
buf[n] = *yypcb->pcb_strptr++; \
|
||||
result = n; \
|
||||
}
|
||||
/*
|
||||
|
@ -1344,18 +1344,24 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
|
||||
/*
|
||||
* Aliases of weak symbols don't get a uniquifier.
|
||||
*/
|
||||
if (GELF_ST_BIND(fsym.st_info) == STB_WEAK)
|
||||
if (GELF_ST_BIND(fsym.st_info) == STB_WEAK) {
|
||||
len = snprintf(NULL, 0, dt_weaksymfmt,
|
||||
dt_symprefix, s) + 1;
|
||||
else
|
||||
} else {
|
||||
len = snprintf(NULL, 0, dt_symfmt, dt_symprefix,
|
||||
objkey, s) + 1;
|
||||
}
|
||||
if ((p = dt_alloc(dtp, len)) == NULL) {
|
||||
dt_strtab_destroy(strtab);
|
||||
goto err;
|
||||
}
|
||||
(void) snprintf(p, len, dt_symfmt, dt_symprefix,
|
||||
objkey, s);
|
||||
if (GELF_ST_BIND(fsym.st_info) == STB_WEAK) {
|
||||
(void) snprintf(p, len, dt_weaksymfmt,
|
||||
dt_symprefix, s);
|
||||
} else {
|
||||
(void) snprintf(p, len, dt_symfmt, dt_symprefix,
|
||||
objkey, s);
|
||||
}
|
||||
|
||||
if (dt_strtab_index(strtab, p) == -1) {
|
||||
/*
|
||||
|
@ -17,7 +17,8 @@ SUBDIR= drti \
|
||||
${_libzfs} \
|
||||
${_libzfsbootenv} \
|
||||
${_libzpool} \
|
||||
${_libzutil}
|
||||
${_libzutil} \
|
||||
${_pam_zfs_key}
|
||||
|
||||
SUBDIR.${MK_TESTS}+= tests
|
||||
|
||||
@ -28,9 +29,10 @@ _libicp_rescue= libicp_rescue
|
||||
_libzfs= libzfs
|
||||
_libzutil= libzutil
|
||||
_libzfsbootenv= libzfsbootenv
|
||||
.if ${MK_LIBTHR} != "no"
|
||||
_libzpool= libzpool
|
||||
_libtpool= libtpool
|
||||
.if ${MK_OPENSSL} != "no"
|
||||
_pam_zfs_key= pam_zfs_key
|
||||
.endif
|
||||
.endif
|
||||
|
||||
@ -43,6 +45,7 @@ SUBDIR_DEPEND_libzfs= libavl libnvpair libumem libuutil libzfs_core libzutil
|
||||
SUBDIR_DEPEND_libzpool= libavl libnvpair libumem libicp
|
||||
SUBDIR_DEPEND_libzutil= libavl libtpool
|
||||
SUBDIR_DEPEND_libzfsbootenv= libzfs libnvpair
|
||||
SUBDIR_DEPEND_pam_zfs_key= libnvpair libuutil libzfs libzfs_core
|
||||
|
||||
SUBDIR_PARALLEL=
|
||||
|
||||
|
@ -64,6 +64,13 @@ FILES= ${DSRCS}
|
||||
FILESDIR= /usr/lib/dtrace
|
||||
FILESMODE= ${NOBINMODE}
|
||||
|
||||
INCSGROUPS= INCS SYSINCS
|
||||
SYSINCSDIR= ${INCLUDEDIR}/sys
|
||||
INCS+= ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h
|
||||
SYSINCS+= ${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
|
||||
SYSINCS+= ${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common/sys/ctf_api.h
|
||||
SYSINCS+= ${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common/sys/ctf.h
|
||||
|
||||
WARNS?= 1
|
||||
|
||||
CFLAGS+= -DIN_BASE
|
||||
@ -122,8 +129,6 @@ SRCS+= dis_tables.c
|
||||
DSRCS+= regs_x86.d
|
||||
.endif
|
||||
|
||||
LFLAGS+=-l
|
||||
|
||||
YFLAGS+=-d
|
||||
|
||||
LIBADD= ctf elf proc pthread rtld_db
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
.PATH: ${SRCTOP}/sys/contrib/openzfs/module/icp
|
||||
|
||||
PACKAGE= runtime
|
||||
PACKAGE= utilities
|
||||
LIB= icp
|
||||
LIBADD=
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
.PATH: ${SRCTOP}/sys/contrib/openzfs/module/icp
|
||||
|
||||
PACKAGE= runtime
|
||||
PACKAGE= utilities
|
||||
LIB= icp_rescue
|
||||
LIBADD=
|
||||
|
||||
|
@ -67,7 +67,6 @@ KERNEL_C = \
|
||||
zfs_fletcher_superscalar4.c \
|
||||
zfs_namecheck.c \
|
||||
zfs_prop.c \
|
||||
zfs_uio.c \
|
||||
zpool_prop.c \
|
||||
zprop_common.c
|
||||
|
||||
@ -104,6 +103,8 @@ CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/module/icp/include
|
||||
CFLAGS+= -include ${SRCTOP}/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h
|
||||
CFLAGS+= -DHAVE_ISSETUGID
|
||||
CFLAGS+= -include ${SRCTOP}/sys/modules/zfs/zfs_config.h
|
||||
CFLAGS+= -DSYSCONFDIR=\"/etc\"
|
||||
CFLAGS+= -DPKGDATADIR=\"/usr/share/zfs\"
|
||||
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
@ -46,7 +46,6 @@ KERNEL_C = \
|
||||
zfs_fletcher_superscalar4.c \
|
||||
zfs_namecheck.c \
|
||||
zfs_prop.c \
|
||||
zfs_uio.c \
|
||||
zfs_zstd.c \
|
||||
zpool_prop.c \
|
||||
zprop_common.c \
|
||||
@ -124,6 +123,8 @@ KERNEL_C = \
|
||||
unique.c \
|
||||
vdev.c \
|
||||
vdev_cache.c \
|
||||
vdev_draid.c \
|
||||
vdev_draid_rand.c \
|
||||
vdev_file.c \
|
||||
vdev_indirect_births.c \
|
||||
vdev_indirect.c \
|
||||
@ -161,6 +162,7 @@ KERNEL_C = \
|
||||
zfs_fuid.c \
|
||||
zfs_sa.c \
|
||||
zfs_znode.c \
|
||||
zfs_racct.c \
|
||||
zfs_ratelimit.c \
|
||||
zfs_rlock.c \
|
||||
zil.c \
|
||||
|
28
cddl/lib/pam_zfs_key/Makefile
Normal file
28
cddl/lib/pam_zfs_key/Makefile
Normal file
@ -0,0 +1,28 @@
|
||||
.PATH: ${SRCTOP}/sys/contrib/openzfs/contrib/pam_zfs_key
|
||||
.PATH: ${SRCTOP}/sys/contrib/openzfs/include
|
||||
|
||||
PACKAGE= utilities
|
||||
LIB= pam_zfs_key
|
||||
|
||||
SHLIBDIR?= /usr/lib
|
||||
|
||||
LIBADD= zfs zfs_core nvpair uutil crypto
|
||||
|
||||
SRCS= pam_zfs_key.c
|
||||
|
||||
WARNS?= 2
|
||||
CSTD= c99
|
||||
CFLAGS+= -DIN_BASE
|
||||
CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/include
|
||||
CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/lib/libspl/include/
|
||||
CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/lib/libspl/include/os/freebsd
|
||||
CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include
|
||||
CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/module/icp/include
|
||||
CFLAGS+= -include ${SRCTOP}/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h
|
||||
CFLAGS+= -DHAVE_ISSETUGID
|
||||
CFLAGS+= -include ${SRCTOP}/sys/modules/zfs/zfs_config.h
|
||||
CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/include/os/freebsd/zfs
|
||||
CFLAGS+= -DRUNSTATEDIR=\"/var/run\"
|
||||
|
||||
.include "../../lib/libpam/modules/Makefile.inc"
|
||||
.include <bsd.lib.mk>
|
@ -71,7 +71,8 @@ CFLAGS+= \
|
||||
-include ${ZFSTOP}/include/os/freebsd/spl/sys/ccompile.h \
|
||||
-DHAVE_ISSETUGID \
|
||||
-include ${SRCTOP}/sys/modules/zfs/zfs_config.h \
|
||||
-DSYSCONFDIR=\"/etc\"
|
||||
-DSYSCONFDIR=\"/etc\" \
|
||||
-DPKGDATADIR=\"/usr/share/zfs\"
|
||||
|
||||
LIBADD= geom nvpair uutil zfs zutil avl spl tpool zfs_core m
|
||||
LDADD+= -pthread
|
||||
|
13
cddl/share/Makefile
Normal file
13
cddl/share/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
|
||||
SUBDIR= ${_zfs}
|
||||
|
||||
.if ${MK_ZFS} != "no"
|
||||
_zfs= zfs
|
||||
.endif
|
||||
|
||||
SUBDIR_PARALLEL=
|
||||
|
||||
.include <bsd.subdir.mk>
|
9
cddl/share/zfs/Makefile
Normal file
9
cddl/share/zfs/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include <src.opts.mk>
|
||||
|
||||
SUBDIR= compatibility.d
|
||||
|
||||
SUBDIR_PARALLEL=
|
||||
|
||||
.include <bsd.subdir.mk>
|
49
cddl/share/zfs/compatibility.d/Makefile
Normal file
49
cddl/share/zfs/compatibility.d/Makefile
Normal file
@ -0,0 +1,49 @@
|
||||
# $FreeBSD$
|
||||
|
||||
ZFSTOP= ${SRCTOP}/sys/contrib/openzfs
|
||||
|
||||
.PATH: ${ZFSTOP}/cmd/zpool/compatibility.d
|
||||
|
||||
FILES= \
|
||||
compat-2018 \
|
||||
compat-2019 \
|
||||
compat-2020 \
|
||||
compat-2021 \
|
||||
freebsd-11.0 \
|
||||
freebsd-11.2 \
|
||||
freebsd-11.3 \
|
||||
freenas-9.10.2 \
|
||||
grub2 \
|
||||
openzfsonosx-1.7.0 \
|
||||
openzfsonosx-1.8.1 \
|
||||
openzfsonosx-1.9.3 \
|
||||
openzfs-2.0-freebsd \
|
||||
openzfs-2.0-linux \
|
||||
zol-0.6.5 \
|
||||
zol-0.7 \
|
||||
zol-0.8
|
||||
|
||||
FILESDIR= ${SHAREDIR}/zfs/compatibility.d
|
||||
|
||||
LINKS= \
|
||||
${FILESDIR}/compat-2018 ${FILESDIR}/2018 \
|
||||
${FILESDIR}/compat-2019 ${FILESDIR}/2019 \
|
||||
${FILESDIR}/compat-2020 ${FILESDIR}/2020 \
|
||||
${FILESDIR}/compat-2021 ${FILESDIR}/2021 \
|
||||
${FILESDIR}/freebsd-11.0 ${FILESDIR}/freebsd-11.1 \
|
||||
${FILESDIR}/freebsd-11.0 ${FILESDIR}/freenas-11.0 \
|
||||
${FILESDIR}/freebsd-11.2 ${FILESDIR}/freenas-11.2 \
|
||||
${FILESDIR}/freebsd-11.3 ${FILESDIR}/freebsd-11.4 \
|
||||
${FILESDIR}/freebsd-11.3 ${FILESDIR}/freebsd-12.0 \
|
||||
${FILESDIR}/freebsd-11.3 ${FILESDIR}/freebsd-12.1 \
|
||||
${FILESDIR}/freebsd-11.3 ${FILESDIR}/freebsd-12.2 \
|
||||
${FILESDIR}/freebsd-11.3 ${FILESDIR}/freenas-11.3 \
|
||||
${FILESDIR}/freenas-11.0 ${FILESDIR}/freenas-11.1 \
|
||||
${FILESDIR}/openzfsonosx-1.9.3 ${FILESDIR}/openzfsonosx-1.9.4 \
|
||||
${FILESDIR}/openzfs-2.0-freebsd ${FILESDIR}/truenas-12.0 \
|
||||
${FILESDIR}/zol-0.7 ${FILESDIR}/ubuntu-18.04 \
|
||||
${FILESDIR}/zol-0.8 ${FILESDIR}/ubuntu-20.04
|
||||
|
||||
LINKMODE= ${NOBINMODE}
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -15,12 +15,10 @@ SUBDIR.${MK_TESTS}+= tests
|
||||
|
||||
.if ${MK_ZFS} != "no"
|
||||
_zinject= zinject
|
||||
.if ${MK_LIBTHR} != "no"
|
||||
_ztest= ztest
|
||||
_zstream = zstream
|
||||
_zstreamdump = zstreamdump
|
||||
.endif
|
||||
.endif
|
||||
|
||||
SUBDIR_PARALLEL=
|
||||
|
||||
|
@ -13,10 +13,8 @@ SUBDIR= ${_dtrace} \
|
||||
SUBDIR.${MK_TESTS}+= tests
|
||||
|
||||
.if ${MK_ZFS} != "no"
|
||||
.if ${MK_LIBTHR} != "no"
|
||||
_zdb= zdb
|
||||
_zhack= zhack
|
||||
.endif
|
||||
. if ${MK_CXX} != "no"
|
||||
_zfsd= zfsd
|
||||
. endif
|
||||
|
26
contrib/atf/.cirrus.yml
Normal file
26
contrib/atf/.cirrus.yml
Normal file
@ -0,0 +1,26 @@
|
||||
env:
|
||||
CIRRUS_CLONE_DEPTH: 1
|
||||
ARCH: amd64
|
||||
|
||||
task:
|
||||
matrix:
|
||||
- name: 13.0-CURRENT
|
||||
freebsd_instance:
|
||||
image_family: freebsd-13-0-snap
|
||||
- name: 12.2-STABLE
|
||||
freebsd_instance:
|
||||
image_family: freebsd-12-2-snap
|
||||
- name: 12.1-RELEASE
|
||||
freebsd_instance:
|
||||
image_family: freebsd-12-1
|
||||
install_script:
|
||||
- sed -i.bak -e 's,pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly,pkg+http://pkg.FreeBSD.org/\${ABI}/latest,' /etc/pkg/FreeBSD.conf
|
||||
- ASSUME_ALWAYS_YES=yes pkg bootstrap -f
|
||||
- pkg install -y autoconf automake libtool kyua
|
||||
script:
|
||||
- env JUNIT_OUTPUT=$(pwd)/test-results.xml ./admin/travis-build.sh
|
||||
always:
|
||||
junit_artifacts:
|
||||
path: "test-results.xml"
|
||||
type: text/xml
|
||||
format: junit
|
25
contrib/atf/.gitignore
vendored
Normal file
25
contrib/atf/.gitignore
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
*.la
|
||||
*.lo
|
||||
*.o
|
||||
*.pc
|
||||
*_helper
|
||||
*_helpers
|
||||
*_test
|
||||
.deps
|
||||
.dirstamp
|
||||
.libs
|
||||
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
config.h
|
||||
config.h.in
|
||||
config.h.in~
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
installcheck.log
|
||||
libtool
|
||||
stamp-h1
|
||||
testsuite.log
|
25
contrib/atf/.travis.yml
Normal file
25
contrib/atf/.travis.yml
Normal file
@ -0,0 +1,25 @@
|
||||
language: cpp
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
before_install:
|
||||
- ./admin/travis-install-deps.sh
|
||||
|
||||
env:
|
||||
- ARCH=amd64 AS_ROOT=no
|
||||
- ARCH=amd64 AS_ROOT=yes
|
||||
- ARCH=i386 AS_ROOT=no
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- compiler: clang
|
||||
env: ARCH=i386 AS_ROOT=no
|
||||
|
||||
script:
|
||||
- ./admin/travis-build.sh
|
||||
|
||||
notifications:
|
||||
email:
|
||||
- atf-log@googlegroups.com
|
@ -1,6 +1,24 @@
|
||||
Major changes between releases Automated Testing Framework
|
||||
===========================================================================
|
||||
|
||||
Changes in version 0.22
|
||||
***********************
|
||||
|
||||
STILL UNDER DEVELOPMENT; NOT RELEASED YET.
|
||||
DON'T FORGET TO BUMP THE -version-info PRE-RELEASE IF NECESSARY!
|
||||
|
||||
* Issue #23: Fix double-free triggered by atf_map_insert in low memory
|
||||
scenarios, caused by an overlook in the atf_list code.
|
||||
|
||||
* Issue #29: Fixed various typos and formatting errors in manual pages.
|
||||
|
||||
* Issue #31: Added require.progs metadata properties to the tests that
|
||||
need a compiler to run.
|
||||
|
||||
* Added the atf_check_not_equal function to atf-sh to check for
|
||||
unequal values.
|
||||
|
||||
|
||||
Changes in version 0.21
|
||||
***********************
|
||||
|
||||
|
47
contrib/atf/README.md
Normal file
47
contrib/atf/README.md
Normal file
@ -0,0 +1,47 @@
|
||||
# Welcome to the ATF project!
|
||||
|
||||
ATF, or Automated Testing Framework, is a **collection of libraries** to
|
||||
write test programs in **C, C++ and POSIX shell**.
|
||||
|
||||
The ATF libraries offer a simple API. The API is orthogonal through the
|
||||
various bindings, allowing developers to quickly learn how to write test
|
||||
programs in different languages.
|
||||
|
||||
ATF-based test programs offer a **consistent end-user command-line
|
||||
interface** to allow both humans and automation to run the tests.
|
||||
|
||||
ATF-based test programs **rely on an execution engine** to be run and
|
||||
this execution engine is *not* shipped with ATF.
|
||||
**[Kyua](https://github.com/jmmv/kyua/) is the engine of choice.**
|
||||
|
||||
## Download
|
||||
|
||||
Formal releases for source files are available for download from GitHub:
|
||||
|
||||
* [atf 0.20](../../releases/tag/atf-0.20), released on February 7th, 2014.
|
||||
|
||||
## Installation
|
||||
|
||||
You are encouraged to install binary packages for your operating system
|
||||
wherever available:
|
||||
|
||||
* Fedora 20 and above: install the `atf` package with `yum install atf`.
|
||||
|
||||
* FreeBSD 10.0 and above: install the `atf` package with `pkg install atf`.
|
||||
|
||||
* NetBSD with pkgsrc: install the `pkgsrc/devel/atf` package.
|
||||
|
||||
* OpenBSD: install the `devel/atf` package with `pkg_add atf`.
|
||||
|
||||
Should you want to build and install ATF from the source tree provided
|
||||
here, follow the instructions in the [INSTALL file](INSTALL).
|
||||
|
||||
## Support
|
||||
|
||||
Please use the
|
||||
[atf-discuss mailing list](https://groups.google.com/forum/#!forum/atf-discuss)
|
||||
for any support inquiries related to `atf-c`, `atf-c++` or `atf-sh`.
|
||||
|
||||
If you have any questions on Kyua proper, please use the
|
||||
[kyua-discuss mailing list](https://groups.google.com/forum/#!forum/kyua-discuss)
|
||||
instead.
|
@ -403,8 +403,8 @@ in the collection.
|
||||
takes the name of an exception and a statement and raises a failure if
|
||||
the statement does not throw the specified exception.
|
||||
.Fn ATF_REQUIRE_THROW_RE
|
||||
takes the name of an exception, a regular expresion and a statement and raises a
|
||||
failure if the statement does not throw the specified exception and if the
|
||||
takes the name of an exception, a regular expression and a statement, and raises
|
||||
a failure if the statement does not throw the specified exception and if the
|
||||
message of the exception does not match the regular expression.
|
||||
.Pp
|
||||
.Fn ATF_CHECK_ERRNO
|
||||
|
@ -36,6 +36,7 @@
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
#include <atf-c++/detail/env.hpp>
|
||||
#include <atf-c++/detail/process.hpp>
|
||||
|
||||
#define HEADER_TC(name, hdrname) \
|
||||
@ -44,6 +45,8 @@
|
||||
{ \
|
||||
set_md_var("descr", "Tests that the " hdrname " file can be " \
|
||||
"included on its own, without any prerequisites"); \
|
||||
const std::string cxx = atf::env::get("ATF_BUILD_CXX", ATF_BUILD_CXX); \
|
||||
set_md_var("require.progs", cxx); \
|
||||
} \
|
||||
ATF_TEST_CASE_BODY(name) \
|
||||
{ \
|
||||
@ -55,6 +58,8 @@
|
||||
ATF_TEST_CASE_HEAD(name) \
|
||||
{ \
|
||||
set_md_var("descr", descr); \
|
||||
const std::string cxx = atf::env::get("ATF_BUILD_CXX", ATF_BUILD_CXX); \
|
||||
set_md_var("require.progs", cxx); \
|
||||
} \
|
||||
ATF_TEST_CASE_BODY(name) \
|
||||
{ \
|
||||
|
@ -73,7 +73,7 @@ class tc {
|
||||
tc(const tc&);
|
||||
tc& operator=(const tc&);
|
||||
|
||||
std::auto_ptr< tc_impl > pimpl;
|
||||
std::unique_ptr< tc_impl > pimpl;
|
||||
|
||||
protected:
|
||||
virtual void head(void);
|
||||
|
@ -70,6 +70,13 @@ atf::utils::fork(void)
|
||||
return atf_utils_fork();
|
||||
}
|
||||
|
||||
void
|
||||
atf::utils::reset_resultsfile(void)
|
||||
{
|
||||
|
||||
atf_utils_reset_resultsfile();
|
||||
}
|
||||
|
||||
bool
|
||||
atf::utils::grep_file(const std::string& regex, const std::string& path)
|
||||
{
|
||||
|
@ -41,6 +41,7 @@ void copy_file(const std::string&, const std::string&);
|
||||
void create_file(const std::string&, const std::string&);
|
||||
bool file_exists(const std::string&);
|
||||
pid_t fork(void);
|
||||
void reset_resultsfile(void);
|
||||
bool grep_file(const std::string&, const std::string&);
|
||||
bool grep_string(const std::string&, const std::string&);
|
||||
void redirect(const int, const std::string&);
|
||||
|
@ -335,6 +335,7 @@ fork_and_wait(const int exitstatus, const char* expout, const char* experr)
|
||||
std::cerr << "Some error\n";
|
||||
exit(123);
|
||||
}
|
||||
atf::utils::reset_resultsfile();
|
||||
atf::utils::wait(pid, exitstatus, expout, experr);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
1
contrib/atf/atf-c/.gitignore
vendored
Normal file
1
contrib/atf/atf-c/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
defs.h
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -106,7 +107,7 @@ static
|
||||
int
|
||||
const_execvp(const char *file, const char *const *argv)
|
||||
{
|
||||
#define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
|
||||
#define UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
|
||||
return execvp(file, UNCONST(argv));
|
||||
#undef UNCONST
|
||||
}
|
||||
|
@ -779,7 +779,7 @@ ATF_TC_BODY(rmdir_enotempty, tc)
|
||||
atf_fs_path_fini(&p);
|
||||
}
|
||||
|
||||
ATF_TC(rmdir_eperm);
|
||||
ATF_TC_WITH_CLEANUP(rmdir_eperm);
|
||||
ATF_TC_HEAD(rmdir_eperm, tc)
|
||||
{
|
||||
atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function");
|
||||
@ -808,6 +808,13 @@ ATF_TC_BODY(rmdir_eperm, tc)
|
||||
|
||||
atf_fs_path_fini(&p);
|
||||
}
|
||||
ATF_TC_CLEANUP(rmdir_eperm, tc)
|
||||
{
|
||||
if (chmod("test-dir", 0755) == -1) {
|
||||
fprintf(stderr, "Failed to unprotect test-dir; test directory "
|
||||
"cleanup will fail\n");
|
||||
}
|
||||
}
|
||||
|
||||
ATF_TC(mkdtemp_ok);
|
||||
ATF_TC_HEAD(mkdtemp_ok, tc)
|
||||
|
@ -74,7 +74,7 @@ new_entry(void *object, bool managed)
|
||||
le->m_prev = le->m_next = NULL;
|
||||
le->m_object = object;
|
||||
le->m_managed = managed;
|
||||
} else
|
||||
} else if (managed)
|
||||
free(object);
|
||||
|
||||
return le;
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -552,7 +553,7 @@ static
|
||||
int
|
||||
const_execvp(const char *file, const char *const *argv)
|
||||
{
|
||||
#define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
|
||||
#define UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
|
||||
return execvp(file, UNCONST(argv));
|
||||
#undef UNCONST
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include <atf-c.h>
|
||||
|
||||
#include <atf-c/detail/env.h>
|
||||
#include <atf-c/error_fwd.h>
|
||||
#include <atf-c/tc.h>
|
||||
|
||||
@ -46,8 +47,11 @@ struct atf_fs_path;
|
||||
ATF_TC(name); \
|
||||
ATF_TC_HEAD(name, tc) \
|
||||
{ \
|
||||
const char *cc; \
|
||||
atf_tc_set_md_var(tc, "descr", "Tests that the " hdrname " file can " \
|
||||
"be included on its own, without any prerequisites"); \
|
||||
cc = atf_env_get_with_default("ATF_BUILD_CC", ATF_BUILD_CC); \
|
||||
atf_tc_set_md_var(tc, "require.progs", cc); \
|
||||
} \
|
||||
ATF_TC_BODY(name, tc) \
|
||||
{ \
|
||||
@ -58,7 +62,10 @@ struct atf_fs_path;
|
||||
ATF_TC(name); \
|
||||
ATF_TC_HEAD(name, tc) \
|
||||
{ \
|
||||
const char *cc; \
|
||||
atf_tc_set_md_var(tc, "descr", descr); \
|
||||
cc = atf_env_get_with_default("ATF_BUILD_CC", ATF_BUILD_CC); \
|
||||
atf_tc_set_md_var(tc, "require.progs", cc); \
|
||||
} \
|
||||
ATF_TC_BODY(name, tc) \
|
||||
{ \
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -62,6 +63,7 @@ enum expect_type {
|
||||
struct context {
|
||||
const atf_tc_t *tc;
|
||||
const char *resfile;
|
||||
int resfilefd;
|
||||
size_t fail_count;
|
||||
|
||||
enum expect_type expect;
|
||||
@ -73,12 +75,14 @@ struct context {
|
||||
};
|
||||
|
||||
static void context_init(struct context *, const atf_tc_t *, const char *);
|
||||
static void context_set_resfile(struct context *, const char *);
|
||||
static void context_close_resfile(struct context *);
|
||||
static void check_fatal_error(atf_error_t);
|
||||
static void report_fatal_error(const char *, ...)
|
||||
ATF_DEFS_ATTRIBUTE_NORETURN;
|
||||
static atf_error_t write_resfile(const int, const char *, const int,
|
||||
const atf_dynstr_t *);
|
||||
static void create_resfile(const char *, const char *, const int,
|
||||
static void create_resfile(struct context *, const char *, const int,
|
||||
atf_dynstr_t *);
|
||||
static void error_in_expect(struct context *, const char *, ...)
|
||||
ATF_DEFS_ATTRIBUTE_NORETURN;
|
||||
@ -102,11 +106,16 @@ static void errno_test(struct context *, const char *, const size_t,
|
||||
static atf_error_t check_prog_in_dir(const char *, void *);
|
||||
static atf_error_t check_prog(struct context *, const char *);
|
||||
|
||||
/* No prototype in header for this one, it's a little sketchy (internal). */
|
||||
void atf_tc_set_resultsfile(const char *);
|
||||
|
||||
static void
|
||||
context_init(struct context *ctx, const atf_tc_t *tc, const char *resfile)
|
||||
{
|
||||
|
||||
ctx->tc = tc;
|
||||
ctx->resfile = resfile;
|
||||
ctx->resfilefd = -1;
|
||||
context_set_resfile(ctx, resfile);
|
||||
ctx->fail_count = 0;
|
||||
ctx->expect = EXPECT_PASS;
|
||||
check_fatal_error(atf_dynstr_init(&ctx->expect_reason));
|
||||
@ -116,6 +125,41 @@ context_init(struct context *ctx, const atf_tc_t *tc, const char *resfile)
|
||||
ctx->expect_signo = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
context_set_resfile(struct context *ctx, const char *resfile)
|
||||
{
|
||||
atf_error_t err;
|
||||
|
||||
context_close_resfile(ctx);
|
||||
ctx->resfile = resfile;
|
||||
if (strcmp(resfile, "/dev/stdout") == 0)
|
||||
ctx->resfilefd = STDOUT_FILENO;
|
||||
else if (strcmp(resfile, "/dev/stderr") == 0)
|
||||
ctx->resfilefd = STDERR_FILENO;
|
||||
else
|
||||
ctx->resfilefd = open(resfile, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (ctx->resfilefd == -1) {
|
||||
err = atf_libc_error(errno,
|
||||
"Cannot create results file '%s'", resfile);
|
||||
check_fatal_error(err);
|
||||
}
|
||||
|
||||
ctx->resfile = resfile;
|
||||
}
|
||||
|
||||
static void
|
||||
context_close_resfile(struct context *ctx)
|
||||
{
|
||||
|
||||
if (ctx->resfilefd == -1)
|
||||
return;
|
||||
if (ctx->resfilefd != STDOUT_FILENO && ctx->resfilefd != STDERR_FILENO)
|
||||
close(ctx->resfilefd);
|
||||
ctx->resfilefd = -1;
|
||||
ctx->resfile = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
check_fatal_error(atf_error_t err)
|
||||
{
|
||||
@ -162,7 +206,7 @@ write_resfile(const int fd, const char *result, const int arg,
|
||||
|
||||
INV(arg == -1 || reason != NULL);
|
||||
|
||||
#define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
|
||||
#define UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
|
||||
iov[count].iov_base = UNCONST(result);
|
||||
iov[count++].iov_len = strlen(result);
|
||||
|
||||
@ -202,26 +246,23 @@ write_resfile(const int fd, const char *result, const int arg,
|
||||
* not return any error code.
|
||||
*/
|
||||
static void
|
||||
create_resfile(const char *resfile, const char *result, const int arg,
|
||||
create_resfile(struct context *ctx, const char *result, const int arg,
|
||||
atf_dynstr_t *reason)
|
||||
{
|
||||
atf_error_t err;
|
||||
|
||||
if (strcmp("/dev/stdout", resfile) == 0) {
|
||||
err = write_resfile(STDOUT_FILENO, result, arg, reason);
|
||||
} else if (strcmp("/dev/stderr", resfile) == 0) {
|
||||
err = write_resfile(STDERR_FILENO, result, arg, reason);
|
||||
} else {
|
||||
const int fd = open(resfile, O_WRONLY | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (fd == -1) {
|
||||
err = atf_libc_error(errno, "Cannot create results file '%s'",
|
||||
resfile);
|
||||
} else {
|
||||
err = write_resfile(fd, result, arg, reason);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We'll attempt to truncate the results file, but only if it's not pointed
|
||||
* at stdout/stderr. We could just blindly ftruncate() here, but it may
|
||||
* be that stdout/stderr have been redirected to a file that we want to
|
||||
* validate expectations on, for example. Kyua will want the truncation,
|
||||
* but it will also redirect the results directly to some file and we'll
|
||||
* have no issue here.
|
||||
*/
|
||||
if (ctx->resfilefd != STDOUT_FILENO && ctx->resfilefd != STDERR_FILENO &&
|
||||
ftruncate(ctx->resfilefd, 0) != -1)
|
||||
lseek(ctx->resfilefd, 0, SEEK_SET);
|
||||
err = write_resfile(ctx->resfilefd, result, arg, reason);
|
||||
|
||||
if (reason != NULL)
|
||||
atf_dynstr_fini(reason);
|
||||
@ -280,7 +321,8 @@ expected_failure(struct context *ctx, atf_dynstr_t *reason)
|
||||
{
|
||||
check_fatal_error(atf_dynstr_prepend_fmt(reason, "%s: ",
|
||||
atf_dynstr_cstring(&ctx->expect_reason)));
|
||||
create_resfile(ctx->resfile, "expected_failure", -1, reason);
|
||||
create_resfile(ctx, "expected_failure", -1, reason);
|
||||
context_close_resfile(ctx);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
@ -290,7 +332,8 @@ fail_requirement(struct context *ctx, atf_dynstr_t *reason)
|
||||
if (ctx->expect == EXPECT_FAIL) {
|
||||
expected_failure(ctx, reason);
|
||||
} else if (ctx->expect == EXPECT_PASS) {
|
||||
create_resfile(ctx->resfile, "failed", -1, reason);
|
||||
create_resfile(ctx, "failed", -1, reason);
|
||||
context_close_resfile(ctx);
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
error_in_expect(ctx, "Test case raised a failure but was not "
|
||||
@ -325,7 +368,8 @@ pass(struct context *ctx)
|
||||
error_in_expect(ctx, "Test case was expecting a failure but got "
|
||||
"a pass instead");
|
||||
} else if (ctx->expect == EXPECT_PASS) {
|
||||
create_resfile(ctx->resfile, "passed", -1, NULL);
|
||||
create_resfile(ctx, "passed", -1, NULL);
|
||||
context_close_resfile(ctx);
|
||||
exit(EXIT_SUCCESS);
|
||||
} else {
|
||||
error_in_expect(ctx, "Test case asked to explicitly pass but was "
|
||||
@ -338,7 +382,8 @@ static void
|
||||
skip(struct context *ctx, atf_dynstr_t *reason)
|
||||
{
|
||||
if (ctx->expect == EXPECT_PASS) {
|
||||
create_resfile(ctx->resfile, "skipped", -1, reason);
|
||||
create_resfile(ctx, "skipped", -1, reason);
|
||||
context_close_resfile(ctx);
|
||||
exit(EXIT_SUCCESS);
|
||||
} else {
|
||||
error_in_expect(ctx, "Can only skip a test case when running in "
|
||||
@ -942,7 +987,7 @@ _atf_tc_expect_exit(struct context *ctx, const int exitcode, const char *reason,
|
||||
check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
|
||||
va_end(ap2);
|
||||
|
||||
create_resfile(ctx->resfile, "expected_exit", exitcode, &formatted);
|
||||
create_resfile(ctx, "expected_exit", exitcode, &formatted);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -959,7 +1004,7 @@ _atf_tc_expect_signal(struct context *ctx, const int signo, const char *reason,
|
||||
check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
|
||||
va_end(ap2);
|
||||
|
||||
create_resfile(ctx->resfile, "expected_signal", signo, &formatted);
|
||||
create_resfile(ctx, "expected_signal", signo, &formatted);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -975,7 +1020,7 @@ _atf_tc_expect_death(struct context *ctx, const char *reason, va_list ap)
|
||||
check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
|
||||
va_end(ap2);
|
||||
|
||||
create_resfile(ctx->resfile, "expected_death", -1, &formatted);
|
||||
create_resfile(ctx, "expected_death", -1, &formatted);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -991,7 +1036,14 @@ _atf_tc_expect_timeout(struct context *ctx, const char *reason, va_list ap)
|
||||
check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
|
||||
va_end(ap2);
|
||||
|
||||
create_resfile(ctx->resfile, "expected_timeout", -1, &formatted);
|
||||
create_resfile(ctx, "expected_timeout", -1, &formatted);
|
||||
}
|
||||
|
||||
static void
|
||||
_atf_tc_set_resultsfile(struct context *ctx, const char *file)
|
||||
{
|
||||
|
||||
context_set_resfile(ctx, file);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
@ -1215,3 +1267,13 @@ atf_tc_expect_timeout(const char *reason, ...)
|
||||
_atf_tc_expect_timeout(&Current, reason, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/* Internal! */
|
||||
void
|
||||
atf_tc_set_resultsfile(const char *file)
|
||||
{
|
||||
|
||||
PRE(Current.tc != NULL);
|
||||
|
||||
_atf_tc_set_resultsfile(&Current, file);
|
||||
}
|
||||
|
@ -41,6 +41,9 @@
|
||||
|
||||
#include "atf-c/detail/dynstr.h"
|
||||
|
||||
/* No prototype in header for this one, it's a little sketchy (internal). */
|
||||
void atf_tc_set_resultsfile(const char *);
|
||||
|
||||
/** Allocate a filename to be used by atf_utils_{fork,wait}.
|
||||
*
|
||||
* In case of a failure, marks the calling test as failed when in_parent is
|
||||
@ -271,6 +274,13 @@ atf_utils_fork(void)
|
||||
return pid;
|
||||
}
|
||||
|
||||
void
|
||||
atf_utils_reset_resultsfile(void)
|
||||
{
|
||||
|
||||
atf_tc_set_resultsfile("/dev/null");
|
||||
}
|
||||
|
||||
/** Frees an dynamically-allocated "argv" array.
|
||||
*
|
||||
* \param argv A dynamically-allocated array of dynamically-allocated
|
||||
|
@ -46,5 +46,6 @@ bool atf_utils_grep_string(const char *, const char *, ...)
|
||||
char *atf_utils_readline(int);
|
||||
void atf_utils_redirect(const int, const char *);
|
||||
void atf_utils_wait(const pid_t, const int, const char *, const char *);
|
||||
void atf_utils_reset_resultsfile(void);
|
||||
|
||||
#endif /* !defined(ATF_C_UTILS_H) */
|
||||
|
@ -395,6 +395,7 @@ fork_and_wait(const int exitstatus, const char* expout, const char* experr)
|
||||
fprintf(stderr, "Some error\n");
|
||||
exit(123);
|
||||
}
|
||||
atf_utils_reset_resultsfile();
|
||||
atf_utils_wait(pid, exitstatus, expout, experr);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
2
contrib/atf/atf-sh/.gitignore
vendored
Normal file
2
contrib/atf/atf-sh/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
atf-check
|
||||
atf-sh
|
@ -22,7 +22,7 @@
|
||||
.\" 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.
|
||||
.Dd March 6, 2017
|
||||
.Dd June 21, 2020
|
||||
.Dt ATF-CHECK 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -120,6 +120,14 @@ as a shell command line, executing it with the system shell defined by
|
||||
.Va ATF_SHELL .
|
||||
You should avoid using this flag if at all possible to prevent shell quoting
|
||||
issues.
|
||||
.It Fl r Ar timeout[:interval]
|
||||
Repeats failed checks until the
|
||||
.Ar timeout
|
||||
(in seconds) expires.
|
||||
If unspecified, the default
|
||||
.Ar interval
|
||||
(in milliseconds) is 50 ms.
|
||||
This can be used to wait for an expected update to the contents of a file.
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width ATFXSHELLXX -compact
|
||||
@ -157,6 +165,11 @@ atf_check -s signal:sigsegv my_program
|
||||
|
||||
# Combined checks
|
||||
atf_check -o match:foo -o not-match:bar echo foo baz
|
||||
|
||||
# Wait 5 seconds for a line to show up in a file
|
||||
( sleep 2 ; echo "testing 123" > $test_path ) &
|
||||
atf-check -o ignore -e ignore -s exit:0 -r 5 \e
|
||||
grep "testing 123" $test_path
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr atf-sh 1
|
||||
|
@ -29,6 +29,7 @@ extern "C" {
|
||||
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
}
|
||||
|
||||
@ -53,6 +54,10 @@ extern "C" {
|
||||
#include "atf-c++/detail/sanity.hpp"
|
||||
#include "atf-c++/detail/text.hpp"
|
||||
|
||||
static const useconds_t seconds_in_useconds = (1000 * 1000);
|
||||
static const useconds_t mseconds_in_useconds = 1000;
|
||||
static const useconds_t useconds_in_nseconds = 1000;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Auxiliary functions.
|
||||
// ------------------------------------------------------------------------
|
||||
@ -162,6 +167,33 @@ public:
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
static useconds_t
|
||||
get_monotonic_useconds(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
useconds_t res;
|
||||
int rc;
|
||||
|
||||
rc = clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
if (rc != 0)
|
||||
throw std::runtime_error("clock_gettime: " +
|
||||
std::string(strerror(errno)));
|
||||
|
||||
res = ts.tv_sec * seconds_in_useconds;
|
||||
res += ts.tv_nsec / useconds_in_nseconds;
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool
|
||||
timo_expired(useconds_t timeout)
|
||||
{
|
||||
|
||||
if (get_monotonic_useconds() >= timeout)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
parse_exit_code(const std::string& str)
|
||||
{
|
||||
@ -216,7 +248,7 @@ parse_signal(const std::string& str)
|
||||
if (signo == INT_MIN) {
|
||||
try {
|
||||
return atf::text::to_type< int >(str);
|
||||
} catch (std::runtime_error) {
|
||||
} catch (const std::runtime_error&) {
|
||||
throw atf::application::usage_error("Invalid signal name or number "
|
||||
"in -s option");
|
||||
}
|
||||
@ -306,6 +338,62 @@ parse_output_check_arg(const std::string& arg)
|
||||
return output_check(type, negated, arg.substr(delimiter + 1));
|
||||
}
|
||||
|
||||
static void
|
||||
parse_repeat_check_arg(const std::string& arg, useconds_t *m_timo,
|
||||
useconds_t *m_interval)
|
||||
{
|
||||
const std::string::size_type delimiter = arg.find(':');
|
||||
const bool has_interval = (delimiter != std::string::npos);
|
||||
const std::string timo_str = arg.substr(0, delimiter);
|
||||
|
||||
long l;
|
||||
char *end;
|
||||
|
||||
// There is no reason this couldn't be a non-integer number of seconds,
|
||||
// this was just easy to do for now.
|
||||
errno = 0;
|
||||
l = strtol(timo_str.c_str(), &end, 10);
|
||||
if (errno == ERANGE)
|
||||
throw atf::application::usage_error("Bogus timeout in seconds");
|
||||
else if (errno != 0)
|
||||
throw atf::application::usage_error("Timeout must be a number");
|
||||
|
||||
if (*end != 0)
|
||||
throw atf::application::usage_error("Timeout must be a number");
|
||||
|
||||
*m_timo = get_monotonic_useconds() + (l * seconds_in_useconds);
|
||||
// 50 milliseconds is chosen arbitrarily. There is a tradeoff between
|
||||
// longer and shorter poll times. A shorter poll time makes for faster
|
||||
// tests. A longer poll time makes for lower CPU overhead for the polled
|
||||
// operation. 50ms is chosen with these tradeoffs in mind: on
|
||||
// microcontrollers, the hope is that we can still avoid meaningful CPU use
|
||||
// with a small test every 50ms. And on typical fast x86 hardware, our
|
||||
// tests can be much more precise with time wasted than they typically are
|
||||
// without this feature.
|
||||
*m_interval = 50 * mseconds_in_useconds;
|
||||
|
||||
if (!has_interval)
|
||||
return;
|
||||
|
||||
const std::string intv_str = arg.substr(delimiter + 1, std::string::npos);
|
||||
|
||||
// Same -- this could be non-integer milliseconds.
|
||||
errno = 0;
|
||||
l = strtol(intv_str.c_str(), &end, 10);
|
||||
if (errno == ERANGE)
|
||||
throw atf::application::usage_error(
|
||||
"Bogus repeat interval in milliseconds");
|
||||
else if (errno != 0)
|
||||
throw atf::application::usage_error(
|
||||
"Repeat interval must be a number");
|
||||
|
||||
if (*end != 0)
|
||||
throw atf::application::usage_error(
|
||||
"Repeat interval must be a number");
|
||||
|
||||
*m_interval = l * mseconds_in_useconds;
|
||||
}
|
||||
|
||||
static
|
||||
std::string
|
||||
flatten_argv(char* const* argv)
|
||||
@ -694,8 +782,12 @@ run_output_checks(const std::vector< output_check >& checks,
|
||||
namespace {
|
||||
|
||||
class atf_check : public atf::application::app {
|
||||
bool m_rflag;
|
||||
bool m_xflag;
|
||||
|
||||
useconds_t m_timo;
|
||||
useconds_t m_interval;
|
||||
|
||||
std::vector< status_check > m_status_checks;
|
||||
std::vector< output_check > m_stdout_checks;
|
||||
std::vector< output_check > m_stderr_checks;
|
||||
@ -722,6 +814,7 @@ const char* atf_check::m_description =
|
||||
|
||||
atf_check::atf_check(void) :
|
||||
app(m_description, "atf-check(1)"),
|
||||
m_rflag(false),
|
||||
m_xflag(false)
|
||||
{
|
||||
}
|
||||
@ -765,6 +858,8 @@ atf_check::specific_options(void)
|
||||
opts.insert(option('e', "action:arg", "Handle stderr. Action must be "
|
||||
"one of: empty ignore file:<path> inline:<val> match:regexp "
|
||||
"save:<path>"));
|
||||
opts.insert(option('r', "timeout[:interval]", "Repeat failed check until "
|
||||
"the timeout expires."));
|
||||
opts.insert(option('x', "", "Execute command as a shell command"));
|
||||
|
||||
return opts;
|
||||
@ -786,6 +881,11 @@ atf_check::process_option(int ch, const char* arg)
|
||||
m_stderr_checks.push_back(parse_output_check_arg(arg));
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
m_rflag = true;
|
||||
parse_repeat_check_arg(arg, &m_timo, &m_interval);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
m_xflag = true;
|
||||
break;
|
||||
@ -803,9 +903,6 @@ atf_check::main(void)
|
||||
|
||||
int status = EXIT_FAILURE;
|
||||
|
||||
std::auto_ptr< atf::check::check_result > r =
|
||||
m_xflag ? execute_with_shell(m_argv) : execute(m_argv);
|
||||
|
||||
if (m_status_checks.empty())
|
||||
m_status_checks.push_back(status_check(sc_exit, false, EXIT_SUCCESS));
|
||||
else if (m_status_checks.size() > 1) {
|
||||
@ -818,12 +915,23 @@ atf_check::main(void)
|
||||
if (m_stderr_checks.empty())
|
||||
m_stderr_checks.push_back(output_check(oc_empty, false, ""));
|
||||
|
||||
if ((run_status_checks(m_status_checks, *r) == false) ||
|
||||
(run_output_checks(*r, "stderr") == false) ||
|
||||
(run_output_checks(*r, "stdout") == false))
|
||||
status = EXIT_FAILURE;
|
||||
else
|
||||
status = EXIT_SUCCESS;
|
||||
do {
|
||||
std::auto_ptr< atf::check::check_result > r =
|
||||
m_xflag ? execute_with_shell(m_argv) : execute(m_argv);
|
||||
|
||||
if ((run_status_checks(m_status_checks, *r) == false) ||
|
||||
(run_output_checks(*r, "stderr") == false) ||
|
||||
(run_output_checks(*r, "stdout") == false))
|
||||
status = EXIT_FAILURE;
|
||||
else
|
||||
status = EXIT_SUCCESS;
|
||||
|
||||
if (m_rflag && status == EXIT_FAILURE) {
|
||||
if (timo_expired(m_timo))
|
||||
break;
|
||||
usleep(m_interval);
|
||||
}
|
||||
} while (m_rflag && status == EXIT_FAILURE);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -22,13 +22,14 @@
|
||||
.\" 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.
|
||||
.Dd March 6, 2017
|
||||
.Dd June 08, 2017
|
||||
.Dt ATF-SH 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm atf_add_test_case ,
|
||||
.Nm atf_check ,
|
||||
.Nm atf_check_equal ,
|
||||
.Nm atf_check_not_equal ,
|
||||
.Nm atf_config_get ,
|
||||
.Nm atf_config_has ,
|
||||
.Nm atf_expect_death ,
|
||||
@ -55,6 +56,9 @@
|
||||
.Nm atf_check_equal
|
||||
.Qq expected_expression
|
||||
.Qq actual_expression
|
||||
.Nm atf_check_not_equal
|
||||
.Qq expected_expression
|
||||
.Qq actual_expression
|
||||
.Nm atf_config_get
|
||||
.Qq var_name
|
||||
.Nm atf_config_has
|
||||
@ -310,6 +314,11 @@ This function takes two expressions, evaluates them and, if their
|
||||
results differ, aborts the test case with an appropriate failure message.
|
||||
The common style is to put the expected value in the first parameter and the
|
||||
actual value in the second parameter.
|
||||
.It Nm atf_check_not_equal Qo expected_expression Qc Qo actual_expression Qc
|
||||
This function takes two expressions, evaluates them and, if their
|
||||
results are equal, aborts the test case with an appropriate failure message.
|
||||
The common style is to put the expected value in the first parameter and the
|
||||
actual value in the second parameter.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
The following shows a complete test program with a single test case that
|
||||
|
@ -164,6 +164,30 @@ equal_body()
|
||||
grep '^failed: \${x} != \${y} (a != b)$' resfile
|
||||
}
|
||||
|
||||
atf_test_case not_equal
|
||||
not_equal_head()
|
||||
{
|
||||
atf_set "descr" "Verifies that atf_check_not_equal works"
|
||||
}
|
||||
not_equal_body()
|
||||
{
|
||||
h="$(atf_get_srcdir)/misc_helpers -s $(atf_get_srcdir)"
|
||||
|
||||
atf_check -s eq:0 -o ignore -e ignore -x "${h} atf_check_not_equal_ok"
|
||||
|
||||
atf_check -s eq:1 -o ignore -e ignore -x \
|
||||
"${h} -r resfile atf_check_not_equal_fail"
|
||||
atf_check -s eq:0 -o ignore -e empty grep '^failed: a == b (a == b)$' \
|
||||
resfile
|
||||
|
||||
atf_check -s eq:0 -o ignore -e ignore -x "${h} atf_check_not_equal_eval_ok"
|
||||
|
||||
atf_check -s eq:1 -o ignore -e ignore -x \
|
||||
"${h} -r resfile atf_check_not_equal_eval_fail"
|
||||
atf_check -s eq:0 -o ignore -e empty \
|
||||
grep '^failed: \${x} == \${y} (a == b)$' resfile
|
||||
}
|
||||
|
||||
atf_test_case flush_stdout_on_death
|
||||
flush_stdout_on_death_body()
|
||||
{
|
||||
|
@ -100,6 +100,23 @@ atf_check_equal()
|
||||
atf_fail "${1} != ${2} (${_val1} != ${_val2})"
|
||||
}
|
||||
|
||||
#
|
||||
# atf_check_not_equal expected_expression actual_expression
|
||||
#
|
||||
# Checks that expected_expression's value does not match actual_expression's
|
||||
# and, if it does, raises an error. Ideally expected_expression and
|
||||
# actual_expression should be provided quoted (not expanded) so that
|
||||
# the error message is helpful; otherwise it will only show the values,
|
||||
# not the expressions themselves.
|
||||
#
|
||||
atf_check_not_equal()
|
||||
{
|
||||
eval _val1=\"${1}\"
|
||||
eval _val2=\"${2}\"
|
||||
test "${_val1}" != "${_val2}" || \
|
||||
atf_fail "${1} == ${2} (${_val1} == ${_val2})"
|
||||
}
|
||||
|
||||
#
|
||||
# atf_config_get varname [defvalue]
|
||||
#
|
||||
@ -536,7 +553,18 @@ _atf_list_tcs()
|
||||
#
|
||||
_atf_normalize()
|
||||
{
|
||||
echo ${1} | tr .- __
|
||||
# Check if the string contains any of the forbidden characters using
|
||||
# POSIX parameter expansion (the ${var//} string substitution is
|
||||
# unfortunately not supported in POSIX sh) and only use tr(1) then.
|
||||
# tr(1) is generally not a builtin, so doing the substring check first
|
||||
# avoids unnecessary fork()+execve() calls. As this function is called
|
||||
# many times in each test script startup, those overheads add up
|
||||
# (especially when running on emulated platforms such as QEMU).
|
||||
if [ "${1#*[.-]}" != "$1" ]; then
|
||||
echo "$1" | tr .- __
|
||||
else
|
||||
echo "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
@ -734,7 +762,7 @@ main()
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift `expr ${OPTIND} - 1`
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
case ${Source_Dir} in
|
||||
/*)
|
||||
|
@ -139,6 +139,50 @@ atf_check_equal_eval_fail_body()
|
||||
atf_check_equal '${x}' '${y}'
|
||||
}
|
||||
|
||||
atf_test_case atf_check_not_equal_ok
|
||||
atf_check_not_equal_ok_head()
|
||||
{
|
||||
atf_set "descr" "Helper test case for the t_atf_check test program"
|
||||
}
|
||||
atf_check_not_equal_ok_body()
|
||||
{
|
||||
atf_check_not_equal a b
|
||||
}
|
||||
|
||||
atf_test_case atf_check_not_equal_fail
|
||||
atf_check_not_equal_fail_head()
|
||||
{
|
||||
atf_set "descr" "Helper test case for the t_atf_check test program"
|
||||
}
|
||||
atf_check_not_equal_fail_body()
|
||||
{
|
||||
atf_check_not_equal a a
|
||||
}
|
||||
|
||||
atf_test_case atf_check_not_equal_eval_ok
|
||||
atf_check_not_equal_eval_ok_head()
|
||||
{
|
||||
atf_set "descr" "Helper test case for the t_atf_check test program"
|
||||
}
|
||||
atf_check_not_equal_eval_ok_body()
|
||||
{
|
||||
x=a
|
||||
y=b
|
||||
atf_check_not_equal '${x}' '${y}'
|
||||
}
|
||||
|
||||
atf_test_case atf_check_not_equal_eval_fail
|
||||
atf_check_not_equal_eval_fail_head()
|
||||
{
|
||||
atf_set "descr" "Helper test case for the t_atf_check test program"
|
||||
}
|
||||
atf_check_not_equal_eval_fail_body()
|
||||
{
|
||||
x=a
|
||||
y=a
|
||||
atf_check_not_equal '${x}' '${y}'
|
||||
}
|
||||
|
||||
atf_test_case atf_check_flush_stdout
|
||||
atf_check_flush_stdout_head()
|
||||
{
|
||||
@ -285,6 +329,10 @@ atf_init_test_cases()
|
||||
atf_add_test_case atf_check_equal_fail
|
||||
atf_add_test_case atf_check_equal_eval_ok
|
||||
atf_add_test_case atf_check_equal_eval_fail
|
||||
atf_add_test_case atf_check_not_equal_ok
|
||||
atf_add_test_case atf_check_not_equal_fail
|
||||
atf_add_test_case atf_check_not_equal_eval_ok
|
||||
atf_add_test_case atf_check_not_equal_eval_fail
|
||||
atf_add_test_case atf_check_flush_stdout
|
||||
|
||||
# Add helper tests for t_config.
|
||||
|
1
contrib/atf/doc/.gitignore
vendored
Normal file
1
contrib/atf/doc/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
atf.7
|
@ -149,11 +149,7 @@ APIs to implement the test cases.
|
||||
The standard input of the test cases is unconditionally connected to
|
||||
.Sq /dev/zero .
|
||||
.Ss Meta-data
|
||||
The following list describes all meta-data properties interpreted
|
||||
internally by ATF.
|
||||
You are free to define new properties in your test cases and use them as
|
||||
you wish, but non-standard properties must be prefixed by
|
||||
.Sq X- .
|
||||
The following metadata properties can be exposed via the test case's head:
|
||||
.Bl -tag -width requireXmachineXX
|
||||
.It descr
|
||||
Type: textual.
|
||||
@ -275,6 +271,17 @@ test program.
|
||||
Can optionally be set to zero, in which case the test case has no run-time
|
||||
limit.
|
||||
This is discouraged.
|
||||
.It X- Ns Sq NAME
|
||||
Type: textual.
|
||||
Optional.
|
||||
.Pp
|
||||
A user-defined property named
|
||||
.Sq NAME .
|
||||
These properties are free form, have no special meaning within ATF, and can
|
||||
be specified at will by the test case.
|
||||
The runtime engine should propagate these properties from the test case to
|
||||
the end user so that the end user can rely on custom properties for test case
|
||||
tagging and classification.
|
||||
.El
|
||||
.Ss Environment
|
||||
Every time a test case is executed, several environment variables are
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user