This commit is contained in:
Oscar Zhao 2021-05-27 14:32:24 -04:00
commit f4cf3aa68b
18838 changed files with 1739396 additions and 990092 deletions

View File

@ -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"]
}

View File

@ -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

View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -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}

View File

@ -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}

View File

@ -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

File diff suppressed because it is too large Load Diff

82
README
View File

@ -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
View File

@ -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
View File

@ -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$

View File

@ -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,

View File

@ -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>

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -39,4 +39,6 @@ void trargs(char **);
void trputc(int);
void trputs(const char *);
void opentrace(void);
extern int debug;
#endif

View File

@ -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

View 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" ]

View File

@ -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 &&

View File

@ -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

View File

@ -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>

View File

@ -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;
}

View File

@ -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>

View File

@ -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

View File

@ -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));
}

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -41,7 +41,7 @@ f2(f func, int i)
}
int
main()
main(void)
{
f2(f1, 3);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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; \
}
/*

View File

@ -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) {
/*

View File

@ -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=

View File

@ -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

View File

@ -2,7 +2,7 @@
.PATH: ${SRCTOP}/sys/contrib/openzfs/module/icp
PACKAGE= runtime
PACKAGE= utilities
LIB= icp
LIBADD=

View File

@ -2,7 +2,7 @@
.PATH: ${SRCTOP}/sys/contrib/openzfs/module/icp
PACKAGE= runtime
PACKAGE= utilities
LIB= icp_rescue
LIBADD=

View File

@ -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>

View File

@ -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 \

View 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>

View File

@ -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
View 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
View File

@ -0,0 +1,9 @@
# $FreeBSD$
.include <src.opts.mk>
SUBDIR= compatibility.d
SUBDIR_PARALLEL=
.include <bsd.subdir.mk>

View 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>

View File

@ -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=

View File

@ -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
View 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
View 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
View 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

View File

@ -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
View 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.

View File

@ -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

View File

@ -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) \
{ \

View File

@ -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);

View File

@ -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)
{

View File

@ -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&);

View File

@ -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
View File

@ -0,0 +1 @@
defs.h

View File

@ -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
}

View File

@ -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)

View File

@ -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;

View File

@ -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
}

View File

@ -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) \
{ \

View File

@ -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);
}

View 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

View File

@ -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) */

View File

@ -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
View File

@ -0,0 +1,2 @@
atf-check
atf-sh

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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()
{

View File

@ -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
/*)

View File

@ -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
View File

@ -0,0 +1 @@
atf.7

View File

@ -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