diff options
93 files changed, 2087 insertions, 1581 deletions
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index faf7c421af80..a5e41d9ac6d6 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -51,6 +51,15 @@ # xargs -n1 | sort | uniq -d; # done +# 20250710: share: Delete bitrotted make_*_driver.sh scripts +OLD_FILES+=usr/share/examples/drivers/README +OLD_FILES+=usr/share/examples/drivers/make_device_driver.sh +OLD_FILES+=usr/share/examples/drivers/make_pseudo_driver.sh +OLD_DIRS+=usr/share/examples/drivers + +# 20250710: shar(1) removed +OLD_FILES+=usr/bin/shar + # 20250708: For 34 days 15.0-CURRENT installed libkadm5clnt symlink without .so OLD_FILES+=usr/lib/libkadm5clnt @@ -60,10 +69,6 @@ MOVED_LIBS+=usr/lib/libtpool.so.2 # 20250626: replace yaml.lua with lyaml OLD_FILES+=usr/share/flua/yaml.lua -# 20250623: fscandir() renamed to fdscandir() -OLD_FILES+=usr/share/man/man3/fscandir.3.gz -OLD_FILES+=usr/share/man/man3/fscandir_b.3.gz - # 20250615: don't install man page for absent function OLD_FILES+=usr/share/man/man9/vm_map_simplify_entry.9.gz @@ -27,6 +27,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 15.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".) +20250710: + The shar(1) utility has been removed from base. The + sysutils/freebsd-shar port was created to maintain this version of + shar(1) past its removal from base. + 20250704: LinuxKPI device.h and acpi changes effecting drivers and drm-kmod. Bump __FreeBSD_version 1500050 to be able to detect these changes. diff --git a/bin/cp/cp.1 b/bin/cp/cp.1 index 2856391a029e..5231fa72621c 100644 --- a/bin/cp/cp.1 +++ b/bin/cp/cp.1 @@ -29,7 +29,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 28, 2024 +.Dd July 9, 2025 .Dt CP 1 .Os .Sh NAME @@ -84,16 +84,16 @@ If the .Fl R option is specified, symbolic links on the command line are followed. (Symbolic links encountered in the tree traversal are not followed.) -.It Fl L +.It Fl L , Fl -dereference If the .Fl R option is specified, all symbolic links are followed. -.It Fl P +.It Fl P , Fl -no-dereference No symbolic links are followed. This is the default if the .Fl R option is specified. -.It Fl R +.It Fl R , Fl -recursive If .Ar source_file designates a directory, @@ -121,11 +121,11 @@ If you need to preserve hard links, consider using or .Xr pax 1 instead. -.It Fl a +.It Fl a , Fl -archive Archive mode. Same as .Fl RpP . -.It Fl f +.It Fl f , Fl -force For each existing destination pathname, remove it and create a new file, without prompting for confirmation regardless of its permissions. @@ -136,10 +136,8 @@ option overrides any previous or .Fl n options.) -.It Fl i -Cause -.Nm -to write a prompt to the standard error output before copying a file +.It Fl i , Fl -interactive +Write a prompt to the standard error output before copying a file that would overwrite an existing file. If the response from the standard input begins with the character .Sq Li y @@ -153,13 +151,13 @@ option overrides any previous or .Fl n options.) -.It Fl l +.It Fl l , Fl -link Create hard links to regular files in a hierarchy instead of copying. .It Fl N When used with .Fl p , suppress copying file flags. -.It Fl n +.It Fl n , Fl -no-clobber Do not overwrite an existing file. (The .Fl n @@ -169,9 +167,7 @@ or .Fl i options.) .It Fl p -Cause -.Nm -to preserve the following attributes of each source +Preserve the following attributes of each source file in the copy: modification time, access time, file flags, file mode, ACL, user ID, and group ID, as allowed by permissions. .Pp @@ -188,14 +184,25 @@ If the source file has both its set-user-ID and set-group-ID bits on, and either the user ID or group ID cannot be preserved, neither the set-user-ID nor set-group-ID bits are preserved in the copy's permissions. -.It Fl s -Create symbolic links to regular files in a hierarchy instead of copying. -.It Fl v -Cause +.It Fl -sort +Visit and traverse sources in (non-localized) lexicographical order. +Normally, .Nm -to be verbose, showing files as they are copied. -.It Fl x -File system mount points are not traversed. +visits the sources in the order they were listed on the command line, +and if recursing, traverses their contents in whichever order they +were returned in by the kernel, which may be the order in which they +were created, lexicographical order, or something else entirely. +With +.Fl -sort , +the sources are both visited and traversed in lexicographical order. +This is mostly useful for testing. +.It Fl s , Fl -symbolic-link +Create symbolic links to regular files in a hierarchy instead of copying. +.It Fl v , Fl -verbose +Be verbose, showing both the source and destination path of each file +as is copied. +.It Fl x , Fl -one-file-system +Do not traverse file system mount points. .El .Pp For each destination file that already exists, its contents are diff --git a/bin/cp/cp.c b/bin/cp/cp.c index 7e97715c3ef4..38fe65399d06 100644 --- a/bin/cp/cp.c +++ b/bin/cp/cp.c @@ -55,6 +55,7 @@ #include <errno.h> #include <fcntl.h> #include <fts.h> +#include <getopt.h> #include <limits.h> #include <signal.h> #include <stdbool.h> @@ -69,8 +70,8 @@ static char dot[] = "."; #define END(buf) (buf + sizeof(buf)) PATH_T to = { .dir = -1, .end = to.path }; -int Nflag, fflag, iflag, lflag, nflag, pflag, sflag, vflag; -static int Hflag, Lflag, Pflag, Rflag, rflag; +bool Nflag, fflag, iflag, lflag, nflag, pflag, sflag, vflag; +static bool Hflag, Lflag, Pflag, Rflag, rflag, Sflag; volatile sig_atomic_t info; enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE }; @@ -78,6 +79,27 @@ enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE }; static int copy(char *[], enum op, int, struct stat *); static void siginfo(int __unused); +enum { + SORT_OPT = CHAR_MAX, +}; + +static const struct option long_opts[] = +{ + { "archive", no_argument, NULL, 'a' }, + { "force", no_argument, NULL, 'f' }, + { "interactive", no_argument, NULL, 'i' }, + { "dereference", no_argument, NULL, 'L' }, + { "link", no_argument, NULL, 'l' }, + { "no-clobber", no_argument, NULL, 'n' }, + { "no-dereference", no_argument, NULL, 'P' }, + { "recursive", no_argument, NULL, 'R' }, + { "symbolic-link", no_argument, NULL, 's' }, + { "verbose", no_argument, NULL, 'v' }, + { "one-file-system", no_argument, NULL, 'x' }, + { "sort", no_argument, NULL, SORT_OPT }, + { 0 } +}; + int main(int argc, char *argv[]) { @@ -88,63 +110,67 @@ main(int argc, char *argv[]) bool have_trailing_slash = false; fts_options = FTS_NOCHDIR | FTS_PHYSICAL; - while ((ch = getopt(argc, argv, "HLPRafilNnprsvx")) != -1) + while ((ch = getopt_long(argc, argv, "+HLPRafilNnprsvx", long_opts, + NULL)) != -1) switch (ch) { case 'H': - Hflag = 1; - Lflag = Pflag = 0; + Hflag = true; + Lflag = Pflag = false; break; case 'L': - Lflag = 1; - Hflag = Pflag = 0; + Lflag = true; + Hflag = Pflag = false; break; case 'P': - Pflag = 1; - Hflag = Lflag = 0; + Pflag = true; + Hflag = Lflag = false; break; case 'R': - Rflag = 1; + Rflag = true; break; case 'a': - pflag = 1; - Rflag = 1; - Pflag = 1; - Hflag = Lflag = 0; + pflag = true; + Rflag = true; + Pflag = true; + Hflag = Lflag = false; break; case 'f': - fflag = 1; - iflag = nflag = 0; + fflag = true; + iflag = nflag = false; break; case 'i': - iflag = 1; - fflag = nflag = 0; + iflag = true; + fflag = nflag = false; break; case 'l': - lflag = 1; + lflag = true; break; case 'N': - Nflag = 1; + Nflag = true; break; case 'n': - nflag = 1; - fflag = iflag = 0; + nflag = true; + fflag = iflag = false; break; case 'p': - pflag = 1; + pflag = true; break; case 'r': - rflag = Lflag = 1; - Hflag = Pflag = 0; + rflag = Lflag = true; + Hflag = Pflag = false; break; case 's': - sflag = 1; + sflag = true; break; case 'v': - vflag = 1; + vflag = true; break; case 'x': fts_options |= FTS_XDEV; break; + case SORT_OPT: + Sflag = true; + break; default: usage(); } @@ -159,7 +185,7 @@ main(int argc, char *argv[]) if (lflag && sflag) errx(1, "the -l and -s options may not be specified together"); if (rflag) - Rflag = 1; + Rflag = true; if (Rflag) { if (Hflag) fts_options |= FTS_COMFOLLOW; @@ -263,6 +289,12 @@ main(int argc, char *argv[]) } static int +ftscmp(const FTSENT * const *a, const FTSENT * const *b) +{ + return (strcmp((*a)->fts_name, (*b)->fts_name)); +} + +static int copy(char *argv[], enum op type, int fts_options, struct stat *root_stat) { char rootname[NAME_MAX]; @@ -305,7 +337,7 @@ copy(char *argv[], enum op type, int fts_options, struct stat *root_stat) } level = FTS_ROOTLEVEL; - if ((ftsp = fts_open(argv, fts_options, NULL)) == NULL) + if ((ftsp = fts_open(argv, fts_options, Sflag ? ftscmp : NULL)) == NULL) err(1, "fts_open"); for (badcp = rval = 0; (curr = fts_read(ftsp)) != NULL; diff --git a/bin/cp/extern.h b/bin/cp/extern.h index c0c524756980..683e6e5f289f 100644 --- a/bin/cp/extern.h +++ b/bin/cp/extern.h @@ -37,7 +37,7 @@ typedef struct { } PATH_T; extern PATH_T to; -extern int Nflag, fflag, iflag, lflag, nflag, pflag, sflag, vflag; +extern bool Nflag, fflag, iflag, lflag, nflag, pflag, sflag, vflag; extern volatile sig_atomic_t info; __BEGIN_DECLS diff --git a/bin/cp/tests/cp_test.sh b/bin/cp/tests/cp_test.sh index 1d2cd4292459..999993bfad67 100755 --- a/bin/cp/tests/cp_test.sh +++ b/bin/cp/tests/cp_test.sh @@ -34,6 +34,10 @@ check_size() } atf_test_case basic +basic_head() +{ + atf_set "descr" "Copy a file" +} basic_body() { echo "foo" > bar @@ -43,18 +47,26 @@ basic_body() } atf_test_case basic_symlink +basic_symlink_head() +{ + atf_set "descr" "Copy a symlink to a file" +} basic_symlink_body() { echo "foo" > bar ln -s bar baz atf_check cp baz foo - atf_check test '!' -L foo + atf_check test ! -L foo atf_check cmp foo bar } atf_test_case chrdev +chrdev_head() +{ + atf_set "descr" "Copy a character device" +} chrdev_body() { echo "foo" > bar @@ -69,6 +81,10 @@ chrdev_body() } atf_test_case hardlink +hardlink_head() +{ + atf_set "descr" "Create a hard link to a file" +} hardlink_body() { echo "foo" >foo @@ -78,6 +94,11 @@ hardlink_body() } atf_test_case hardlink_exists +hardlink_exists_head() +{ + atf_set "descr" "Attempt to create a hard link to a file, " \ + "but the destination already exists" +} hardlink_exists_body() { echo "foo" >foo @@ -88,6 +109,11 @@ hardlink_exists_body() } atf_test_case hardlink_exists_force +hardlink_exists_force_head() +{ + atf_set "descr" "Force creation of a hard link to a file " \ + "when the destination already exists" +} hardlink_exists_force_body() { echo "foo" >foo @@ -98,9 +124,12 @@ hardlink_exists_force_body() } atf_test_case matching_srctgt +matching_srctgt_head() +{ + atf_set "descr" "Avoid infinite loop when copying a directory to itself" +} matching_srctgt_body() { - # PR235438: `cp -R foo foo` would previously infinitely recurse and # eventually error out. mkdir foo @@ -110,13 +139,17 @@ matching_srctgt_body() atf_check cp -R foo foo atf_check -o inline:"qux\n" cat foo/foo/bar atf_check -o inline:"qux\n" cat foo/foo/zoo - atf_check -e not-empty -s not-exit:0 stat foo/foo/foo + atf_check test ! -e foo/foo/foo } atf_test_case matching_srctgt_contained +matching_srctgt_contained_head() +{ + atf_set "descr" "Avoid infinite loop when copying a directory " \ + "into an existing subdirectory of itself" +} matching_srctgt_contained_body() { - # Let's do the same thing, except we'll try to recursively copy foo into # one of its subdirectories. mkdir foo @@ -142,9 +175,13 @@ matching_srctgt_contained_body() } atf_test_case matching_srctgt_link +matching_srctgt_link_head() +{ + atf_set "descr" "Avoid infinite loop when recursively copying a " \ + "symlink to a directory into the directory it links to" +} matching_srctgt_link_body() { - mkdir foo echo "qux" > foo/bar cp foo/bar foo/zoo @@ -156,9 +193,13 @@ matching_srctgt_link_body() } atf_test_case matching_srctgt_nonexistent +matching_srctgt_nonexistent_head() +{ + atf_set "descr" "Avoid infinite loop when recursively copying a " \ + "directory into a new subdirectory of itself" +} matching_srctgt_nonexistent_body() { - # We'll copy foo to a nonexistent subdirectory; ideally, we would # skip just the directory and end up with a layout like; # @@ -180,6 +221,10 @@ matching_srctgt_nonexistent_body() } atf_test_case pflag_acls +pflag_acls_head() +{ + atf_set "descr" "Verify that -p preserves access control lists" +} pflag_acls_body() { mkdir dir @@ -216,6 +261,10 @@ pflag_acls_body() } atf_test_case pflag_flags +pflag_flags_head() +{ + atf_set "descr" "Verify that -p preserves file flags" +} pflag_flags_body() { mkdir dir @@ -263,6 +312,11 @@ recursive_link_setup() } atf_test_case recursive_link_dflt +recursive_link_dflt_head() +{ + atf_set "descr" "Copy a directory containing a subdirectory and a " \ + "symlink to that subdirectory" +} recursive_link_dflt_body() { recursive_link_setup @@ -270,9 +324,15 @@ recursive_link_dflt_body() # -P is the default, so this should work and preserve the link. atf_check cp -R foo foo-mirror atf_check test -L foo-mirror/foo/baz + atf_check test -d foo-mirror/foo/baz } atf_test_case recursive_link_Hflag +recursive_link_Hflag_head() +{ + atf_set "descr" "Copy a directory containing a subdirectory and a " \ + "symlink to that subdirectory" +} recursive_link_Hflag_body() { recursive_link_setup @@ -281,22 +341,32 @@ recursive_link_Hflag_body() # link. atf_check cp -RH foo foo-mirror atf_check test -L foo-mirror/foo/baz + atf_check test -d foo-mirror/foo/baz } atf_test_case recursive_link_Lflag +recursive_link_Lflag_head() +{ + atf_set "descr" "Copy a directory containing a subdirectory and a " \ + "symlink to that subdirectory" +} recursive_link_Lflag_body() { recursive_link_setup -L # -L will work, but foo/baz ends up expanded to a directory. - atf_check test -d foo-mirror/foo/baz -a \ - '(' ! -L foo-mirror/foo/baz ')' + atf_check test ! -L foo-mirror/foo/baz + atf_check test -d foo-mirror/foo/baz atf_check cp -RL foo foo-mirror - atf_check test -d foo-mirror/foo/baz -a \ - '(' ! -L foo-mirror/foo/baz ')' + atf_check test ! -L foo-mirror/foo/baz + atf_check test -d foo-mirror/foo/baz } atf_test_case samefile +samefile_head() +{ + atf_set "descr" "Copy a file to itself" +} samefile_body() { echo "foo" >foo @@ -324,6 +394,10 @@ files_are_equal() } atf_test_case sparse_leading_hole +sparse_leading_hole_head() +{ + atf_set "descr" "Copy a sparse file stat starts with a hole" +} sparse_leading_hole_body() { # A 16-megabyte hole followed by one megabyte of data @@ -337,6 +411,10 @@ sparse_leading_hole_body() } atf_test_case sparse_multiple_holes +sparse_multiple_hole_head() +{ + atf_set "descr" "Copy a sparse file with multiple holes" +} sparse_multiple_holes_body() { # Three one-megabyte blocks of data preceded, separated, and @@ -356,6 +434,10 @@ sparse_multiple_holes_body() } atf_test_case sparse_only_hole +sparse_only_hole_head() +{ + atf_set "descr" "Copy a sparse file consisting entirely of a hole" +} sparse_only_hole_body() { # A 16-megabyte hole @@ -368,6 +450,10 @@ sparse_only_hole_body() } atf_test_case sparse_to_dev +sparse_to_dev_head() +{ + atf_set "descr" "Copy a sparse file to a device" +} sparse_to_dev_body() { # Three one-megabyte blocks of data preceded, separated, and @@ -385,6 +471,10 @@ sparse_to_dev_body() } atf_test_case sparse_trailing_hole +sparse_trailing_hole_head() +{ + atf_set "descr" "Copy a sparse file that ends with a hole" +} sparse_trailing_hole_body() { # One megabyte of data followed by a 16-megabyte hole @@ -398,16 +488,24 @@ sparse_trailing_hole_body() } atf_test_case standalone_Pflag +standalone_Pflag_head() +{ + atf_set "descr" "Test -P without -R" +} standalone_Pflag_body() { echo "foo" > bar ln -s bar foo atf_check cp -P foo baz - atf_check -o inline:'Symbolic Link\n' stat -f %SHT baz + atf_check test -L baz } atf_test_case symlink +symlink_head() +{ + atf_set "descr" "Create a symbolic link to a file" +} symlink_body() { echo "foo" >foo @@ -417,6 +515,11 @@ symlink_body() } atf_test_case symlink_exists +symlink_exists_head() +{ + atf_set "descr" "Attempt to create a symbolic link to a file, " \ + "but the destination already exists" +} symlink_exists_body() { echo "foo" >foo @@ -426,6 +529,11 @@ symlink_exists_body() } atf_test_case symlink_exists_force +symlink_exists_force_head() +{ + atf_set "descr" "Force creation of a symbolic link to a file " \ + "when the destination already exists" +} symlink_exists_force_body() { echo "foo" >foo @@ -436,6 +544,10 @@ symlink_exists_force_body() } atf_test_case directory_to_symlink +directory_to_symlink_head() +{ + atf_set "descr" "Attempt to copy a directory to a symlink" +} directory_to_symlink_body() { mkdir -p foo @@ -449,6 +561,10 @@ directory_to_symlink_body() } atf_test_case overwrite_directory +overwrite_directory_head() +{ + atf_set "descr" "Attempt to overwrite a directory with a file" +} overwrite_directory_body() { mkdir -p foo/bar/baz @@ -465,6 +581,10 @@ overwrite_directory_body() } atf_test_case to_dir_dne +to_dir_dne_head() +{ + atf_set "descr" "Copy a directory to a nonexistent directory" +} to_dir_dne_body() { mkdir dir @@ -476,6 +596,10 @@ to_dir_dne_body() } atf_test_case to_nondir +to_dir_dne_head() +{ + atf_set "descr" "Copy one or more files to a non-directory" +} to_nondir_body() { echo "foo" >foo @@ -490,6 +614,10 @@ to_nondir_body() } atf_test_case to_deadlink +to_deadlink_head() +{ + atf_set "descr" "Copy a file to a dead symbolic link" +} to_deadlink_body() { echo "foo" >foo @@ -499,6 +627,10 @@ to_deadlink_body() } atf_test_case to_deadlink_append +to_deadlink_append_head() +{ + atf_set "descr" "Copy multiple files to a dead symbolic link" +} to_deadlink_append_body() { echo "foo" >foo @@ -517,6 +649,10 @@ to_deadlink_append_body() } atf_test_case to_dirlink +to_dirlink_head() +{ + atf_set "descr" "Copy things to a symbolic link to a directory" +} to_dirlink_body() { mkdir src dir @@ -542,6 +678,11 @@ to_dirlink_body() } atf_test_case to_deaddirlink +to_deaddirlink_head() +{ + atf_set "descr" "Copy things to a symbolic link to a nonexistent " \ + "directory" +} to_deaddirlink_body() { mkdir src @@ -572,6 +713,11 @@ to_deaddirlink_body() } atf_test_case to_link_outside +to_link_outside_head() +{ + atf_set "descr" "Recursively copy a directory containing a symbolic " \ + "link that points to somewhere outside the source directory" +} to_link_outside_body() { mkdir dir dst dst/dir @@ -584,6 +730,11 @@ to_link_outside_body() } atf_test_case dstmode +dstmode_head() +{ + atf_set "descr" "Verify that directories are created with the " \ + "correct permissions" +} dstmode_body() { mkdir -m 0755 dir @@ -646,6 +797,7 @@ atf_test_case unrdir unrdir_head() { atf_set "descr" "Test handling of unreadable directories" + atf_set "require.user" "unprivileged" } unrdir_body() { @@ -657,7 +809,7 @@ unrdir_body() atf_check \ -s exit:1 \ -e match:"^cp: src/b: Permission denied" \ - cp -R src dst + cp -R --sort src dst atf_check test -d dst/a atf_check cmp src/a/f dst/a/f atf_check test -d dst/b @@ -670,6 +822,7 @@ atf_test_case unrfile unrfile_head() { atf_set "descr" "Test handling of unreadable files" + atf_set "require.user" "unprivileged" } unrfile_body() { @@ -681,13 +834,28 @@ unrfile_body() atf_check \ -s exit:1 \ -e match:"^cp: src/b: Permission denied" \ - cp -R src dst + cp -R --sort src dst atf_check test -d dst atf_check cmp src/a dst/a atf_check test ! -e dst/b atf_check cmp src/c dst/c } +atf_test_case nopermute +nopermute_head() +{ + atf_set descr "Check that getopt_long does not permute options" +} +nopermute_body() +{ + mkdir src dst + atf_check \ + -s exit:1 \ + -e match:'cp: -p: No such file' \ + cp -R src -p dst + atf_check test -d dst/src +} + atf_init_test_cases() { atf_add_test_case basic @@ -729,4 +897,5 @@ atf_init_test_cases() atf_add_test_case dirloop atf_add_test_case unrdir atf_add_test_case unrfile + atf_add_test_case nopermute } diff --git a/bin/cp/utils.c b/bin/cp/utils.c index cfc0f0f12603..2036056ada68 100644 --- a/bin/cp/utils.c +++ b/bin/cp/utils.c @@ -105,7 +105,7 @@ copy_file(const FTSENT *entp, bool dne, bool beneath) ssize_t wcount; off_t wtotal; int ch, checkch, from_fd, rval, to_fd; - int use_copy_file_range = 1; + bool use_copy_file_range = true; fs = entp->fts_statp; from_fd = to_fd = -1; @@ -210,7 +210,7 @@ copy_file(const FTSENT *entp, bool dne, bool beneath) to_fd, NULL, SSIZE_MAX, 0); if (wcount < 0 && errno == EINVAL) { /* probably a non-seekable descriptor */ - use_copy_file_range = 0; + use_copy_file_range = false; } } if (!use_copy_file_range) { diff --git a/contrib/kyua/utils/fs/operations.cpp b/contrib/kyua/utils/fs/operations.cpp index 7a96d0b2058a..185d164b88d7 100644 --- a/contrib/kyua/utils/fs/operations.cpp +++ b/contrib/kyua/utils/fs/operations.cpp @@ -692,6 +692,7 @@ fs::rm_r(const fs::path& directory) { const fs::directory dir(directory); + ::chmod(directory.c_str(), 0700); for (fs::directory::const_iterator iter = dir.begin(); iter != dir.end(); ++iter) { if (iter->name == "." || iter->name == "..") @@ -701,6 +702,7 @@ fs::rm_r(const fs::path& directory) if (fs::is_directory(entry)) { LD(F("Descending into %s") % entry); + ::chmod(entry.c_str(), 0700); fs::rm_r(entry); } else { LD(F("Removing file %s") % entry); diff --git a/contrib/kyua/utils/fs/operations_test.cpp b/contrib/kyua/utils/fs/operations_test.cpp index f1349351166e..6f0fa52811c9 100644 --- a/contrib/kyua/utils/fs/operations_test.cpp +++ b/contrib/kyua/utils/fs/operations_test.cpp @@ -664,6 +664,19 @@ ATF_TEST_CASE_BODY(rm_r__files_and_directories) } +ATF_TEST_CASE_WITHOUT_HEAD(rm_r__bad_perms); +ATF_TEST_CASE_BODY(rm_r__bad_perms) +{ + fs::mkdir(fs::path("root"), 0755); + fs::mkdir(fs::path("root/dir"), 0755); + atf::utils::create_file("root/dir/file", ""); + ::chmod(fs::path("root/dir").c_str(), 0000); + ATF_REQUIRE(lookup(".", "root", S_IFDIR)); + fs::rm_r(fs::path("root")); + ATF_REQUIRE(!lookup(".", "root", S_IFDIR)); +} + + ATF_TEST_CASE_WITHOUT_HEAD(rmdir__ok) ATF_TEST_CASE_BODY(rmdir__ok) { @@ -811,6 +824,7 @@ ATF_INIT_TEST_CASES(tcs) ATF_ADD_TEST_CASE(tcs, rm_r__empty); ATF_ADD_TEST_CASE(tcs, rm_r__files_and_directories); + ATF_ADD_TEST_CASE(tcs, rm_r__bad_perms); ATF_ADD_TEST_CASE(tcs, rmdir__ok); ATF_ADD_TEST_CASE(tcs, rmdir__fail); diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index 50dbf3425964..26f638568efc 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -458,8 +458,6 @@ FBSD_1.8 { aio_read2; aio_write2; execvpe; - fscandir; - fscandir_b; fdscandir; fdscandir_b; fts_open_b; @@ -598,7 +596,6 @@ FBSDprivate_1.0 { __libc_tcdrain; - __pthread_distribute_static_tls; __pthread_map_stacks_exec; __fillcontextx; __fillcontextx2; diff --git a/lib/libc/gen/elf_utils.c b/lib/libc/gen/elf_utils.c index 330aa8f17f7e..3714a0dc42b5 100644 --- a/lib/libc/gen/elf_utils.c +++ b/lib/libc/gen/elf_utils.c @@ -41,7 +41,6 @@ #include "libc_private.h" void __pthread_map_stacks_exec(void); -void __pthread_distribute_static_tls(size_t, void *, size_t, size_t); int __elf_phdr_match_addr(struct dl_phdr_info *phdr_info, void *addr) @@ -105,28 +104,3 @@ __pthread_map_stacks_exec(void) ((void (*)(void))__libc_interposing[INTERPOS_map_stacks_exec])(); } - -void -__libc_distribute_static_tls(size_t offset, void *src, size_t len, - size_t total_len) -{ - char *tlsbase; - -#ifdef TLS_VARIANT_I - tlsbase = (char *)_tcb_get() + offset; -#else - tlsbase = (char *)_tcb_get() - offset; -#endif - memcpy(tlsbase, src, len); - memset(tlsbase + len, 0, total_len - len); -} - -#pragma weak __pthread_distribute_static_tls -void -__pthread_distribute_static_tls(size_t offset, void *src, size_t len, - size_t total_len) -{ - - ((void (*)(size_t, void *, size_t, size_t))__libc_interposing[ - INTERPOS_distribute_static_tls])(offset, src, len, total_len); -} diff --git a/lib/libc/gen/gen-private.h b/lib/libc/gen/gen-private.h index 3792a61ff942..b6749b3435cd 100644 --- a/lib/libc/gen/gen-private.h +++ b/lib/libc/gen/gen-private.h @@ -43,8 +43,8 @@ struct pthread_mutex; */ struct _dirdesc { int dd_fd; /* file descriptor associated with directory */ - long dd_loc; /* offset in current buffer */ - long dd_size; /* amount of data returned by getdirentries */ + size_t dd_loc; /* offset in current buffer */ + size_t dd_size; /* amount of data returned by getdirentries */ char *dd_buf; /* data buffer */ int dd_len; /* size of data buffer */ off_t dd_seek; /* magic cookie returned by getdirentries */ diff --git a/lib/libc/gen/libc_interposing_table.c b/lib/libc/gen/libc_interposing_table.c index 8eae6c7f5d95..025a67ac3eac 100644 --- a/lib/libc/gen/libc_interposing_table.c +++ b/lib/libc/gen/libc_interposing_table.c @@ -42,7 +42,6 @@ interpos_func_t __libc_interposing[INTERPOS_MAX] = { SLOT(spinlock, __libc_spinlock_stub), SLOT(spinunlock, __libc_spinunlock_stub), SLOT(map_stacks_exec, __libc_map_stacks_exec), - SLOT(distribute_static_tls, __libc_distribute_static_tls), SLOT(uexterr_gettext, __libc_uexterr_gettext), }; #undef SLOT diff --git a/lib/libc/gen/opendir2.c b/lib/libc/gen/opendir2.c index 928145b468c1..c5c2e662efd8 100644 --- a/lib/libc/gen/opendir2.c +++ b/lib/libc/gen/opendir2.c @@ -264,6 +264,7 @@ DIR * __opendir_common(int fd, int flags, bool use_current_pos) { DIR *dirp; + ssize_t ret; int incr; int saved_errno; bool unionstack; @@ -313,13 +314,11 @@ __opendir_common(int fd, int flags, bool use_current_pos) * to prime dd_seek. This also checks if the * fd passed to fdopendir() is a directory. */ - dirp->dd_size = _getdirentries(dirp->dd_fd, + ret = _getdirentries(dirp->dd_fd, dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); - if (dirp->dd_size < 0) { - if (errno == EINVAL) - errno = ENOTDIR; + if (ret < 0) goto fail; - } + dirp->dd_size = (size_t)ret; dirp->dd_flags |= __DTF_SKIPREAD; } else { dirp->dd_size = 0; diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c index 2a2fa999b7ce..b70102954df1 100644 --- a/lib/libc/gen/readdir.c +++ b/lib/libc/gen/readdir.c @@ -48,8 +48,9 @@ struct dirent * _readdir_unlocked(DIR *dirp, int flags) { struct dirent *dp; - long initial_seek; - long initial_loc = 0; + off_t initial_seek; + size_t initial_loc = 0; + ssize_t ret; for (;;) { if (dirp->dd_loc >= dirp->dd_size) { @@ -61,11 +62,13 @@ _readdir_unlocked(DIR *dirp, int flags) } if (dirp->dd_loc == 0 && !(dirp->dd_flags & (__DTF_READALL | __DTF_SKIPREAD))) { + dirp->dd_size = 0; initial_seek = dirp->dd_seek; - dirp->dd_size = _getdirentries(dirp->dd_fd, + ret = _getdirentries(dirp->dd_fd, dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); - if (dirp->dd_size <= 0) + if (ret <= 0) return (NULL); + dirp->dd_size = (size_t)ret; _fixtelldir(dirp, initial_seek, initial_loc); } dirp->dd_flags &= ~__DTF_SKIPREAD; diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c index 8e62fe980868..fb589f4b36b6 100644 --- a/lib/libc/gen/scandir.c +++ b/lib/libc/gen/scandir.c @@ -252,9 +252,3 @@ scandir_thunk_cmp(const void *p1, const void *p2, void *thunk) return (dc((const struct dirent **)p1, (const struct dirent **)p2)); } #endif - -#ifdef I_AM_SCANDIR_B -__weak_reference(fdscandir_b, fscandir_b); -#else -__weak_reference(fdscandir, fscandir); -#endif diff --git a/lib/libc/gen/telldir.c b/lib/libc/gen/telldir.c index b751fafd975f..1731cc4d7a2c 100644 --- a/lib/libc/gen/telldir.c +++ b/lib/libc/gen/telldir.c @@ -118,7 +118,7 @@ _seekdir(DIR *dirp, long loc) struct dirent *dp; union ddloc_packed ddloc; off_t loc_seek; - long loc_loc; + size_t loc_loc; ddloc.l = loc; @@ -171,7 +171,7 @@ _seekdir(DIR *dirp, long loc) * fetching a new block to fix any such telldir locations. */ void -_fixtelldir(DIR *dirp, long oldseek, long oldloc) +_fixtelldir(DIR *dirp, off_t oldseek, size_t oldloc) { struct ddloc_mem *lp; diff --git a/lib/libc/gen/telldir.h b/lib/libc/gen/telldir.h index 6d113491e819..02fd52af9060 100644 --- a/lib/libc/gen/telldir.h +++ b/lib/libc/gen/telldir.h @@ -46,9 +46,9 @@ */ struct ddloc_mem { LIST_ENTRY(ddloc_mem) loc_lqe; /* entry in list */ - long loc_index; /* key associated with structure */ + size_t loc_index; /* key associated with structure */ off_t loc_seek; /* magic cookie returned by getdirentries */ - long loc_loc; /* offset of entry in buffer */ + size_t loc_loc; /* offset of entry in buffer */ }; #ifdef __LP64__ @@ -102,7 +102,7 @@ bool _filldir(DIR *, bool); struct dirent *_readdir_unlocked(DIR *, int); void _reclaim_telldir(DIR *); void _seekdir(DIR *, long); -void _fixtelldir(DIR *dirp, long oldseek, long oldloc); +void _fixtelldir(DIR *dirp, off_t oldseek, size_t oldloc); DIR *__opendir_common(int, int, bool); #define RDU_SKIP 0x0001 diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h index 1bc22f3931a5..db4cbc32be35 100644 --- a/lib/libc/include/libc_private.h +++ b/lib/libc/include/libc_private.h @@ -249,7 +249,7 @@ enum { INTERPOS_map_stacks_exec, INTERPOS_fdatasync, INTERPOS_clock_nanosleep, - INTERPOS_distribute_static_tls, + INTERPOS__reserved0, /* was distribute_static_tls */ INTERPOS_pdfork, INTERPOS_uexterr_gettext, INTERPOS_MAX @@ -361,8 +361,6 @@ struct dl_phdr_info; int __elf_phdr_match_addr(struct dl_phdr_info *, void *); void __init_elf_aux_vector(void); void __libc_map_stacks_exec(void); -void __libc_distribute_static_tls(__size_t, void *, __size_t, __size_t); -__uintptr_t __libc_static_tls_base(__size_t); void _pthread_cancel_enter(int); void _pthread_cancel_leave(int); diff --git a/lib/libc/tests/gen/opendir_test.c b/lib/libc/tests/gen/opendir_test.c index 89be2becc607..b7481255654f 100644 --- a/lib/libc/tests/gen/opendir_test.c +++ b/lib/libc/tests/gen/opendir_test.c @@ -46,6 +46,7 @@ opendir_check(const struct atf_tc *tc, DIR *dirp) ATF_CHECK_STREQ("subdir", ent->d_name); ATF_CHECK_EQ(DT_DIR, ent->d_type); ATF_CHECK(readdir(dirp) == NULL); + ATF_CHECK(readdir(dirp) == NULL); } ATF_TC(opendir_ok); diff --git a/lib/libc/tests/gen/scandir_test.c b/lib/libc/tests/gen/scandir_test.c index f7b52b5e3616..afd25bf7c0b2 100644 --- a/lib/libc/tests/gen/scandir_test.c +++ b/lib/libc/tests/gen/scandir_test.c @@ -157,7 +157,7 @@ ATF_TC_BODY(scandir_error, tc) { char path[16]; struct dirent **namelist = NULL; - int fd, i, ret; + int fd, i; ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); for (i = 0; i < 1024; i++) { @@ -170,9 +170,8 @@ ATF_TC_BODY(scandir_error, tc) scandir_error_count = 0; scandir_error_fd = fd; scandir_error_select_return = 0; - ret = fdscandir(fd, &namelist, scandir_error_select, NULL); - ATF_CHECK_EQ(-1, ret); - ATF_CHECK_ERRNO(EBADF, ret < 0); + ATF_CHECK_ERRNO(EBADF, + fdscandir(fd, &namelist, scandir_error_select, NULL) < 0); ATF_CHECK_EQ(NULL, namelist); /* second pass, select everything */ @@ -180,9 +179,8 @@ ATF_TC_BODY(scandir_error, tc) scandir_error_count = 0; scandir_error_fd = fd; scandir_error_select_return = 1; - ret = fdscandir(fd, &namelist, scandir_error_select, NULL); - ATF_CHECK_EQ(-1, ret); - ATF_CHECK_ERRNO(EBADF, ret < 0); + ATF_CHECK_ERRNO(EBADF, + fdscandir(fd, &namelist, scandir_error_select, NULL) < 0); ATF_CHECK_EQ(NULL, namelist); } diff --git a/lib/libsys/getdirentries.2 b/lib/libsys/getdirentries.2 index 0e5840ce25cd..202ae133f548 100644 --- a/lib/libsys/getdirentries.2 +++ b/lib/libsys/getdirentries.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd September 5, 2023 +.Dd July 8, 2025 .Dt GETDIRENTRIES 2 .Os .Sh NAME @@ -178,9 +178,7 @@ or non-NULL .Fa basep point outside the allocated address space. .It Bq Er EINVAL -The file referenced by -.Fa fd -is not a directory, or +The value of .Fa nbytes is too small for returning a directory entry or block of entries, or the current position pointer is invalid. @@ -192,6 +190,10 @@ error occurred while reading from or writing to the file system. Corrupted data was detected while reading from the file system. .It Bq Er ENOENT Directory unlinked but still open. +.It Bq Er ENOTDIR +The file referenced by +.Fa fd +is not a directory. .El .Sh SEE ALSO .Xr lseek 2 , diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map index 1c8dde03367b..3a5353a32dc3 100644 --- a/lib/libthr/pthread.map +++ b/lib/libthr/pthread.map @@ -136,7 +136,6 @@ FBSDprivate_1.0 { __pthread_mutex_lock; __pthread_mutex_timedlock; __pthread_mutex_trylock; - __pthread_distribute_static_tls; _pthread_atfork; _pthread_barrier_destroy; _pthread_barrier_init; diff --git a/lib/libthr/thread/thr_list.c b/lib/libthr/thread/thr_list.c index 820766f6f5e0..cbf16179f619 100644 --- a/lib/libthr/thread/thr_list.c +++ b/lib/libthr/thread/thr_list.c @@ -363,41 +363,3 @@ _thr_find_thread(struct pthread *curthread, struct pthread *thread, THREAD_LIST_UNLOCK(curthread); return (ret); } - -static void -thr_distribute_static_tls(char *tlsbase, void *src, size_t len, - size_t total_len) -{ - - memcpy(tlsbase, src, len); - memset(tlsbase + len, 0, total_len - len); -} - -void -__pthread_distribute_static_tls(size_t offset, void *src, size_t len, - size_t total_len) -{ - struct pthread *curthread, *thrd; - char *tlsbase; - - if (!_thr_is_inited()) { -#ifdef TLS_VARIANT_I - tlsbase = (char *)_tcb_get() + offset; -#else - tlsbase = (char *)_tcb_get() - offset; -#endif - thr_distribute_static_tls(tlsbase, src, len, total_len); - return; - } - curthread = _get_curthread(); - THREAD_LIST_RDLOCK(curthread); - TAILQ_FOREACH(thrd, &_thread_list, tle) { -#ifdef TLS_VARIANT_I - tlsbase = (char *)thrd->tcb + offset; -#else - tlsbase = (char *)thrd->tcb - offset; -#endif - thr_distribute_static_tls(tlsbase, src, len, total_len); - } - THREAD_LIST_UNLOCK(curthread); -} diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index bca890829057..d7b889930365 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -986,8 +986,6 @@ void __pthread_cxa_finalize(struct dl_phdr_info *phdr_info); void _thr_tsd_unload(struct dl_phdr_info *phdr_info) __hidden; void _thr_sigact_unload(struct dl_phdr_info *phdr_info) __hidden; void _thr_stack_fix_protection(struct pthread *thrd); -void __pthread_distribute_static_tls(size_t offset, void *src, size_t len, - size_t total_len); int *__error_threaded(void) __hidden; void __thr_interpose_libc(void) __hidden; diff --git a/lib/libusb/libusb.3 b/lib/libusb/libusb.3 index a9a99f307a86..74b85d4aa17e 100644 --- a/lib/libusb/libusb.3 +++ b/lib/libusb/libusb.3 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 12, 2025 +.Dd June 13, 2025 .Dt LIBUSB 3 .Os .Sh NAME @@ -106,6 +106,19 @@ Get the ASCII representation of the error given by the argument. This function does not return NULL. .Pp +.Ft int +.Fn libusb_setlocale "const char *locale" +Set locale for the error message when using +.Fn libusb_strerror +to +.Ft locale . +Note other +.Nm +implementations only support the first two bytes, that means +.Ql en-US +is equivalent to +.Ql en-CA . +.Pp .Ft const char * .Fn libusb_error_name "int code" Get the ASCII representation of the error enum given by the diff --git a/lib/libusb/libusb.h b/lib/libusb/libusb.h index 17d341d1b91c..6fb1c19fad13 100644 --- a/lib/libusb/libusb.h +++ b/lib/libusb/libusb.h @@ -210,6 +210,8 @@ enum libusb_error { LIBUSB_ERROR_OTHER = -99, }; +#define LIBUSB_ERROR_COUNT 14 + enum libusb_speed { LIBUSB_SPEED_UNKNOWN = 0, LIBUSB_SPEED_LOW = 1, @@ -475,6 +477,7 @@ int libusb_init(libusb_context ** context); int libusb_init_context(libusb_context **, const struct libusb_init_option [], int num_options); void libusb_exit(struct libusb_context *ctx); int libusb_has_capability(uint32_t capability); +int libusb_setlocale(const char *locale); /* Device handling and enumeration */ diff --git a/lib/libusb/libusb10.c b/lib/libusb/libusb10.c index 173f51aa88b3..6f1ca877fc28 100644 --- a/lib/libusb/libusb10.c +++ b/lib/libusb/libusb10.c @@ -4,6 +4,7 @@ * Copyright (c) 2009 Sylvestre Gallon. All rights reserved. * Copyright (c) 2009-2023 Hans Petter Selasky * Copyright (c) 2024 Aymeric Wibo + * Copyright (c) 2025 ShengYi Hung * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,6 +32,7 @@ #include LIBUSB_GLOBAL_INCLUDE_FILE #else #include <assert.h> +#include <ctype.h> #include <errno.h> #include <poll.h> #include <pthread.h> @@ -84,6 +86,52 @@ static const struct libusb_version libusb_version = { .describe = "https://www.freebsd.org" }; +static const struct libusb_language_context libusb_language_ctx[] = { + { + .lang_name = "en", + .err_strs = { + [-LIBUSB_SUCCESS] = "Success", + [-LIBUSB_ERROR_IO] = "I/O error", + [-LIBUSB_ERROR_INVALID_PARAM] = "Invalid parameter", + [-LIBUSB_ERROR_ACCESS] = "Permissions error", + [-LIBUSB_ERROR_NO_DEVICE] = "No device", + [-LIBUSB_ERROR_NOT_FOUND] = "Not found", + [-LIBUSB_ERROR_BUSY] = "Device busy", + [-LIBUSB_ERROR_TIMEOUT] = "Timeout", + [-LIBUSB_ERROR_OVERFLOW] = "Overflow", + [-LIBUSB_ERROR_PIPE] = "Pipe error", + [-LIBUSB_ERROR_INTERRUPTED] = "Interrupted", + [-LIBUSB_ERROR_NO_MEM] = "Out of memory", + [-LIBUSB_ERROR_NOT_SUPPORTED] ="Not supported", + [LIBUSB_ERROR_COUNT - 1] = "Other error", + [LIBUSB_ERROR_COUNT] = "Unknown error", + } + }, + { + .lang_name = "zh", + .err_strs = { + [-LIBUSB_SUCCESS] = "成功", + [-LIBUSB_ERROR_IO] = "I/O 錯誤", + [-LIBUSB_ERROR_INVALID_PARAM] = "不合法的參數", + [-LIBUSB_ERROR_ACCESS] = "權限錯誤", + [-LIBUSB_ERROR_NO_DEVICE] = "裝置不存在", + [-LIBUSB_ERROR_NOT_FOUND] = "不存在", + [-LIBUSB_ERROR_BUSY] = "裝置忙碌中", + [-LIBUSB_ERROR_TIMEOUT] = "逾時", + [-LIBUSB_ERROR_OVERFLOW] = "溢位", + [-LIBUSB_ERROR_PIPE] = "管道錯誤", + [-LIBUSB_ERROR_INTERRUPTED] = "被中斷", + [-LIBUSB_ERROR_NO_MEM] = "記憶體不足", + [-LIBUSB_ERROR_NOT_SUPPORTED] ="不支援", + [LIBUSB_ERROR_COUNT - 1] = "其他錯誤", + [LIBUSB_ERROR_COUNT] = "未知錯誤", + } + }, +}; + +static const struct libusb_language_context *default_language_context = + &libusb_language_ctx[0]; + const struct libusb_version * libusb_get_version(void) { @@ -1728,38 +1776,26 @@ libusb_le16_to_cpu(uint16_t x) const char * libusb_strerror(int code) { - switch (code) { - case LIBUSB_SUCCESS: - return ("Success"); - case LIBUSB_ERROR_IO: - return ("I/O error"); - case LIBUSB_ERROR_INVALID_PARAM: - return ("Invalid parameter"); - case LIBUSB_ERROR_ACCESS: - return ("Permissions error"); - case LIBUSB_ERROR_NO_DEVICE: - return ("No device"); - case LIBUSB_ERROR_NOT_FOUND: - return ("Not found"); - case LIBUSB_ERROR_BUSY: - return ("Device busy"); - case LIBUSB_ERROR_TIMEOUT: - return ("Timeout"); - case LIBUSB_ERROR_OVERFLOW: - return ("Overflow"); - case LIBUSB_ERROR_PIPE: - return ("Pipe error"); - case LIBUSB_ERROR_INTERRUPTED: - return ("Interrupted"); - case LIBUSB_ERROR_NO_MEM: - return ("Out of memory"); - case LIBUSB_ERROR_NOT_SUPPORTED: - return ("Not supported"); - case LIBUSB_ERROR_OTHER: - return ("Other error"); - default: - return ("Unknown error"); - } + int entry = -code; + + if (code == LIBUSB_ERROR_OTHER) + entry = LIBUSB_ERROR_COUNT - 1; + /* + * The libusb upstream considers all code out of range a + * LIBUSB_ERROR_OTHER. In FreeBSD, it is a special unknown error. We + * preserve the FreeBSD implementation as I think it make sense. + */ + if (entry < 0 || entry >= LIBUSB_ERROR_COUNT) + entry = LIBUSB_ERROR_COUNT; + + /* + * Fall back to English one as the translation may be unimplemented + * when adding new error code. + */ + if (default_language_context->err_strs[entry] == NULL) + return (libusb_language_ctx[0].err_strs[entry]); + + return (default_language_context->err_strs[entry]); } const char * @@ -1842,3 +1878,29 @@ libusb_log_va_args(struct libusb_context *ctx, enum libusb_log_level level, va_end(args); } + +/* + * Upstream code actually recognizes the first two characters to identify a + * language. We do so to provide API compatibility with setlocale. + */ +int +libusb_setlocale(const char *locale) +{ + size_t idx; + const char *lang; + + if (locale == NULL || strlen(locale) < 2 || + (locale[2] != '\0' && strchr("-_.", locale[2]) == NULL)) + return (LIBUSB_ERROR_INVALID_PARAM); + + for (idx = 0; idx < nitems(libusb_language_ctx); ++idx) { + lang = libusb_language_ctx[idx].lang_name; + if (tolower(locale[0]) == lang[0] && + tolower(locale[1]) == lang[1]) { + default_language_context = &libusb_language_ctx[idx]; + return (LIBUSB_SUCCESS); + } + } + + return (LIBUSB_ERROR_INVALID_PARAM); +} diff --git a/lib/libusb/libusb10.h b/lib/libusb/libusb10.h index 9ad08edf075b..eced364ef857 100644 --- a/lib/libusb/libusb10.h +++ b/lib/libusb/libusb10.h @@ -139,6 +139,12 @@ struct libusb_device { struct libusb20_device *os_priv; }; +struct libusb_language_context { + const char *lang_name; + /* All error Plus 1 UNKNOWN */ + const char *err_strs[LIBUSB_ERROR_COUNT + 1]; +}; + extern struct libusb_context *usbi_default_context; void libusb10_add_pollfd(libusb_context *ctx, struct libusb_super_pollfd *pollfd, struct libusb20_device *pdev, int fd, short events); diff --git a/libexec/rtld-elf/aarch64/reloc.c b/libexec/rtld-elf/aarch64/reloc.c index 2b64b48585db..62d664f8fb80 100644 --- a/libexec/rtld-elf/aarch64/reloc.c +++ b/libexec/rtld-elf/aarch64/reloc.c @@ -37,13 +37,6 @@ #include "rtld_printf.h" /* - * It is possible for the compiler to emit relocations for unaligned data. - * We handle this situation with these inlines. - */ -#define RELOC_ALIGNED_P(x) \ - (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0) - -/* * This is not the correct prototype, but we only need it for * a function pointer to a simple asm function. */ diff --git a/libexec/rtld-elf/riscv/reloc.c b/libexec/rtld-elf/riscv/reloc.c index 390e8c458c28..25c0befb774e 100644 --- a/libexec/rtld-elf/riscv/reloc.c +++ b/libexec/rtld-elf/riscv/reloc.c @@ -40,13 +40,6 @@ #include "rtld.h" #include "rtld_printf.h" -/* - * It is possible for the compiler to emit relocations for unaligned data. - * We handle this situation with these inlines. - */ -#define RELOC_ALIGNED_P(x) \ - (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0) - uint64_t set_gp(Obj_Entry *obj) { diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 1459b38f3720..17196f55c271 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -82,9 +82,15 @@ struct dlerror_save { char *msg; }; +struct tcb_list_entry { + TAILQ_ENTRY(tcb_list_entry) next; +}; + /* * Function declarations. */ +static bool allocate_tls_offset_common(size_t *offp, size_t tlssize, + size_t tlsalign, size_t tlspoffset); static const char *basename(const char *); static void digest_dynamic1(Obj_Entry *, int, const Elf_Dyn **, const Elf_Dyn **, const Elf_Dyn **); @@ -92,7 +98,7 @@ static bool digest_dynamic2(Obj_Entry *, const Elf_Dyn *, const Elf_Dyn *, const Elf_Dyn *); static bool digest_dynamic(Obj_Entry *, int); static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); -static void distribute_static_tls(Objlist *, RtldLockState *); +static void distribute_static_tls(Objlist *); static Obj_Entry *dlcheck(void *); static int dlclose_locked(void *, RtldLockState *); static Obj_Entry *dlopen_object(const char *name, int fd, Obj_Entry *refobj, @@ -303,6 +309,10 @@ static size_t tls_static_max_align; Elf_Addr tls_dtv_generation = 1; /* Used to detect when dtv size changes */ int tls_max_index = 1; /* Largest module index allocated */ +static TAILQ_HEAD(, tcb_list_entry) tcb_list = + TAILQ_HEAD_INITIALIZER(tcb_list); +static size_t tcb_list_entry_offset; + static bool ld_library_path_rpath = false; bool ld_fast_sigblock = false; @@ -929,6 +939,19 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) allocate_tls_offset(entry->obj); } + if (!allocate_tls_offset_common(&tcb_list_entry_offset, + sizeof(struct tcb_list_entry), _Alignof(struct tcb_list_entry), + 0)) { + /* + * This should be impossible as the static block size is not + * yet fixed, but catch and diagnose it failing if that ever + * changes or somehow turns out to be false. + */ + _rtld_error("Could not allocate offset for tcb_list_entry"); + rtld_die(); + } + dbg("tcb_list_entry_offset %zu", tcb_list_entry_offset); + if (relocate_objects(obj_main, ld_bind_now != NULL && *ld_bind_now != '\0', &obj_rtld, SYMLOOK_EARLY, NULL) == -1) @@ -3973,7 +3996,7 @@ dlopen_object(const char *name, int fd, Obj_Entry *refobj, int lo_flags, if ((lo_flags & RTLD_LO_EARLY) == 0) { map_stacks_exec(lockstate); if (obj != NULL) - distribute_static_tls(&initlist, lockstate); + distribute_static_tls(&initlist); } if (initlist_objects_ifunc(&initlist, (mode & RTLD_MODEMASK) == @@ -5400,6 +5423,44 @@ tls_get_addr_common(struct tcb *tcb, int index, size_t offset) return (tls_get_addr_slow(tcb, index, offset, false)); } +static struct tcb * +tcb_from_tcb_list_entry(struct tcb_list_entry *tcbelm) +{ +#ifdef TLS_VARIANT_I + return ((struct tcb *)((char *)tcbelm - tcb_list_entry_offset)); +#else + return ((struct tcb *)((char *)tcbelm + tcb_list_entry_offset)); +#endif +} + +static struct tcb_list_entry * +tcb_list_entry_from_tcb(struct tcb *tcb) +{ +#ifdef TLS_VARIANT_I + return ((struct tcb_list_entry *)((char *)tcb + tcb_list_entry_offset)); +#else + return ((struct tcb_list_entry *)((char *)tcb - tcb_list_entry_offset)); +#endif +} + +static void +tcb_list_insert(struct tcb *tcb) +{ + struct tcb_list_entry *tcbelm; + + tcbelm = tcb_list_entry_from_tcb(tcb); + TAILQ_INSERT_TAIL(&tcb_list, tcbelm, next); +} + +static void +tcb_list_remove(struct tcb *tcb) +{ + struct tcb_list_entry *tcbelm; + + tcbelm = tcb_list_entry_from_tcb(tcb); + TAILQ_REMOVE(&tcb_list, tcbelm, next); +} + #ifdef TLS_VARIANT_I /* @@ -5513,6 +5574,7 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) } } + tcb_list_insert(tcb); return (tcb); } @@ -5524,6 +5586,8 @@ free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused) size_t post_size; size_t i, tls_init_align __unused; + tcb_list_remove(tcb); + assert(tcbsize >= TLS_TCB_SIZE); tls_init_align = MAX(obj_main->tlsalign, 1); @@ -5624,6 +5688,7 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) } } + tcb_list_insert(tcb); return (tcb); } @@ -5635,6 +5700,8 @@ free_tls(void *tcb, size_t tcbsize __unused, size_t tcbalign) size_t i; uintptr_t tlsstart, tlsend; + tcb_list_remove(tcb); + /* * Figure out the size of the initial TLS block so that we can * find stuff which ___tls_get_addr() allocated dynamically. @@ -5698,32 +5765,22 @@ allocate_module_tls(struct tcb *tcb, int index) return (p); } -bool -allocate_tls_offset(Obj_Entry *obj) +static bool +allocate_tls_offset_common(size_t *offp, size_t tlssize, size_t tlsalign, + size_t tlspoffset __unused) { size_t off; - if (obj->tls_dynamic) - return (false); - - if (obj->tls_static) - return (true); - - if (obj->tlssize == 0) { - obj->tls_static = true; - return (true); - } - if (tls_last_offset == 0) - off = calculate_first_tls_offset(obj->tlssize, obj->tlsalign, - obj->tlspoffset); + off = calculate_first_tls_offset(tlssize, tlsalign, + tlspoffset); else off = calculate_tls_offset(tls_last_offset, tls_last_size, - obj->tlssize, obj->tlsalign, obj->tlspoffset); + tlssize, tlsalign, tlspoffset); - obj->tlsoffset = off; + *offp = off; #ifdef TLS_VARIANT_I - off += obj->tlssize; + off += tlssize; #endif /* @@ -5735,12 +5792,34 @@ allocate_tls_offset(Obj_Entry *obj) if (tls_static_space != 0) { if (off > tls_static_space) return (false); - } else if (obj->tlsalign > tls_static_max_align) { - tls_static_max_align = obj->tlsalign; + } else if (tlsalign > tls_static_max_align) { + tls_static_max_align = tlsalign; } tls_last_offset = off; - tls_last_size = obj->tlssize; + tls_last_size = tlssize; + + return (true); +} + +bool +allocate_tls_offset(Obj_Entry *obj) +{ + if (obj->tls_dynamic) + return (false); + + if (obj->tls_static) + return (true); + + if (obj->tlssize == 0) { + obj->tls_static = true; + return (true); + } + + if (!allocate_tls_offset_common(&obj->tlsoffset, obj->tlssize, + obj->tlsalign, obj->tlspoffset)) + return (false); + obj->tls_static = true; return (true); @@ -6124,25 +6203,29 @@ map_stacks_exec(RtldLockState *lockstate) } static void -distribute_static_tls(Objlist *list, RtldLockState *lockstate) +distribute_static_tls(Objlist *list) { - Objlist_Entry *elm; + struct tcb_list_entry *tcbelm; + Objlist_Entry *objelm; + struct tcb *tcb; Obj_Entry *obj; - void (*distrib)(size_t, void *, size_t, size_t); + char *tlsbase; - distrib = (void (*)(size_t, void *, size_t, size_t))( - uintptr_t)get_program_var_addr("__pthread_distribute_static_tls", - lockstate); - if (distrib == NULL) - return; - STAILQ_FOREACH(elm, list, link) { - obj = elm->obj; + STAILQ_FOREACH(objelm, list, link) { + obj = objelm->obj; if (obj->marker || !obj->tls_static || obj->static_tls_copied) continue; - lock_release(rtld_bind_lock, lockstate); - distrib(obj->tlsoffset, obj->tlsinit, obj->tlsinitsize, - obj->tlssize); - wlock_acquire(rtld_bind_lock, lockstate); + TAILQ_FOREACH(tcbelm, &tcb_list, next) { + tcb = tcb_from_tcb_list_entry(tcbelm); +#ifdef TLS_VARIANT_I + tlsbase = (char *)tcb + obj->tlsoffset; +#else + tlsbase = (char *)tcb - obj->tlsoffset; +#endif + memcpy(tlsbase, obj->tlsinit, obj->tlsinitsize); + memset(tlsbase + obj->tlsinitsize, 0, + obj->tlssize - obj->tlsinitsize); + } obj->static_tls_copied = true; } } diff --git a/sbin/bectl/bectl.8 b/sbin/bectl/bectl.8 index cc88c7019d13..0e08b3383e9a 100644 --- a/sbin/bectl/bectl.8 +++ b/sbin/bectl/bectl.8 @@ -3,12 +3,12 @@ .\" .\" SPDX-License-Identifier: BSD-2-Clause .\" -.Dd April 9, 2024 +.Dd June 13, 2025 .Dt BECTL 8 .Os .Sh NAME .Nm bectl -.Nd Utility to manage boot environments on ZFS +.Nd manage ZFS boot environments .Sh SYNOPSIS .Nm .Op Fl h @@ -80,34 +80,31 @@ .Sh DESCRIPTION The .Nm -command is used to setup and interact with ZFS boot environments, which are -bootable clones of datasets. -.Pp -A boot environment allows the system to be upgraded, while preserving the -pre-upgrade system environment. -.Pp -.Nm -itself accepts an -.Fl r -flag specified before the command to indicate the -.Ar beroot -that should be used as the boot environment root, or the dataset whose children -are all boot environments. -Normally this information is derived from the bootfs property of the pool that -is mounted at -.Pa / , -but it is useful when the system has not been booted into a ZFS root or a -different pool should be operated on. -For instance, booting into the recovery media and manually importing a pool from -one of the system's resident disks will require the -.Fl r -flag to work. +utility manages bootable ZFS clones called boot environments. +Boot envionments allow system changes to be tested safely, +as they are selectable directly from the boot +.Xr loader 8 . +This utility can +.Cm create , +.Cm list , +.Cm mount , +or +.Cm jail +boot environments. +Once the changes have been tested, the boot environment can be +.Cm unmount Ns ed , +.Cm activate Ns d , +.Cm rename Ns d , +and +.Cm destroy Ns ed . .Ss Supported Subcommands and Flags -.Bl -tag -width activate -.It Xo -.Fl h -.Xc +.Bl -tag -width indent +.It Fl h Print usage information and exit. +.It Fl r Ar beroot Sy Ar subcommand +Specify a parent dataset for the boot environment to use for +.Ar subcommand +for operation on manually imported pools or unusual layouts. .It Xo .Cm activate .Op Fl t | Fl T @@ -122,19 +119,19 @@ flag is given, this takes effect only for the next boot. Flag .Fl T removes temporary boot once configuration. -Without temporary configuration, the next boot will use zfs dataset specified -in boot pool +Without temporary configuration, +the next boot will use zfs dataset specified in boot pool .Ar bootfs property. .It Xo .Cm check .Xc -Performs a silent sanity check on the current system. +Perform a check to see if the current system can use boot environments. If boot environments are supported and used, .Nm will exit with a status code of 0. -Any other status code is not currently defined and may, in the future, grow -special meaning for different degrees of sanity check failures. +Any other status code is not currently defined and may, in the future, +grow special meaning for different degrees of sanity check failures. .It Xo .Cm create .Op Fl r @@ -162,8 +159,8 @@ environment. .Pp If .Nm -is creating from another boot environment, a snapshot of that boot environment -will be created to clone from. +is creating from another boot environment, +a snapshot of that boot environment will be created to clone from. .It Xo .Cm create .Op Fl r @@ -174,8 +171,10 @@ Create a snapshot of the boot environment named .Pp If the .Fl r -flag is given, a recursive snapshot of the boot environment will be created. -A snapshot is created for each descendant dataset of the boot environment. +flag is given, +a recursive snapshot of the boot environment will be created. +A snapshot is created for each descendant dataset +of the boot environment. See .Sx Boot Environment Structures for a discussion on different layouts. @@ -241,8 +240,8 @@ If .Ar utility is specified, it will be executed instead of .Pa /bin/sh . -The jail will be destroyed and the boot environment unmounted when the command -finishes executing, unless the +The jail will be destroyed and the boot environment unmounted +when the command finishes executing, unless the .Fl U argument is specified. .Pp @@ -269,11 +268,11 @@ The following default parameters are provided: .It Va allow.mount Ta Cm true .It Va allow.mount.devfs Ta Cm true .It Va enforce_statfs Ta Cm 1 -.It Va name Ta Set to jail ID. +.It Va name Ta set to jail ID .It Va host.hostname Ta Va bootenv -.It Va path Ta Set to a path in Pa /tmp +.It Va path Ta set to a path in Pa /tmp generated by -.Xr libbe 3 . +.Xr libbe 3 .El .Pp All default parameters may be overwritten. @@ -298,8 +297,8 @@ or combination of .It Fl a Display all datasets. .It Fl D -Display the full space usage for each boot environment, assuming all -other boot environments were destroyed. +Display the full space usage for each boot environment, +assuming all other boot environments were destroyed. .It Fl H Used for scripting. Do not print headers and separate fields by a single tab instead of @@ -351,8 +350,8 @@ will make a directory such as .Pa be_mount.c6Sf in .Pa /tmp . -Randomness in the last four characters of the directory name will prevent -mount point conflicts. +Randomness in the last four characters of the directory name +will prevent mount point conflicts. Unmount of an environment, followed by mount of the same environment without giving a .Ar mountpoint , @@ -362,7 +361,7 @@ Rename the given .Ar origBeName to the given .Ar newBeName . -The boot environment will not be unmounted in order for this rename to occur. +The boot environment will not be unmounted for this rename to occur. .It Cm ujail Brq Ar jailId | jailName | beName .It Cm unjail Brq Ar jailId | jailName | beName Destroy the jail created from the given boot environment. @@ -390,8 +389,8 @@ boot environment layout, as created by the Auto ZFS option to .Xr bsdinstall 8 , is a .Dq shallow -boot environment structure, where boot environment datasets do not have any -directly subordinate datasets. +boot environment structure, where boot environment datasets +do not have any directly subordinate datasets. Instead, they're organized off in .Pa zroot/ROOT , and they rely on datasets elsewhere in the pool having @@ -419,7 +418,8 @@ set to .Dv off , thus files in .Pa /usr -typically fall into the boot environment because this dataset is not mounted. +typically fall into the boot environment +because this dataset is not mounted. .Pa zroot/usr/src is mounted, thus files in .Pa /usr/src @@ -445,8 +445,8 @@ Note that the subordinate datasets now have .Dv canmount set to .Dv noauto . -These are more obviously a part of the boot environment, as indicated by their -positioning in the layout. +These are more obviously a part of the boot environment, +as indicated by their positioning in the layout. These subordinate datasets will be mounted by the .Dv zfsbe .Xr rc 8 @@ -468,16 +468,25 @@ A future version of may default to handling both styles and deprecate the various .Fl r flags. -.\" .Sh EXAMPLES -.\" .Bl -bullet -.\" .It +.Sh EXAMPLES +Create a boot environment, named with today's date, +containing snapshots of the root dataset and of all child datasets: +.Pp +.Dl bectl create -r `date +%Y%m%d` +.Pp +Mount a previous boot environment, +.Ar yesterdaysbe , +to +.Pa /mnt : +.Pp +.Dl bectl mount yesterdaysbe /mnt .\" To fill in with jail upgrade example when behavior is firm. -.\" .El .Sh SEE ALSO .Xr libbe 3 , .Xr zfsprops 7 , .Xr beinstall.sh 8 , .Xr jail 8 , +.Xr loader 8 , .Xr zfs 8 , .Xr zpool 8 .Sh HISTORY diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index 3fb8b5f02b76..6c61af48abec 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -28,7 +28,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 5, 2025 +.Dd July 11, 2025 .Dt IFCONFIG 8 .Os .Sh NAME @@ -2878,16 +2878,6 @@ interfaces previously configured with Another name for the .Fl tunnel parameter. -.It Cm accept_rev_ethip_ver -Set a flag to accept both correct EtherIP packets and ones -with reversed version field. -Enabled by default. -This is for backward compatibility with -.Fx 6.1 , -6.2, 6.3, 7.0, and 7.1. -.It Cm -accept_rev_ethip_ver -Clear a flag -.Cm accept_rev_ethip_ver . .It Cm ignore_source Set a flag to accept encapsulated packets destined to this host independently from source address. @@ -2896,16 +2886,6 @@ from the load balancers. .It Cm -ignore_source Clear a flag .Cm ignore_source . -.It Cm send_rev_ethip_ver -Set a flag to send EtherIP packets with reversed version -field intentionally. -Disabled by default. -This is for backward compatibility with -.Fx 6.1 , -6.2, 6.3, 7.0, and 7.1. -.It Cm -send_rev_ethip_ver -Clear a flag -.Cm send_rev_ethip_ver . .El .Ss GRE Tunnel Parameters The following parameters apply to GRE tunnel interfaces, diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c index 29d51214e2e5..bd2c10c8080f 100644 --- a/sbin/pfctl/pfctl_parser.c +++ b/sbin/pfctl/pfctl_parser.c @@ -368,8 +368,8 @@ print_ugid(u_int8_t op, id_t i1, id_t i2, const char *t) { char a1[11], a2[11]; - snprintf(a1, sizeof(a1), "%lu", i1); - snprintf(a2, sizeof(a2), "%lu", i2); + snprintf(a1, sizeof(a1), "%ju", (uintmax_t)i1); + snprintf(a2, sizeof(a2), "%ju", (uintmax_t)i2); printf(" %s", t); if (i1 == -1 && (op == PF_OP_EQ || op == PF_OP_NE)) print_op(op, "unknown", a2); diff --git a/sbin/pfctl/tests/pfctl_test.c b/sbin/pfctl/tests/pfctl_test.c index dbdcaa4900ea..5f0aa7826bb4 100644 --- a/sbin/pfctl/tests/pfctl_test.c +++ b/sbin/pfctl/tests/pfctl_test.c @@ -65,24 +65,6 @@ * Copied from OpenBSD. */ -static bool -check_pf_module_available(void) -{ - int modid; - struct module_stat stat; - - if ((modid = modfind("pf")) < 0) { - warn("pf module not found"); - return false; - } - stat.version = sizeof(struct module_stat); - if (modstat(modid, &stat) < 0) { - warn("can't stat pf module id %d", modid); - return false; - } - return (true); -} - extern char **environ; static struct sbuf * @@ -185,9 +167,6 @@ run_pfctl_test(const char *input_path, const char *output_path, struct sbuf *expected_output; struct sbuf *real_output; - if (!check_pf_module_available()) - atf_tc_skip("pf(4) is not loaded"); - /* The test inputs need to be able to use relative includes. */ snprintf(input_files_path, sizeof(input_files_path), "%s/files", atf_tc_get_config_var(tc, "srcdir")); @@ -292,6 +271,7 @@ do_selfpf_test(const char *number, const atf_tc_t *tc) ATF_TC_HEAD(pf##number, tc) \ { \ atf_tc_set_md_var(tc, "descr", descr); \ + atf_tc_set_md_var(tc, "require.kmods", "pf"); \ } \ ATF_TC_BODY(pf##number, tc) \ { \ @@ -301,6 +281,7 @@ do_selfpf_test(const char *number, const atf_tc_t *tc) ATF_TC_HEAD(selfpf##number, tc) \ { \ atf_tc_set_md_var(tc, "descr", "Self " descr); \ + atf_tc_set_md_var(tc, "require.kmods", "pf"); \ } \ ATF_TC_BODY(selfpf##number, tc) \ { \ @@ -312,6 +293,7 @@ do_selfpf_test(const char *number, const atf_tc_t *tc) ATF_TC_HEAD(pf##number, tc) \ { \ atf_tc_set_md_var(tc, "descr", descr); \ + atf_tc_set_md_var(tc, "require.kmods", "pf"); \ } \ ATF_TC_BODY(pf##number, tc) \ { \ @@ -325,6 +307,7 @@ do_selfpf_test(const char *number, const atf_tc_t *tc) atf_tc_set_md_var(tc, "descr", descr); \ atf_tc_set_md_var(tc, "execenv", "jail"); \ atf_tc_set_md_var(tc, "execenv.jail.params", "vnet"); \ + atf_tc_set_md_var(tc, "require.kmods", "pf"); \ } \ ATF_TC_BODY(pf##number, tc) \ { \ diff --git a/share/examples/Makefile b/share/examples/Makefile index f0c050a36306..0a65b8c40d39 100644 --- a/share/examples/Makefile +++ b/share/examples/Makefile @@ -10,7 +10,6 @@ LDIRS= BSD_daemon \ FreeBSD_version \ bootforth \ csh \ - drivers \ etc \ find_interface \ flua \ @@ -74,12 +73,6 @@ SE_DIRS+= csh SE_CSHPACKAGE= csh SE_CSH= dot.cshrc -SE_DIRS+= drivers -SE_DRIVERS= \ - README \ - make_device_driver.sh \ - make_pseudo_driver.sh - SE_DIRS+= etc SE_ETC= \ README.examples \ diff --git a/share/examples/drivers/README b/share/examples/drivers/README deleted file mode 100644 index 8628029a62f8..000000000000 --- a/share/examples/drivers/README +++ /dev/null @@ -1,42 +0,0 @@ - -Author: Julian Elischer - -The files in this directory are shell scripts. - -They will, when run, create an example skeleton driver -for you. You can use this driver as a starting point for -writing drivers for your own devices. They have all the hooks needed -for initialization, probing, attaching, as well as DEVFS -node creation. They also create sample ioctl commands and a sample -ioctl definition .h file in /sys/sys. In other words they are fully -functional in a 'skeleton' sort of a way. They support multiple devices -so that you may have several of your 'foobar' devices probed and attached -at once. - -I expect that these scripts will improve with time. - -At present these scripts also link the newly created driver into -the kernel sources in /sys. Possibly a better way would be -to make them interactive. (and ask what kernel tree to use as well as -a name for the driver.). - -There are presently two scripts. -One for making a real device driver for ISA devices, and -one for making a device driver for pseudo devices (e.g. /dev/null). -Hopefully they will be joined by similar scripts for creating -skeletons for PCI devices as well. - -Give them a single argument: the name of the driver. -They will use this given name in many places within the driver, -both in lower and upper case form. (conforming to normal usage). - -The skeleton driver should already link with the kernel -and in fact the shell script will compile a kernel with the new -drive linked in.. The new kernel should still be -runnable and the new driver should be -fully callable (once you get your device to probe). -You should simply edit the driver and continue to use -'make' (as done in the script) until your driver does what you want. - -The driver will end up in /sys/i386/isa for the device driver script, -and in /sys/dev for the pseudo driver script. diff --git a/share/examples/drivers/make_pseudo_driver.sh b/share/examples/drivers/make_pseudo_driver.sh deleted file mode 100644 index 5d6d09aa9648..000000000000 --- a/share/examples/drivers/make_pseudo_driver.sh +++ /dev/null @@ -1,435 +0,0 @@ -#!/bin/sh -# This writes a skeleton driver and puts it into the kernel tree for you -# -# arg1 is lowercase "foo" -# arg2 path to the kernel sources, "/sys" if omitted -# -# Trust me, RUN THIS SCRIPT :) -# -# -#-------cut here------------------ - -if [ "${1}X" = "X" ] -then - echo "Hey , how about some help here.. give me a device name!" - exit 1 -fi -if [ "X${2}" = "X" ]; then - TOP=`cd /sys; pwd -P` - echo "Using ${TOP} as the path to the kernel sources!" -else - TOP=${2} -fi - -for i in "" "conf" "i386" "i386/conf" "dev" "sys" "modules" -do - if [ -d ${TOP}/${i} ] - then - continue - fi - echo "${TOP}/${i}: no such directory." - echo "Please, correct the error and try again." - exit 1 -done - -UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"` - -if [ -d ${TOP}/modules/${1} ]; then - echo "There appears to already be a module called ${1}" - echo -n "Should it be overwritten? [Y]" - read VAL - if [ "-z" "$VAL" ]; then - VAL=YES - fi - case ${VAL} in - [yY]*) - echo "Cleaning up from prior runs" - rm -rf ${TOP}/dev/${1} - rm -rf ${TOP}/modules/${1} - rm ${TOP}/conf/files.${UPPER} - rm ${TOP}/i386/conf/${UPPER} - rm ${TOP}/sys/${1}io.h - ;; - *) - exit 1 - ;; - esac -fi - -echo "The following files will be created:" -echo ${TOP}/modules/${1} -echo ${TOP}/conf/files.${UPPER} -echo ${TOP}/i386/conf/${UPPER} -echo ${TOP}/dev/${1} -echo ${TOP}/dev/${1}/${1}.c -echo ${TOP}/sys/${1}io.h -echo ${TOP}/modules/${1} -echo ${TOP}/modules/${1}/Makefile - -mkdir ${TOP}/modules/${1} - -cat >${TOP}/conf/files.${UPPER} <<DONE -dev/${1}/${1}.c optional ${1} -DONE - -cat >${TOP}/i386/conf/${UPPER} <<DONE -# Configuration file for kernel type: ${UPPER} - -files "${TOP}/conf/files.${UPPER}" - -include GENERIC - -ident ${UPPER} - -# trust me, you'll need this -options KDB -options DDB -device ${1} -DONE - -if [ ! -d ${TOP}/dev/${1} ]; then - mkdir -p ${TOP}/dev/${1} -fi - -cat >${TOP}/dev/${1}/${1}.c <<DONE -/* - * Copyright (c) [year] [your name] - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * ${1} driver - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> /* SYSINIT stuff */ -#include <sys/uio.h> /* SYSINIT stuff */ -#include <sys/conf.h> /* cdevsw stuff */ -#include <sys/malloc.h> /* malloc region definitions */ -#include <sys/proc.h> -#include <sys/${1}io.h> /* ${1} IOCTL definitions */ - -#include <machine/clock.h> /* DELAY() */ - -#define N${UPPER} 3 /* defines number of instances */ - -/* XXX These should be defined in terms of bus-space ops. */ -#define ${UPPER}_INB(port) inb(port) -#define ${UPPER}_OUTB(port, val) (port, (val)) - -/* Function prototypes (these should all be static) */ -static d_open_t ${1}open; -static d_close_t ${1}close; -static d_read_t ${1}read; -static d_write_t ${1}write; -static d_ioctl_t ${1}ioctl; -static d_mmap_t ${1}mmap; -static d_poll_t ${1}poll; - -#define CDEV_MAJOR 20 -static struct cdevsw ${1}_cdevsw = { - .d_version = D_VERSION, - .d_open = ${1}open, - .d_close = ${1}close, - .d_read = ${1}read, - .d_write = ${1}write, - .d_ioctl = ${1}ioctl, - .d_poll = ${1}poll, - .d_mmap = ${1}mmap, - .d_name = "${1}", -}; - -/* - * device specific Misc defines - */ -#define BUFFERSIZE 1024 -#define UNIT(dev) dev2unit(dev) /* assume one minor number per unit */ - -/* - * One of these per allocated device - */ -struct ${1}_softc { - u_long iobase; - char buffer[BUFFERSIZE]; - struct cdev *dev; -}; - -typedef struct ${1}_softc *sc_p; - -static sc_p sca[N${UPPER}]; - -/* - * Macro to check that the unit number is valid - * Often this isn't needed as once the open() is performed, - * the unit number is pretty much safe.. The exception would be if we - * implemented devices that could "go away". in which case all these routines - * would be wise to check the number, DIAGNOSTIC or not. - */ -#define CHECKUNIT(RETVAL) \ -do { /* the do-while is a safe way to do this grouping */ \ - if (unit > N${UPPER}) { \ - printf("%s: bad unit %d\n", __func__, unit); \ - return (RETVAL); \ - } \ - if (scp == NULL) { \ - printf("%s: unit %d not attached\n", __func__, unit); \ - return (RETVAL); \ - } \ -} while (0) - -#ifdef DIAGNOSTIC -#define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL) -#else /* DIAGNOSTIC */ -#define CHECKUNIT_DIAG(RETVAL) -#endif /* DIAGNOSTIC */ - -static int -${1}ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) -{ - int unit = UNIT(dev); - sc_p scp = sca[unit]; - - CHECKUNIT_DIAG(ENXIO); - - switch (cmd) { - case DHIOCRESET: - /* whatever resets it */ - (void)scp; /* Delete this line after using scp. */ -#if 0 - ${UPPER}_OUTB(scp->iobase, 0xff); -#endif - break; - default: - return ENXIO; - } - return (0); -} - -/* - * You also need read, write, open, close routines. - * This should get you started - */ -static int -${1}open(struct cdev *dev, int oflags, int devtype, struct thread *td) -{ - int unit = UNIT(dev); - sc_p scp = sca[unit]; - - CHECKUNIT(ENXIO); - - (void)scp; /* Delete this line after using scp. */ - /* - * Do processing - */ - return (0); -} - -static int -${1}close(struct cdev *dev, int fflag, int devtype, struct thread *td) -{ - int unit = UNIT(dev); - sc_p scp = sca[unit]; - - CHECKUNIT_DIAG(ENXIO); - - (void)scp; /* Delete this line after using scp. */ - /* - * Do processing - */ - return (0); -} - -static int -${1}read(struct cdev *dev, struct uio *uio, int ioflag) -{ - int unit = UNIT(dev); - sc_p scp = sca[unit]; - int toread; - - - CHECKUNIT_DIAG(ENXIO); - - /* - * Do processing - * read from buffer - */ - toread = (min(uio->uio_resid, sizeof(scp->buffer))); - return(uiomove(scp->buffer, toread, uio)); -} - -static int -${1}write(struct cdev *dev, struct uio *uio, int ioflag) -{ - int unit = UNIT(dev); - sc_p scp = sca[unit]; - int towrite; - - CHECKUNIT_DIAG(ENXIO); - - /* - * Do processing - * write to buffer - */ - towrite = (min(uio->uio_resid, sizeof(scp->buffer))); - return(uiomove(scp->buffer, towrite, uio)); -} - -static int -${1}mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot) -{ - int unit = UNIT(dev); - sc_p scp = sca[unit]; - - CHECKUNIT_DIAG(-1); - - (void)scp; /* Delete this line after using scp. */ - /* - * Do processing - */ -#if 0 /* if we had a frame buffer or whatever.. do this */ - if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) { - return (-1); - } - return i386_btop((FRAMEBASE + offset)); -#else - return (-1); -#endif -} - -static int -${1}poll(struct cdev *dev, int which, struct thread *td) -{ - int unit = UNIT(dev); - sc_p scp = sca[unit]; - - CHECKUNIT_DIAG(ENXIO); - - (void)scp; /* Delete this line after using scp. */ - /* - * Do processing - */ - return (0); /* this is the wrong value I'm sure */ -} - -/* - * Now for some driver initialisation. - * Occurs ONCE during boot (very early). - */ -static void -${1}_drvinit(void *unused) -{ - int unit; - sc_p scp; - - for (unit = 0; unit < N${UPPER}; unit++) { - /* - * Allocate storage for this instance . - */ - scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT | M_ZERO); - if( scp == NULL) { - printf("${1}%d failed to allocate strorage\n", unit); - return; - } - sca[unit] = scp; - scp->dev = make_dev(&${1}_cdevsw, unit, - UID_ROOT, GID_KMEM, 0640, "${1}%d", unit); - } -} - -SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR, - ${1}_drvinit, NULL); -DONE - -cat >${TOP}/sys/${1}io.h <<DONE -/* - * Definitions needed to access the ${1} device (ioctls etc) - * see mtio.h , ioctl.h as examples - */ -#ifndef SYS_DHIO_H -#define SYS_DHIO_H - -#ifndef KERNEL -#include <sys/types.h> -#endif -#include <sys/ioccom.h> - -/* - * define an ioctl here - */ -#define DHIOCRESET _IO('D', 0) /* reset the ${1} device */ -#endif -DONE - -if [ ! -d ${TOP}/modules/${1} ]; then - mkdir -p ${TOP}/modules/${1} -fi - -cat >${TOP}/modules/${1}/Makefile <<DONE -# ${UPPER} Loadable Kernel Module - -.PATH: \${.CURDIR}/../../dev/${1} -KMOD = ${1} -SRCS = ${1}.c - -.include <bsd.kmod.mk> -DONE - -echo -n "Do you want to build the '${1}' module? [Y]" -read VAL -if [ "-z" "$VAL" ]; then - VAL=YES -fi -case ${VAL} in -[yY]*) - (cd ${TOP}/modules/${1}; make depend; make ) - ;; -*) -# exit - ;; -esac - -echo "" -echo -n "Do you want to build the '${UPPER}' kernel? [Y]" -read VAL -if [ "-z" "$VAL" ]; then - VAL=YES -fi -case ${VAL} in -[yY]*) - ( - cd ${TOP}/i386/conf; \ - config ${UPPER}; \ - cd ${TOP}/i386/compile/${UPPER}; \ - make depend; \ - make; \ - ) - ;; -*) -# exit - ;; -esac - -#--------------end of script--------------- -# -#edit to your taste.. -# -# diff --git a/share/man/man1/Makefile b/share/man/man1/Makefile index e5ab6597ead2..5b1d3ac1091d 100644 --- a/share/man/man1/Makefile +++ b/share/man/man1/Makefile @@ -55,6 +55,7 @@ MLINKS= builtin.1 alias.1 \ builtin.1 if.1 \ builtin.1 jobid.1 \ builtin.1 jobs.1 \ + builtin.1 keybinds.1 \ builtin.1 limit.1 \ builtin.1 log.1 \ builtin.1 logout.1 \ diff --git a/share/man/man1/builtin.1 b/share/man/man1/builtin.1 index d546548ab4e5..ee89006caea5 100644 --- a/share/man/man1/builtin.1 +++ b/share/man/man1/builtin.1 @@ -1,4 +1,6 @@ .\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" .\" Copyright (c) 1999 Sheldon Hearn .\" .\" All rights reserved. @@ -24,175 +26,33 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 21, 2010 +.Dd March 29, 2025 .Dt BUILTIN 1 .Os .Sh NAME .Nm builtin , -.Nm \&! , -.Nm % , -.Nm \&. , -.Nm \&: , -.Nm @ , -.Nm \&[ , -.Nm { , -.Nm } , -.Nm alias , -.Nm alloc , -.Nm bg , -.Nm bind , -.Nm bindkey , -.Nm break , -.Nm breaksw , -.Nm builtins , -.Nm case , -.Nm cd , -.Nm chdir , -.Nm command , -.Nm complete , -.Nm continue , -.Nm default , -.Nm dirs , -.Nm do , -.Nm done , -.Nm echo , -.Nm echotc , -.Nm elif , -.Nm else , -.Nm end , -.Nm endif , -.Nm endsw , -.Nm esac , -.Nm eval , -.Nm exec , -.Nm exit , -.Nm export , -.Nm false , -.Nm fc , -.Nm fg , -.Nm filetest , -.Nm fi , -.Nm for , -.Nm foreach , -.Nm getopts , -.Nm glob , -.Nm goto , -.Nm hash , -.Nm hashstat , -.Nm history , -.Nm hup , -.Nm if , -.Nm jobid , -.Nm jobs , -.Nm kill , -.Nm limit , -.Nm local , -.Nm log , -.Nm login , -.Nm logout , -.Nm ls-F , -.Nm nice , -.Nm nohup , -.Nm notify , -.Nm onintr , -.Nm popd , -.Nm printenv , -.Nm printf , -.Nm pushd , -.Nm pwd , -.Nm read , -.Nm readonly , -.Nm rehash , -.Nm repeat , -.Nm return , -.Nm sched , -.Nm set , -.Nm setenv , -.Nm settc , -.Nm setty , -.Nm setvar , -.Nm shift , -.Nm source , -.Nm stop , -.Nm suspend , -.Nm switch , -.Nm telltc , -.Nm test , -.Nm then , -.Nm time , -.Nm times , -.Nm trap , -.Nm true , -.Nm type , -.Nm ulimit , -.Nm umask , -.Nm unalias , -.Nm uncomplete , -.Nm unhash , -.Nm unlimit , -.Nm unset , -.Nm unsetenv , -.Nm until , -.Nm wait , -.Nm where , -.Nm which , -.Nm while -.Nd shell built-in commands +.Nm keybinds +.Nd index of FreeBSD shell built-in commands .Sh SYNOPSIS -See the built-in command description in the appropriate shell manual page. +See the manual for your shell for operation details. .Sh DESCRIPTION -Shell builtin commands are commands that can be executed within the -running shell's process. -Note that, in the case of -.Xr csh 1 -builtin commands, the command is executed in a subshell if it occurs as -any component of a pipeline except the last. -.Pp -If a command specified to the shell contains a slash -.Ql / , -the shell will not execute a builtin command, even if the last component -of the specified command matches the name of a builtin command. -Thus, while specifying -.Dq Li echo -causes a builtin command to be executed under shells that support the -.Nm echo -builtin command, -specifying -.Dq Li /bin/echo -or -.Dq Li ./echo -does not. -.Pp -While some builtin commands may exist in more than one shell, their -operation may be different under each shell which supports them. -Below is a table which lists shell builtin commands, the standard shells -that support them and whether they exist as standalone utilities. -.Pp -Only builtin commands for the +This page provides an index of +.Nm +commands, keywords, and keyboard bindings provided by .Xr csh 1 and -.Xr sh 1 -shells are listed here. -Consult a shell's manual page for -details on the operation its builtin commands. -Beware that the -.Xr sh 1 -manual page, at least, calls some of these commands -.Dq built-in commands -and some of them -.Dq reserved words . -Users of other shells may need to consult an -.Xr info 1 -page or other sources of documentation. -.Pp -Commands marked -.Dq Li No** -under -.Em External -do exist externally, -but are implemented as scripts using a builtin command of the same name. -.Bl -column ".Ic uncomplete" ".Em External" ".Xr csh 1" ".Xr sh 1" -offset indent -.It Em Command Ta Em External Ta Xr csh 1 Ta Xr sh 1 +.Xr sh 1 , +the command line interpreters which comprise the +.Bx +user environment. +.Ss Commands +Below is a table which lists +.Nm +commands and keywords, +whether they exist as standalone utilities, +and the standard shells that provide them. +.Bl -column "uncomplete" "Standalone" "csh(1)" "sh(1)" -offset indent +.It Em Command Ta Em Standalone Ta Xr csh 1 Ta Xr sh 1 .It Ic \&! Ta \&No Ta \&No Ta Yes .It Ic % Ta \&No Ta Yes Ta \&No .It Ic \&. Ta \&No Ta \&No Ta Yes @@ -201,9 +61,9 @@ but are implemented as scripts using a builtin command of the same name. .It Ic \&[ Ta Yes Ta \&No Ta Yes .It Ic { Ta \&No Ta \&No Ta Yes .It Ic } Ta \&No Ta \&No Ta Yes -.It Ic alias Ta No** Ta Yes Ta Yes +.It Ic alias Ta No* Ta Yes Ta Yes .It Ic alloc Ta \&No Ta Yes Ta \&No -.It Ic bg Ta No** Ta Yes Ta Yes +.It Ic bg Ta No* Ta Yes Ta Yes .It Ic bind Ta \&No Ta \&No Ta Yes .It Ic bindkey Ta \&No Ta Yes Ta \&No .It Ic break Ta \&No Ta Yes Ta Yes @@ -211,9 +71,9 @@ but are implemented as scripts using a builtin command of the same name. .It Ic builtin Ta \&No Ta \&No Ta Yes .It Ic builtins Ta \&No Ta Yes Ta \&No .It Ic case Ta \&No Ta Yes Ta Yes -.It Ic cd Ta No** Ta Yes Ta Yes +.It Ic cd Ta No* Ta Yes Ta Yes .It Ic chdir Ta \&No Ta Yes Ta Yes -.It Ic command Ta No** Ta \&No Ta Yes +.It Ic command Ta No* Ta \&No Ta Yes .It Ic complete Ta \&No Ta Yes Ta \&No .It Ic continue Ta \&No Ta Yes Ta Yes .It Ic default Ta \&No Ta Yes Ta \&No @@ -233,22 +93,22 @@ but are implemented as scripts using a builtin command of the same name. .It Ic exit Ta \&No Ta Yes Ta Yes .It Ic export Ta \&No Ta \&No Ta Yes .It Ic false Ta Yes Ta \&No Ta Yes -.It Ic fc Ta No** Ta \&No Ta Yes -.It Ic fg Ta No** Ta Yes Ta Yes +.It Ic fc Ta No* Ta \&No Ta Yes +.It Ic fg Ta No* Ta Yes Ta Yes .It Ic filetest Ta \&No Ta Yes Ta \&No .It Ic fi Ta \&No Ta \&No Ta Yes .It Ic for Ta \&No Ta \&No Ta Yes .It Ic foreach Ta \&No Ta Yes Ta \&No -.It Ic getopts Ta No** Ta \&No Ta Yes +.It Ic getopts Ta No* Ta \&No Ta Yes .It Ic glob Ta \&No Ta Yes Ta \&No .It Ic goto Ta \&No Ta Yes Ta \&No -.It Ic hash Ta No** Ta \&No Ta Yes +.It Ic hash Ta No* Ta \&No Ta Yes .It Ic hashstat Ta \&No Ta Yes Ta \&No .It Ic history Ta \&No Ta Yes Ta \&No .It Ic hup Ta \&No Ta Yes Ta \&No .It Ic if Ta \&No Ta Yes Ta Yes .It Ic jobid Ta \&No Ta \&No Ta Yes -.It Ic jobs Ta No** Ta Yes Ta Yes +.It Ic jobs Ta No* Ta Yes Ta Yes .It Ic kill Ta Yes Ta Yes Ta Yes .It Ic limit Ta \&No Ta Yes Ta \&No .It Ic local Ta \&No Ta \&No Ta Yes @@ -265,7 +125,7 @@ but are implemented as scripts using a builtin command of the same name. .It Ic printf Ta Yes Ta \&No Ta Yes .It Ic pushd Ta \&No Ta Yes Ta \&No .It Ic pwd Ta Yes Ta \&No Ta Yes -.It Ic read Ta No** Ta \&No Ta Yes +.It Ic read Ta No* Ta \&No Ta Yes .It Ic readonly Ta \&No Ta \&No Ta Yes .It Ic rehash Ta \&No Ta Yes Ta \&No .It Ic repeat Ta \&No Ta Yes Ta \&No @@ -288,26 +148,68 @@ but are implemented as scripts using a builtin command of the same name. .It Ic times Ta \&No Ta \&No Ta Yes .It Ic trap Ta \&No Ta \&No Ta Yes .It Ic true Ta Yes Ta \&No Ta Yes -.It Ic type Ta No** Ta \&No Ta Yes -.It Ic ulimit Ta No** Ta \&No Ta Yes -.It Ic umask Ta No** Ta Yes Ta Yes -.It Ic unalias Ta No** Ta Yes Ta Yes +.It Ic type Ta No* Ta \&No Ta Yes +.It Ic ulimit Ta No* Ta \&No Ta Yes +.It Ic umask Ta No* Ta Yes Ta Yes +.It Ic unalias Ta No* Ta Yes Ta Yes .It Ic uncomplete Ta \&No Ta Yes Ta \&No .It Ic unhash Ta \&No Ta Yes Ta \&No .It Ic unlimit Ta \&No Ta Yes Ta \&No .It Ic unset Ta \&No Ta Yes Ta Yes .It Ic unsetenv Ta \&No Ta Yes Ta \&No .It Ic until Ta \&No Ta \&No Ta Yes -.It Ic wait Ta No** Ta Yes Ta Yes +.It Ic wait Ta No* Ta Yes Ta Yes .It Ic where Ta \&No Ta Yes Ta \&No .It Ic which Ta Yes Ta Yes Ta \&No .It Ic while Ta \&No Ta Yes Ta Yes .El +.Pp +\&No*: Commands marked +.Ql No* +exist externally, but are implemented as scripts using a +.Nm +command of the same name. +.Ss Keybinds +The command line environment also provides the following +default keyboard bindings: +.Bl -column "Process Info (SIGINFO)" "^M | ^J" "^M | ^J" -offset indent +.It Em Signal Ta Xr csh 1 Ta Xr sh 1 +.It Ic Backspace Ta ^H Ta ^H +.It Ic Carriage Return Ta ^M | ^J Ta ^M | ^J +.It Ic Tab Ta ^I Ta ^I +.It Ic Beginning of Line Ta ^A Ta ^A +.It Ic End of Line Ta ^E Ta ^E +.It Ic Cursor Forward Ta ^F Ta ^F +.It Ic Cursor Backward Ta ^B Ta ^B +.It Ic Clear Screen Ta ^L Ta ^L +.It Ic Cut Line Ta ^U Ta ^U +.It Ic Cut Word Backwards Ta ^W Ta ^W +.It Ic Cut Rest of Line Ta ^K Ta ^K +.It Ic Paste Last Cut Ta ^Y Ta ^Y +.It Ic Typo Ta ^T Ta ^T +.It End of File Po Ic EOF Pc Ta ^D Ta ^D +.It Interupt Po Ic SIGINT Pc Ta ^C Ta ^C +.It Process info Po Ic SIGINFO Pc Ta ^T Ta ^T +.It Ic Search History Ta \&No Ta ^R +.It Ic Exit Search History Ta \&No Ta ^G +.It Ic Previous Command Ta ^P Ta ^P +.It Ic Next Command Ta ^N Ta ^N +.It Ic Print Next Character Ta ^V Ta ^V +.It Ic Pause Job Ta ^S Ta ^S +.It Ic Resume Job Ta ^Q Ta ^Q +.It Suspend Job Ic (SIGTSTP) Ta ^Z Ta ^Z +.It Ic Scrollback Mode Ta ScrLk* Ta ScrLk* +.El +.Pp +\&*: Bindings marked +.Ql * +are provided by +.Xr vt 4 , +the console driver. .Sh SEE ALSO .Xr csh 1 , .Xr echo 1 , .Xr false 1 , -.Xr info 1 , .Xr kill 1 , .Xr login 1 , .Xr nice 1 , @@ -326,5 +228,18 @@ The manual page first appeared in .Fx 3.4 . .Sh AUTHORS +.An -nosplit This manual page was written by +.An Alexander Ziaee Aq Mt ziaee@FreeBSD.org +from an earlier version by .An Sheldon Hearn Aq Mt sheldonh@FreeBSD.org . +.Sh CAVEATS +While +.Nm +commands may exist in more than one shell or standalone, +each may be implemented differently. +.Pp +Standalone utilities and their manuals must be called by their path +from a shell with a +.Nm +command of the same name. diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 4f12e70f2ae4..7c8a8f3afc45 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -213,6 +213,7 @@ MAN= aac.4 \ ${_hv_vmbus.4} \ ${_hv_vss.4} \ hwpmc.4 \ + ${_hwt.4} \ ${_hwpstate_intel.4} \ i2ctinyusb.4 \ iavf.4 \ @@ -926,6 +927,17 @@ _vmm.4= vmm.4 .endif .endif +.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "aarch64" +_hwt.4= hwt.4 +.if ${MACHINE_CPUARCH} == "amd64" +MLINKS+=hwt.4 intel_pt.4 +.endif +.if ${MACHINE_CPUARCH} == "aarch64" +MLINKS+=hwt.4 coresight.4 +MLINKS+=hwt.4 spe.4 +.endif +.endif + .if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" || \ ${MACHINE_CPUARCH} == "aarch64" _gve.4= gve.4 diff --git a/share/man/man4/hwt.4 b/share/man/man4/hwt.4 new file mode 100644 index 000000000000..df02a4672f36 --- /dev/null +++ b/share/man/man4/hwt.4 @@ -0,0 +1,143 @@ +.\" +.\" Copyright (c) 2025 Ruslan Bukin <br@bsdpad.com> +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd July 7, 2025 +.Dt HWT 4 +.Os +.Sh NAME +.Nm hwt +.Nd Hardware Trace Framework +.Sh SYNOPSIS +.Cd "options HWT_HOOKS" +.Cd "device hwt" +.Pp +At least one of: +.Cd "device intel_pt" +.Pq amd64 +.Cd "device coresight" +.Pq arm64 +.Cd "device spe" +.Pq arm64 +.Pp +In +.Xr rc.conf 5 : +.Cd kld_list="hwt" +.Sh DESCRIPTION +The +.Nm +framework provides infrastructure for hardware-assisted tracing. +It collects detailed information about software execution and stores it as +events in highly compressed format into DRAM. +The events cover information about control flow changes of a program, whether +branches taken or not, exceptions taken, timing information, cycles elapsed and +more. +The information collected allows to reconstruct entire program flow of a given +application without noticeable performance impact. +.Sh HARDWARE +The framework supports several tracing technologies found on +.Cd arm64 +and +.Cd amd64 +systems: +.Pp +.Bl -bullet -compact +.It +ARM Coresight +.It +ARM Statistical Profiling Extension (SPE) +.It +Intel Processor Trace (PT) +.El +.Pp +The +.Nm +framework supports two modes of operation: +.Bl -tag -width "Thread mode" +.It Em CPU mode +Capture CPU activity in kernel mode. +.It Em Thread mode +Capture activity of each of a process's threads in user mode. +.El +.Sh MANAGEMENT +When loaded into kernel, the +.Nm +framework provides +.Pa /dev/hwt +character device. +The only +.Xr ioctl 2 +request it accepts is +.Dv HWT_IOC_ALLOC . +This request allocates kernel tracing context (CTX) based on requested mode of +operation, set of CPUs and/or pid. +.Pp +Upon successful CTX allocation, the ioctl returns a CTX identification +number (ident). +.Pp +Each CTX is then managed using its own dedicated character device found at +.Pa "/dev/hwt_${ident}_${d}", +where ident is a unique identification number of tracing context, d is either +cpu_id (in HWT CPU mode) or process pid (in HWT Thread mode). +.Sh HOOKS +During tracing of a target process, HWT records runtime events such as threads +creation, exec and mmap system calls. +These events are logged as "records" within a particular CTX associated with +traced process. +.Pp +Additionally, HWT can suspend the target thread upon exec or mmap system calls +if requested by the user. +This pause allows user-space tools to retrieve the records and adjust tracing +settings before execution continues. +This feature is especially useful when address range filtering is enabled, +allowing tracing of specific functions within the target executable or a +dynamic library. +.Sh KERNEL OPTIONS +The following options in the kernel configuration file are mandatory and +related to +.Nm +operation: +.Pp +.Bl -tag -width ".Dv HWT_HOOKS" -compact +.It Dv HWT_HOOKS +Enable kernel hooks. +.El +.Sh IOCTL INTERFACE +Once a CTX is allocated, its management character device accepts several +.Xr ioctl 2 +requests: +.Bl -tag -width "HWT_IOC_RECORD_GET" +.It Dv HWT_IOC_START +Start tracing. +In HWT CPU mode the tracing does actually start with this +.Xr ioctl 2 +request. +In the Thread mode, the tracing "running" flag set, but tracing begins after +scheduler switches the target thread onto CPU and return to user mode. +.It Dv HWT_IOC_STOP +Stop tracing of the particular CTX. +.It Dv HWT_IOC_RECORD_GET +Copy all or part of records collected during hook invocation and associated +with this CTX to userspace. +.It Dv HWT_IOC_BUFPTR_GET +Get current pointer in buffer that is filled by tracing units in real-time. +.It Dv HWT_IOC_SET_CONFIG +Set architecture-specific config (optional). +.It Dv HWT_IOC_WAKEUP +Wake up a thread that has been put to sleep by HWT framework hooks. +.It Dv HWT_IOC_SVC_BUF +For SPE-only, the kernel is waiting for userspace to notify that it has copied +out a buffer to avoid data loss/overwriting buffers. +.El +.Sh SEE ALSO +.Xr hwt 8 +.Sh HISTORY +The +.Nm +framework first appeared in +.Fx 15.0 . +.Sh AUTHORS +.An Ruslan Bukin Aq Mt br@FreeBSD.org +.An Bojan Novković Aq Mt bnovkov@freebsd.org +.An Zachary Leaf Aq Mt zachary.leaf@arm.com diff --git a/share/man/man7/Makefile b/share/man/man7/Makefile index 021bf9251bda..7daa0ffed8ea 100644 --- a/share/man/man7/Makefile +++ b/share/man/man7/Makefile @@ -17,6 +17,7 @@ MAN= arch.7 \ intro.7 \ maclabel.7 \ mitigations.7 \ + named_attribute.7 \ operator.7 \ orders.7 \ ports.7 \ diff --git a/share/man/man7/named_attribute.7 b/share/man/man7/named_attribute.7 new file mode 100644 index 000000000000..7cd778620357 --- /dev/null +++ b/share/man/man7/named_attribute.7 @@ -0,0 +1,275 @@ +.\" +.\" Copyright (c) 2025 Rick Macklem +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd July 3, 2025 +.Dt NAMED_ATTRIBUTE 7 +.Os +.Sh NAME +.Nm named_attribute +.Nd Solaris-like extended attribute system interface +.Sh DESCRIPTION +Description of the system interface for named attributes +(the NFS Version 4 terminology). +.Ss Introduction +This document describes an alternate system interface for extended +attributes as compared to +.Xr extattr 2 . +It is based on the interface provided by Solaris and NFS Version 4. +.Pp +This interface associates a directory, known as a named attribute directory, +to a file system object. +This directory is read in the same manner as a normal directory via the +.Xr getdents 2 +or +.Xr getdirentries 2 +system calls. +The +.Pa .\& +and +.Pa ..\& +entries refer to the directory itself and to the associated file object, +respectively. +The other entries in this directory +are the names of the extended attributes for the associated file object +and are referred to as named attributes. +These named attributes are regular files used to store the attribute's +value. +.Pp +A named attribute directory does not live in the file system's name space. +It is accessed via an +.Xr open 2 +or +.Xr openat 2 +system call done on a file to query the named attributes for the file, +with the +.Dv O_NAMEDATTR +flag specified and a +.Fa path +argument of +.Pa .\& . +This file descriptor can be used as the +.Fa fd +argument for a variety of system calls, such as: +.Xr fchdir 2 , +.Xr unlinkat 2 +and +.Xr renameat 2 . +.Xr renameat 2 +is only permitted to rename a named attribute within the same named +attribute directory. +.Pp +When a file descriptor for a file object in the file system's namespace +is used as the +.Fa fd +argument of an +.Xr openat 2 +along with the +.Fa flag +.Dv O_NAMEDATTR +and a +.Fa path +argument that is the name of a named attribute (not +.Pa .\& +or +.Pa ..\& +), a file descriptor for the named attribute is returned. +If the +.Fa flag +.Dv O_CREAT +is specified, the named attribute will be created if it does not exist. +The +.Fa path +argument must be a single component name, with no embedded +.Dq / +in it. +I/O on these named attribute file descriptors may be performed by +standard I/O system calls +such as: +.Xr read 2 , +.Xr write 2 , +.Xr lseek 2 +and +.Xr ftruncate 2 . +.Pp +The +.Dv _PC_NAMEDATTR_ENABLED +.Fa name +argument to +.Xr pathconf 2 +will return 1 if the file system supports named attributes. +The +.Dv _PC_HAS_NAMEDATTR +.Fa name +argument to +.Xr pathconf 2 +will return 1 if there are one or more named attributes for the file. +If an application does a +.Xr openat 2 +of +.Dq .\& +to open a named attribute directory when no named attribute directory exists, +an empty named attribute directory will be created. +Testing +.Dv _PC_HAS_NAMEDATTR +can be done to avoid creating these named attribute directories unnecessarily. +.Pp +The named attribute interface is a different mechanism/system call interface for +manipulating extended attributes compared with +.Xr extattr 2 . +Although the named attribute machanism might require different internal +implementation +of extended attributes within a file system, both ZFS and NFSv4 provide +both mechanisms, which can be used interchangeably to manipulate +extended attributes, but with a couple of limitations. +.Bl -bullet +.It +The +.Xr extattr 2 +interface requires that an extended attribute's value be set or acquired +via a single system call using a single buffer. +This limits the size of the attribute's value. +.It +The named attribute interface does not support system namespace +extended attributes and, +as such, system namespace extended attributes must be manipulated via +.Xr extattr 2 . +.El +.Pp +The named attribute mechanism/system call interface provides certain +advantages over +.Xr extattr 2 . +Since the attribute's value is updated via +.Xr read 2 +and +.Xr write 2 +system calls, the attribute's data may be as large as any regular file +and may be partially updated. +(Note that this interface does not provide the atomicity guarantee that +.Xr extattr 2 +does.) +The permission to access a named attribute directory is determined from +the access control information for the associated file object. +However, access control information can be set on each individual attribute +in a manner similar to a regular file. +This provides +.Dq per attribute +granular control over attribute permissions via +.Xr fchown 2 . +.Pp +At this time, the only local file system which supports this interface +is ZFS and only if the +.Dv xattr +property is set to +.Dq dir . +(Note that, even when +.Dq zfs get xattr <file-system> +shows +.Dq on +the command +.Dq zfs set xattr=dir <file-system> +must be done, followed by a remount to make the setting take effect.) +A NFSv4 mount will also support this interface, but only if the NFSv4 +server file system supports named attributes (the openattr operation). +The +.Fx +NFSv4 server supports named attributes only +for ZFS exported file systems where the +.Dq xattr +property is set to +.Dq dir +for the file system. +.Sh EXAMPLES +.Bd -literal +#include <stdio.h> +#include <dirent.h> +#include <fcntl.h> +#include <unistd.h> + +\&... + +/* For a file called "myfile". Failure checks removed for brevity. */ +int file_fd, nameddir_fd, namedattr_fd; +ssize_t siz; +char buf[DIRBLKSIZ], *cp; +struct dirent *dp; +long named_enabled, has_named_attrs; + +\&... +/* Check to see if named attributes are supported. */ +named_enabled = pathconf("myfile", _PC_NAMEDATTR_ENABLED); +if (named_enabled <= 0) + err(1, "Named attributes not enabled"); +/* Test to see if named attribute(s) exist for the file. */ +has_named_attrs = pathconf("myfile", _PC_HAS_NAMEDATTR); +if (has_named_attrs == 1) + printf("myfile has named attribute(s)\\n"); +else + printf("myfile does not have any named attributes\\n"); +/* Open a named attribute directory. */ +file_fd = open("myfile", O_RDONLY, 0); +nameddir_fd = openat(file_fd, ".", O_NAMEDATTR, 0); +\&... +/* and read it, assuming it all fits in DIRBLKSIZ for simplicity. */ +siz = getdents(fd, buf, sizeof(buf)); +cp = buf; +while (cp < &buf[siz]) { + dp = (struct dirent *)cp; + printf("name=%s\\n", dp->d_name); + cp += dp->d_reclen; +} +\&... +/* Open/create a named attribute called "foo". */ +namedattr_fd = openat(file_fd, "foo", O_CREAT | O_RDWR | + O_TRUNC | O_NAMEDATTR, 0600); +\&... +/* Write foo's attribute value. */ +write(namedattr_fd, "xxxyyy", 6); +\&... +/* Read foo's attribute value. */ +lseek(namedattr_fd, 0, SEEK_SET); +siz = read(namedattr_fd, buf, sizeof(buf)); +\&... +/* And close "foo". */ +close(namedattr_fd); +\&... +/* Rename "foo" to "oldfoo". */ +renameat(nameddir_fd, "foo", nameddir_fd, "oldfoo"); +/* and delete "oldfoo". */ +unlinkat(nameddir_fd, "oldfoo", AT_RESOLVE_BENEATH); +.Ed +.Pp +The +.Xr runat 1 +command may be used to perform shell commands on named attributes. +For example: +.Bd -literal +$ runat myfile cp /etc/hosts attrhosts # creates attrhosts +$ runat myfile cat attrhosts # displays contents of attrhosts +$ runat myfile ls -l # lists the attributes for myfile +.Ed +.Pp +If using the +.Xr bash 1 +shell, the command +.Dq cd -@ foo +enters the named attribute directory for the file object +.Dq foo . +.Sh SEE ALSO +.Xr bash 1 , +.Xr runat 1 , +.Xr chdir 2 , +.Xr extattr 2 , +.Xr lseek 2 , +.Xr open 2 , +.Xr pathconf 2 , +.Xr read 2 , +.Xr rename 2 , +.Xr truncate 2 , +.Xr unlinkat 2 , +.Xr write 2 , +.Xr zfsprops 7 +.Sh HISTORY +This interface first appeared in +.Fx 15.0 . diff --git a/stand/efi/libefi/efinet.c b/stand/efi/libefi/efinet.c index 186d816cd323..e872110ef08f 100644 --- a/stand/efi/libefi/efinet.c +++ b/stand/efi/libefi/efinet.c @@ -256,6 +256,7 @@ efi_env_net_params(struct iodesc *desc) rootip.s_addr = rootaddr; #ifdef EFINET_DEBUG + printf("%s: proto=%d\n", __func__, netproto); printf("%s: ip=%s\n", __func__, inet_ntoa(myip)); printf("%s: mask=%s\n", __func__, intoa(netmask)); printf("%s: gateway=%s\n", __func__, inet_ntoa(gateip)); @@ -427,6 +428,7 @@ efinet_dev_init(void) dif->dif_private = handles2[i]; } + efinet_dev.dv_cleanup = netdev.dv_cleanup; efinet_dev.dv_open = netdev.dv_open; efinet_dev.dv_close = netdev.dv_close; efinet_dev.dv_strategy = netdev.dv_strategy; diff --git a/stand/efi/loader/arch/amd64/elf64_freebsd.c b/stand/efi/loader/arch/amd64/elf64_freebsd.c index c4265aca035e..35bd4d6c1419 100644 --- a/stand/efi/loader/arch/amd64/elf64_freebsd.c +++ b/stand/efi/loader/arch/amd64/elf64_freebsd.c @@ -209,6 +209,12 @@ elf64_exec(struct preloaded_file *fp) trampoline, PT4); printf("Start @ 0x%lx ...\n", ehdr->e_entry); + /* + * we have to cleanup here because net_cleanup() doesn't work after + * we call ExitBootServices + */ + dev_cleanup(); + efi_time_fini(); err = bi_load(fp->f_args, &modulep, &kernend, true); if (err != 0) { @@ -218,8 +224,6 @@ elf64_exec(struct preloaded_file *fp) return (err); } - dev_cleanup(); - trampoline(trampstack, copy_staging == COPY_STAGING_ENABLE ? efi_copy_finish : efi_copy_finish_nop, kernend, modulep, PT4, ehdr->e_entry); diff --git a/stand/efi/loader/arch/arm/exec.c b/stand/efi/loader/arch/arm/exec.c index c2a79523c02a..3963b6c0104b 100644 --- a/stand/efi/loader/arch/arm/exec.c +++ b/stand/efi/loader/arch/arm/exec.c @@ -74,16 +74,17 @@ __elfN(arm_exec)(struct preloaded_file *fp) printf("Kernel entry at %p...\n", entry); printf("Kernel args: %s\n", fp->f_args); + /* + * we have to cleanup here because net_cleanup() doesn't work after + * we call ExitBootServices + */ + dev_cleanup(); + if ((error = bi_load(fp->f_args, &modulep, &kernend, true)) != 0) { efi_time_init(); return (error); } - /* At this point we've called ExitBootServices, so we can't call - * printf or any other function that uses Boot Services */ - - dev_cleanup(); - (*entry)((void *)modulep); panic("exec returned"); } diff --git a/stand/efi/loader/arch/arm64/exec.c b/stand/efi/loader/arch/arm64/exec.c index 91a0503a976f..89e2ad7521a8 100644 --- a/stand/efi/loader/arch/arm64/exec.c +++ b/stand/efi/loader/arch/arm64/exec.c @@ -69,6 +69,12 @@ elf64_exec(struct preloaded_file *fp) ehdr = (Elf_Ehdr *)&(md->md_data); entry = efi_translate(ehdr->e_entry); + /* + * we have to cleanup here because net_cleanup() doesn't work after + * we call ExitBootServices + */ + dev_cleanup(); + efi_time_fini(); err = bi_load(fp->f_args, &modulep, &kernendp, true); if (err != 0) { @@ -76,8 +82,6 @@ elf64_exec(struct preloaded_file *fp) return (err); } - dev_cleanup(); - /* Clean D-cache under kernel area and invalidate whole I-cache */ clean_addr = (vm_offset_t)efi_translate(fp->f_addr); clean_size = (vm_offset_t)efi_translate(kernendp) - clean_addr; diff --git a/stand/efi/loader/arch/i386/elf64_freebsd.c b/stand/efi/loader/arch/i386/elf64_freebsd.c index b02cda2269bc..22cdd685ea9b 100644 --- a/stand/efi/loader/arch/i386/elf64_freebsd.c +++ b/stand/efi/loader/arch/i386/elf64_freebsd.c @@ -252,6 +252,13 @@ elf64_exec(struct preloaded_file *fp) ehdr->e_entry ); + + /* + * we have to cleanup here because net_cleanup() doesn't work after + * we call ExitBootServices + */ + dev_cleanup(); + efi_time_fini(); err = bi_load(fp->f_args, &modulep, &kernend, true); if (err != 0) { @@ -259,8 +266,6 @@ elf64_exec(struct preloaded_file *fp) return (err); } - dev_cleanup(); - trampoline(trampstack, type == AllocateMaxAddress ? efi_copy_finish : efi_copy_finish_nop, kernend, modulep, PT4, gdtr, ehdr->e_entry); diff --git a/stand/efi/loader/arch/riscv/exec.c b/stand/efi/loader/arch/riscv/exec.c index 9da61229ef68..a53fbd9442b0 100644 --- a/stand/efi/loader/arch/riscv/exec.c +++ b/stand/efi/loader/arch/riscv/exec.c @@ -86,17 +86,17 @@ __elfN(exec)(struct preloaded_file *fp) printf("Kernel entry at %p...\n", entry); printf("Kernel args: %s\n", fp->f_args); + /* + * we have to cleanup here because net_cleanup() doesn't work after + * we call ExitBootServices + */ + dev_cleanup(); + if ((error = bi_load(fp->f_args, &modulep, &kernend, true)) != 0) { efi_time_init(); return (error); } - /* - * At this point we've called ExitBootServices, so we can't call - * printf or any other function that uses Boot Services - */ - dev_cleanup(); - (*entry)((void *)modulep); panic("exec returned"); } diff --git a/stand/libsa/zfs/zfsimpl.c b/stand/libsa/zfs/zfsimpl.c index 41ef5a46f30e..c7dc72561eff 100644 --- a/stand/libsa/zfs/zfsimpl.c +++ b/stand/libsa/zfs/zfsimpl.c @@ -1379,7 +1379,7 @@ spa_create(uint64_t guid, const char *name) free(spa); return (NULL); } - spa->spa_root_vdev->v_name = strdup("root"); + spa->spa_root_vdev->v_name = spa->spa_name; STAILQ_INSERT_TAIL(&zfs_pools, spa, spa_link); return (spa); @@ -2006,7 +2006,7 @@ vdev_probe(vdev_phys_read_t *_read, vdev_phys_write_t *_write, void *priv, vdev_t *vdev; nvlist_t *nvl; uint64_t val; - uint64_t guid, vdev_children; + uint64_t guid; uint64_t pool_txg, pool_guid; const char *pool_name; int rc, namelen; @@ -2067,7 +2067,9 @@ vdev_probe(vdev_phys_read_t *_read, vdev_phys_write_t *_write, void *priv, nvlist_find(nvl, ZPOOL_CONFIG_POOL_GUID, DATA_TYPE_UINT64, NULL, &pool_guid, NULL) != 0 || nvlist_find(nvl, ZPOOL_CONFIG_POOL_NAME, DATA_TYPE_STRING, - NULL, &pool_name, &namelen) != 0) { + NULL, &pool_name, &namelen) != 0 || + nvlist_find(nvl, ZPOOL_CONFIG_GUID, DATA_TYPE_UINT64, + NULL, &guid, NULL) != 0) { /* * Cache and spare devices end up here - just ignore * them. @@ -2083,8 +2085,6 @@ vdev_probe(vdev_phys_read_t *_read, vdev_phys_write_t *_write, void *priv, if (spa == NULL) { char *name; - nvlist_find(nvl, ZPOOL_CONFIG_VDEV_CHILDREN, - DATA_TYPE_UINT64, NULL, &vdev_children, NULL); name = malloc(namelen + 1); if (name == NULL) { nvlist_destroy(nvl); @@ -2098,7 +2098,6 @@ vdev_probe(vdev_phys_read_t *_read, vdev_phys_write_t *_write, void *priv, nvlist_destroy(nvl); return (ENOMEM); } - spa->spa_root_vdev->v_nchildren = vdev_children; } if (pool_txg > spa->spa_txg) spa->spa_txg = pool_txg; @@ -2109,11 +2108,6 @@ vdev_probe(vdev_phys_read_t *_read, vdev_phys_write_t *_write, void *priv, * be some kind of alias (overlapping slices, dangerously dedicated * disks etc). */ - if (nvlist_find(nvl, ZPOOL_CONFIG_GUID, DATA_TYPE_UINT64, - NULL, &guid, NULL) != 0) { - nvlist_destroy(nvl); - return (EIO); - } vdev = vdev_find(guid); /* Has this vdev already been inited? */ if (vdev && vdev->v_phys_read) { @@ -3541,8 +3535,10 @@ zfs_spa_init(spa_t *spa) return (EIO); } rc = load_nvlist(spa, config_object, &nvlist); - if (rc != 0) + if (rc != 0) { + printf("ZFS: failed to load pool %s nvlist\n", spa->spa_name); return (rc); + } rc = zap_lookup(spa, &dir, DMU_POOL_ZPOOL_CHECKPOINT, sizeof(uint64_t), sizeof(checkpoint) / sizeof(uint64_t), diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c index ae7cf14c8f8e..1facab47473c 100644 --- a/sys/cam/ata/ata_da.c +++ b/sys/cam/ata/ata_da.c @@ -1359,10 +1359,7 @@ adaasync(void *callback_arg, uint32_t code, case AC_GETDEV_CHANGED: { softc = (struct ada_softc *)periph->softc; - memset(&cgd, 0, sizeof(cgd)); - xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL); - cgd.ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action((union ccb *)&cgd); + xpt_gdev_type(&cgd, periph->path); /* * Update our information based on the new Identify data. diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c index 833df6cfb99b..730656684e2a 100644 --- a/sys/cam/cam_periph.c +++ b/sys/cam/cam_periph.c @@ -767,27 +767,28 @@ camperiphfree(struct cam_periph *periph) CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph destroyed\n")); if (periph->flags & CAM_PERIPH_NEW_DEV_FOUND) { - union ccb ccb; - void *arg; - - memset(&ccb, 0, sizeof(ccb)); switch (periph->deferred_ac) { - case AC_FOUND_DEVICE: - ccb.ccb_h.func_code = XPT_GDEV_TYPE; - xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL); - xpt_action(&ccb); - arg = &ccb; + case AC_FOUND_DEVICE: { + struct ccb_getdev cgd; + + xpt_gdev_type(&cgd, periph->path); + periph->deferred_callback(NULL, periph->deferred_ac, + periph->path, &cgd); break; - case AC_PATH_REGISTERED: - xpt_path_inq(&ccb.cpi, periph->path); - arg = &ccb; + } + case AC_PATH_REGISTERED: { + struct ccb_pathinq cpi; + + xpt_path_inq(&cpi, periph->path); + periph->deferred_callback(NULL, periph->deferred_ac, + periph->path, &cpi); break; + } default: - arg = NULL; + periph->deferred_callback(NULL, periph->deferred_ac, + periph->path, NULL); break; } - periph->deferred_callback(NULL, periph->deferred_ac, - periph->path, arg); } xpt_free_path(periph->path); free(periph, M_CAMPERIPH); @@ -1682,10 +1683,7 @@ camperiphscsisenseerror(union ccb *ccb, union ccb **orig, /* * Grab the inquiry data for this device. */ - memset(&cgd, 0, sizeof(cgd)); - xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path, CAM_PRIORITY_NORMAL); - cgd.ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action((union ccb *)&cgd); + xpt_gdev_type(&cgd, ccb->ccb_h.path); err_action = scsi_error_action(&ccb->csio, &cgd.inq_data, sense_flags); @@ -2133,11 +2131,7 @@ cam_periph_devctl_notify(union ccb *ccb) sbuf_cat(&sb, "serial=\""); if ((cgd = (struct ccb_getdev *)xpt_alloc_ccb_nowait()) != NULL) { - xpt_setup_ccb(&cgd->ccb_h, ccb->ccb_h.path, - CAM_PRIORITY_NORMAL); - cgd->ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action((union ccb *)cgd); - + xpt_gdev_type(cgd, ccb->ccb_h.path); if (cgd->ccb_h.status == CAM_REQ_CMP) sbuf_bcat(&sb, cgd->serial_num, cgd->serial_num_len); xpt_free_ccb((union ccb *)cgd); diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index 38bc82c69aad..2ec736e7f4ac 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -2471,15 +2471,12 @@ xptsetasyncfunc(struct cam_ed *device, void *arg) if ((device->flags & CAM_DEV_UNCONFIGURED) != 0) return (1); - memset(&cgd, 0, sizeof(cgd)); xpt_compile_path(&path, NULL, device->target->bus->path_id, device->target->target_id, device->lun_id); - xpt_setup_ccb(&cgd.ccb_h, &path, CAM_PRIORITY_NORMAL); - cgd.ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action((union ccb *)&cgd); + xpt_gdev_type(&cgd, &path); csa->callback(csa->callback_arg, AC_FOUND_DEVICE, &path, &cgd); diff --git a/sys/cam/cam_xpt.h b/sys/cam/cam_xpt.h index 57225a0ae92d..efa6c823245a 100644 --- a/sys/cam/cam_xpt.h +++ b/sys/cam/cam_xpt.h @@ -145,19 +145,31 @@ uint32_t xpt_poll_setup(union ccb *start_ccb); void xpt_sim_poll(struct cam_sim *sim); /* - * Perform a path inquiry at the request priority. bzero may be redundant for - * allocated CCBs, but for the on-stack CCBs it's required. + * Perform a path inquiry. bzero may be redundant for allocated CCBs, but for + * the on-stack CCBs it's required. */ static inline void xpt_path_inq(struct ccb_pathinq *cpi, struct cam_path *path) { - bzero(cpi, sizeof(*cpi)); xpt_setup_ccb(&cpi->ccb_h, path, CAM_PRIORITY_NONE); cpi->ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)cpi); } +/* + * Perform get device type. bzero may be redundant for allocated CCBs, but for + * the on-stack CCBs it's required. + */ +static inline void +xpt_gdev_type(struct ccb_getdev *cgd, struct cam_path *path) +{ + bzero(cgd, sizeof(*cgd)); + xpt_setup_ccb(&cgd->ccb_h, path, CAM_PRIORITY_NONE); + cgd->ccb_h.func_code = XPT_GDEV_TYPE; + xpt_action((union ccb *)cgd); +} + #endif /* _KERNEL */ #endif /* _CAM_CAM_XPT_H */ diff --git a/sys/cam/mmc/mmc_da.c b/sys/cam/mmc/mmc_da.c index f7c478076144..7f8bf3516804 100644 --- a/sys/cam/mmc/mmc_da.c +++ b/sys/cam/mmc/mmc_da.c @@ -692,10 +692,7 @@ sddaasync(void *callback_arg, uint32_t code, case AC_GETDEV_CHANGED: { CAM_DEBUG(path, CAM_DEBUG_TRACE, ("=> AC_GETDEV_CHANGED\n")); - memset(&cgd, 0, sizeof(cgd)); - xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL); - cgd.ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action((union ccb *)&cgd); + xpt_gdev_type(&cgd, periph->path); cam_periph_async(periph, code, path, arg); break; } diff --git a/sys/cam/scsi/scsi_all.c b/sys/cam/scsi/scsi_all.c index 13a376ebb6e3..b518f84454ad 100644 --- a/sys/cam/scsi/scsi_all.c +++ b/sys/cam/scsi/scsi_all.c @@ -3708,11 +3708,7 @@ scsi_command_string(struct cam_device *device, struct ccb_scsiio *csio, /* * Get the device information. */ - xpt_setup_ccb(&cgd->ccb_h, - csio->ccb_h.path, - CAM_PRIORITY_NORMAL); - cgd->ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action((union ccb *)cgd); + xpt_gdev_type(cgd, csio->ccb_h.path); /* * If the device is unconfigured, just pretend that it is a hard @@ -5144,11 +5140,7 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio, /* * Get the device information. */ - xpt_setup_ccb(&cgd->ccb_h, - csio->ccb_h.path, - CAM_PRIORITY_NORMAL); - cgd->ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action((union ccb *)cgd); + xpt_gdev_type(cgd, csio->ccb_h.path); /* * If the device is unconfigured, just pretend that it is a hard diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c index 00a417f65052..e622a96ec77e 100644 --- a/sys/cam/scsi/scsi_cd.c +++ b/sys/cam/scsi/scsi_cd.c @@ -1240,13 +1240,7 @@ cddone(struct cam_periph *periph, union ccb *done_ccb) /*getcount_only*/0); status = done_ccb->ccb_h.status; - - bzero(&cgd, sizeof(cgd)); - xpt_setup_ccb(&cgd.ccb_h, - done_ccb->ccb_h.path, - CAM_PRIORITY_NORMAL); - cgd.ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action((union ccb *)&cgd); + xpt_gdev_type(&cgd, done_ccb->ccb_h.path); if (scsi_extract_sense_ccb(done_ccb, &error_code, &sense_key, &asc, &ascq)) diff --git a/sys/cam/scsi/scsi_ch.c b/sys/cam/scsi/scsi_ch.c index 89a817c1b488..3da22ba61392 100644 --- a/sys/cam/scsi/scsi_ch.c +++ b/sys/cam/scsi/scsi_ch.c @@ -1705,11 +1705,7 @@ chscsiversion(struct cam_periph *periph) /* * Get the device information. */ - xpt_setup_ccb(&cgd->ccb_h, - periph->path, - CAM_PRIORITY_NORMAL); - cgd->ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action((union ccb *)cgd); + xpt_gdev_type(cgd, periph->path); if (cgd->ccb_h.status != CAM_REQ_CMP) { xpt_free_ccb((union ccb *)cgd); diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c index 0a2389cd9b5d..d02750aaacaf 100644 --- a/sys/cam/scsi/scsi_da.c +++ b/sys/cam/scsi/scsi_da.c @@ -5035,11 +5035,7 @@ dadone_proberc(struct cam_periph *periph, union ccb *done_ccb) /*timeout*/0, /*getcount_only*/0); - memset(&cgd, 0, sizeof(cgd)); - xpt_setup_ccb(&cgd.ccb_h, done_ccb->ccb_h.path, - CAM_PRIORITY_NORMAL); - cgd.ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action((union ccb *)&cgd); + xpt_gdev_type(&cgd, done_ccb->ccb_h.path); if (scsi_extract_sense_ccb(done_ccb, &error_code, &sense_key, &asc, &ascq)) @@ -5077,6 +5073,18 @@ dadone_proberc(struct cam_periph *periph, union ccb *done_ccb) * behind a SATL translation that's fallen into a * terminally fatal state. * + * 4/2 happens on some HGST drives that are quite + * ill. We've already sent the start unit command (for + * which we ignore a 44/0 asc/ascq, which I'm hesitant + * to change since it's so basic and there's other error + * conditions to the START UNIT we should ignore). So to + * require initialization at this point when it should + * be fine implies to me, at least, that we should + * invalidate. Since we do read capacity in geom tasting + * a lot, and since this timeout is long, this leads to + * up to a 10 minute delay in booting. + * + * 4/2: LOGICAL UNIT NOT READY, INITIALIZING COMMAND REQUIRED * 25/0: LOGICAL UNIT NOT SUPPORTED * 44/0: INTERNAL TARGET FAILURE * 44/1: PERSISTENT RESERVATION INFORMATION LOST @@ -5084,6 +5092,7 @@ dadone_proberc(struct cam_periph *periph, union ccb *done_ccb) */ if ((have_sense) && (asc != 0x25) && (asc != 0x44) + && (asc != 0x04 && ascq != 0x02) && (error_code == SSD_CURRENT_ERROR || error_code == SSD_DESC_CURRENT_ERROR)) { const char *sense_key_desc; diff --git a/sys/cam/scsi/scsi_enc_ses.c b/sys/cam/scsi/scsi_enc_ses.c index c429e820a1fd..435874a9874a 100644 --- a/sys/cam/scsi/scsi_enc_ses.c +++ b/sys/cam/scsi/scsi_enc_ses.c @@ -979,10 +979,7 @@ ses_paths_iter(enc_softc_t *enc, enc_element_t *elm, != CAM_REQ_CMP) return; - memset(&cgd, 0, sizeof(cgd)); - xpt_setup_ccb(&cgd.ccb_h, path, CAM_PRIORITY_NORMAL); - cgd.ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action((union ccb *)&cgd); + xpt_gdev_type(&cgd, path); if (cam_ccb_success((union ccb *)&cgd)) callback(enc, elm, path, callback_arg); diff --git a/sys/cam/scsi/scsi_sa.c b/sys/cam/scsi/scsi_sa.c index cfd48c98f30e..88147393192f 100644 --- a/sys/cam/scsi/scsi_sa.c +++ b/sys/cam/scsi/scsi_sa.c @@ -4731,12 +4731,7 @@ saextget(struct cdev *dev, struct cam_periph *periph, struct sbuf *sb, SASBADDVARSTR(sb, indent, periph->periph_name, %s, periph_name, strlen(periph->periph_name) + 1); SASBADDUINT(sb, indent, periph->unit_number, %u, unit_number); - memset(&cgd, 0, sizeof(cgd)); - xpt_setup_ccb(&cgd.ccb_h, - periph->path, - CAM_PRIORITY_NORMAL); - cgd.ccb_h.func_code = XPT_GDEV_TYPE; - xpt_action((union ccb *)&cgd); + xpt_gdev_type(&cgd, periph->path); if ((cgd.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { g->status = MT_EXT_GET_ERROR; snprintf(g->error_str, sizeof(g->error_str), diff --git a/sys/dev/gpio/acpi_gpiobus.c b/sys/dev/gpio/acpi_gpiobus.c index f9468e0deda0..94f4e5771266 100644 --- a/sys/dev/gpio/acpi_gpiobus.c +++ b/sys/dev/gpio/acpi_gpiobus.c @@ -357,7 +357,7 @@ acpi_gpiobus_attach(device_t dev) status = AcpiWalkResources(handle, "_AEI", acpi_gpiobus_enumerate_aei, &ctx); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) device_printf(dev, "Failed to enumerate AEI resources\n"); return (0); diff --git a/sys/dev/hyperv/vmbus/vmbus_chan.c b/sys/dev/hyperv/vmbus/vmbus_chan.c index 189a3e66a039..7ea60a499c72 100644 --- a/sys/dev/hyperv/vmbus/vmbus_chan.c +++ b/sys/dev/hyperv/vmbus/vmbus_chan.c @@ -1555,7 +1555,7 @@ vmbus_event_flags_proc(struct vmbus_softc *sc, volatile u_long *event_flags, continue; flags = atomic_swap_long(&event_flags[f], 0); - chid_base = f << VMBUS_EVTFLAG_SHIFT; + chid_base = f * VMBUS_EVTFLAG_LEN; while ((chid_ofs = ffsl(flags)) != 0) { struct vmbus_channel *chan; @@ -1599,7 +1599,7 @@ vmbus_event_proc_compat(struct vmbus_softc *sc, int cpu) eventf = VMBUS_PCPU_GET(sc, event_flags, cpu) + VMBUS_SINT_MESSAGE; if (atomic_testandclear_long(&eventf->evt_flags[0], 0)) { vmbus_event_flags_proc(sc, sc->vmbus_rx_evtflags, - VMBUS_CHAN_MAX_COMPAT >> VMBUS_EVTFLAG_SHIFT); + VMBUS_CHAN_MAX_COMPAT / VMBUS_EVTFLAG_LEN); } } @@ -1903,7 +1903,7 @@ vmbus_chan_msgproc_choffer(struct vmbus_softc *sc, * Setup event flag. */ chan->ch_evtflag = - &sc->vmbus_tx_evtflags[chan->ch_id >> VMBUS_EVTFLAG_SHIFT]; + &sc->vmbus_tx_evtflags[chan->ch_id / VMBUS_EVTFLAG_LEN]; chan->ch_evtflag_mask = 1UL << (chan->ch_id & VMBUS_EVTFLAG_MASK); /* diff --git a/sys/dev/hyperv/vmbus/vmbus_reg.h b/sys/dev/hyperv/vmbus/vmbus_reg.h index 4aa729475b5d..76cdca0ebeb2 100644 --- a/sys/dev/hyperv/vmbus/vmbus_reg.h +++ b/sys/dev/hyperv/vmbus/vmbus_reg.h @@ -60,16 +60,10 @@ CTASSERT(sizeof(struct vmbus_message) == VMBUS_MSG_SIZE); * Hyper-V SynIC event flags */ -#ifdef __LP64__ -#define VMBUS_EVTFLAGS_MAX 32 -#define VMBUS_EVTFLAG_SHIFT 6 -#else -#define VMBUS_EVTFLAGS_MAX 64 -#define VMBUS_EVTFLAG_SHIFT 5 -#endif -#define VMBUS_EVTFLAG_LEN (1 << VMBUS_EVTFLAG_SHIFT) +#define VMBUS_EVTFLAG_LEN (sizeof(u_long) * 8) #define VMBUS_EVTFLAG_MASK (VMBUS_EVTFLAG_LEN - 1) #define VMBUS_EVTFLAGS_SIZE 256 +#define VMBUS_EVTFLAGS_MAX (VMBUS_EVTFLAGS_SIZE / sizeof(u_long)) struct vmbus_evtflags { u_long evt_flags[VMBUS_EVTFLAGS_MAX]; diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c b/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c index 8b8f2e570245..4de451f1b039 100644 --- a/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c +++ b/sys/dev/mlx5/mlx5_en/mlx5_en_hw_tls_rx.c @@ -42,13 +42,30 @@ static if_snd_tag_free_t mlx5e_tls_rx_snd_tag_free; static if_snd_tag_modify_t mlx5e_tls_rx_snd_tag_modify; +static if_snd_tag_status_str_t mlx5e_tls_rx_snd_tag_status_str; static const struct if_snd_tag_sw mlx5e_tls_rx_snd_tag_sw = { .snd_tag_modify = mlx5e_tls_rx_snd_tag_modify, .snd_tag_free = mlx5e_tls_rx_snd_tag_free, + .snd_tag_status_str = mlx5e_tls_rx_snd_tag_status_str, .type = IF_SND_TAG_TYPE_TLS_RX }; +static const char *mlx5e_tls_rx_progress_params_auth_state_str[] = { + [MLX5E_TLS_RX_PROGRESS_PARAMS_AUTH_STATE_NO_OFFLOAD] = "no_offload", + [MLX5E_TLS_RX_PROGRESS_PARAMS_AUTH_STATE_OFFLOAD] = "offload", + [MLX5E_TLS_RX_PROGRESS_PARAMS_AUTH_STATE_AUTHENTICATION] = + "authentication", +}; + +static const char *mlx5e_tls_rx_progress_params_record_tracker_state_str[] = { + [MLX5E_TLS_RX_PROGRESS_PARAMS_RECORD_TRACKER_STATE_START] = "start", + [MLX5E_TLS_RX_PROGRESS_PARAMS_RECORD_TRACKER_STATE_TRACKING] = + "tracking", + [MLX5E_TLS_RX_PROGRESS_PARAMS_RECORD_TRACKER_STATE_SEARCHING] = + "searching", +}; + MALLOC_DEFINE(M_MLX5E_TLS_RX, "MLX5E_TLS_RX", "MLX5 ethernet HW TLS RX"); /* software TLS RX context */ @@ -250,7 +267,8 @@ mlx5e_tls_rx_send_progress_parameters_sync(struct mlx5e_iq *iq, mtx_unlock(&iq->lock); while (1) { - if (wait_for_completion_timeout(&ptag->progress_complete, hz) != 0) + if (wait_for_completion_timeout(&ptag->progress_complete, + msecs_to_jiffies(1000)) != 0) break; priv = container_of(iq, struct mlx5e_channel, iq)->priv; if (priv->mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR || @@ -331,7 +349,8 @@ done: * Zero is returned upon success, else some error happened. */ static int -mlx5e_tls_rx_receive_progress_parameters(struct mlx5e_iq *iq, struct mlx5e_tls_rx_tag *ptag) +mlx5e_tls_rx_receive_progress_parameters(struct mlx5e_iq *iq, + struct mlx5e_tls_rx_tag *ptag, mlx5e_iq_callback_t *cb) { struct mlx5e_get_tls_progress_params_wqe *wqe; const u32 ds_cnt = DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS); @@ -367,7 +386,7 @@ mlx5e_tls_rx_receive_progress_parameters(struct mlx5e_iq *iq, struct mlx5e_tls_r memcpy(iq->doorbell.d32, &wqe->ctrl, sizeof(iq->doorbell.d32)); iq->data[pi].num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS); - iq->data[pi].callback = &mlx5e_tls_rx_receive_progress_parameters_cb; + iq->data[pi].callback = cb; iq->data[pi].arg = ptag; m_snd_tag_ref(&ptag->tag); @@ -819,6 +838,7 @@ mlx5e_tls_rx_snd_tag_alloc(if_t ifp, } ptag->flow_rule = flow_rule; + init_completion(&ptag->progress_complete); return (0); @@ -968,7 +988,8 @@ mlx5e_tls_rx_snd_tag_modify(struct m_snd_tag *pmt, union if_snd_tag_modify_param params->tls_rx.tls_rec_length, params->tls_rx.tls_seq_number) && ptag->tcp_resync_pending == 0) { - err = mlx5e_tls_rx_receive_progress_parameters(iq, ptag); + err = mlx5e_tls_rx_receive_progress_parameters(iq, ptag, + &mlx5e_tls_rx_receive_progress_parameters_cb); if (err != 0) { MLX5E_TLS_RX_STAT_INC(ptag, rx_resync_err, 1); } else { @@ -1001,6 +1022,74 @@ mlx5e_tls_rx_snd_tag_free(struct m_snd_tag *pmt) queue_work(priv->tls_rx.wq, &ptag->work); } +static void +mlx5e_tls_rx_str_status_cb(void *arg) +{ + struct mlx5e_tls_rx_tag *ptag; + + ptag = (struct mlx5e_tls_rx_tag *)arg; + complete_all(&ptag->progress_complete); + m_snd_tag_rele(&ptag->tag); +} + +static int +mlx5e_tls_rx_snd_tag_status_str(struct m_snd_tag *pmt, char *buf, size_t *sz) +{ + int err, out_size; + struct mlx5e_iq *iq; + void *buffer; + uint32_t tracker_state_val; + uint32_t auth_state_val; + struct mlx5e_priv *priv; + struct mlx5e_tls_rx_tag *ptag = + container_of(pmt, struct mlx5e_tls_rx_tag, tag); + + if (buf == NULL) + return (0); + + MLX5E_TLS_RX_TAG_LOCK(ptag); + priv = container_of(ptag->tls_rx, struct mlx5e_priv, tls_rx); + iq = mlx5e_tls_rx_get_iq(priv, ptag->flowid, ptag->flowtype); + reinit_completion(&ptag->progress_complete); + err = mlx5e_tls_rx_receive_progress_parameters(iq, ptag, + &mlx5e_tls_rx_str_status_cb); + MLX5E_TLS_RX_TAG_UNLOCK(ptag); + if (err != 0) + return (err); + + for (;;) { + if (wait_for_completion_timeout(&ptag->progress_complete, + msecs_to_jiffies(1000)) != 0) + break; + if (priv->mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR || + pci_channel_offline(priv->mdev->pdev) != 0) + return (ENXIO); + } + buffer = mlx5e_tls_rx_get_progress_buffer(ptag); + tracker_state_val = MLX5_GET(tls_progress_params, buffer, + record_tracker_state); + auth_state_val = MLX5_GET(tls_progress_params, buffer, auth_state); + + /* Validate tracker state value is in range */ + if (tracker_state_val > + MLX5E_TLS_RX_PROGRESS_PARAMS_RECORD_TRACKER_STATE_SEARCHING) + return (EINVAL); + + /* Validate auth state value is in range */ + if (auth_state_val > + MLX5E_TLS_RX_PROGRESS_PARAMS_AUTH_STATE_AUTHENTICATION) + return (EINVAL); + + out_size = snprintf(buf, *sz, "tracker_state: %s, auth_state: %s", + mlx5e_tls_rx_progress_params_record_tracker_state_str[ + tracker_state_val], + mlx5e_tls_rx_progress_params_auth_state_str[auth_state_val]); + + if (out_size <= *sz) + *sz = out_size; + return (0); +} + #else int diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index fbfcdafaa06b..fa451887e73e 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -1096,12 +1096,11 @@ nfs_setattr(struct vop_setattr_args *ap) /* * Disallow write attempts if the filesystem is mounted read-only. */ - if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || + if ((vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || vap->va_birthtime.tv_sec != VNOVAL || - vap->va_mode != (mode_t)VNOVAL || - vap->va_flags != (u_long)VNOVAL) && + vap->va_mode != (mode_t)VNOVAL) && (vp->v_mount->mnt_flag & MNT_RDONLY)) return (EROFS); if (vap->va_size != VNOVAL) { diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index a81f1492ef95..43ee0383669f 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -1652,10 +1652,11 @@ nfsvno_rename(struct nameidata *fromndp, struct nameidata *tondp, } if (fvp == tvp) { /* - * If source and destination are the same, there is nothing to - * do. Set error to -1 to indicate this. + * If source and destination are the same, there is + * nothing to do. Set error to EJUSTRETURN to indicate + * this. */ - error = -1; + error = EJUSTRETURN; goto out; } if (nd->nd_flag & ND_NFSV4) { @@ -1697,10 +1698,26 @@ nfsvno_rename(struct nameidata *fromndp, struct nameidata *tondp, " dsdvp=%p\n", dsdvp[0]); } out: - if (!error) { + mp = NULL; + if (error == 0) { + error = VOP_GETWRITEMOUNT(tondp->ni_dvp, &mp); + if (error == 0) { + if (mp == NULL) { + error = ENOENT; + } else { + error = lockmgr(&mp->mnt_renamelock, + LK_EXCLUSIVE | LK_NOWAIT, NULL); + if (error != 0) + error = ERELOOKUP; + } + } + } + if (error == 0) { error = VOP_RENAME(fromndp->ni_dvp, fromndp->ni_vp, &fromndp->ni_cnd, tondp->ni_dvp, tondp->ni_vp, &tondp->ni_cnd); + lockmgr(&mp->mnt_renamelock, LK_RELEASE, 0); + vfs_rel(mp); } else { if (tdvp == tvp) vrele(tdvp); @@ -1710,8 +1727,13 @@ out: vput(tvp); vrele(fromndp->ni_dvp); vrele(fvp); - if (error == -1) + if (error == EJUSTRETURN) { error = 0; + } else if (error == ERELOOKUP && mp != NULL) { + lockmgr(&mp->mnt_renamelock, LK_EXCLUSIVE, 0); + lockmgr(&mp->mnt_renamelock, LK_RELEASE, 0); + vfs_rel(mp); + } } /* diff --git a/sys/kern/subr_pctrie.c b/sys/kern/subr_pctrie.c index 3a3548bad52b..bb86c779b936 100644 --- a/sys/kern/subr_pctrie.c +++ b/sys/kern/subr_pctrie.c @@ -691,21 +691,23 @@ _pctrie_lookup_ge(struct pctrie *ptree, struct pctrie_node *node, */ if (node == PCTRIE_NULL || *pctrie_toval(node) < index) { /* Climb the path to find a node with a descendant > index. */ - for (node = parent; node != NULL; node = pctrie_parent(node)) { - slot = pctrie_slot(node, index) + 1; - if ((node->pn_popmap >> slot) != 0) + node = NULL; + while (parent != NULL) { + slot = pctrie_slot(parent, index) + 1; + if ((parent->pn_popmap >> slot) != 0) break; + node = parent; + parent = pctrie_parent(node); } - if (node == NULL) { + if (parent == NULL) { if (parent_out != NULL) - *parent_out = NULL; + *parent_out = node; return (NULL); } /* Step to the least child with a descendant > index. */ - slot += ffs(node->pn_popmap >> slot) - 1; - parent = node; - node = pctrie_node_load(&node->pn_child[slot], NULL, + slot += ffs(parent->pn_popmap >> slot) - 1; + node = pctrie_node_load(&parent->pn_child[slot], NULL, PCTRIE_LOCKED); } /* Descend to the least leaf of the subtrie. */ @@ -785,21 +787,23 @@ _pctrie_lookup_le(struct pctrie *ptree, struct pctrie_node *node, */ if (node == PCTRIE_NULL || *pctrie_toval(node) > index) { /* Climb the path to find a node with a descendant < index. */ - for (node = parent; node != NULL; node = pctrie_parent(node)) { - slot = pctrie_slot(node, index); - if ((node->pn_popmap & ((1 << slot) - 1)) != 0) + node = NULL; + while (parent != NULL) { + slot = pctrie_slot(parent, index); + if ((parent->pn_popmap & ((1 << slot) - 1)) != 0) break; + node = parent; + parent = pctrie_parent(node); } - if (node == NULL) { + if (parent == NULL) { if (parent_out != NULL) - *parent_out = NULL; + *parent_out = node; return (NULL); } /* Step to the greatest child with a descendant < index. */ - slot = ilog2(node->pn_popmap & ((1 << slot) - 1)); - parent = node; - node = pctrie_node_load(&node->pn_child[slot], NULL, + slot = ilog2(parent->pn_popmap & ((1 << slot) - 1)); + node = pctrie_node_load(&parent->pn_child[slot], NULL, PCTRIE_LOCKED); } /* Descend to the greatest leaf of the subtrie. */ diff --git a/sys/kern/vfs_inotify.c b/sys/kern/vfs_inotify.c index 41e73bb41a49..2b42228465a4 100644 --- a/sys/kern/vfs_inotify.c +++ b/sys/kern/vfs_inotify.c @@ -760,9 +760,11 @@ vn_inotify_add_watch(struct vnode *vp, struct inotify_softc *sc, uint32_t mask, * directory if it's specified as a vnode. */ vrefact(vp); + VOP_UNLOCK(vp); NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, dp->d_name, vp); error = namei(&nd); + vn_lock(vp, LK_SHARED | LK_RETRY); if (error != 0) break; vn_irflag_set_cond(nd.ni_vp, VIRF_INOTIFY_PARENT); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index d880733cbfe7..c71e0d9ee569 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -4314,10 +4314,6 @@ kern_getdirentries(struct thread *td, int fd, char *buf, size_t count, vp = fp->f_vnode; foffset = foffset_lock(fp, 0); unionread: - if (vp->v_type != VDIR) { - error = EINVAL; - goto fail; - } if (__predict_false((vp->v_vflag & VV_UNLINKED) != 0)) { error = ENOENT; goto fail; @@ -4330,6 +4326,19 @@ unionread: auio.uio_segflg = bufseg; auio.uio_td = td; vn_lock(vp, LK_SHARED | LK_RETRY); + /* + * We want to return ENOTDIR for anything that is not VDIR, but + * not for VBAD, and we can't check for VBAD while the vnode is + * unlocked. + */ + if (vp->v_type != VDIR) { + if (vp->v_type == VBAD) + error = EBADF; + else + error = ENOTDIR; + VOP_UNLOCK(vp); + goto fail; + } AUDIT_ARG_VNODE1(vp); loff = auio.uio_offset = foffset; #ifdef MAC diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index bccd4b84561a..dbe48242381d 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1745,6 +1745,23 @@ in_pcbrele(struct inpcb *inp, const inp_lookup_t lock) } /* + * Dereference and rlock inp, for which the caller must own the + * reference. Returns true if inp no longer usable, false otherwise. + */ +bool +in_pcbrele_rlock(struct inpcb *inp) +{ + INP_RLOCK(inp); + if (in_pcbrele_rlocked(inp)) + return (true); + if ((inp->inp_flags & INP_FREED) != 0) { + INP_RUNLOCK(inp); + return (true); + } + return (false); +} + +/* * Unconditionally schedule an inpcb to be freed by decrementing its * reference count, which should occur only after the inpcb has been detached * from its socket. If another thread holds a temporary reference (acquired diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 57cf15ca37fc..9e0618e87601 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -681,6 +681,7 @@ void in_pcbref(struct inpcb *); bool in_pcbrele(struct inpcb *, inp_lookup_t); bool in_pcbrele_rlocked(struct inpcb *); bool in_pcbrele_wlocked(struct inpcb *); +bool in_pcbrele_rlock(struct inpcb *inp); typedef bool inp_match_t(const struct inpcb *, void *); struct inpcb_iterator { diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index cd42a67294a6..db415f6bdf03 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -2720,9 +2720,15 @@ tcp_ktlslist_locked(SYSCTL_HANDLER_ARGS, bool export_keys) ksr->snd_tag->sw->snd_tag_status_str != NULL) { sz = SND_TAG_STATUS_MAXLEN; - ksr->snd_tag->sw->snd_tag_status_str( + in_pcbref(inp); + INP_RUNLOCK(inp); + error = ksr->snd_tag->sw-> + snd_tag_status_str( ksr->snd_tag, NULL, &sz); - len += sz; + if (in_pcbrele_rlock(inp)) + return (EDEADLK); + if (error == 0) + len += sz; } } kss = so->so_snd.sb_tls_info; @@ -2739,9 +2745,15 @@ tcp_ktlslist_locked(SYSCTL_HANDLER_ARGS, bool export_keys) kss->snd_tag->sw->snd_tag_status_str != NULL) { sz = SND_TAG_STATUS_MAXLEN; - kss->snd_tag->sw->snd_tag_status_str( + in_pcbref(inp); + INP_RUNLOCK(inp); + error = kss->snd_tag->sw-> + snd_tag_status_str( kss->snd_tag, NULL, &sz); - len += sz; + if (in_pcbrele_rlock(inp)) + return (EDEADLK); + if (error == 0) + len += sz; } } if (p) { @@ -2811,9 +2823,16 @@ tcp_ktlslist_locked(SYSCTL_HANDLER_ARGS, bool export_keys) if (ksr->snd_tag != NULL && ksr->snd_tag->sw->snd_tag_status_str != NULL) { sz = SND_TAG_STATUS_MAXLEN; - ksr->snd_tag->sw->snd_tag_status_str( + in_pcbref(inp); + INP_RUNLOCK(inp); + error = ksr->snd_tag->sw->snd_tag_status_str( ksr->snd_tag, buf + len, &sz); - len += sz; + if (in_pcbrele_rlock(inp)) + return (EDEADLK); + if (error == 0) { + xktls->rcv.drv_st_len = sz; + len += sz; + } } } if (kss != NULL && kss->gen == xig.xig_gen) { @@ -2828,9 +2847,16 @@ tcp_ktlslist_locked(SYSCTL_HANDLER_ARGS, bool export_keys) if (kss->snd_tag != NULL && kss->snd_tag->sw->snd_tag_status_str != NULL) { sz = SND_TAG_STATUS_MAXLEN; - kss->snd_tag->sw->snd_tag_status_str( + in_pcbref(inp); + INP_RUNLOCK(inp); + error = kss->snd_tag->sw->snd_tag_status_str( kss->snd_tag, buf + len, &sz); - len += sz; + if (in_pcbrele_rlock(inp)) + return (EDEADLK); + if (error == 0) { + xktls->snd.drv_st_len = sz; + len += sz; + } } } len = roundup2(len, __alignof(*xktls)); @@ -2858,12 +2884,23 @@ tcp_ktlslist_locked(SYSCTL_HANDLER_ARGS, bool export_keys) static int tcp_ktlslist1(SYSCTL_HANDLER_ARGS, bool export_keys) { - int res; - - sx_xlock(&ktlslist_lock); - res = tcp_ktlslist_locked(oidp, arg1, arg2, req, export_keys); - sx_xunlock(&ktlslist_lock); - return (res); + int repeats, error; + + for (repeats = 0; repeats < 100; repeats++) { + if (sx_xlock_sig(&ktlslist_lock)) + return (EINTR); + error = tcp_ktlslist_locked(oidp, arg1, arg2, req, + export_keys); + sx_xunlock(&ktlslist_lock); + if (error != EDEADLK) + break; + if (sig_intr() != 0) { + error = EINTR; + break; + } + req->oldidx = 0; + } + return (error); } static int diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h index 87460aae2dd4..efda38279848 100644 --- a/sys/sys/elf_common.h +++ b/sys/sys/elf_common.h @@ -306,7 +306,7 @@ typedef struct { and MPRC of Peking University */ #define EM_AARCH64 183 /* AArch64 (64-bit ARM) */ #define EM_RISCV 243 /* RISC-V */ -#define EM_LOONGARCH 258 /* Loongson LoongArch */ +#define EM_LOONGARCH 258 /* Loongson LoongArch */ /* Non-standard or deprecated. */ #define EM_486 6 /* Intel i486. */ @@ -392,15 +392,15 @@ typedef struct { */ /* LoongArch Base ABI Modifiers */ -#define EF_LOONGARCH_ABI_SOFT_FLOAT 0x00000001 -#define EF_LOONGARCH_ABI_SINGLE_FLOAT 0x00000002 -#define EF_LOONGARCH_ABI_DOUBLE_FLOAT 0x00000003 -#define EF_LOONGARCH_ABI_MODIFIER_MASK 0x00000007 +#define EF_LOONGARCH_ABI_SOFT_FLOAT 0x00000001 +#define EF_LOONGARCH_ABI_SINGLE_FLOAT 0x00000002 +#define EF_LOONGARCH_ABI_DOUBLE_FLOAT 0x00000003 +#define EF_LOONGARCH_ABI_MODIFIER_MASK 0x00000007 /* LoongArch Object file ABI versions */ -#define EF_LOONGARCH_OBJABI_V0 0x00000000 -#define EF_LOONGARCH_OBJABI_V1 0x00000040 -#define EF_LOONGARCH_OBJABI_MASK 0x000000C0 +#define EF_LOONGARCH_OBJABI_V0 0x00000000 +#define EF_LOONGARCH_OBJABI_V1 0x00000040 +#define EF_LOONGARCH_OBJABI_MASK 0x000000C0 #define EF_SPARC_EXT_MASK 0x00ffff00 #define EF_SPARC_32PLUS 0x00000100 @@ -470,12 +470,12 @@ typedef struct { #define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ #define SHT_LOPROC 0x70000000 /* reserved range for processor */ #define SHT_X86_64_UNWIND 0x70000001 /* unwind information */ -#define SHT_AMD64_UNWIND SHT_X86_64_UNWIND +#define SHT_AMD64_UNWIND SHT_X86_64_UNWIND #define SHT_ARM_EXIDX 0x70000001 /* Exception index table. */ -#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking +#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking pre-emption map. */ -#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility +#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility attributes. */ #define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details. */ #define SHT_ARM_OVERLAYSECTION 0x70000005 /* See DBGOVL for details. */ @@ -791,7 +791,7 @@ typedef struct { #define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */ #define DF_1_LOADFLTR 0x00000010 /* Immediate loading of filtees */ #define DF_1_INITFIRST 0x00000020 /* Initialize DSO first at runtime */ -#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ +#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ #define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */ #define DF_1_INTERPOSE 0x00000400 /* Interpose all objects but main */ #define DF_1_NODEFLIB 0x00000800 /* Do not search default paths */ @@ -908,7 +908,7 @@ typedef struct { #define STV_ELIMINATE 0x6 /* Architecture specific data - st_other */ -#define STO_AARCH64_VARIANT_PCS 0x80 +#define STO_AARCH64_VARIANT_PCS 0x80 /* Special symbol table indexes. */ #define STN_UNDEF 0 /* Undefined symbol index. */ @@ -1084,11 +1084,11 @@ typedef struct { #define R_AARCH64_COPY 1024 /* Copy data from shared object */ #define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address */ #define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address */ -#define R_AARCH64_RELATIVE 1027 /* Add load address of shared object */ +#define R_AARCH64_RELATIVE 1027 /* Add load address of shared object */ #define R_AARCH64_TLS_DTPREL64 1028 #define R_AARCH64_TLS_DTPMOD64 1029 -#define R_AARCH64_TLS_TPREL64 1030 -#define R_AARCH64_TLSDESC 1031 /* Identify the TLS descriptor */ +#define R_AARCH64_TLS_TPREL64 1030 +#define R_AARCH64_TLSDESC 1031 /* Identify the TLS descriptor */ #define R_AARCH64_IRELATIVE 1032 #define R_ARM_NONE 0 /* No relocation. */ @@ -1231,8 +1231,8 @@ typedef struct { #define R_MIPS_GOT_HI16 22 /* GOT HI 16 bit */ #define R_MIPS_GOT_LO16 23 /* GOT LO 16 bit */ #define R_MIPS_SUB 24 -#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ -#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ +#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ +#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ #define R_MIPS_JALR 37 #define R_MIPS_TLS_GD 42 #define R_MIPS_COPY 126 @@ -1352,7 +1352,6 @@ typedef struct { * RISC-V relocation types. */ -/* Relocation types used by the dynamic linker. */ #define R_RISCV_NONE 0 #define R_RISCV_32 1 #define R_RISCV_64 2 @@ -1365,8 +1364,7 @@ typedef struct { #define R_RISCV_TLS_DTPREL64 9 #define R_RISCV_TLS_TPREL32 10 #define R_RISCV_TLS_TPREL64 11 - -/* Relocation types not used by the dynamic linker. */ +#define R_RISCV_TLSDESC 12 #define R_RISCV_BRANCH 16 #define R_RISCV_JAL 17 #define R_RISCV_CALL 18 @@ -1392,10 +1390,10 @@ typedef struct { #define R_RISCV_SUB16 38 #define R_RISCV_SUB32 39 #define R_RISCV_SUB64 40 +#define R_RISCV_GOT32_PCREL 41 #define R_RISCV_ALIGN 43 #define R_RISCV_RVC_BRANCH 44 #define R_RISCV_RVC_JUMP 45 -#define R_RISCV_RVC_LUI 46 #define R_RISCV_RELAX 51 #define R_RISCV_SUB6 52 #define R_RISCV_SET6 53 @@ -1404,6 +1402,14 @@ typedef struct { #define R_RISCV_SET32 56 #define R_RISCV_32_PCREL 57 #define R_RISCV_IRELATIVE 58 +#define R_RISCV_PLT32 59 +#define R_RISCV_SET_ULEB128 60 +#define R_RISCV_SUB_ULEB128 61 +#define R_RISCV_TLSDESC_HI20 62 +#define R_RISCV_TLSDESC_LOAD_LO12 63 +#define R_RISCV_TLSDESC_ADD_LO12 64 +#define R_RISCV_TLSDESC_CALL 65 +#define R_RISCV_VENDOR 191 /* * Loongson LoongArch relocation types. @@ -1413,101 +1419,101 @@ typedef struct { */ /* Relocation types used by the dynamic linker */ -#define R_LARCH_NONE 0 -#define R_LARCH_32 1 -#define R_LARCH_64 2 -#define R_LARCH_RELATIVE 3 -#define R_LARCH_COPY 4 -#define R_LARCH_JUMP_SLOT 5 -#define R_LARCH_TLS_DTPMOD32 6 -#define R_LARCH_TLS_DTPMOD64 7 -#define R_LARCH_TLS_DTPREL32 8 -#define R_LARCH_TLS_DTPREL64 9 -#define R_LARCH_TLS_TPREL32 10 -#define R_LARCH_TLS_TPREL64 11 -#define R_LARCH_IRELATIVE 12 -#define R_LARCH_MARK_LA 20 -#define R_LARCH_MARK_PCREL 21 -#define R_LARCH_SOP_PUSH_PCREL 22 -#define R_LARCH_SOP_PUSH_ABSOLUTE 23 -#define R_LARCH_SOP_PUSH_DUP 24 -#define R_LARCH_SOP_PUSH_GPREL 25 -#define R_LARCH_SOP_PUSH_TLS_TPREL 26 -#define R_LARCH_SOP_PUSH_TLS_GOT 27 -#define R_LARCH_SOP_PUSH_TLS_GD 28 -#define R_LARCH_SOP_PUSH_PLT_PCREL 29 -#define R_LARCH_SOP_ASSERT 30 -#define R_LARCH_SOP_NOT 31 -#define R_LARCH_SOP_SUB 32 -#define R_LARCH_SOP_SL 33 -#define R_LARCH_SOP_SR 34 -#define R_LARCH_SOP_ADD 35 -#define R_LARCH_SOP_AND 36 -#define R_LARCH_SOP_IF_ELSE 37 -#define R_LARCH_SOP_POP_32_S_10_5 38 -#define R_LARCH_SOP_POP_32_U_10_12 39 -#define R_LARCH_SOP_POP_32_S_10_12 40 -#define R_LARCH_SOP_POP_32_S_10_16 41 -#define R_LARCH_SOP_POP_32_S_10_16_S2 42 -#define R_LARCH_SOP_POP_32_S_5_20 43 -#define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44 -#define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45 -#define R_LARCH_SOP_POP_32_U 46 -#define R_LARCH_ADD8 47 -#define R_LARCH_ADD16 48 -#define R_LARCH_ADD24 49 -#define R_LARCH_ADD32 50 -#define R_LARCH_ADD64 51 -#define R_LARCH_SUB8 52 -#define R_LARCH_SUB16 53 -#define R_LARCH_SUB24 54 -#define R_LARCH_SUB32 55 -#define R_LARCH_SUB64 56 -#define R_LARCH_GNU_VTINHERIT 57 -#define R_LARCH_GNU_VTENTRY 58 +#define R_LARCH_NONE 0 +#define R_LARCH_32 1 +#define R_LARCH_64 2 +#define R_LARCH_RELATIVE 3 +#define R_LARCH_COPY 4 +#define R_LARCH_JUMP_SLOT 5 +#define R_LARCH_TLS_DTPMOD32 6 +#define R_LARCH_TLS_DTPMOD64 7 +#define R_LARCH_TLS_DTPREL32 8 +#define R_LARCH_TLS_DTPREL64 9 +#define R_LARCH_TLS_TPREL32 10 +#define R_LARCH_TLS_TPREL64 11 +#define R_LARCH_IRELATIVE 12 +#define R_LARCH_MARK_LA 20 +#define R_LARCH_MARK_PCREL 21 +#define R_LARCH_SOP_PUSH_PCREL 22 +#define R_LARCH_SOP_PUSH_ABSOLUTE 23 +#define R_LARCH_SOP_PUSH_DUP 24 +#define R_LARCH_SOP_PUSH_GPREL 25 +#define R_LARCH_SOP_PUSH_TLS_TPREL 26 +#define R_LARCH_SOP_PUSH_TLS_GOT 27 +#define R_LARCH_SOP_PUSH_TLS_GD 28 +#define R_LARCH_SOP_PUSH_PLT_PCREL 29 +#define R_LARCH_SOP_ASSERT 30 +#define R_LARCH_SOP_NOT 31 +#define R_LARCH_SOP_SUB 32 +#define R_LARCH_SOP_SL 33 +#define R_LARCH_SOP_SR 34 +#define R_LARCH_SOP_ADD 35 +#define R_LARCH_SOP_AND 36 +#define R_LARCH_SOP_IF_ELSE 37 +#define R_LARCH_SOP_POP_32_S_10_5 38 +#define R_LARCH_SOP_POP_32_U_10_12 39 +#define R_LARCH_SOP_POP_32_S_10_12 40 +#define R_LARCH_SOP_POP_32_S_10_16 41 +#define R_LARCH_SOP_POP_32_S_10_16_S2 42 +#define R_LARCH_SOP_POP_32_S_5_20 43 +#define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44 +#define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45 +#define R_LARCH_SOP_POP_32_U 46 +#define R_LARCH_ADD8 47 +#define R_LARCH_ADD16 48 +#define R_LARCH_ADD24 49 +#define R_LARCH_ADD32 50 +#define R_LARCH_ADD64 51 +#define R_LARCH_SUB8 52 +#define R_LARCH_SUB16 53 +#define R_LARCH_SUB24 54 +#define R_LARCH_SUB32 55 +#define R_LARCH_SUB64 56 +#define R_LARCH_GNU_VTINHERIT 57 +#define R_LARCH_GNU_VTENTRY 58 /* * Relocs whose processing do not require a stack machine. * * Spec addition: https://github.com/loongson/LoongArch-Documentation/pull/57 */ -#define R_LARCH_B16 64 -#define R_LARCH_B21 65 -#define R_LARCH_B26 66 -#define R_LARCH_ABS_HI20 67 -#define R_LARCH_ABS_LO12 68 -#define R_LARCH_ABS64_LO20 69 -#define R_LARCH_ABS64_HI12 70 -#define R_LARCH_PCALA_HI20 71 -#define R_LARCH_PCALA_LO12 72 -#define R_LARCH_PCALA64_LO20 73 -#define R_LARCH_PCALA64_HI12 74 -#define R_LARCH_GOT_PC_HI20 75 -#define R_LARCH_GOT_PC_LO12 76 -#define R_LARCH_GOT64_PC_LO20 77 -#define R_LARCH_GOT64_PC_HI12 78 -#define R_LARCH_GOT_HI20 79 -#define R_LARCH_GOT_LO12 80 -#define R_LARCH_GOT64_LO20 81 -#define R_LARCH_GOT64_HI12 82 -#define R_LARCH_TLS_LE_HI20 83 -#define R_LARCH_TLS_LE_LO12 84 -#define R_LARCH_TLS_LE64_LO20 85 -#define R_LARCH_TLS_LE64_HI12 86 -#define R_LARCH_TLS_IE_PC_HI20 87 -#define R_LARCH_TLS_IE_PC_LO12 88 -#define R_LARCH_TLS_IE64_PC_LO20 89 -#define R_LARCH_TLS_IE64_PC_HI12 90 -#define R_LARCH_TLS_IE_HI20 91 -#define R_LARCH_TLS_IE_LO12 92 -#define R_LARCH_TLS_IE64_LO20 93 -#define R_LARCH_TLS_IE64_HI12 94 -#define R_LARCH_TLS_LD_PC_HI20 95 -#define R_LARCH_TLS_LD_HI20 96 -#define R_LARCH_TLS_GD_PC_HI20 97 -#define R_LARCH_TLS_GD_HI20 98 -#define R_LARCH_32_PCREL 99 -#define R_LARCH_RELAX 100 +#define R_LARCH_B16 64 +#define R_LARCH_B21 65 +#define R_LARCH_B26 66 +#define R_LARCH_ABS_HI20 67 +#define R_LARCH_ABS_LO12 68 +#define R_LARCH_ABS64_LO20 69 +#define R_LARCH_ABS64_HI12 70 +#define R_LARCH_PCALA_HI20 71 +#define R_LARCH_PCALA_LO12 72 +#define R_LARCH_PCALA64_LO20 73 +#define R_LARCH_PCALA64_HI12 74 +#define R_LARCH_GOT_PC_HI20 75 +#define R_LARCH_GOT_PC_LO12 76 +#define R_LARCH_GOT64_PC_LO20 77 +#define R_LARCH_GOT64_PC_HI12 78 +#define R_LARCH_GOT_HI20 79 +#define R_LARCH_GOT_LO12 80 +#define R_LARCH_GOT64_LO20 81 +#define R_LARCH_GOT64_HI12 82 +#define R_LARCH_TLS_LE_HI20 83 +#define R_LARCH_TLS_LE_LO12 84 +#define R_LARCH_TLS_LE64_LO20 85 +#define R_LARCH_TLS_LE64_HI12 86 +#define R_LARCH_TLS_IE_PC_HI20 87 +#define R_LARCH_TLS_IE_PC_LO12 88 +#define R_LARCH_TLS_IE64_PC_LO20 89 +#define R_LARCH_TLS_IE64_PC_HI12 90 +#define R_LARCH_TLS_IE_HI20 91 +#define R_LARCH_TLS_IE_LO12 92 +#define R_LARCH_TLS_IE64_LO20 93 +#define R_LARCH_TLS_IE64_HI12 94 +#define R_LARCH_TLS_LD_PC_HI20 95 +#define R_LARCH_TLS_LD_HI20 96 +#define R_LARCH_TLS_GD_PC_HI20 97 +#define R_LARCH_TLS_GD_HI20 98 +#define R_LARCH_32_PCREL 99 +#define R_LARCH_RELAX 100 /* * Relocs added in ELF for the LoongArch™ Architecture v20230519, part of the @@ -1520,13 +1526,13 @@ typedef struct { * in psABI v2.20 because they were proved not necessary to be exposed outside * of the linker. */ -#define R_LARCH_ALIGN 102 -#define R_LARCH_PCREL20_S2 103 -#define R_LARCH_ADD6 105 -#define R_LARCH_SUB6 106 -#define R_LARCH_ADD_ULEB128 107 -#define R_LARCH_SUB_ULEB128 108 -#define R_LARCH_64_PCREL 109 +#define R_LARCH_ALIGN 102 +#define R_LARCH_PCREL20_S2 103 +#define R_LARCH_ADD6 105 +#define R_LARCH_SUB6 106 +#define R_LARCH_ADD_ULEB128 107 +#define R_LARCH_SUB_ULEB128 108 +#define R_LARCH_64_PCREL 109 /* * Relocs added in ELF for the LoongArch™ Architecture v20231102, part of the @@ -1534,7 +1540,7 @@ typedef struct { * * Spec addition: https://github.com/loongson/la-abi-specs/pull/4 */ -#define R_LARCH_CALL36 110 +#define R_LARCH_CALL36 110 /* * Relocs added in ELF for the LoongArch™ Architecture v20231219, part of the @@ -1542,24 +1548,24 @@ typedef struct { * * Spec addition: https://github.com/loongson/la-abi-specs/pull/5 */ -#define R_LARCH_TLS_DESC32 13 -#define R_LARCH_TLS_DESC64 14 -#define R_LARCH_TLS_DESC_PC_HI20 111 -#define R_LARCH_TLS_DESC_PC_LO12 112 -#define R_LARCH_TLS_DESC64_PC_LO20 113 -#define R_LARCH_TLS_DESC64_PC_HI12 114 -#define R_LARCH_TLS_DESC_HI20 115 -#define R_LARCH_TLS_DESC_LO12 116 -#define R_LARCH_TLS_DESC64_LO20 117 -#define R_LARCH_TLS_DESC64_HI12 118 -#define R_LARCH_TLS_DESC_LD 119 -#define R_LARCH_TLS_DESC_CALL 120 -#define R_LARCH_TLS_LE_HI20_R 121 -#define R_LARCH_TLS_LE_ADD_R 122 -#define R_LARCH_TLS_LE_LO12_R 123 -#define R_LARCH_TLS_LD_PCREL20_S2 124 -#define R_LARCH_TLS_GD_PCREL20_S2 125 -#define R_LARCH_TLS_DESC_PCREL20_S2 126 +#define R_LARCH_TLS_DESC32 13 +#define R_LARCH_TLS_DESC64 14 +#define R_LARCH_TLS_DESC_PC_HI20 111 +#define R_LARCH_TLS_DESC_PC_LO12 112 +#define R_LARCH_TLS_DESC64_PC_LO20 113 +#define R_LARCH_TLS_DESC64_PC_HI12 114 +#define R_LARCH_TLS_DESC_HI20 115 +#define R_LARCH_TLS_DESC_LO12 116 +#define R_LARCH_TLS_DESC64_LO20 117 +#define R_LARCH_TLS_DESC64_HI12 118 +#define R_LARCH_TLS_DESC_LD 119 +#define R_LARCH_TLS_DESC_CALL 120 +#define R_LARCH_TLS_LE_HI20_R 121 +#define R_LARCH_TLS_LE_ADD_R 122 +#define R_LARCH_TLS_LE_LO12_R 123 +#define R_LARCH_TLS_LD_PCREL20_S2 124 +#define R_LARCH_TLS_GD_PCREL20_S2 125 +#define R_LARCH_TLS_DESC_PCREL20_S2 126 #define R_SPARC_NONE 0 #define R_SPARC_8 1 diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile index 26c0013696c7..f2c24ad9dec9 100644 --- a/tests/sys/kern/Makefile +++ b/tests/sys/kern/Makefile @@ -18,6 +18,7 @@ ATF_TESTS_C+= kern_descrip_test # One test modifies the maxfiles limit, which can cause spurious test failures. TEST_METADATA.kern_descrip_test+= is_exclusive="true" ATF_TESTS_C+= fdgrowtable_test +ATF_TESTS_C+= getdirentries_test ATF_TESTS_C+= jail_lookup_root ATF_TESTS_C+= inotify_test ATF_TESTS_C+= kill_zombie diff --git a/tests/sys/kern/getdirentries_test.c b/tests/sys/kern/getdirentries_test.c new file mode 100644 index 000000000000..e66872ffe5b6 --- /dev/null +++ b/tests/sys/kern/getdirentries_test.c @@ -0,0 +1,172 @@ +/*- + * Copyright (c) 2025 Klara, Inc. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/stat.h> +#include <sys/mount.h> + +#include <dirent.h> +#include <fcntl.h> +#include <errno.h> +#include <stdint.h> + +#include <atf-c.h> + +ATF_TC(getdirentries_ok); +ATF_TC_HEAD(getdirentries_ok, tc) +{ + atf_tc_set_md_var(tc, "descr", "Successfully read a directory."); +} +ATF_TC_BODY(getdirentries_ok, tc) +{ + char dbuf[4096]; + struct dirent *d; + off_t base; + ssize_t ret; + int dd, n; + + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); + ATF_REQUIRE((ret = getdirentries(dd, dbuf, sizeof(dbuf), &base)) > 0); + ATF_REQUIRE_EQ(0, getdirentries(dd, dbuf, sizeof(dbuf), &base)); + ATF_REQUIRE_EQ(base, lseek(dd, 0, SEEK_CUR)); + ATF_CHECK_EQ(0, close(dd)); + for (n = 0, d = (struct dirent *)dbuf; + d < (struct dirent *)(dbuf + ret); + d = (struct dirent *)((char *)d + d->d_reclen), n++) + /* nothing */ ; + ATF_CHECK_EQ((struct dirent *)(dbuf + ret), d); + ATF_CHECK_EQ(2, n); +} + +ATF_TC(getdirentries_ebadf); +ATF_TC_HEAD(getdirentries_ebadf, tc) +{ + atf_tc_set_md_var(tc, "descr", "Attempt to read a directory " + "from an invalid descriptor."); +} +ATF_TC_BODY(getdirentries_ebadf, tc) +{ + char dbuf[4096]; + off_t base; + int fd; + + ATF_REQUIRE((fd = open("file", O_CREAT | O_WRONLY, 0644)) >= 0); + ATF_REQUIRE_EQ(-1, getdirentries(fd, dbuf, sizeof(dbuf), &base)); + ATF_CHECK_EQ(EBADF, errno); + ATF_REQUIRE_EQ(0, close(fd)); + ATF_REQUIRE_EQ(-1, getdirentries(fd, dbuf, sizeof(dbuf), &base)); + ATF_CHECK_EQ(EBADF, errno); +} + +ATF_TC(getdirentries_efault); +ATF_TC_HEAD(getdirentries_efault, tc) +{ + atf_tc_set_md_var(tc, "descr", "Attempt to read a directory " + "to an invalid buffer."); +} +ATF_TC_BODY(getdirentries_efault, tc) +{ + char dbuf[4096]; + off_t base, *basep; + int dd; + + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); + ATF_REQUIRE_EQ(-1, getdirentries(dd, NULL, sizeof(dbuf), &base)); + ATF_CHECK_EQ(EFAULT, errno); + basep = NULL; + basep++; + ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, sizeof(dbuf), basep)); + ATF_CHECK_EQ(EFAULT, errno); + ATF_CHECK_EQ(0, close(dd)); +} + +ATF_TC(getdirentries_einval); +ATF_TC_HEAD(getdirentries_einval, tc) +{ + atf_tc_set_md_var(tc, "descr", "Attempt to read a directory " + "with various invalid parameters."); +} +ATF_TC_BODY(getdirentries_einval, tc) +{ + struct statfs fsb; + char dbuf[4096]; + off_t base; + ssize_t ret; + int dd; + + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); + ATF_REQUIRE_EQ(0, fstatfs(dd, &fsb)); + /* nbytes too small */ + ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, 8, &base)); + ATF_CHECK_EQ(EINVAL, errno); + /* nbytes too big */ + ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, SIZE_MAX, &base)); + ATF_CHECK_EQ(EINVAL, errno); + /* invalid position */ + ATF_REQUIRE((ret = getdirentries(dd, dbuf, sizeof(dbuf), &base)) > 0); + ATF_REQUIRE_EQ(0, getdirentries(dd, dbuf, sizeof(dbuf), &base)); + ATF_REQUIRE(base > 0); + ATF_REQUIRE_EQ(base + 3, lseek(dd, 3, SEEK_CUR)); + /* known to fail on ufs (FFS2) and zfs, and work on tmpfs */ + if (strcmp(fsb.f_fstypename, "ufs") == 0 || + strcmp(fsb.f_fstypename, "zfs") == 0) { + atf_tc_expect_fail("incorrectly returns 0 instead of EINVAL " + "on %s", fsb.f_fstypename); + } + ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, sizeof(dbuf), &base)); + ATF_CHECK_EQ(EINVAL, errno); + ATF_CHECK_EQ(0, close(dd)); +} + +ATF_TC(getdirentries_enoent); +ATF_TC_HEAD(getdirentries_enoent, tc) +{ + atf_tc_set_md_var(tc, "descr", "Attempt to read a directory " + "after it is deleted."); +} +ATF_TC_BODY(getdirentries_enoent, tc) +{ + char dbuf[4096]; + off_t base; + int dd; + + ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); + ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0); + ATF_REQUIRE_EQ(0, rmdir("dir")); + ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, sizeof(dbuf), &base)); + ATF_CHECK_EQ(ENOENT, errno); +} + +ATF_TC(getdirentries_enotdir); +ATF_TC_HEAD(getdirentries_enotdir, tc) +{ + atf_tc_set_md_var(tc, "descr", "Attempt to read a directory " + "from a descriptor not associated with a directory."); +} +ATF_TC_BODY(getdirentries_enotdir, tc) +{ + char dbuf[4096]; + off_t base; + int fd; + + ATF_REQUIRE((fd = open("file", O_CREAT | O_RDWR, 0644)) >= 0); + ATF_REQUIRE_EQ(-1, getdirentries(fd, dbuf, sizeof(dbuf), &base)); + ATF_CHECK_EQ(ENOTDIR, errno); + ATF_CHECK_EQ(0, close(fd)); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, getdirentries_ok); + ATF_TP_ADD_TC(tp, getdirentries_ebadf); + ATF_TP_ADD_TC(tp, getdirentries_efault); + ATF_TP_ADD_TC(tp, getdirentries_einval); + ATF_TP_ADD_TC(tp, getdirentries_enoent); + ATF_TP_ADD_TC(tp, getdirentries_enotdir); + return (atf_no_error()); +} diff --git a/tools/build/cross-build/include/common/exterr.h b/tools/build/cross-build/include/common/exterr.h new file mode 100644 index 000000000000..62482841c7b2 --- /dev/null +++ b/tools/build/cross-build/include/common/exterr.h @@ -0,0 +1,14 @@ +#ifndef _EXTERR_H_ +#define _EXTERR_H_ + +#include <sys/types.h> + +static inline int +uexterr_gettext(char *buf, size_t bufsz) +{ + if (bufsz > 0) + buf[0] = '\0'; + return (0); +} + +#endif diff --git a/tools/build/cross-build/include/common/sys/exterrvar.h b/tools/build/cross-build/include/common/sys/exterrvar.h new file mode 100644 index 000000000000..0ba821aadef2 --- /dev/null +++ b/tools/build/cross-build/include/common/sys/exterrvar.h @@ -0,0 +1,6 @@ +#ifndef _SYS_EXTERRVAR_H_ +#define _SYS_EXTERRVAR_H_ + +#define UEXTERROR_MAXLEN 256 + +#endif diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index e0689b2d811f..1e63e4616909 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -1683,9 +1683,6 @@ OLD_FILES+=usr/share/examples/diskless/README.BOOTP OLD_FILES+=usr/share/examples/diskless/README.TEMPLATING OLD_FILES+=usr/share/examples/diskless/clone_root OLD_FILES+=usr/share/examples/dma/mailer.conf -OLD_FILES+=usr/share/examples/drivers/README -OLD_FILES+=usr/share/examples/drivers/make_device_driver.sh -OLD_FILES+=usr/share/examples/drivers/make_pseudo_driver.sh OLD_FILES+=usr/share/examples/dwatch/profile_template OLD_FILES+=usr/share/examples/etc/README.examples OLD_FILES+=usr/share/examples/etc/bsd-style-copyright @@ -1912,7 +1909,6 @@ OLD_DIRS+=usr/share/examples/bsdconfig OLD_DIRS+=usr/share/examples/csh OLD_DIRS+=usr/share/examples/diskless OLD_DIRS+=usr/share/examples/dma -OLD_DIRS+=usr/share/examples/drivers OLD_DIRS+=usr/share/examples/dwatch OLD_DIRS+=usr/share/examples/etc OLD_DIRS+=usr/share/examples/etc/defaults diff --git a/usr.bin/Makefile b/usr.bin/Makefile index b69d25480479..512f75b5d093 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -133,7 +133,6 @@ SUBDIR= alias \ sdiff \ sed \ seq \ - shar \ showmount \ sockstat \ soelim \ diff --git a/usr.bin/kyua/Makefile b/usr.bin/kyua/Makefile index d3a7b9b61f64..a4f95f1106d9 100644 --- a/usr.bin/kyua/Makefile +++ b/usr.bin/kyua/Makefile @@ -32,7 +32,7 @@ MAN= kyua-about.1 \ CFLAGS+= -I${KYUA_SRCDIR} -I${.CURDIR} CFLAGS+= -I${SRCTOP}/contrib/lutok/include -CFLAGS+= -I${SRCTOP}/contrib/sqlite3 +CFLAGS+= -I${SYSROOT:U${DESTDIR}}/${INCLUDEDIR}/private/sqlite3 CFLAGS+= -DHAVE_CONFIG_H # We compile the kyua libraries as part of the main executable as this saves diff --git a/usr.bin/lockf/lockf.1 b/usr.bin/lockf/lockf.1 index d73033101632..40b4497bc80c 100644 --- a/usr.bin/lockf/lockf.1 +++ b/usr.bin/lockf/lockf.1 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd November 25, 2023 +.Dd June 24, 2025 .Dt LOCKF 1 .Os .Sh NAME @@ -30,7 +30,7 @@ .Nd execute a command while holding a file lock .Sh SYNOPSIS .Nm -.Op Fl knsw +.Op Fl knpsTw .Op Fl t Ar seconds .Ar file .Ar command @@ -126,6 +126,32 @@ is not specified, will create .Ar file if necessary. +.It Fl p +Write the pid of the +.Ar command +to +.Ar file . +This option will cause +.Nm +to open +.Ar file +for writing rather than reading. +.It Fl T +Upon receipt of a +.Dv SIGTERM , +forward a +.Dv SIGTERM +along to the +.Ar command +before cleaning up the +.Ar file +and exiting. +By default, +.Nm +effectively orphans the +.Ar command +after cleaning up the +.Ar file . .It Fl t Ar seconds Specifies a timeout for waiting for the lock. By default, diff --git a/usr.bin/lockf/lockf.c b/usr.bin/lockf/lockf.c index 7f88753d1743..16bae36a21e0 100644 --- a/usr.bin/lockf/lockf.c +++ b/usr.bin/lockf/lockf.c @@ -34,6 +34,8 @@ #include <fcntl.h> #include <limits.h> #include <signal.h> +#include <stdatomic.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -50,39 +52,45 @@ union lock_subject { static int acquire_lock(union lock_subject *subj, int flags, int silent); static void cleanup(void); static void killed(int sig); +static void sigchld(int sig); static void timeout(int sig); static void usage(void) __dead2; static void wait_for_lock(const char *name); static const char *lockname; +_Static_assert(sizeof(sig_atomic_t) >= sizeof(pid_t), + "PIDs cannot be managed safely from a signal handler on this platform."); +static sig_atomic_t child = -1; static int lockfd = -1; -static int keep; -static int fdlock; -static volatile sig_atomic_t timed_out; +static bool keep; +static bool fdlock; +static int status; +static bool termchild; +static sig_atomic_t timed_out; /* * Check if fdlock is implied by the given `lockname`. We'll write the fd that * is represented by it out to ofd, and the caller is expected to do any * necessary validation on it. */ -static int +static bool fdlock_implied(const char *name, long *ofd) { char *endp; long fd; if (strncmp(name, FDLOCK_PREFIX, sizeof(FDLOCK_PREFIX) - 1) != 0) - return (0); + return (false); /* Skip past the prefix. */ name += sizeof(FDLOCK_PREFIX) - 1; errno = 0; fd = strtol(name, &endp, 10); if (errno != 0 || *endp != '\0') - return (0); + return (false); *ofd = fd; - return (1); + return (true); } /* @@ -91,35 +99,44 @@ fdlock_implied(const char *name, long *ofd) int main(int argc, char **argv) { - int ch, flags, silent, status; + struct sigaction sa_chld = { + .sa_handler = sigchld, + .sa_flags = SA_NOCLDSTOP, + }, sa_prev; + sigset_t mask, omask; long long waitsec; - pid_t child; + const char *errstr; union lock_subject subj; + int ch, flags; + bool silent, writepid; - silent = keep = 0; + silent = writepid = false; flags = O_CREAT | O_RDONLY; waitsec = -1; /* Infinite. */ - while ((ch = getopt(argc, argv, "knst:w")) != -1) { + while ((ch = getopt(argc, argv, "knpsTt:w")) != -1) { switch (ch) { case 'k': - keep = 1; + keep = true; break; case 'n': flags &= ~O_CREAT; break; case 's': - silent = 1; + silent = true; + break; + case 'T': + termchild = true; break; case 't': - { - const char *errstr; - waitsec = strtonum(optarg, 0, UINT_MAX, &errstr); if (errstr != NULL) errx(EX_USAGE, "invalid timeout \"%s\"", optarg); - } break; + case 'p': + writepid = true; + flags |= O_TRUNC; + /* FALLTHROUGH */ case 'w': flags = (flags & ~O_RDONLY) | O_WRONLY; break; @@ -143,7 +160,7 @@ main(int argc, char **argv) * If there aren't any arguments left, then we must be in fdlock mode. */ if (argc == 0 && *lockname != '/') { - fdlock = 1; + fdlock = true; subj.subj_fd = -1; } else { fdlock = fdlock_implied(lockname, &subj.subj_fd); @@ -208,13 +225,16 @@ main(int argc, char **argv) */ lockfd = acquire_lock(&subj, flags | O_NONBLOCK, silent); while (lockfd == -1 && !timed_out && waitsec != 0) { - if (keep || fdlock) + if (keep || fdlock) { lockfd = acquire_lock(&subj, flags, silent); - else { + } else { wait_for_lock(lockname); lockfd = acquire_lock(&subj, flags | O_NONBLOCK, silent); } + + /* timed_out */ + atomic_signal_fence(memory_order_acquire); } if (waitsec > 0) alarm(0); @@ -234,9 +254,30 @@ main(int argc, char **argv) if (atexit(cleanup) == -1) err(EX_OSERR, "atexit failed"); + + /* + * Block SIGTERM while SIGCHLD is being processed, so that we can safely + * waitpid(2) for the child without a concurrent termination observing + * an invalid pid (i.e., waited-on). If our setup between here and the + * sigsuspend loop gets any more complicated, we should rewrite it to + * just use a pipe to signal the child onto execvp(). + * + * We're blocking SIGCHLD and SIGTERM here so that we don't do any + * cleanup before we're ready to (after the pid is written out). + */ + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + sigaddset(&mask, SIGTERM); + (void)sigprocmask(SIG_BLOCK, &mask, &omask); + + memcpy(&sa_chld.sa_mask, &omask, sizeof(omask)); + sigaddset(&sa_chld.sa_mask, SIGTERM); + (void)sigaction(SIGCHLD, &sa_chld, &sa_prev); + if ((child = fork()) == -1) err(EX_OSERR, "cannot fork"); if (child == 0) { /* The child process. */ + (void)sigprocmask(SIG_SETMASK, &omask, NULL); close(lockfd); execvp(argv[0], argv); warn("%s", argv[0]); @@ -246,11 +287,24 @@ main(int argc, char **argv) signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGTERM, killed); + fclose(stdin); fclose(stdout); fclose(stderr); - if (waitpid(child, &status, 0) == -1) - exit(EX_OSERR); + + /* Write out the pid before we sleep on it. */ + if (writepid) + (void)dprintf(lockfd, "%d\n", (int)child); + + /* Just in case they were blocked on entry. */ + sigdelset(&omask, SIGCHLD); + sigdelset(&omask, SIGTERM); + while (child >= 0) { + (void)sigsuspend(&omask); + /* child */ + atomic_signal_fence(memory_order_acquire); + } + return (WIFEXITED(status) ? WEXITSTATUS(status) : EX_SOFTWARE); } @@ -308,13 +362,35 @@ static void killed(int sig) { + if (termchild && child >= 0) + kill(child, sig); cleanup(); signal(sig, SIG_DFL); - if (kill(getpid(), sig) == -1) + if (raise(sig) == -1) _Exit(EX_OSERR); } /* + * Signal handler for SIGCHLD. Simply waits for the child and ensures that we + * don't end up in a sticky situation if we receive a SIGTERM around the same + * time. + */ +static void +sigchld(int sig __unused) +{ + int ostatus; + + while (waitpid(child, &ostatus, 0) != child) { + if (errno != EINTR) + _exit(EX_OSERR); + } + + status = ostatus; + child = -1; + atomic_signal_fence(memory_order_release); +} + +/* * Signal handler for SIGALRM. */ static void @@ -322,6 +398,7 @@ timeout(int sig __unused) { timed_out = 1; + atomic_signal_fence(memory_order_release); } static void diff --git a/usr.bin/lockf/tests/lockf_test.sh b/usr.bin/lockf/tests/lockf_test.sh index d73c7590653d..823b5673a176 100644 --- a/usr.bin/lockf/tests/lockf_test.sh +++ b/usr.bin/lockf/tests/lockf_test.sh @@ -31,6 +31,24 @@ : ${EX_CANTCREAT:=73} : ${EX_TEMPFAIL:=75} +waitlock() +{ + local cur lockfile tmo + + lockfile="$1" + + cur=0 + tmo=20 + + while [ "$cur" -lt "$tmo" -a ! -f "$lockfile" ]; do + sleep 0.1 + cur=$((cur + 1)) + done + + atf_check_not_equal "$cur" "$tmo" +} + + atf_test_case badargs badargs_body() { @@ -62,6 +80,13 @@ basic_body() atf_check test ! -e "testlock" } +atf_test_case bubble_error +bubble_error_body() +{ + # Ensure that lockf bubbles up the error as expected. + atf_check -s exit:9 lockf testlock sh -c 'exit 9' +} + atf_test_case fdlock fdlock_body() { @@ -189,6 +214,52 @@ needfile_body() atf_check test "$tpass" -lt 10 } +atf_test_case termchild +termchild_body() +{ + lockf -kp testlock sleep 30 & + lpid=$! + + waitlock testlock + + atf_check -o file:testlock pgrep -F testlock + + start=$(date +"%s") + atf_check kill -TERM "$lpid" + wait "$lpid" + end=$(date +"%s") + elapsed=$((end - start)) + + if [ "$elapsed" -gt 5 ]; then + atf_fail "lockf seems to have dodged the SIGTERM ($elapsed passed)" + fi + + # We didn't start lockf with -T this time, so the process should not + # have been terminated. + atf_check -o file:testlock pgrep -F testlock + + lockf -kpT testlock sleep 30 & + lpid=$! + + waitlock testlock + + atf_check -o file:testlock pgrep -F testlock + + start=$(date +"%s") + atf_check kill -TERM "$lpid" + wait "$lpid" + end=$(date +"%s") + elapsed=$((end - start)) + + if [ "$elapsed" -gt 5 ]; then + atf_fail "lockf -T seems to have dodged the SIGTERM ($elapsed passed)" + fi + + # This time, it should have terminated (notably much earlier than our + # 30 second timeout). + atf_check -o empty -e not-empty -s not-exit:0 pgrep -F testlock +} + atf_test_case timeout timeout_body() { @@ -212,6 +283,34 @@ timeout_body() wait "$lpid" || true } +atf_test_case writepid +writepid_body() +{ + lockf -p "testlock" sleep 10 & + lpid=$! + + waitlock "testlock" + + atf_check test -s testlock + atf_check -o file:testlock pgrep -F testlock + atf_check -o file:testlock pgrep -F testlock -fx "sleep 10" + atf_check pkill -TERM -F testlock + + wait + + atf_check test ! -f testlock +} + +atf_test_case writepid_keep +writepid_keep_body() +{ + # Check that we'll clobber any existing contents (a pid, usually) + # once we acquire the lock. + jot -b A -s "" 64 > testlock + atf_check lockf -kp testlock sleep 0 + atf_check -o not-match:"A" cat testlock +} + atf_test_case wrlock wrlock_head() { @@ -233,9 +332,13 @@ atf_init_test_cases() { atf_add_test_case badargs atf_add_test_case basic + atf_add_test_case bubble_error atf_add_test_case fdlock atf_add_test_case keep atf_add_test_case needfile + atf_add_test_case termchild atf_add_test_case timeout + atf_add_test_case writepid + atf_add_test_case writepid_keep atf_add_test_case wrlock } diff --git a/usr.bin/shar/Makefile b/usr.bin/shar/Makefile deleted file mode 100644 index fc940c06d463..000000000000 --- a/usr.bin/shar/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -SCRIPTS=shar.sh -MAN= shar.1 - -.include <bsd.prog.mk> diff --git a/usr.bin/shar/Makefile.depend b/usr.bin/shar/Makefile.depend deleted file mode 100644 index 11aba52f82cf..000000000000 --- a/usr.bin/shar/Makefile.depend +++ /dev/null @@ -1,10 +0,0 @@ -# Autogenerated - do NOT edit! - -DIRDEPS = \ - - -.include <dirdeps.mk> - -.if ${DEP_RELDIR} == ${_DEP_RELDIR} -# local dependencies - needed for -jN in clean tree -.endif diff --git a/usr.bin/shar/shar.1 b/usr.bin/shar/shar.1 deleted file mode 100644 index 6beb1e84ceab..000000000000 --- a/usr.bin/shar/shar.1 +++ /dev/null @@ -1,121 +0,0 @@ -.\" Copyright (c) 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.Dd January 1, 2025 -.Dt SHAR 1 -.Os -.Sh NAME -.Nm shar -.Nd create a shell archive of files -.Sh DEPRECATION NOTICE -.Nm -is obsolete and may not be present in -.Fx 15 -and later. -Because shell archives are simultaneously data and code and are typically -interpreted by -.Xr sh 1 , -they can easily be trojan-horsed and pose a significant security risk to users. -The -.Xr tar 1 -utility can still produce shar encodings of files if needed. -The -.Pa sysutils/freebsd-shar -port has been created to maintain this version of -.Nm -past its deprecation in base. -.Sh SYNOPSIS -.Nm -.Ar -.Sh DESCRIPTION -The -.Nm -command writes a -.Xr sh 1 -shell script to the standard output which will recreate the file -hierarchy specified by the command line operands. -Directories will be recreated and must be specified before the -files they contain (the -.Xr find 1 -utility does this correctly). -.Pp -The -.Nm -command is normally used for distributing files by -.Xr ftp 1 -or -.Xr mail 1 . -.Sh EXAMPLES -To create a shell archive of the program -.Xr ls 1 -and mail it to Rick: -.Bd -literal -offset indent -cd ls -shar `find . -print` \&| mail -s "ls source" rick -.Ed -.Pp -To recreate the program directory: -.Bd -literal -offset indent -mkdir ls -cd ls -\&... -<delete header lines and examine mailed archive> -\&... -sh archive -.Ed -.Sh SEE ALSO -.Xr compress 1 , -.Xr mail 1 , -.Xr tar 1 , -.Xr uuencode 1 -.Sh HISTORY -The -.Nm -command appeared in -.Bx 4.4 . -.Sh BUGS -The -.Nm -command makes no provisions for special types of files or files containing -magic characters. -The -.Nm -command cannot handle files without a newline ('\\n') -as the last character. -.Pp -It is easy to insert trojan horses into -.Nm -files. -It is strongly recommended that all shell archive files be examined -before running them through -.Xr sh 1 . -Archives produced using this implementation of -.Nm -may be easily examined with the command: -.Bd -literal -offset indent -egrep -av '^[X#]' shar.file -.Ed diff --git a/usr.bin/shar/shar.sh b/usr.bin/shar/shar.sh deleted file mode 100644 index 52c31b419fc4..000000000000 --- a/usr.bin/shar/shar.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/sh - -# -# SPDX-License-Identifier: BSD-3-Clause -# -# Copyright (c) 1990, 1993 -# The Regents of the University of California. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. - -if [ $# -eq 0 ]; then - echo 'usage: shar file ...' 1>&2 - exit 64 # EX_USAGE -fi - -for i -do - if [ ! \( -d $i -o -r $i \) ]; then - echo "$i inaccessible or not exist" 1>&2 - exit 66 # EX_NOINPUT - fi -done - -cat << EOF -# This is a shell archive. Save it in a file, remove anything before -# this line, and then unpack it by entering "sh file". Note, it may -# create directories; files and directories will be owned by you and -# have default permissions. -# -# This archive contains: -# -EOF - -for i -do - echo "# $i" -done - -echo "#" - -for i -do - if [ -d "$i" ]; then - echo "echo c - '$i'" - echo "mkdir -p '$i' > /dev/null 2>&1" - else - md5sum=`echo -n "$i" | md5` - echo "echo x - '$i'" - echo "sed 's/^X//' >'$i' << '$md5sum'" - sed 's/^/X/' "$i" || exit 1 - echo "$md5sum" - fi -done -echo exit -echo "" - -exit 0 diff --git a/usr.bin/truncate/truncate.1 b/usr.bin/truncate/truncate.1 index f6b8b0cc37c9..aa70943b889f 100644 --- a/usr.bin/truncate/truncate.1 +++ b/usr.bin/truncate/truncate.1 @@ -1,4 +1,6 @@ .\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" .\" Copyright (c) 2000 Sheldon Hearn <sheldonh@FreeBSD.org>. .\" All rights reserved. .\" Copyright (c) 2021 The FreeBSD Foundation @@ -27,12 +29,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 6, 2025 +.Dd July 9, 2025 .Dt TRUNCATE 1 .Os .Sh NAME .Nm truncate -.Nd truncate, extend the length of files, or perform space management in files +.Nd resize files or manage file space .Sh SYNOPSIS .Nm .Op Fl c @@ -132,7 +134,8 @@ file system space deallocation may be performed in the operation region. The space management operation is performed at the given .Ar offset bytes in the file. -If this option is not specified, the operation is performed at the beginning of the file. +If this option is not specified, +the operation is performed at the beginning of the file. .It Fl l Ar length The length of the operation range in bytes. This option must always be specified if option @@ -195,9 +198,9 @@ truncate -c -s 10M test_file .Pp Same as above but create the file if it does not exist: .Bd -literal -offset indent -truncate -s 10M test_file -ls -l test_file --rw-r--r-- 1 root wheel 10485760 Jul 22 18:48 test_file +truncate -s +10M test_file +ls -lh test_file +-rw-r--r-- 1 root wheel 10M Jul 22 18:48 test_file .Ed .Pp Adjust the size of @@ -207,10 +210,10 @@ to the size of the kernel and create another file with the same size: .Bd -literal -offset indent truncate -r /boot/kernel/kernel test_file test_file2 -ls -l /boot/kernel/kernel test_file* --r-xr-xr-x 1 root wheel 31352552 May 15 14:18 /boot/kernel/kernel --rw-r--r-- 1 root wheel 31352552 Jul 22 19:15 test_file --rw-r--r-- 1 root wheel 31352552 Jul 22 19:15 test_file2 +ls -lh /boot/kernel/kernel test_file* +-r--r--r-- 1 root wheel 30M May 15 14:18 /boot/kernel/kernel +-rw-r--r-- 1 root wheel 30M Jul 22 19:15 test_file +-rw-r--r-- 1 root wheel 30M Jul 22 19:15 test_file2 .Ed .Pp Increase the size of the file @@ -228,9 +231,9 @@ Reduce the size of the file by 5 megabytes: .Bd -literal -offset indent truncate -s -5M test_file -ls -l test_file* --rw-r--r-- 1 root wheel 31352552 Jul 22 19:19 test_file --rw-r--r-- 1 root wheel 31352552 Jul 22 19:15 test_file2 +ls -lh test_file* +-rw-r--r-- 1 root wheel 25M Jul 22 19:17 test_file +-rw-r--r-- 1 root wheel 30M Jul 22 19:15 test_file2 .Ed .Sh SEE ALSO .Xr dd 1 , @@ -247,6 +250,7 @@ The utility first appeared in .Fx 4.2 . .Sh AUTHORS +.An -nosplit The .Nm utility was written by diff --git a/usr.sbin/crunch/examples/really-big.conf b/usr.sbin/crunch/examples/really-big.conf index 12c08b73936f..9c227a7b8d29 100644 --- a/usr.sbin/crunch/examples/really-big.conf +++ b/usr.sbin/crunch/examples/really-big.conf @@ -52,7 +52,7 @@ progs tty ul uname unexpand unifdef uniq units unvis users uudecode uuencode progs vacation vgrind vi vis vmstat w wall wc what whatis whereis who progs whois window write xargs xinstall xstr yacc yes ypcat ypmatch ypwhich -# shell scripts: lorder mkdep shar which +# shell scripts: lorder mkdep which # problems: rdist uses libcompat.a(regex.o), which conflicts with # libedit(readline.o) over regerror(). diff --git a/usr.sbin/gstat/gstat.8 b/usr.sbin/gstat/gstat.8 index 02dbbbc54a3d..2975a93c7fef 100644 --- a/usr.sbin/gstat/gstat.8 +++ b/usr.sbin/gstat/gstat.8 @@ -122,6 +122,9 @@ Quit .El .Sh EXIT STATUS .Ex -std +.Sh EXAMPLES +To filter the output to only physical disks named ada0 through ada4: +.Dl # gstat -f ada0[0-4]$ .Sh SEE ALSO .Xr systat 1 , .Xr geom 4 , |