diff options
Diffstat (limited to 'usr.bin')
115 files changed, 1482 insertions, 515 deletions
diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 0f0233bb5091..6ca784ef6cb6 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -24,10 +24,12 @@ SUBDIR= apply \ comm \ command \ compress \ + cpio \ csplit \ ctlstat \ cut \ diff \ + diff3 \ dirname \ dtc \ du \ @@ -185,7 +187,6 @@ SUBDIR= apply \ SUBDIR.${MK_ACCT}+= lastcomm SUBDIR.${MK_AT}+= at SUBDIR.${MK_BLUETOOTH}+= bluetooth -SUBDIR.${MK_BSD_CPIO}+= cpio SUBDIR.${MK_CALENDAR}+= calendar .if ${MK_CLANG} != "no" || ${MK_LLVM_BINUTILS} != "no" || \ ${MK_LLD} != "no" || ${MK_LLDB} != "no" @@ -206,9 +207,6 @@ SUBDIR.${MK_GAMES}+= pom SUBDIR.${MK_GAMES}+= primes SUBDIR.${MK_GAMES}+= random SUBDIR+= gh-bc -.if ${MK_GNU_DIFF} == "no" -SUBDIR+= diff3 -.endif SUBDIR.${MK_HESIOD}+= hesinfo SUBDIR.${MK_ICONV}+= iconv SUBDIR.${MK_ICONV}+= mkcsmapper @@ -250,6 +248,7 @@ SUBDIR.${MK_TFTP}+= tftp # Only build the elftoolchain tools if we aren't using the LLVM ones. SUBDIR.${MK_TOOLCHAIN}+= addr2line SUBDIR.${MK_TOOLCHAIN}+= ar +SUBDIR.${MK_TOOLCHAIN}+= cxxfilt SUBDIR.${MK_TOOLCHAIN}+= nm SUBDIR.${MK_TOOLCHAIN}+= readelf SUBDIR.${MK_TOOLCHAIN}+= size @@ -257,9 +256,6 @@ SUBDIR.${MK_TOOLCHAIN}+= size SUBDIR.${MK_TOOLCHAIN}+= c89 SUBDIR.${MK_TOOLCHAIN}+= c99 SUBDIR.${MK_TOOLCHAIN}+= ctags -.if ${MK_LLVM_CXXFILT} == "no" -SUBDIR.${MK_TOOLCHAIN}+= cxxfilt -.endif # ELF Tool Chain elfcopy required for EFI objects (PR280771) SUBDIR.${MK_TOOLCHAIN}+= elfcopy SUBDIR.${MK_TOOLCHAIN}+= file2c diff --git a/usr.bin/beep/beep.c b/usr.bin/beep/beep.c index d16ad5b699c3..a6e09fbf61c1 100644 --- a/usr.bin/beep/beep.c +++ b/usr.bin/beep/beep.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2021 Hans Petter Selasky <hselasky@freebsd.org> * * Redistribution and use in source and binary forms, with or without diff --git a/usr.bin/bsdcat/tests/functional_test.sh b/usr.bin/bsdcat/tests/functional_test.sh index efed232374e2..27bf51298bb8 100755 --- a/usr.bin/bsdcat/tests/functional_test.sh +++ b/usr.bin/bsdcat/tests/functional_test.sh @@ -46,7 +46,7 @@ atf_init_test_cases() # Redirect stderr to stdout for the usage message because if you don't # kyua list/kyua test will break: # https://github.com/jmmv/kyua/issues/149 - testcases=$(${TESTER} -h 2>&1 | awk 'p != 0 && $1 ~ /^[0-9]+:/ { print $NF } /Available tests:/ { p=1 }') + testcases=$(${TESTER} -l 2>&1 | awk '/^ [0-9]+: / { print $2 }') for testcase in ${testcases}; do atf_test_case ${testcase} eval "${testcase}_body() { check ${testcase}; }" diff --git a/usr.bin/calendar/calendars/calendar.freebsd b/usr.bin/calendar/calendars/calendar.freebsd index bfcdfe5f9a75..37dad2d237a7 100644 --- a/usr.bin/calendar/calendars/calendar.freebsd +++ b/usr.bin/calendar/calendars/calendar.freebsd @@ -123,7 +123,6 @@ 03/14 Eric Turgeon <ericbsd@FreeBSD.org> born in Edmundston, New Brunswick, Canada, 1982 03/15 Paolo Pisati <piso@FreeBSD.org> born in Lodi, Italy, 1977 03/15 Brian Fundakowski Feldman <green@FreeBSD.org> born in Alexandria, Virginia, United States, 1983 -03/15 First quarterly status reports are due on 03/31 03/17 Michael Smith <msmith@FreeBSD.org> born in Bankstown, New South Wales, Australia, 1971 03/17 Alexander Motin <mav@FreeBSD.org> born in Simferopol, Ukraine, 1979 03/18 Koop Mast <kwm@FreeBSD.org> born in Dokkum, the Netherlands, 1981 @@ -260,7 +259,6 @@ 06/09 Stanislav Galabov <sgalabov@FreeBSD.org> born in Sofia, Bulgaria, 1978 06/11 Alonso Cardenas Marquez <acm@FreeBSD.org> born in Arequipa, Peru, 1979 06/14 Josh Paetzel <jpaetzel@FreeBSD.org> born in Minneapolis, Minnesota, United States, 1973 -06/15 Second quarterly status reports are due on 06/30 06/15 Aymeric Wibo <obiwac@FreeBSD.org> born in Plaistow, London, United Kingdom, 2004 06/17 Tilman Linneweh <arved@FreeBSD.org> born in Weinheim, Baden-Wuerttemberg, Germany, 1978 06/18 Li-Wen Hsu <lwhsu@FreeBSD.org> born in Taipei, Taiwan, Republic of China, 1984 @@ -382,7 +380,6 @@ 09/14 Matthew Seaman <matthew@FreeBSD.org> born in Bristol, United Kingdom, 1965 09/15 Aleksandr Rybalko <ray@FreeBSD.org> born in Odessa, Ukraine, 1977 09/15 Dima Panov <fluffy@FreeBSD.org> born in Khabarovsk, Russian Federation, 1978 -09/15 Third quarterly status reports are due on 09/30 09/16 Maksim Yevmenkin <emax@FreeBSD.org> born in Taganrog, USSR, 1974 09/17 Maxim Bolotin <mb@FreeBSD.org> born in Rostov-on-Don, Russian Federation, 1976 09/18 Matthew Fleming <mdf@FreeBSD.org> born in Cleveland, Ohio, United States, 1975 @@ -488,7 +485,6 @@ 12/11 Koichiro Iwao <meta@FreeBSD.org> born in Oita, Japan, 1987 12/15 James FitzGibbon <jfitz@FreeBSD.org> born in Amersham, Buckinghamshire, United Kingdom, 1974 12/15 Timur I. Bakeyev <timur@FreeBSD.org> born in Kazan, Republic of Tatarstan, USSR, 1974 -12/15 Fourth quarterly status reports are due on 12/31 12/18 Chris Timmons <cwt@FreeBSD.org> born in Ellensburg, Washington, United States, 1964 12/18 Dag-Erling Smorgrav <des@FreeBSD.org> born in Brussels, Belgium, 1977 12/18 Muhammad Moinur Rahman <bofh@FreeBSD.org> born in Dhaka, Bangladesh, 1983 diff --git a/usr.bin/calendar/calendars/calendar.status_reports b/usr.bin/calendar/calendars/calendar.status_reports new file mode 100644 index 000000000000..f4e1e7b822cf --- /dev/null +++ b/usr.bin/calendar/calendars/calendar.status_reports @@ -0,0 +1,28 @@ +/* + * FreeBSD + */ + +#ifndef _calendar_status_reports_ +#define _calendar_status_reports_ + +03/01 Status Reports: First call for Q1 +03/15 Status Reports: 1 month left reminder for Q1 +03/31 Status Reports: 2 weeks left reminder for Q1 +04/14 Status Reports: Q1 deadline + +06/01 Status Reports: First call for Q2 +06/15 Status Reports: 1 month left reminder for Q2 +06/30 Status Reports: 2 weeks left reminder for Q2 +07/14 Status Reports: Q2 deadline + +09/01 Status Reports: First call for Q3 +09/15 Status Reports: 1 month left reminder for Q3 +09/30 Status Reports: 2 weeks left reminder for Q3 +10/14 Status Reports: Q3 deadline + +12/01 Status Reports: First call for Q4 +12/15 Status Reports: 1 month left reminder for Q4 +12/31 Status Reports: 2 weeks left reminder for Q4 +01/14 Status Reports: Q4 deadline + +#endif /* !_calendar_status_reports_ */ diff --git a/usr.bin/clang/Makefile b/usr.bin/clang/Makefile index e2debfb8c582..ac92b08a54cb 100644 --- a/usr.bin/clang/Makefile +++ b/usr.bin/clang/Makefile @@ -14,6 +14,7 @@ SUBDIR+= clang-scan-deps # as the default binutils (ar,nm,addr2line, etc.). .if ${MK_CLANG} != "no" || ${MK_LLVM_BINUTILS} != "no" SUBDIR+= llvm-ar +SUBDIR+= llvm-cxxfilt SUBDIR+= llvm-nm SUBDIR+= llvm-objcopy SUBDIR+= llvm-objdump @@ -23,10 +24,6 @@ SUBDIR+= llvm-strings SUBDIR+= llvm-symbolizer .endif -.if ${MK_LLVM_BINUTILS} != "no" || ${MK_LLVM_CXXFILT} != "no" -SUBDIR+= llvm-cxxfilt -.endif - .if ${MK_CLANG_EXTRAS} != "no" SUBDIR+= bugpoint SUBDIR+= llc diff --git a/usr.bin/clang/llvm-ar/Makefile b/usr.bin/clang/llvm-ar/Makefile index e019c89b3581..ee776a7c0d9e 100644 --- a/usr.bin/clang/llvm-ar/Makefile +++ b/usr.bin/clang/llvm-ar/Makefile @@ -11,7 +11,8 @@ SRCS+= llvm-ar.cpp LINKS+= ${BINDIR}/llvm-ar ${BINDIR}/llvm-ranlib .if ${MK_LLVM_BINUTILS} != "no" -LINKS+= ${BINDIR}/llvm-ar ${BINDIR}/ar ${BINDIR}/llvm-ar ${BINDIR}/ranlib +SYMLINKS+= llvm-ar ${BINDIR}/ar +SYMLINKS+= llvm-ranlib ${BINDIR}/ranlib MLINKS+= llvm-ar.1 ar.1 llvm-ar.1 ranlib.1 .endif diff --git a/usr.bin/clang/llvm-cov/Makefile b/usr.bin/clang/llvm-cov/Makefile index 3eb14eb37139..3c02d4b7d144 100644 --- a/usr.bin/clang/llvm-cov/Makefile +++ b/usr.bin/clang/llvm-cov/Makefile @@ -1,7 +1,7 @@ .include <src.opts.mk> PROG_CXX= llvm-cov -LINKS= ${BINDIR}/llvm-cov ${BINDIR}/gcov +SYMLINKS= llvm-cov ${BINDIR}/gcov MLINKS= llvm-cov.1 gcov.1 SRCDIR= llvm/tools/llvm-cov diff --git a/usr.bin/clang/llvm-cxxfilt/Makefile b/usr.bin/clang/llvm-cxxfilt/Makefile index f9621da8da89..26a5d9e8975d 100644 --- a/usr.bin/clang/llvm-cxxfilt/Makefile +++ b/usr.bin/clang/llvm-cxxfilt/Makefile @@ -22,8 +22,8 @@ DEPENDFILES+= ${TGHDRS:C/$/.d/} DPSRCS+= ${TGHDRS} CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/} -.if ${MK_LLVM_CXXFILT} != "no" -LINKS= ${BINDIR}/llvm-cxxfilt ${BINDIR}/c++filt +.if ${MK_LLVM_BINUTILS} != "no" +SYMLINKS= llvm-cxxfilt ${BINDIR}/c++filt MLINKS= llvm-cxxfilt.1 c++filt.1 .endif diff --git a/usr.bin/clang/llvm-nm/Makefile b/usr.bin/clang/llvm-nm/Makefile index 7e089d1b408d..333513246cb6 100644 --- a/usr.bin/clang/llvm-nm/Makefile +++ b/usr.bin/clang/llvm-nm/Makefile @@ -24,7 +24,7 @@ DPSRCS+= ${TGHDRS} CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/} .if ${MK_LLVM_BINUTILS} != "no" -LINKS+= ${BINDIR}/llvm-nm ${BINDIR}/nm +SYMLINKS+= llvm-nm ${BINDIR}/nm MLINKS+= llvm-nm.1 nm.1 .endif diff --git a/usr.bin/clang/llvm-objcopy/Makefile b/usr.bin/clang/llvm-objcopy/Makefile index fcf59e4b4bca..13bbab97899f 100644 --- a/usr.bin/clang/llvm-objcopy/Makefile +++ b/usr.bin/clang/llvm-objcopy/Makefile @@ -27,8 +27,8 @@ CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/} LINKS= ${BINDIR}/llvm-objcopy ${BINDIR}/llvm-strip .if ${MK_LLVM_BINUTILS} != "no" -LINKS+= ${BINDIR}/llvm-objcopy ${BINDIR}/objcopy \ - ${BINDIR}/llvm-strip ${BINDIR}/strip +SYMLINKS+= llvm-objcopy ${BINDIR}/objcopy \ + llvm-strip ${BINDIR}/strip MLINKS= llvm-objcopy.1 objcopy.1 \ llvm-objcopy.1 strip.1 .endif diff --git a/usr.bin/clang/llvm-objdump/Makefile b/usr.bin/clang/llvm-objdump/Makefile index ad1c7beee95f..86281217ee0a 100644 --- a/usr.bin/clang/llvm-objdump/Makefile +++ b/usr.bin/clang/llvm-objdump/Makefile @@ -29,7 +29,7 @@ DEPENDFILES+= ${TGHDRS:C/$/.d/} DPSRCS+= ${TGHDRS} CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/} -LINKS= ${BINDIR}/llvm-objdump ${BINDIR}/objdump +SYMLINKS= llvm-objdump ${BINDIR}/objdump MLINKS= llvm-objdump.1 objdump.1 .include "../llvm.prog.mk" diff --git a/usr.bin/clang/llvm-readobj/Makefile b/usr.bin/clang/llvm-readobj/Makefile index f532358ea79e..3f705431e509 100644 --- a/usr.bin/clang/llvm-readobj/Makefile +++ b/usr.bin/clang/llvm-readobj/Makefile @@ -36,7 +36,7 @@ CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/} LINKS+= ${BINDIR}/llvm-readobj ${BINDIR}/llvm-readelf .if ${MK_LLVM_BINUTILS} != "no" -LINKS+= ${BINDIR}/llvm-readelf ${BINDIR}/readelf +SYMLINKS+= llvm-readelf ${BINDIR}/readelf MLINKS+= llvm-readelf.1 readelf.1 .endif diff --git a/usr.bin/clang/llvm-size/Makefile b/usr.bin/clang/llvm-size/Makefile index 9d3505cdd319..1991065b61b2 100644 --- a/usr.bin/clang/llvm-size/Makefile +++ b/usr.bin/clang/llvm-size/Makefile @@ -24,7 +24,7 @@ DPSRCS+= ${TGHDRS} CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/} .if ${MK_LLVM_BINUTILS} != "no" -LINKS+= ${BINDIR}/llvm-size ${BINDIR}/size +SYMLINKS+= llvm-size ${BINDIR}/size MLINKS+= llvm-size.1 size.1 .endif diff --git a/usr.bin/clang/llvm-symbolizer/Makefile b/usr.bin/clang/llvm-symbolizer/Makefile index c45300c92a90..1a3a65c774c9 100644 --- a/usr.bin/clang/llvm-symbolizer/Makefile +++ b/usr.bin/clang/llvm-symbolizer/Makefile @@ -26,7 +26,7 @@ CLEANFILES+= ${TGHDRS} ${TGHDRS:C/$/.d/} LINKS+= ${BINDIR}/llvm-symbolizer ${BINDIR}/llvm-addr2line .if ${MK_LLVM_BINUTILS} != "no" -LINKS+= ${BINDIR}/llvm-symbolizer ${BINDIR}/addr2line +SYMLINKS+= llvm-addr2line ${BINDIR}/addr2line MLINKS+= llvm-addr2line.1 addr2line.1 .endif diff --git a/usr.bin/cpio/tests/functional_test.sh b/usr.bin/cpio/tests/functional_test.sh index a915cc91faea..6bc58e5236ae 100755 --- a/usr.bin/cpio/tests/functional_test.sh +++ b/usr.bin/cpio/tests/functional_test.sh @@ -46,7 +46,7 @@ atf_init_test_cases() # Redirect stderr to stdout for the usage message because if you don't # kyua list/kyua test will break: # https://github.com/jmmv/kyua/issues/149 - testcases=$(${TESTER} -h 2>&1 | awk 'p != 0 && $1 ~ /^[0-9]+:/ { print $NF } /Available tests:/ { p=1 }') + testcases=$(${TESTER} -l 2>&1 | awk '/^ [0-9]+: / { print $2 }') for testcase in ${testcases}; do atf_test_case ${testcase} eval "${testcase}_body() { check ${testcase}; }" diff --git a/usr.bin/diff/diff.c b/usr.bin/diff/diff.c index 83aa20c52cf3..b5fa12268bac 100644 --- a/usr.bin/diff/diff.c +++ b/usr.bin/diff/diff.c @@ -35,7 +35,7 @@ #include "diff.h" #include "xmalloc.h" -static const char diff_version[] = "FreeBSD diff 20240307"; +static const char diff_version[] = "FreeBSD diff 20260206"; bool lflag, Nflag, Pflag, rflag, sflag, Tflag, cflag; bool ignore_file_case, suppress_common, color, noderef; static bool help = false; @@ -137,10 +137,9 @@ static bool do_color(void); int main(int argc, char **argv) { - const char *errstr = NULL; - char *ep, **oargv; - long l; - int ch, dflags, lastch, gotstdin, prevoptind, newarg; + const char *errstr; + char **oargv; + int ch, dflags, lastch, gotstdin, prevoptind, newarg; oargv = argv; gotstdin = 0; @@ -177,7 +176,7 @@ main(int argc, char **argv) } if (diff_algorithm == D_DIFFNONE) { - printf("unknown algorithm: %s\n", optarg); + warnx("unknown algorithm: %s", optarg); usage(); } break; @@ -194,10 +193,13 @@ main(int argc, char **argv) cflag = true; diff_format = D_CONTEXT; if (optarg != NULL) { - l = strtol(optarg, &ep, 10); - if (*ep != '\0' || l < 0 || l >= INT_MAX) + diff_context = (int) strtonum(optarg, + 1, INT_MAX, &errstr); + if (errstr != NULL) { + warnx("context size is %s: %s", + errstr, optarg); usage(); - diff_context = (int)l; + } } break; case 'd': @@ -249,6 +251,7 @@ main(int argc, char **argv) usage(); break; case 'l': + dflags |= D_PAGINATION; lflag = true; break; case 'N': @@ -293,10 +296,13 @@ main(int argc, char **argv) conflicting_format(); diff_format = D_UNIFIED; if (optarg != NULL) { - l = strtol(optarg, &ep, 10); - if (*ep != '\0' || l < 0 || l >= INT_MAX) + diff_context = (int) strtonum(optarg, + 0, INT_MAX, &errstr); + if (errstr != NULL) { + warnx("context size is %s: %s", + errstr, optarg); usage(); - diff_context = (int)l; + } } break; case 'w': @@ -304,8 +310,8 @@ main(int argc, char **argv) break; case 'W': width = (int) strtonum(optarg, 1, INT_MAX, &errstr); - if (errstr) { - warnx("Invalid argument for width"); + if (errstr != NULL) { + warnx("width is %s: %s", errstr, optarg); usage(); } break; @@ -345,8 +351,8 @@ main(int argc, char **argv) break; case OPT_TSIZE: tabsize = (int) strtonum(optarg, 1, INT_MAX, &errstr); - if (errstr) { - warnx("Invalid argument for tabsize"); + if (errstr != NULL) { + warnx("tabsize is %s: %s", errstr, optarg); usage(); } break; @@ -363,9 +369,12 @@ main(int argc, char **argv) colorflag = COLORFLAG_ALWAYS; else if (strncmp(optarg, "never", 5) == 0) colorflag = COLORFLAG_NEVER; - else - errx(2, "unsupported --color value '%s' (must be always, auto, or never)", - optarg); + else { + warnx("unsupported --color value " + "(must be always, auto, or never): " + "%s", optarg); + usage(); + } break; case OPT_NO_DEREFERENCE: noderef = true; diff --git a/usr.bin/diff/diff.h b/usr.bin/diff/diff.h index 74be55db8a33..fe41e8746f4d 100644 --- a/usr.bin/diff/diff.h +++ b/usr.bin/diff/diff.h @@ -1,6 +1,8 @@ /* $OpenBSD: diff.h,v 1.34 2020/11/01 18:16:08 jcs Exp $ */ /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * @@ -80,6 +82,7 @@ #define D_STRIPCR 0x400 /* Strip trailing cr */ #define D_SKIPBLANKLINES 0x800 /* Skip blank lines */ #define D_MATCHLAST 0x1000 /* Display last line matching provided regex */ +#define D_PAGINATION 0x2000 /* Paginate via pr(1) */ /* Features supported by new algorithms */ #define D_NEWALGO_FLAGS (D_FORCEASCII | D_PROTOTYPE | D_IGNOREBLANKS) diff --git a/usr.bin/diff/diffdir.c b/usr.bin/diff/diffdir.c index a55a2bec70ee..489b873e2fcf 100644 --- a/usr.bin/diff/diffdir.c +++ b/usr.bin/diff/diffdir.c @@ -41,8 +41,6 @@ static void diffit(struct dirent *, char *, size_t, struct dirent *, char *, size_t, int); static void print_only(const char *, size_t, const char *); -#define d_status d_type /* we need to store status for -l */ - struct inode { dev_t dev; ino_t ino; @@ -62,7 +60,8 @@ static struct inodetree v2 = RB_INITIALIZER(&v2); RB_GENERATE_STATIC(inodetree, inode, entry, inodecmp); static int -vscandir(struct inodetree *tree, const char *path, struct dirent ***dirp, +vscandir(struct inodetree *tree, struct inode **inop, + const char *path, struct dirent ***dirp, int (*selectf)(const struct dirent *), int (*comparf)(const struct dirent **, const struct dirent **)) { @@ -87,6 +86,7 @@ vscandir(struct inodetree *tree, const char *path, struct dirent ***dirp, goto fail; RB_INSERT(inodetree, tree, ino); close(fd); + *inop = ino; return (ret); fail: serrno = errno; @@ -98,6 +98,13 @@ fail: return (-1); } +static void +leavedir(struct inodetree *tree, struct inode *ino) +{ + RB_REMOVE(inodetree, tree, ino); + free(ino); +} + /* * Diff directory traversal. Will be called recursively if -r was specified. */ @@ -106,6 +113,7 @@ diffdir(char *p1, char *p2, int flags) { struct dirent *dent1, **dp1, **edp1, **dirp1 = NULL; struct dirent *dent2, **dp2, **edp2, **dirp2 = NULL; + struct inode *ino1 = NULL, *ino2 = NULL; size_t dirlen1, dirlen2; char path1[PATH_MAX], path2[PATH_MAX]; int pos; @@ -133,7 +141,7 @@ diffdir(char *p1, char *p2, int flags) * Get a list of entries in each directory, skipping "excluded" files * and sorting alphabetically. */ - pos = vscandir(&v1, path1, &dirp1, selectfile, alphasort); + pos = vscandir(&v1, &ino1, path1, &dirp1, selectfile, alphasort); if (pos == -1) { if (errno == ENOENT && (Nflag || Pflag)) { pos = 0; @@ -145,7 +153,7 @@ diffdir(char *p1, char *p2, int flags) dp1 = dirp1; edp1 = dirp1 + pos; - pos = vscandir(&v2, path2, &dirp2, selectfile, alphasort); + pos = vscandir(&v2, &ino2, path2, &dirp2, selectfile, alphasort); if (pos == -1) { if (errno == ENOENT && Nflag) { pos = 0; @@ -219,11 +227,15 @@ diffdir(char *p1, char *p2, int flags) closem: if (dirp1 != NULL) { + if (ino1 != NULL) + leavedir(&v1, ino1); for (dp1 = dirp1; dp1 < edp1; dp1++) free(*dp1); free(dirp1); } if (dirp2 != NULL) { + if (ino2 != NULL) + leavedir(&v2, ino2); for (dp2 = dirp2; dp2 < edp2; dp2++) free(*dp2); free(dirp2); @@ -237,6 +249,8 @@ static void diffit(struct dirent *dp, char *path1, size_t plen1, struct dirent *dp2, char *path2, size_t plen2, int flags) { + int rc; + flags |= D_HEADER; strlcpy(path1 + plen1, dp->d_name, PATH_MAX - plen1); @@ -258,7 +272,6 @@ diffit(struct dirent *dp, char *path1, size_t plen1, struct dirent *dp2, flags |= D_EMPTY1; memset(&stb1, 0, sizeof(stb1)); } - if (lstat(path2, &stb2) != 0) { if (!Nflag || errno != ENOENT) { warn("%s", path2); @@ -315,7 +328,6 @@ diffit(struct dirent *dp, char *path1, size_t plen1, struct dirent *dp2, flags |= D_EMPTY1; memset(&stb1, 0, sizeof(stb1)); } - if (stat(path2, &stb2) != 0) { if (!Nflag || errno != ENOENT) { warn("%s", path2); @@ -328,6 +340,8 @@ diffit(struct dirent *dp, char *path1, size_t plen1, struct dirent *dp2, if (stb1.st_mode == 0) stb1.st_mode = stb2.st_mode; } + if (stb1.st_dev == stb2.st_dev && stb1.st_ino == stb2.st_ino) + return; if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode)) { if (rflag) diffdir(path1, path2, flags); @@ -337,12 +351,12 @@ diffit(struct dirent *dp, char *path1, size_t plen1, struct dirent *dp2, return; } if (!S_ISREG(stb1.st_mode) && !S_ISDIR(stb1.st_mode)) - dp->d_status = D_SKIPPED1; + rc = D_SKIPPED1; else if (!S_ISREG(stb2.st_mode) && !S_ISDIR(stb2.st_mode)) - dp->d_status = D_SKIPPED2; + rc = D_SKIPPED2; else - dp->d_status = diffreg(path1, path2, flags, 0); - print_status(dp->d_status, path1, path2, ""); + rc = diffreg(path1, path2, flags, 0); + print_status(rc, path1, path2, ""); } /* diff --git a/usr.bin/diff/diffreg.c b/usr.bin/diff/diffreg.c index ffa5568bf442..8dcf55a7190b 100644 --- a/usr.bin/diff/diffreg.c +++ b/usr.bin/diff/diffreg.c @@ -77,6 +77,7 @@ #include <paths.h> #include <regex.h> #include <stdbool.h> +#include <stdckdint.h> #include <stddef.h> #include <stdint.h> #include <stdio.h> @@ -371,6 +372,9 @@ diffreg_stone(char *file1, char *file2, int flags, int capsicum) goto closem; } + if (stb1.st_dev == stb2.st_dev && stb1.st_ino == stb2.st_ino) + goto closem; + if (lflag) pr = start_pr(file1, file2); @@ -402,6 +406,10 @@ diffreg_stone(char *file1, char *file2, int flags, int capsicum) break; default: /* error */ + if (ferror(f1)) + warn("%s", file1); + if (ferror(f2)) + warn("%s", file2); rval = D_ERROR; status |= 2; goto closem; @@ -495,9 +503,9 @@ files_differ(FILE *f1, FILE *f2, int flags) return (0); for (;;) { - i = fread(buf1, 1, sizeof(buf1), f1); - j = fread(buf2, 1, sizeof(buf2), f2); - if ((!i && ferror(f1)) || (!j && ferror(f2))) + if ((i = fread(buf1, 1, sizeof(buf1), f1)) == 0 && ferror(f1)) + return (-1); + if ((j = fread(buf2, 1, sizeof(buf2), f2)) == 0 && ferror(f2)) return (-1); if (i != j) return (1); @@ -1056,7 +1064,7 @@ change(char *file1, FILE *f1, char *file2, FILE *f2, int a, int b, int c, int d, { static size_t max_context = 64; long curpos; - int i, nc; + int dist, i, nc; const char *walk; bool skip_blanks, ignore; @@ -1120,8 +1128,9 @@ proceed: */ print_header(file1, file2); anychange = 1; - } else if (a > context_vec_ptr->b + (2 * diff_context) + 1 && - c > context_vec_ptr->d + (2 * diff_context) + 1) { + } else if (!ckd_add(&dist, diff_context, diff_context) && + a - context_vec_ptr->b - 1 > dist && + c - context_vec_ptr->d - 1 > dist) { /* * If this change is more than 'diff_context' lines from the * previous change, dump the record and reset it. @@ -1506,10 +1515,14 @@ dump_context_vec(FILE *f1, FILE *f2, int flags) return; b = d = 0; /* gcc */ - lowa = MAX(1, cvp->a - diff_context); - upb = MIN((int)len[0], context_vec_ptr->b + diff_context); - lowc = MAX(1, cvp->c - diff_context); - upd = MIN((int)len[1], context_vec_ptr->d + diff_context); + if (ckd_sub(&lowa, cvp->a, diff_context) || lowa < 1) + lowa = 1; + if (ckd_add(&upb, context_vec_ptr->b, diff_context) || upb > (int)len[0]) + upb = (int)len[0]; + if (ckd_sub(&lowc, cvp->c, diff_context) || lowc < 1) + lowc = 1; + if (ckd_add(&upd, context_vec_ptr->d, diff_context) || upd > (int)len[1]) + upd = (int)len[1]; printf("***************"); if (flags & (D_PROTOTYPE | D_MATCHLAST)) { @@ -1609,10 +1622,14 @@ dump_unified_vec(FILE *f1, FILE *f2, int flags) return; b = d = 0; /* gcc */ - lowa = MAX(1, cvp->a - diff_context); - upb = MIN((int)len[0], context_vec_ptr->b + diff_context); - lowc = MAX(1, cvp->c - diff_context); - upd = MIN((int)len[1], context_vec_ptr->d + diff_context); + if (ckd_sub(&lowa, cvp->a, diff_context) || lowa < 1) + lowa = 1; + if (ckd_add(&upb, context_vec_ptr->b, diff_context) || upb > (int)len[0]) + upb = (int)len[0]; + if (ckd_sub(&lowc, cvp->c, diff_context) || lowc < 1) + lowc = 1; + if (ckd_add(&upd, context_vec_ptr->d, diff_context) || upd > (int)len[1]) + upd = (int)len[1]; printf("@@ -"); uni_range(lowa, upb); diff --git a/usr.bin/diff/diffreg_new.c b/usr.bin/diff/diffreg_new.c index f54cd554ccad..69deae497962 100644 --- a/usr.bin/diff/diffreg_new.c +++ b/usr.bin/diff/diffreg_new.c @@ -33,6 +33,7 @@ #include <time.h> #include <unistd.h> +#include "pr.h" #include "diff.h" #include <arraylist.h> #include <diff_main.h> @@ -55,7 +56,7 @@ static const struct diff_algo_config myers_then_myers_divide; static const struct diff_algo_config patience; static const struct diff_algo_config myers_divide; -static const struct diff_algo_config myers_then_patience = (struct diff_algo_config){ +static const struct diff_algo_config myers_then_patience = { .impl = diff_algo_myers, .permitted_state_size = 1024 * 1024 * sizeof(int), .fallback_algo = &patience, @@ -68,7 +69,7 @@ static const struct diff_algo_config myers_then_myers_divide = .fallback_algo = &myers_divide, }; -static const struct diff_algo_config patience = (struct diff_algo_config){ +static const struct diff_algo_config patience = { .impl = diff_algo_patience, /* After subdivision, do Patience again: */ .inner_algo = &patience, @@ -76,14 +77,14 @@ static const struct diff_algo_config patience = (struct diff_algo_config){ .fallback_algo = &myers_then_myers_divide, }; -static const struct diff_algo_config myers_divide = (struct diff_algo_config){ +static const struct diff_algo_config myers_divide = { .impl = diff_algo_myers_divide, /* When division succeeded, start from the top: */ .inner_algo = &myers_then_myers_divide, /* (fallback_algo = NULL implies diff_algo_none). */ }; -static const struct diff_algo_config no_algo = (struct diff_algo_config){ +static const struct diff_algo_config none = { .impl = diff_algo_none, }; @@ -108,8 +109,9 @@ static const struct diff_config diff_config_patience = { }; /* Directly force Patience as a first divider of the source file. */ -static const struct diff_config diff_config_no_algo = { +static const struct diff_config diff_config_none = { .atomize_func = diff_atomize_text_by_line, + .algo = &none, }; const char * @@ -146,6 +148,7 @@ diffreg_new(char *file1, char *file2, int flags, int capsicum) { char *str1, *str2; FILE *f1, *f2; + struct pr *pr = NULL; struct stat st1, st2; struct diff_input_info info; struct diff_data left = {}, right = {}; @@ -156,6 +159,7 @@ diffreg_new(char *file1, char *file2, int flags, int capsicum) const struct diff_config *cfg; enum diffreg_algo algo; cap_rights_t rights_ro; + int ret; algo = DIFFREG_ALGO_MYERS_THEN_MYERS_DIVIDE; @@ -171,13 +175,16 @@ diffreg_new(char *file1, char *file2, int flags, int capsicum) cfg = &diff_config_patience; break; case DIFFREG_ALGO_NONE: - cfg = &diff_config_no_algo; + cfg = &diff_config_none; break; } f1 = openfile(file1, &str1, &st1); f2 = openfile(file2, &str2, &st2); + if (flags & D_PAGINATION) + pr = start_pr(file1, file2); + if (capsicum) { cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK); if (caph_rights_limit(fileno(f1), &rights_ro) < 0) @@ -214,18 +221,22 @@ diffreg_new(char *file1, char *file2, int flags, int capsicum) if (flags & D_PROTOTYPE) diff_flags |= DIFF_FLAG_SHOW_PROTOTYPES; - if (diff_atomize_file(&left, cfg, f1, (uint8_t *)str1, st1.st_size, diff_flags)) { + ret = diff_atomize_file(&left, cfg, f1, (uint8_t *)str1, st1.st_size, + diff_flags); + if (ret != DIFF_RC_OK) { + warnc(ret, "%s", file1); rc = D_ERROR; + status |= 2; goto done; } - if (left.atomizer_flags & DIFF_ATOMIZER_FILE_TRUNCATED) - warnx("%s truncated", file1); - if (diff_atomize_file(&right, cfg, f2, (uint8_t *)str2, st2.st_size, diff_flags)) { + ret = diff_atomize_file(&right, cfg, f2, (uint8_t *)str2, st2.st_size, + diff_flags); + if (ret != DIFF_RC_OK) { + warnc(ret, "%s", file2); rc = D_ERROR; + status |= 2; goto done; } - if (right.atomizer_flags & DIFF_ATOMIZER_FILE_TRUNCATED) - warnx("%s truncated", file2); result = diff_main(cfg, &left, &right); if (result->rc != DIFF_RC_OK) { @@ -271,6 +282,8 @@ diffreg_new(char *file1, char *file2, int flags, int capsicum) status |= 1; } done: + if (pr != NULL) + stop_pr(pr); diff_result_free(result); diff_data_free(&left); diff_data_free(&right); diff --git a/usr.bin/diff/pr.c b/usr.bin/diff/pr.c index c3ea280073af..189e6b34649e 100644 --- a/usr.bin/diff/pr.c +++ b/usr.bin/diff/pr.c @@ -28,6 +28,7 @@ #include <sys/wait.h> #include <err.h> +#include <errno.h> #include <paths.h> #include <signal.h> #include <stdio.h> @@ -44,7 +45,6 @@ struct pr * start_pr(char *file1, char *file2) { int pfd[2]; - int pr_pd; pid_t pid; char *header; struct pr *pr; @@ -54,13 +54,10 @@ start_pr(char *file1, char *file2) xasprintf(&header, "%s %s %s", diffargs, file1, file2); signal(SIGPIPE, SIG_IGN); fflush(stdout); - rewind(stdout); if (pipe(pfd) == -1) err(2, "pipe"); - switch ((pid = pdfork(&pr_pd, PD_CLOEXEC))) { + switch ((pid = pdfork(&pr->procd, PD_CLOEXEC))) { case -1: - status |= 2; - free(header); err(2, "No more processes"); case 0: /* child */ @@ -72,24 +69,18 @@ start_pr(char *file1, char *file2) execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0); _exit(127); default: - /* parent */ - if (pfd[1] != STDOUT_FILENO) { - pr->ostdout = dup(STDOUT_FILENO); - dup2(pfd[1], STDOUT_FILENO); + if (pfd[1] == STDOUT_FILENO) { + pr->ostdout = STDOUT_FILENO; + } else { + if ((pr->ostdout = dup(STDOUT_FILENO)) < 0 || + dup2(pfd[1], STDOUT_FILENO) < 0) { + err(2, "stdout"); + } close(pfd[1]); } close(pfd[0]); - rewind(stdout); free(header); - pr->kq = kqueue(); - if (pr->kq == -1) - err(2, "kqueue"); - pr->e = xmalloc(sizeof(struct kevent)); - EV_SET(pr->e, pr_pd, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT, 0, - NULL); - if (kevent(pr->kq, pr->e, 1, NULL, 0, NULL) == -1) - err(2, "kevent"); } return (pr); } @@ -105,14 +96,14 @@ stop_pr(struct pr *pr) fflush(stdout); if (pr->ostdout != STDOUT_FILENO) { - close(STDOUT_FILENO); dup2(pr->ostdout, STDOUT_FILENO); close(pr->ostdout); } - if (kevent(pr->kq, NULL, 0, pr->e, 1, NULL) == -1) - err(2, "kevent"); - wstatus = pr->e[0].data; - close(pr->kq); + while (pdwait(pr->procd, &wstatus, WEXITED, NULL, NULL) == -1) { + if (errno != EINTR) + err(2, "pdwait"); + } + close(pr->procd); free(pr); if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) errx(2, "pr exited abnormally"); diff --git a/usr.bin/diff/pr.h b/usr.bin/diff/pr.h index 2ff5949f282f..e6abad4466a6 100644 --- a/usr.bin/diff/pr.h +++ b/usr.bin/diff/pr.h @@ -24,12 +24,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/event.h> - struct pr { int ostdout; - int kq; - struct kevent *e; + int procd; }; struct pr *start_pr(char *file1, char *file2); diff --git a/usr.bin/diff/tests/diff_test.sh b/usr.bin/diff/tests/diff_test.sh index 691b649813a1..872103b24cef 100755 --- a/usr.bin/diff/tests/diff_test.sh +++ b/usr.bin/diff/tests/diff_test.sh @@ -1,4 +1,3 @@ - atf_test_case simple atf_test_case unified atf_test_case header @@ -24,6 +23,10 @@ atf_test_case functionname atf_test_case noderef atf_test_case ignorecase atf_test_case dirloop +atf_test_case crange +atf_test_case urange +atf_test_case prleak +atf_test_case same simple_body() { @@ -187,19 +190,19 @@ brief_format_body() atf_check \ -s exit:1 \ -o inline:"Files A/test-file and B/test-file differ\n" \ - diff -rq A B + diff -q A B atf_check diff -rq A C atf_check \ -s exit:1 \ -o inline:"Only in D: another-test-file\n" \ - diff -rq A D + diff -q A D atf_check \ -s exit:1 \ -o inline:"Files A/another-test-file and D/another-test-file differ\n" \ - diff -Nrq A D + diff -Nq A D } Bflag_body() @@ -221,9 +224,9 @@ Nflag_body() { atf_check -x 'printf "foo" > A' - atf_check -s exit:1 -o ignore -e ignore diff -N A NOFILE - atf_check -s exit:1 -o ignore -e ignore diff -N NOFILE A - atf_check -s exit:2 -o ignore -e ignore diff -N NOFILE1 NOFILE2 + atf_check -s exit:1 -o ignore -e ignore diff -N A NOFILE + atf_check -s exit:1 -o ignore -e ignore diff -N NOFILE A + atf_check -s exit:2 -o ignore -e ignore diff -N NOFILE1 NOFILE2 } tabsize_body() @@ -335,23 +338,23 @@ noderef_body() atf_check ln -s $(pwd)/test-file B/test-file - atf_check -o empty -s exit:0 diff -r A B + atf_check -o empty -s exit:0 diff A B atf_check -o inline:"File A/test-file is a file while file B/test-file is a symbolic link\n" \ - -s exit:1 diff -r --no-dereference A B + -s exit:1 diff --no-dereference A B # both test files are now the same symbolic link atf_check rm A/test-file atf_check ln -s $(pwd)/test-file A/test-file - atf_check -o empty -s exit:0 diff -r A B - atf_check -o empty -s exit:0 diff -r --no-dereference A B + atf_check -o empty -s exit:0 diff A B + atf_check -o empty -s exit:0 diff --no-dereference A B # make test files different symbolic links, but same contents atf_check unlink A/test-file atf_check ln -s $(pwd)/test-file2 A/test-file - atf_check -o empty -s exit:0 diff -r A B - atf_check -o inline:"Symbolic links A/test-file and B/test-file differ\n" -s exit:1 diff -r --no-dereference A B + atf_check -o empty -s exit:0 diff A B + atf_check -o inline:"Symbolic links A/test-file and B/test-file differ\n" -s exit:1 diff --no-dereference A B } ignorecase_body() @@ -362,7 +365,7 @@ ignorecase_body() atf_check -x "echo hello > A/foo" atf_check -x "echo hello > B/FOO" - atf_check -o empty -s exit:0 diff -u -r --ignore-file-name-case A B + atf_check -o empty -s exit:0 diff -u --ignore-file-name-case A B } dirloop_head() @@ -375,9 +378,100 @@ dirloop_body() atf_check ln -s .. a/foo/bar/up atf_check cp -a a b atf_check \ + -o inline:"Common subdirectories: a/foo and b/foo\n" \ + diff a b + atf_check \ -e match:"a/foo/bar/up: Directory loop detected" \ -e match:"b/foo/bar/up: Directory loop detected" \ diff -r a b + atf_check rm [ab]/foo/bar/up + atf_check mkdir -p b/foo/bar + atf_check ln -s foo a/baz + atf_check ln -s foo b/baz + atf_check diff -r a b +} + +crange_head() +{ + atf_set "descr" "Context diff context length range" +} +crange_body() +{ + echo $'x\nx\na\ny\ny' >a + echo $'x\nx\nb\ny\ny' >b + atf_check -s exit:2 -e match:'too small' \ + diff -C-1 a b + atf_check -s exit:2 -e match:'too small' \ + diff -C0 a b + atf_check -s exit:1 -o match:'--- 2,4 ---' \ + diff -C1 a b + atf_check -s exit:1 -o match:'--- 2,4 ---' \ + diff -Astone -C1 a b + atf_check -s exit:2 -e match:'too large' \ + diff -C$((1<<31)) a b + atf_check -s exit:1 -o match:'--- 1,5 ---' \ + diff -C$(((1<<31)-1)) a b + atf_check -s exit:1 -o match:'--- 1,5 ---' \ + diff -Astone -C$(((1<<31)-1)) a b +} + +urange_head() +{ + atf_set "descr" "Unified diff context length range" +} +urange_body() +{ + echo $'x\nx\na\ny\ny' >a + echo $'x\nx\nb\ny\ny' >b + atf_check -s exit:2 -e match:'too small' \ + diff -U-1 a b + atf_check -s exit:1 -o match:'^@@ -3 \+3 @@$' \ + diff -U0 a b + atf_check -s exit:2 -e match:'too large' \ + diff -U$((1<<31)) a b + atf_check -s exit:1 -o match:'^@@ -1,5 \+1,5 @@$' \ + diff -U$(((1<<31)-1)) a b + atf_check -s exit:1 -o match:'^@@ -1,5 \+1,5 @@$' \ + diff -Astone -U$(((1<<31)-1)) a b +} + +prleak_head() +{ + atf_set "descr" "Verify that pagination does not leak resources" +} +prleak_body() +{ + local n=32 + mkdir a b + for hi in $(jot -w%02x $n 0) ; do + mkdir a/$hi b/$hi + for lo in $(jot -w%02x $n 0) ; do + echo "$hi$lo" >a/$hi/$lo + echo "$hi$lo" >b/$hi/$lo + done + done + ulimit -n 1000 + ulimit -u 1000 + atf_check diff -rul a b + atf_check diff -Astone -rul a b +} + +same_head() +{ + atf_set "descr" "Don't diff a file or directory with itself" +} +same_body() +{ + local n=256 + mkdir a + for hi in $(jot -w%02x $n 0) ; do + mkdir a/$hi + for lo in $(jot -w%02x $n 0) ; do + echo "$hi$lo" >a/$hi/$lo + done + done + ln -s a b + atf_check timeout 1s diff -rqs a b } atf_init_test_cases() @@ -407,4 +501,8 @@ atf_init_test_cases() atf_add_test_case noderef atf_add_test_case ignorecase atf_add_test_case dirloop + atf_add_test_case crange + atf_add_test_case urange + atf_add_test_case prleak + atf_add_test_case same } diff --git a/usr.bin/diff3/diff3.1 b/usr.bin/diff3/diff3.1 index 9286a79e6ec6..8ca2d9f853af 100644 --- a/usr.bin/diff3/diff3.1 +++ b/usr.bin/diff3/diff3.1 @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 23, 2022 +.Dd March 1, 2026 .Dt DIFF3 1 .Os .Sh NAME @@ -196,6 +196,21 @@ The lines beneath this notation are ranges of lines which are exclusively different in file .Va n . .El +.Sh EXIT STATUS +The +.Nm +utility exits with a status of 0 on success +and >1 if an error occurred. +Additionally, if the +.Fl A , +.Fl E , +.Fl L , +.Fl m , +or +.Fl X +flags were specified, +it exits with a status of 1 if conflicts were found. +.El .Sh SEE ALSO .Xr diff 1 , .Xr ed 1 , diff --git a/usr.bin/diff3/diff3.c b/usr.bin/diff3/diff3.c index 39523f6e6b38..d85a5da94b10 100644 --- a/usr.bin/diff3/diff3.c +++ b/usr.bin/diff3/diff3.c @@ -1,6 +1,8 @@ /* $OpenBSD: diff3prog.c,v 1.11 2009/10/27 23:59:37 deraadt Exp $ */ /* + * SPDX-License-Identifier: Caldera-no-preamble AND BSD-3-Clause + * * Copyright (C) Caldera International Inc. 2001-2002. * All rights reserved. * @@ -62,20 +64,20 @@ * SUCH DAMAGE. */ +#include <sys/types.h> #include <sys/capsicum.h> #include <sys/procdesc.h> -#include <sys/types.h> -#include <sys/event.h> #include <sys/wait.h> +#include <assert.h> #include <capsicum_helpers.h> #include <ctype.h> #include <err.h> #include <getopt.h> +#include <inttypes.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> -#include <limits.h> -#include <inttypes.h> #include <string.h> #include <unistd.h> @@ -88,14 +90,15 @@ struct range { int to; }; +enum difftype { + DIFF_NONE, + DIFF_TYPE1, + DIFF_TYPE2, + DIFF_TYPE3, +}; + struct diff { -#define DIFF_TYPE1 1 -#define DIFF_TYPE2 2 -#define DIFF_TYPE3 3 - int type; -#if DEBUG - char *line; -#endif /* DEBUG */ + enum difftype type; /* Ranges as lines */ struct range old; @@ -119,6 +122,7 @@ static struct diff *d23; */ static struct diff *de; static char *overlap; +static int *de_delta; /* file1-file3 line number delta per edit */ static int overlapcnt; static FILE *fp[3]; static int cline[3]; /* # of the last-read line in each file (0-2) */ @@ -137,7 +141,7 @@ static const char *newmark = ">>>>>>>"; static const char *divider = "======="; static bool duplicate(struct range *, struct range *); -static int edit(struct diff *, bool, int, int); +static int edit(struct diff *, bool, int, enum difftype); static char *getchange(FILE *); static char *get_line(FILE *, size_t *); static int readin(int fd, struct diff **); @@ -150,12 +154,12 @@ static void repos(int); static void separate(const char *); static void edscript(int) __dead2; static void Ascript(int) __dead2; -static void mergescript(int) __dead2; +static void mergescript(int, int) __dead2; static void increase(void); static void usage(void); static void printrange(FILE *, struct range *); -static const char diff3_version[] = "FreeBSD diff3 20240925"; +static const char diff3_version[] = "FreeBSD diff3 20260213"; enum { DIFFPROG_OPT, @@ -200,7 +204,7 @@ strtoi(char *str, char **end) if ((end != NULL && *end == str) || num < 0 || num > INT_MAX || errno == EINVAL || errno == ERANGE) - err(1, "error in diff output"); + err(2, "error in diff output"); return (int)num; } @@ -256,9 +260,6 @@ readin(int fd, struct diff **dd) for (i = 0; (p = getchange(f)) != NULL; i++) { if ((size_t)i >= szchanges - 1) increase(); -#if DEBUG - (*dd)[i].line = strdup(p); -#endif /* DEBUG */ a = b = strtoi(p, &p); if (*p == ',') @@ -268,7 +269,7 @@ readin(int fd, struct diff **dd) if (*p == ',') d = strtoi(p + 1, &p); if (*p != '\n') - errx(1, "error in diff output"); + errx(2, "error in diff output"); if (kind == 'a') a++; else if (kind == 'c') @@ -276,11 +277,11 @@ readin(int fd, struct diff **dd) else if (kind == 'd') c++; else - errx(1, "error in diff output"); + errx(2, "error in diff output"); b++; d++; if (b < a || d < c) - errx(1, "error in diff output"); + errx(2, "error in diff output"); (*dd)[i].old.from = a; (*dd)[i].old.to = b; (*dd)[i].new.from = c; @@ -288,7 +289,7 @@ readin(int fd, struct diff **dd) if (i > 0) { if ((*dd)[i].old.from < (*dd)[i - 1].old.to || (*dd)[i].new.from < (*dd)[i - 1].new.to) - errx(1, "diff output out of order"); + errx(2, "diff output out of order"); } } if (i > 0) { @@ -361,11 +362,13 @@ merge(int m1, int m2) { struct diff *d1, *d2, *d3; int j, t1, t2; + int f1f3delta; bool dup = false; d1 = d13; d2 = d23; j = 0; + f1f3delta = 0; for (;;) { t1 = (d1 < d13 + m1); @@ -381,9 +384,17 @@ merge(int m1, int m2) change(1, &d1->old, false); keep(2, &d1->new); change(3, &d1->new, false); + } else if (mflag) { + j++; + de[j].type = DIFF_TYPE1; + de[j].old = d1->old; + de[j].new = d1->new; + overlap[j] = 0; } else if (eflag == EFLAG_OVERLAP) { j = edit(d2, dup, j, DIFF_TYPE1); } + f1f3delta += (d1->old.to - d1->old.from) - + (d1->new.to - d1->new.from); d1++; continue; } @@ -395,9 +406,10 @@ merge(int m1, int m2) change(3, &d2->new, false); change(2, &d2->old, false); } else if (Aflag || mflag) { - // XXX-THJ: What does it mean for the second file to differ? - if (eflag == EFLAG_UNMERGED) + if (eflag == EFLAG_UNMERGED) { j = edit(d2, dup, j, DIFF_TYPE2); + de_delta[j] = f1f3delta; + } } d2++; continue; @@ -433,10 +445,20 @@ merge(int m1, int m2) change(2, &d2->old, false); d3 = d1->old.to > d1->old.from ? d1 : d2; change(3, &d3->new, false); + } else if (mflag) { + j++; + de[j].type = DIFF_TYPE3; + de[j].old = d1->old; + de[j].new = d1->new; + overlap[j] = !dup; + if (!dup) + overlapcnt++; } else { j = edit(d1, dup, j, DIFF_TYPE3); } dup = false; + f1f3delta += (d1->old.to - d1->old.from) - + (d1->new.to - d1->new.from); d1++; d2++; continue; @@ -462,7 +484,7 @@ merge(int m1, int m2) } if (mflag) - mergescript(j); + mergescript(j, f1f3delta); else if (Aflag) Ascript(j); else if (eflag) @@ -544,7 +566,7 @@ skip(int i, int from, const char *pr) for (n = 0; cline[i] < from - 1; n += j) { if ((line = get_line(fp[i], &j)) == NULL) - errx(EXIT_FAILURE, "logic error"); + errx(2, "logic error"); if (pr != NULL) printf("%s%s", Tflag == 1 ? "\t" : pr, line); cline[i]++; @@ -575,7 +597,7 @@ duplicate(struct range *r1, struct range *r2) if (c == -1 && d == -1) break; if (c == -1 || d == -1) - errx(EXIT_FAILURE, "logic error"); + errx(2, "logic error"); nchar++; if (c != d) { repos(nchar); @@ -600,7 +622,7 @@ repos(int nchar) * collect an editing script for later regurgitation */ static int -edit(struct diff *diff, bool dup, int j, int difftype) +edit(struct diff *diff, bool dup, int j, enum difftype difftype) { if (!(eflag == EFLAG_UNMERGED || (!dup && eflag == EFLAG_OVERLAP ) || @@ -613,10 +635,6 @@ edit(struct diff *diff, bool dup, int j, int difftype) overlapcnt++; de[j].type = difftype; -#if DEBUG - de[j].line = strdup(diff->line); -#endif /* DEBUG */ - de[j].old.from = diff->old.from; de[j].old.to = diff->old.to; de[j].new.from = diff->new.from; @@ -636,7 +654,7 @@ printrange(FILE *p, struct range *r) return; if (r->from > r->to) - errx(EXIT_FAILURE, "invalid print range"); + errx(2, "invalid print range"); /* * XXX-THJ: We read through all of the file for each range printed. @@ -695,7 +713,7 @@ edscript(int n) if (iflag) printf("w\nq\n"); - exit(eflag == EFLAG_NONE ? overlapcnt : 0); + exit(oflag ? overlapcnt > 0 : 0); } /* @@ -724,7 +742,7 @@ Ascript(int n) prange(old, deletenew); printrange(fp[2], new); } else { - startmark = new->to - 1; + startmark = new->to - 1 + de_delta[n]; printf("%da\n", startmark); printf("%s %s\n", newmark, f3mark); @@ -789,11 +807,10 @@ Ascript(int n) * inbetween lines. */ static void -mergescript(int i) +mergescript(int i, int f1f3delta) { struct range r, *new, *old; int n; - bool delete = false; r.from = 1; r.to = 1; @@ -806,21 +823,17 @@ mergescript(int i) * Print any lines leading up to here. If we are merging don't * print deleted ranges. */ - delete = (new->from == new->to); - if (de[n].type == DIFF_TYPE1 && delete) - r.to = new->from - 1; - else if (de[n].type == DIFF_TYPE3 && (old->from == old->to)) { - r.from = old->from - 1; - r.to = new->from; - } else + if (de[n].type == DIFF_TYPE1) + r.to = old->to; + else if (de[n].type == DIFF_TYPE2) + r.to = new->from + de_delta[n]; + else r.to = old->from; printrange(fp[0], &r); switch (de[n].type) { case DIFF_TYPE1: - /* If this isn't a delete print it */ - if (!delete) - printrange(fp[2], new); + /* Content included in "between" printing from fp[0] */ break; case DIFF_TYPE2: printf("%s %s\n", oldmark, f2mark); @@ -856,12 +869,11 @@ mergescript(int i) } break; default: - printf("Error: Unhandled diff type - exiting\n"); - exit(EXIT_FAILURE); + __assert_unreachable(); } - if (old->from == old->to) - r.from = new->to; + if (de[n].type == DIFF_TYPE2) + r.from = new->to + de_delta[n]; else r.from = old->to; } @@ -869,19 +881,8 @@ mergescript(int i) /* * Print from the final range to the end of 'myfile'. Any deletions or * additions to this file should have been handled by now. - * - * If the ranges are the same we need to rewind a line. - * If the new range is 0 length (from == to), we need to use the old - * range. */ - new = &de[n-1].new; - old = &de[n-1].old; - - if (old->from == new->from && old->to == new->to) - r.from--; - else if (new->from == new->to) - r.from = old->from; - + r.from -= f1f3delta; r.to = INT_MAX; printrange(fp[2], &r); exit(overlapcnt > 0); @@ -892,6 +893,7 @@ increase(void) { struct diff *p; char *q; + int *s; size_t newsz, incr; /* are the memset(3) calls needed? */ @@ -900,32 +902,52 @@ increase(void) p = reallocarray(d13, newsz, sizeof(*p)); if (p == NULL) - err(1, NULL); + err(2, NULL); memset(p + szchanges, 0, incr * sizeof(*p)); d13 = p; p = reallocarray(d23, newsz, sizeof(*p)); if (p == NULL) - err(1, NULL); + err(2, NULL); memset(p + szchanges, 0, incr * sizeof(*p)); d23 = p; p = reallocarray(de, newsz, sizeof(*p)); if (p == NULL) - err(1, NULL); + err(2, NULL); memset(p + szchanges, 0, incr * sizeof(*p)); de = p; q = reallocarray(overlap, newsz, 1); if (q == NULL) - err(1, NULL); + err(2, NULL); memset(q + szchanges, 0, incr * 1); overlap = q; + s = reallocarray(de_delta, newsz, sizeof(*s)); + if (s == NULL) + err(2, NULL); + memset(s + szchanges, 0, incr * sizeof(*s)); + de_delta = s; szchanges = newsz; } +static void +wait_and_check(int pd) +{ + int status; + + while (pdwait(pd, &status, WEXITED, NULL, NULL) == -1) { + if (errno != EINTR) + err(2, "pdwait"); + } + + if (WIFEXITED(status) && WEXITSTATUS(status) >= 2) + errx(2, "diff exited abnormally"); + if (WIFSIGNALED(status)) + errx(2, "diff killed by signal %d", WTERMSIG(status)); +} int main(int argc, char **argv) { - int ch, nblabels, status, m, n, kq, nke, nleft, i; + int ch, nblabels, m, n; char *labels[] = { NULL, NULL, NULL }; const char *diffprog = DIFF_PATH; char *file1, *file2, *file3; @@ -934,7 +956,6 @@ main(int argc, char **argv) int fd13[2], fd23[2]; int pd13, pd23; cap_rights_t rights_ro; - struct kevent *e; nblabels = 0; eflag = EFLAG_NONE; @@ -1016,14 +1037,6 @@ main(int argc, char **argv) cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK); - kq = kqueue(); - if (kq == -1) - err(2, "kqueue"); - - e = malloc(2 * sizeof(*e)); - if (e == NULL) - err(2, "malloc"); - /* TODO stdio */ file1 = argv[0]; file2 = argv[1]; @@ -1069,20 +1082,10 @@ main(int argc, char **argv) diffargv[diffargc] = file1; diffargv[diffargc + 1] = file3; diffargv[diffargc + 2] = NULL; - - nleft = 0; pd13 = diffexec(diffprog, diffargv, fd13); - EV_SET(e + nleft , pd13, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT, 0, NULL); - if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1) - err(2, "kevent1"); - nleft++; diffargv[diffargc] = file2; pd23 = diffexec(diffprog, diffargv, fd23); - EV_SET(e + nleft , pd23, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT, 0, NULL); - if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1) - err(2, "kevent2"); - nleft++; caph_cache_catpages(); if (caph_enter() < 0) @@ -1093,23 +1096,10 @@ main(int argc, char **argv) m = readin(fd13[0], &d13); n = readin(fd23[0], &d23); - /* waitpid cooked over pdforks */ - while (nleft > 0) { - nke = kevent(kq, NULL, 0, e, nleft, NULL); - if (nke == -1) - err(2, "kevent"); - for (i = 0; i < nke; i++) { - status = e[i].data; - if (WIFEXITED(status) && WEXITSTATUS(status) >= 2) - errx(2, "diff exited abnormally"); - else if (WIFSIGNALED(status)) - errx(2, "diff killed by signal %d", - WTERMSIG(status)); - } - nleft -= nke; - } - free(e); + wait_and_check(pd13); + wait_and_check(pd23); + merge(m, n); - return (EXIT_SUCCESS); + exit(0); } diff --git a/usr.bin/diff3/tests/Makefile b/usr.bin/diff3/tests/Makefile index 864f27beede8..e35ab095f2f7 100644 --- a/usr.bin/diff3/tests/Makefile +++ b/usr.bin/diff3/tests/Makefile @@ -23,6 +23,20 @@ ${PACKAGE}FILES+= \ long-A.out \ long-merge.out \ fbsdid1.txt \ - fbsdid2.txt + fbsdid2.txt \ + conflict1.txt \ + conflict2.txt \ + conflict3.txt \ + conflict-merge.out \ + simple1.txt \ + simple2.txt \ + simple3.txt \ + simple-merge.out \ + simple-Em.out \ + conflict-Em.out \ + passwd-test.txt \ + passwd-old.txt \ + passwd-new.txt \ + passwd-Em.out .include <bsd.test.mk> diff --git a/usr.bin/diff3/tests/conflict-Em.out b/usr.bin/diff3/tests/conflict-Em.out new file mode 100644 index 000000000000..dcc1ddaff6fb --- /dev/null +++ b/usr.bin/diff3/tests/conflict-Em.out @@ -0,0 +1,19 @@ +<<<<<<< conflict3.txt +root:someone@example.com +======= +#root:me@my.domain +>>>>>>> conflict2.txt + +<<<<<<< conflict3.txt +#Basicsystemaliases--theseMUSTbepresent +MAILER-DAEMON:postmaster +postmaster:root +======= +#Basicsystemaliases--theseMUSTbepresent +MAILER-DAEMON:postmaster +postmaster:root + +#Generalredirectionsforpseudoaccounts +_dhcp:root +_pflogd:root +>>>>>>> conflict2.txt diff --git a/usr.bin/diff3/tests/conflict-merge.out b/usr.bin/diff3/tests/conflict-merge.out new file mode 100644 index 000000000000..737cba7dc224 --- /dev/null +++ b/usr.bin/diff3/tests/conflict-merge.out @@ -0,0 +1,25 @@ +<<<<<<< conflict3.txt +root:someone@example.com +||||||| conflict1.txt +# root: me@my.domain +======= +#root:me@my.domain +>>>>>>> conflict2.txt + +<<<<<<< conflict3.txt +#Basicsystemaliases--theseMUSTbepresent +MAILER-DAEMON:postmaster +postmaster:root +||||||| conflict1.txt +# Basic system aliases -- these MUST be present +MAILER-DAEMON: postmaster +postmaster: root +======= +#Basicsystemaliases--theseMUSTbepresent +MAILER-DAEMON:postmaster +postmaster:root + +#Generalredirectionsforpseudoaccounts +_dhcp:root +_pflogd:root +>>>>>>> conflict2.txt diff --git a/usr.bin/diff3/tests/conflict1.txt b/usr.bin/diff3/tests/conflict1.txt new file mode 100644 index 000000000000..d5bde7598f68 --- /dev/null +++ b/usr.bin/diff3/tests/conflict1.txt @@ -0,0 +1,5 @@ +# root: me@my.domain + +# Basic system aliases -- these MUST be present +MAILER-DAEMON: postmaster +postmaster: root diff --git a/usr.bin/diff3/tests/conflict2.txt b/usr.bin/diff3/tests/conflict2.txt new file mode 100644 index 000000000000..9afb26959e35 --- /dev/null +++ b/usr.bin/diff3/tests/conflict2.txt @@ -0,0 +1,9 @@ +#root:me@my.domain + +#Basicsystemaliases--theseMUSTbepresent +MAILER-DAEMON:postmaster +postmaster:root + +#Generalredirectionsforpseudoaccounts +_dhcp:root +_pflogd:root diff --git a/usr.bin/diff3/tests/conflict3.txt b/usr.bin/diff3/tests/conflict3.txt new file mode 100644 index 000000000000..14ac33b41853 --- /dev/null +++ b/usr.bin/diff3/tests/conflict3.txt @@ -0,0 +1,5 @@ +root:someone@example.com + +#Basicsystemaliases--theseMUSTbepresent +MAILER-DAEMON:postmaster +postmaster:root diff --git a/usr.bin/diff3/tests/diff3_test.sh b/usr.bin/diff3/tests/diff3_test.sh index 3cbd7dac1ed9..4510653bcd47 100755 --- a/usr.bin/diff3/tests/diff3_test.sh +++ b/usr.bin/diff3/tests/diff3_test.sh @@ -5,6 +5,11 @@ atf_test_case diff3_ed atf_test_case diff3_A atf_test_case diff3_merge atf_test_case diff3_E_merge +atf_test_case diff3_merge_conflict +atf_test_case diff3_merge_simple +atf_test_case diff3_Em_simple +atf_test_case diff3_Em_conflict +atf_test_case diff3_Em_insert diff3_body() { @@ -20,10 +25,10 @@ diff3_body() atf_check -o file:$(atf_get_srcdir)/2.out \ diff3 -e $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt - atf_check -o file:$(atf_get_srcdir)/3.out \ + atf_check -s exit:1 -o file:$(atf_get_srcdir)/3.out \ diff3 -E -L 1 -L 2 -L 3 $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt - atf_check -o file:$(atf_get_srcdir)/4.out \ + atf_check -s exit:1 -o file:$(atf_get_srcdir)/4.out \ diff3 -X -L 1 -L 2 -L 3 $(atf_get_srcdir)/1.txt $(atf_get_srcdir)/2.txt $(atf_get_srcdir)/3.txt atf_check -o file:$(atf_get_srcdir)/5.out \ @@ -75,7 +80,6 @@ expected="<<<<<<< 2 ======= # \$FreeBSD: head/local 12345 jhb \$ >>>>>>> 3 -# \$FreeBSD: head/local 12345 jhb \$ this is a file @@ -97,6 +101,36 @@ these are some local mods to the file } +diff3_merge_conflict_body() +{ + atf_check -s exit:1 -o file:$(atf_get_srcdir)/conflict-merge.out \ + diff3 -m -L conflict3.txt -L conflict1.txt -L conflict2.txt $(atf_get_srcdir)/conflict3.txt $(atf_get_srcdir)/conflict1.txt $(atf_get_srcdir)/conflict2.txt +} + +diff3_merge_simple_body() +{ + atf_check -s exit:0 -o file:$(atf_get_srcdir)/simple-merge.out \ + diff3 -m $(atf_get_srcdir)/simple3.txt $(atf_get_srcdir)/simple1.txt $(atf_get_srcdir)/simple2.txt +} + +diff3_Em_simple_body() +{ + atf_check -s exit:0 -o file:$(atf_get_srcdir)/simple-Em.out \ + diff3 -E -m $(atf_get_srcdir)/simple3.txt $(atf_get_srcdir)/simple1.txt $(atf_get_srcdir)/simple2.txt +} + +diff3_Em_conflict_body() +{ + atf_check -s exit:1 -o file:$(atf_get_srcdir)/conflict-Em.out \ + diff3 -E -m -L conflict3.txt -L conflict1.txt -L conflict2.txt $(atf_get_srcdir)/conflict3.txt $(atf_get_srcdir)/conflict1.txt $(atf_get_srcdir)/conflict2.txt +} + +diff3_Em_insert_body() +{ + atf_check -s exit:0 -o file:$(atf_get_srcdir)/passwd-Em.out \ + diff3 -E -m $(atf_get_srcdir)/passwd-test.txt $(atf_get_srcdir)/passwd-old.txt $(atf_get_srcdir)/passwd-new.txt +} + atf_init_test_cases() { atf_add_test_case diff3 @@ -105,4 +139,9 @@ atf_init_test_cases() atf_add_test_case diff3_A atf_add_test_case diff3_merge atf_add_test_case diff3_E_merge + atf_add_test_case diff3_merge_conflict + atf_add_test_case diff3_merge_simple + atf_add_test_case diff3_Em_simple + atf_add_test_case diff3_Em_conflict + atf_add_test_case diff3_Em_insert } diff --git a/usr.bin/diff3/tests/passwd-Em.out b/usr.bin/diff3/tests/passwd-Em.out new file mode 100644 index 000000000000..2b52a6440f6b --- /dev/null +++ b/usr.bin/diff3/tests/passwd-Em.out @@ -0,0 +1,16 @@ +# +root:<rpass>:0:0::0:0:Charlie &:/root:/bin/csh +toor:*:0:0::0:0:Bourne-again Superuser:/root: +daemon:*:1:1::0:0:Owner of many system processes:/root:/usr/sbin/nologin +operator:*:2:5::0:0:System &:/:/usr/sbin/nologin +_dhcp:*:65:65::0:0:dhcp programs:/var/empty:/usr/sbin/nologin +uucp:*:66:66::0:0:UUCP pseudo-user:/var/spool/uucppublic:/usr/local/libexec/uucp/uucico +pop:*:68:6::0:0:Post Office Owner:/nonexistent:/usr/sbin/nologin +auditdistd:*:78:77::0:0:Auditdistd unprivileged user:/var/empty:/usr/sbin/nologin +www:*:80:80::0:0:World Wide Web Owner:/nonexistent:/usr/sbin/nologin +hast:*:845:845::0:0:HAST unprivileged user:/var/empty:/usr/sbin/nologin +nobody:*:65534:65534::0:0:Unprivileged user:/nonexistent:/usr/sbin/nologin +john:<password>:1001:1001::0:0:John Baldwin:/home/john:/bin/tcsh +messagebus:*:556:556::0:0:D-BUS Daemon User:/nonexistent:/usr/sbin/nologin +polkit:*:562:562::0:0:PolicyKit User:/nonexistent:/usr/sbin/nologin +haldaemon:*:560:560::0:0:HAL Daemon User:/nonexistent:/usr/sbin/nologin diff --git a/usr.bin/diff3/tests/passwd-new.txt b/usr.bin/diff3/tests/passwd-new.txt new file mode 100644 index 000000000000..8bec617219a3 --- /dev/null +++ b/usr.bin/diff3/tests/passwd-new.txt @@ -0,0 +1,12 @@ +# +root::0:0::0:0:Charlie &:/root:/bin/csh +toor:*:0:0::0:0:Bourne-again Superuser:/root: +daemon:*:1:1::0:0:Owner of many system processes:/root:/usr/sbin/nologin +operator:*:2:5::0:0:System &:/:/usr/sbin/nologin +_dhcp:*:65:65::0:0:dhcp programs:/var/empty:/usr/sbin/nologin +uucp:*:66:66::0:0:UUCP pseudo-user:/var/spool/uucppublic:/usr/local/libexec/uucp/uucico +pop:*:68:6::0:0:Post Office Owner:/nonexistent:/usr/sbin/nologin +auditdistd:*:78:77::0:0:Auditdistd unprivileged user:/var/empty:/usr/sbin/nologin +www:*:80:80::0:0:World Wide Web Owner:/nonexistent:/usr/sbin/nologin +hast:*:845:845::0:0:HAST unprivileged user:/var/empty:/usr/sbin/nologin +nobody:*:65534:65534::0:0:Unprivileged user:/nonexistent:/usr/sbin/nologin diff --git a/usr.bin/diff3/tests/passwd-old.txt b/usr.bin/diff3/tests/passwd-old.txt new file mode 100644 index 000000000000..7a6f936e90c9 --- /dev/null +++ b/usr.bin/diff3/tests/passwd-old.txt @@ -0,0 +1,11 @@ +# +root::0:0::0:0:Charlie &:/root:/bin/csh +toor:*:0:0::0:0:Bourne-again Superuser:/root: +daemon:*:1:1::0:0:Owner of many system processes:/root:/usr/sbin/nologin +operator:*:2:5::0:0:System &:/:/usr/sbin/nologin +_dhcp:*:65:65::0:0:dhcp programs:/var/empty:/usr/sbin/nologin +uucp:*:66:66::0:0:UUCP pseudo-user:/var/spool/uucppublic:/usr/local/libexec/uucp/uucico +pop:*:68:6::0:0:Post Office Owner:/nonexistent:/usr/sbin/nologin +www:*:80:80::0:0:World Wide Web Owner:/nonexistent:/usr/sbin/nologin +hast:*:845:845::0:0:HAST unprivileged user:/var/empty:/usr/sbin/nologin +nobody:*:65534:65534::0:0:Unprivileged user:/nonexistent:/usr/sbin/nologin diff --git a/usr.bin/diff3/tests/passwd-test.txt b/usr.bin/diff3/tests/passwd-test.txt new file mode 100644 index 000000000000..f2b277fb3b4c --- /dev/null +++ b/usr.bin/diff3/tests/passwd-test.txt @@ -0,0 +1,15 @@ +# +root:<rpass>:0:0::0:0:Charlie &:/root:/bin/csh +toor:*:0:0::0:0:Bourne-again Superuser:/root: +daemon:*:1:1::0:0:Owner of many system processes:/root:/usr/sbin/nologin +operator:*:2:5::0:0:System &:/:/usr/sbin/nologin +_dhcp:*:65:65::0:0:dhcp programs:/var/empty:/usr/sbin/nologin +uucp:*:66:66::0:0:UUCP pseudo-user:/var/spool/uucppublic:/usr/local/libexec/uucp/uucico +pop:*:68:6::0:0:Post Office Owner:/nonexistent:/usr/sbin/nologin +www:*:80:80::0:0:World Wide Web Owner:/nonexistent:/usr/sbin/nologin +hast:*:845:845::0:0:HAST unprivileged user:/var/empty:/usr/sbin/nologin +nobody:*:65534:65534::0:0:Unprivileged user:/nonexistent:/usr/sbin/nologin +john:<password>:1001:1001::0:0:John Baldwin:/home/john:/bin/tcsh +messagebus:*:556:556::0:0:D-BUS Daemon User:/nonexistent:/usr/sbin/nologin +polkit:*:562:562::0:0:PolicyKit User:/nonexistent:/usr/sbin/nologin +haldaemon:*:560:560::0:0:HAL Daemon User:/nonexistent:/usr/sbin/nologin diff --git a/usr.bin/diff3/tests/simple-Em.out b/usr.bin/diff3/tests/simple-Em.out new file mode 100644 index 000000000000..c9ad1c1bed8f --- /dev/null +++ b/usr.bin/diff3/tests/simple-Em.out @@ -0,0 +1,3 @@ +this is an new line + +this is a local line diff --git a/usr.bin/diff3/tests/simple-merge.out b/usr.bin/diff3/tests/simple-merge.out new file mode 100644 index 000000000000..c9ad1c1bed8f --- /dev/null +++ b/usr.bin/diff3/tests/simple-merge.out @@ -0,0 +1,3 @@ +this is an new line + +this is a local line diff --git a/usr.bin/diff3/tests/simple1.txt b/usr.bin/diff3/tests/simple1.txt new file mode 100644 index 000000000000..4c4c2cd1a4e7 --- /dev/null +++ b/usr.bin/diff3/tests/simple1.txt @@ -0,0 +1,2 @@ +this is an old line + diff --git a/usr.bin/diff3/tests/simple2.txt b/usr.bin/diff3/tests/simple2.txt new file mode 100644 index 000000000000..e880a8af5c39 --- /dev/null +++ b/usr.bin/diff3/tests/simple2.txt @@ -0,0 +1,2 @@ +this is an new line + diff --git a/usr.bin/diff3/tests/simple3.txt b/usr.bin/diff3/tests/simple3.txt new file mode 100644 index 000000000000..4ab38534cba1 --- /dev/null +++ b/usr.bin/diff3/tests/simple3.txt @@ -0,0 +1,3 @@ +this is an old line + +this is a local line diff --git a/usr.bin/etdump/etdump.c b/usr.bin/etdump/etdump.c index 6c4a256e15f5..dce2d70bf0ec 100644 --- a/usr.bin/etdump/etdump.c +++ b/usr.bin/etdump/etdump.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2018 iXsystems, Inc. * All rights reserved. * diff --git a/usr.bin/etdump/etdump.h b/usr.bin/etdump/etdump.h index c61070d05018..8e4acc13dd77 100644 --- a/usr.bin/etdump/etdump.h +++ b/usr.bin/etdump/etdump.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2018 iXsystems, Inc. * All rights reserved. * diff --git a/usr.bin/etdump/output_shell.c b/usr.bin/etdump/output_shell.c index d709684c02dc..1d5ec4af998b 100644 --- a/usr.bin/etdump/output_shell.c +++ b/usr.bin/etdump/output_shell.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2018 iXsystems, Inc. * All rights reserved. * diff --git a/usr.bin/etdump/output_text.c b/usr.bin/etdump/output_text.c index aafc6d702a54..b538a2097a31 100644 --- a/usr.bin/etdump/output_text.c +++ b/usr.bin/etdump/output_text.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2018 iXsystems, Inc. * All rights reserved. * diff --git a/usr.bin/from/from.c b/usr.bin/from/from.c index 031803ebae16..63eb69daf36a 100644 --- a/usr.bin/from/from.c +++ b/usr.bin/from/from.c @@ -30,6 +30,8 @@ */ #include <sys/types.h> + +#include <capsicum_helpers.h> #include <ctype.h> #include <err.h> #include <pwd.h> @@ -97,9 +99,12 @@ main(int argc, char **argv) /* read from stdin */ if (strcmp(file, "-") == 0) { mbox = stdin; - } + } else if ((mbox = fopen(file, "r")) == NULL) { - errx(1, "can't read %s", file); + errx(EXIT_FAILURE, "can't read %s", file); + } + if (caph_limit_stdio() < 0 || caph_enter() < 0) { + err(EXIT_FAILURE, "capsicum"); } for (newline = 1; fgets(buf, sizeof(buf), mbox);) { if (*buf == '\n') { @@ -117,16 +122,16 @@ main(int argc, char **argv) } if (count != -1) printf("There %s %d message%s in your incoming mailbox.\n", - count == 1 ? "is" : "are", count, count == 1 ? "" : "s"); + count == 1 ? "is" : "are", count, count == 1 ? "" : "s"); fclose(mbox); - exit(0); + exit(EXIT_SUCCESS); } static void usage(void) { fprintf(stderr, "usage: from [-c] [-f file] [-s sender] [user]\n"); - exit(1); + exit(EXIT_FAILURE); } static int @@ -137,14 +142,14 @@ match(const char *line, const char *sender) for (first = *sender++;;) { if (isspace(ch = *line)) - return(0); + return (0); ++line; ch = tolower(ch); if (ch != first) continue; for (p = sender, t = line;;) { if (!(pch = *p++)) - return(1); + return (1); ch = tolower(*t); t++; if (ch != pch) diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c index 17ed43b55c5a..d3f2ac882e61 100644 --- a/usr.bin/kdump/kdump.c +++ b/usr.bin/kdump/kdump.c @@ -2404,11 +2404,7 @@ ktrstructarray(struct ktr_struct_array *ksa, size_t buflen) kev.filter = kev32.filter; kev.flags = kev32.flags; kev.fflags = kev32.fflags; -#if BYTE_ORDER == BIG_ENDIAN - kev.data = kev32.data2 | ((int64_t)kev32.data1 << 32); -#else - kev.data = kev32.data1 | ((int64_t)kev32.data2 << 32); -#endif + memcpy(&kev.data, &kev32.data, sizeof(kev.data)); kev.udata = (void *)(uintptr_t)kev32.udata; ktrkevent(&kev); } else if (strcmp(name, "freebsd11_kevent32") == 0) { diff --git a/usr.bin/kyua/Makefile b/usr.bin/kyua/Makefile index d6131651afbf..aa0e5cbbcad2 100644 --- a/usr.bin/kyua/Makefile +++ b/usr.bin/kyua/Makefile @@ -49,6 +49,8 @@ CFLAGS+= -DGDB=\"/usr/local/bin/gdb\" \ -DPACKAGE_VERSION=\"${KYUA_VERSION}\" \ -DVERSION=\"${KYUA_VERSION}\" +CXXWARNFLAGS.gcc+= -Wno-free-nonheap-object + SRCS+= utils/datetime.cpp \ utils/env.cpp \ utils/memory.cpp \ diff --git a/usr.bin/less/defines.h b/usr.bin/less/defines.h index d95ff956bd37..a051790d0f49 100644 --- a/usr.bin/less/defines.h +++ b/usr.bin/less/defines.h @@ -21,91 +21,91 @@ * be safe to run by unprivileged users. * SECURE_COMPILE is set by the --with-secure configure option. */ -#define SECURE SECURE_COMPILE +#define SECURE SECURE_COMPILE /* * SHELL_ESCAPE is 1 if you wish to allow shell escapes. * (This is possible only if your system supplies the system() function.) */ -#define SHELL_ESCAPE (!SECURE) +#define SHELL_ESCAPE (!SECURE) /* * EXAMINE is 1 if you wish to allow examining files by name from within less. */ -#define EXAMINE (!SECURE) +#define EXAMINE (!SECURE) /* * TAB_COMPLETE_FILENAME is 1 if you wish to allow the TAB key * to complete filenames at prompts. */ -#define TAB_COMPLETE_FILENAME (!SECURE) +#define TAB_COMPLETE_FILENAME (!SECURE) /* * CMD_HISTORY is 1 if you wish to allow keys to cycle through * previous commands at prompts. */ -#define CMD_HISTORY 1 +#define CMD_HISTORY 1 /* * HILITE_SEARCH is 1 if you wish to have search targets to be * displayed in standout mode. */ -#define HILITE_SEARCH 1 +#define HILITE_SEARCH 1 /* * EDITOR is 1 if you wish to allow editor invocation (the "v" command). * (This is possible only if your system supplies the system() function.) * EDIT_PGM is the name of the (default) editor to be invoked. */ -#define EDITOR (!SECURE) +#define EDITOR (!SECURE) /* * TAGS is 1 if you wish to support tag files. */ -#define TAGS (!SECURE) +#define TAGS (!SECURE) /* - * USERFILE is 1 if you wish to allow a .less file to specify + * USERFILE is 1 if you wish to allow a .lesskey or .less file to specify * user-defined key bindings. */ -#define USERFILE (!SECURE) +#define USERFILE (!SECURE) /* * GLOB is 1 if you wish to have shell metacharacters expanded in filenames. * This will generally work if your system provides the "popen" function * and the "echo" shell command. */ -#define GLOB (!SECURE) +#define GLOB (!SECURE) /* * PIPEC is 1 if you wish to have the "|" command * which allows the user to pipe data into a shell command. */ -#define PIPEC (!SECURE && HAVE_POPEN) +#define PIPEC (!SECURE && HAVE_POPEN) /* * LOGFILE is 1 if you wish to allow the -o option (to create log files). */ -#define LOGFILE (!SECURE) +#define LOGFILE (!SECURE) /* - * OSC8_SEARCH is 1 if you wish to allow the ^O^O and related commands + * OSC8_LINK is 1 if you wish to allow the ^O^O and related commands * (to open OSC8 hyperlinks). */ -#define OSC8_LINK 1 +#define OSC8_LINK 1 /* * GNU_OPTIONS is 1 if you wish to support the GNU-style command * line options --help and --version. */ -#define GNU_OPTIONS 1 +#define GNU_OPTIONS 1 /* * ONLY_RETURN is 1 if you want RETURN to be the only input which * will continue past an error message. * Otherwise, any key will continue past an error message. */ -#define ONLY_RETURN 0 +#define ONLY_RETURN 0 /* * LESSKEYFILE is the filename of the default lesskey output file @@ -116,33 +116,36 @@ * LESSHISTFILE is the filename of the history file * (in the HOME directory). */ -#define LESSKEYFILE ".less" -#define LESSKEYFILE_SYS "/etc/lesskey" -#define DEF_LESSKEYINFILE ".lesskey" -#define LESSKEYINFILE_SYS "/etc/syslesskey" -#define LESSHISTFILE ".lesshst" +/* FreeBSD */ +#define SYSDIR "/etc" + +#define LESSKEYFILE ".less" +#define LESSKEYFILE_SYS SYSDIR "/sysless" +#define DEF_LESSKEYINFILE ".lesskey" +#define LESSKEYINFILE_SYS SYSDIR "/syslesskey" +#define LESSHISTFILE ".lesshst" /* Autodetect mingw */ #if defined(__MINGW32__) /* * Define MSDOS_COMPILER if compiling under Microsoft C. */ -#define MSDOS_COMPILER WIN32C +#define MSDOS_COMPILER WIN32C /* * Pathname separator character. */ -#define PATHNAME_SEP "\\" +#define PATHNAME_SEP "\\" #else /* * Define MSDOS_COMPILER if compiling under Microsoft C. */ -#define MSDOS_COMPILER 0 +#define MSDOS_COMPILER 0 /* * Pathname separator character. */ -#define PATHNAME_SEP "/" +#define PATHNAME_SEP "/" #endif /* Settings always true on Unix. */ @@ -154,9 +157,9 @@ #define TGETENT_OK 1 /* - * HAVE_ANSI_PROTOS is 1 if your compiler supports ANSI function prototypes. + * HAVE_ANSI_PROTOS is 1 if your compiler supports ANSI function prototypes. */ -#define HAVE_ANSI_PROTOS 1 +#define HAVE_ANSI_PROTOS 1 /* * HAVE_SYS_TYPES_H is 1 if your system has <sys/types.h>. @@ -172,28 +175,28 @@ * HAVE_PERROR is 1 if your system has the perror() call. * (Actually, if it has sys_errlist, sys_nerr and errno.) */ -#define HAVE_PERROR 1 +#define HAVE_PERROR 1 /* * HAVE_TIME is 1 if your system has the time() call. */ -#define HAVE_TIME 1 +#define HAVE_TIME 1 /* * HAVE_SHELL is 1 if your system supports a SHELL command interpreter. */ -#define HAVE_SHELL 1 +#define HAVE_SHELL 1 /* * Default shell metacharacters and meta-escape character. */ -#define DEF_METACHARS "; *?\t\n'\"()<>[]|&^`#\\$%=~{}," -#define DEF_METAESCAPE "\\" +#define DEF_METACHARS "; *?\t\n'\"()<>[]|&^`#\\$%=~{}," +#define DEF_METAESCAPE "\\" /* * HAVE_DUP is 1 if your system has the dup() call. */ -#define HAVE_DUP 1 +#define HAVE_DUP 1 /* Define to 1 if you have the memcpy() function. */ #define HAVE_MEMCPY 1 @@ -211,26 +214,26 @@ * Sizes of various buffers. */ #if 0 /* old sizes for small memory machines */ -#define CMDBUF_SIZE 512 /* Buffer for multichar commands */ -#define UNGOT_SIZE 100 /* Max chars to unget() */ -#define LINEBUF_SIZE 1024 /* Max size of line in input file */ -#define OUTBUF_SIZE 1024 /* Output buffer */ -#define PROMPT_SIZE 200 /* Max size of prompt string */ -#define TERMBUF_SIZE 2048 /* Termcap buffer for tgetent */ -#define TERMSBUF_SIZE 1024 /* Buffer to hold termcap strings */ -#define TAGLINE_SIZE 512 /* Max size of line in tags file */ -#define TABSTOP_MAX 32 /* Max number of custom tab stops */ +#define CMDBUF_SIZE 512 /* Buffer for multichar commands */ +#define UNGOT_SIZE 100 /* Max chars to unget() */ +#define LINEBUF_SIZE 1024 /* Max size of line in input file */ +#define OUTBUF_SIZE 1024 /* Output buffer */ +#define PROMPT_SIZE 200 /* Max size of prompt string */ +#define TERMBUF_SIZE 2048 /* Termcap buffer for tgetent */ +#define TERMSBUF_SIZE 1024 /* Buffer to hold termcap strings */ +#define TAGLINE_SIZE 512 /* Max size of line in tags file */ +#define TABSTOP_MAX 32 /* Max number of custom tab stops */ #define LINENUM_POOL 200 /* Size of line number pool */ #else /* more reasonable sizes for modern machines */ -#define CMDBUF_SIZE 2048 /* Buffer for multichar commands */ -#define UNGOT_SIZE 200 /* Max chars to unget() */ -#define LINEBUF_SIZE 1024 /* Initial max size of line in input file */ -#define OUTBUF_SIZE 1024 /* Output buffer */ -#define PROMPT_SIZE 2048 /* Max size of prompt string */ -#define TERMBUF_SIZE 2048 /* Termcap buffer for tgetent */ -#define TERMSBUF_SIZE 1024 /* Buffer to hold termcap strings */ -#define TAGLINE_SIZE 1024 /* Max size of line in tags file */ -#define TABSTOP_MAX 128 /* Max number of custom tab stops */ +#define CMDBUF_SIZE 2048 /* Buffer for multichar commands */ +#define UNGOT_SIZE 200 /* Max chars to unget() */ +#define LINEBUF_SIZE 1024 /* Initial max size of line in input file */ +#define OUTBUF_SIZE 1024 /* Output buffer */ +#define PROMPT_SIZE 2048 /* Max size of prompt string */ +#define TERMBUF_SIZE 2048 /* Termcap buffer for tgetent */ +#define TERMSBUF_SIZE 1024 /* Buffer to hold termcap strings */ +#define TAGLINE_SIZE 1024 /* Max size of line in tags file */ +#define TABSTOP_MAX 128 /* Max number of custom tab stops */ #define LINENUM_POOL 1024 /* Size of line number pool */ #endif @@ -393,6 +396,9 @@ /* Define to 1 if you have the <termcap.h> header file. */ #define HAVE_TERMCAP_H 1 +/* Define HAVE_TERMINFO if you have the terminfo library. */ +#define HAVE_TERMINFO 1 + /* Define HAVE_TERMIOS_FUNCS if you have tcgetattr/tcsetattr. */ #define HAVE_TERMIOS_FUNCS 1 @@ -429,12 +435,6 @@ /* Define HAVE_VOID if your compiler supports the "void" type. */ #define HAVE_VOID 1 -/* Define HAVE_WCTYPE if you have iswupper, iswlower, towupper, towlower. */ -#define HAVE_WCTYPE 1 - -/* Define to 1 if you have the <wctype.h> header file. */ -#define HAVE_WCTYPE_H 1 - /* Define to 1 if you have the '_setjmp' function. */ #define HAVE__SETJMP 1 diff --git a/usr.bin/less/lesspipe.sh b/usr.bin/less/lesspipe.sh index 253914b8b3ee..7992cc4e2e3d 100644 --- a/usr.bin/less/lesspipe.sh +++ b/usr.bin/less/lesspipe.sh @@ -21,7 +21,7 @@ case "$1" in exec lzma -d -c "$1" 2>/dev/null ;; *.zst) - exec zstd -d -q -c "$1" 2>/dev/null + exec zstdcat -q "$1" 2>/dev/null ;; *) exec cat "$1" 2>/dev/null ;; diff --git a/usr.bin/m4/eval.c b/usr.bin/m4/eval.c index 3170d52bfe2a..0963a61a2914 100644 --- a/usr.bin/m4/eval.c +++ b/usr.bin/m4/eval.c @@ -178,7 +178,7 @@ expand_builtin(const char *argv[], int argc, int td) */ { int base = 10; - int maxdigits = 0; + int mindigits = 0; const char *errstr; if (argc > 3 && *argv[3] != '\0') { @@ -189,14 +189,14 @@ expand_builtin(const char *argv[], int argc, int td) } } if (argc > 4) { - maxdigits = strtonum(argv[4], 0, INT_MAX, &errstr); + mindigits = strtonum(argv[4], 0, INT_MAX, &errstr); if (errstr) { - m4errx(1, "expr: maxdigits is %s: %s.", + m4errx(1, "expr: mindigits is %s: %s.", errstr, argv[4]); } } if (argc > 2) - pbnumbase(expr(argv[2]), base, maxdigits); + pbnumbase(expr(argv[2]), base, mindigits); break; } @@ -490,7 +490,7 @@ expand_builtin(const char *argv[], int argc, int td) case DEFNTYPE: if (argc > 2) - for (n = 2; n < argc; n++) + for (n = argc - 1; n >= 2; n--) dodefn(argv[n]); break; diff --git a/usr.bin/m4/misc.c b/usr.bin/m4/misc.c index 3091f2ad1f9e..fd72292aeac0 100644 --- a/usr.bin/m4/misc.c +++ b/usr.bin/m4/misc.c @@ -138,8 +138,6 @@ pbnumbase(int n, int base, int d) } while ((num /= base) > 0); - if (n < 0) - printed++; while (printed++ < d) pushback('0'); diff --git a/usr.bin/m4/tests/Makefile b/usr.bin/m4/tests/Makefile index 45245d75e85d..fd7a44cea14c 100644 --- a/usr.bin/m4/tests/Makefile +++ b/usr.bin/m4/tests/Makefile @@ -1,10 +1,11 @@ PACKAGE= tests -TAP_TESTS_SH= legacy_test +ATF_TESTS_SH= m4_test ${PACKAGE}FILES+= args.m4 ${PACKAGE}FILES+= args2.m4 ${PACKAGE}FILES+= comments.m4 +${PACKAGE}FILES+= defn.m4 ${PACKAGE}FILES+= esyscmd.m4 ${PACKAGE}FILES+= eval.m4 ${PACKAGE}FILES+= ff_after_dnl.m4.uu @@ -20,9 +21,14 @@ ${PACKAGE}FILES+= m4wrap3.m4 ${PACKAGE}FILES+= patterns.m4 ${PACKAGE}FILES+= quotes.m4 ${PACKAGE}FILES+= redef.m4 +${PACKAGE}FILES+= strangequotes.m4.uu +${PACKAGE}FILES+= translit.m4 +${PACKAGE}FILES+= translit2.m4 + ${PACKAGE}FILES+= regress.args.out ${PACKAGE}FILES+= regress.args2.out ${PACKAGE}FILES+= regress.comments.out +${PACKAGE}FILES+= regress.defn.out ${PACKAGE}FILES+= regress.esyscmd.out ${PACKAGE}FILES+= regress.eval.out ${PACKAGE}FILES+= regress.ff_after_dnl.out @@ -31,19 +37,18 @@ ${PACKAGE}FILES+= regress.gnuformat.out ${PACKAGE}FILES+= regress.gnupatterns.out ${PACKAGE}FILES+= regress.gnupatterns2.out ${PACKAGE}FILES+= regress.gnuprefix.out +${PACKAGE}FILES+= regress.gnuprefix.err ${PACKAGE}FILES+= regress.gnusofterror.out +${PACKAGE}FILES+= regress.gnusofterror.err ${PACKAGE}FILES+= regress.gnutranslit2.out ${PACKAGE}FILES+= regress.includes.out ${PACKAGE}FILES+= regress.m4wrap3.out ${PACKAGE}FILES+= regress.patterns.out ${PACKAGE}FILES+= regress.quotes.out +${PACKAGE}FILES+= regress.quotes.err ${PACKAGE}FILES+= regress.redef.out -${PACKAGE}FILES+= regress.sh ${PACKAGE}FILES+= regress.strangequotes.out ${PACKAGE}FILES+= regress.translit.out ${PACKAGE}FILES+= regress.translit2.out -${PACKAGE}FILES+= strangequotes.m4.uu -${PACKAGE}FILES+= translit.m4 -${PACKAGE}FILES+= translit2.m4 .include <bsd.test.mk> diff --git a/usr.bin/m4/tests/defn.m4 b/usr.bin/m4/tests/defn.m4 new file mode 100644 index 000000000000..6599f95a5f20 --- /dev/null +++ b/usr.bin/m4/tests/defn.m4 @@ -0,0 +1,5 @@ +dnl Check that our defn processes its arguments in order. +define(a,1)dnl +define(b,2)dnl +define(c,3)dnl +defn(`a',`b',`c') diff --git a/usr.bin/m4/tests/eval.m4 b/usr.bin/m4/tests/eval.m4 index 1d3f886d0d89..dc0fada781f1 100644 --- a/usr.bin/m4/tests/eval.m4 +++ b/usr.bin/m4/tests/eval.m4 @@ -3,3 +3,5 @@ dnl expr parser eval(224&127) eval(224|127) eval(224&&127) +eval(3-2, 10, 5) +eval(2-3, 10, 4) diff --git a/usr.bin/m4/tests/legacy_test.sh b/usr.bin/m4/tests/legacy_test.sh deleted file mode 100644 index 3c7842d07bf0..000000000000 --- a/usr.bin/m4/tests/legacy_test.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -SRCDIR="$(dirname "${0}")"; export SRCDIR - -m4 "${SRCDIR}/../regress.m4" "${SRCDIR}/regress.sh" | sh diff --git a/usr.bin/m4/tests/m4_test.sh b/usr.bin/m4/tests/m4_test.sh new file mode 100644 index 000000000000..aa9be767d1c9 --- /dev/null +++ b/usr.bin/m4/tests/m4_test.sh @@ -0,0 +1,249 @@ +# +# Copyright (c) 2026 Klara, Inc. +# +# SPDX-License-Identifier: BSD-2-Clause +# + +m4_test() +{ + local dir=$(atf_get_srcdir) + local rc=0 + local args opt output script + while getopts "1gP" opt ; do + case ${opt} in + 1) + rc=1 + ;; + *) + args="${args% }-${opt}" + ;; + esac + done + shift $((OPTIND - 1)) + script=$1 + output=$2 + if [ -z "${output}" ] ; then + output="${script}" + fi + if [ -f "${dir}/regress.${output}.out" ] ; then + ln -s "${dir}/regress.${output}.out" out + else + atf_fail "regress.${output}.out not found" + fi + if [ -f "${dir}/regress.${output}.err" ] ; then + ln -s "${dir}/regress.${output}.err" err + else + touch err + fi + if [ -f "${dir}/${script}.m4.uu" ] ; then + atf_check uudecode -o "${script}.m4" "${dir}/${script}.m4.uu" + elif [ -f "${dir}/${script}.m4" ] ; then + ln -s "${dir}/${script}.m4" "${script}.m4" + else + atf_fail "${script}.m4 not found" + fi + atf_check -s exit:${rc} -o file:out -e file:err \ + m4 -I "${dir}" ${args} "${script}.m4" +} + +args_head() +{ +} +args_body() +{ + m4_test args +} + +args2_head() +{ +} +args2_body() +{ + m4_test args2 +} + +comments_head() +{ +} +comments_body() +{ + m4_test comments +} + +defn_head() +{ +} +defn_body() +{ + m4_test defn +} + +esyscmd_head() +{ +} +esyscmd_body() +{ + m4_test esyscmd +} + +eval_head() +{ +} +eval_body() +{ + m4_test eval +} + +ff_after_dnl_head() +{ +} +ff_after_dnl_body() +{ + m4_test ff_after_dnl +} + +gnueval_head() +{ +} +gnueval_body() +{ + m4_test -g gnueval +} + +gnuformat_head() +{ +} +gnuformat_body() +{ + m4_test -g gnuformat +} + +gnupatterns_head() +{ +} +gnupatterns_body() +{ + m4_test -g gnupatterns +} + +gnupatterns2_head() +{ +} +gnupatterns2_body() +{ + m4_test -g gnupatterns2 +} + +gnuprefix_head() +{ +} +gnuprefix_body() +{ + m4_test -P gnuprefix +} + +gnusofterror_head() +{ +} +gnusofterror_body() +{ + m4_test -1 -g gnusofterror +} + +gnutranslit2_head() +{ +} +gnutranslit2_body() +{ + m4_test -g translit2 gnutranslit2 +} + +includes_head() +{ +} +includes_body() +{ + m4_test includes +} + +m4wrap3_head() +{ +} +m4wrap3_body() +{ + m4_test m4wrap3 +} + +patterns_head() +{ +} +patterns_body() +{ + m4_test patterns +} + +quotes_head() +{ +} +quotes_body() +{ + m4_test -1 quotes +} + +redef_head() +{ +} +redef_body() +{ + m4_test redef +} + +strangequotes_head() +{ +} +strangequotes_body() +{ + m4_test strangequotes +} + +translit_head() +{ +} +translit_body() +{ + m4_test translit +} + +translit2_head() +{ +} +translit2_body() +{ + m4_test translit2 +} + +atf_init_test_cases() +{ + atf_add_test_case args + atf_add_test_case args2 + atf_add_test_case comments + atf_add_test_case defn + atf_add_test_case esyscmd + atf_add_test_case eval + atf_add_test_case ff_after_dnl + atf_add_test_case gnueval + atf_add_test_case gnuformat + atf_add_test_case gnupatterns + atf_add_test_case gnupatterns2 + atf_add_test_case gnuprefix + atf_add_test_case gnusofterror + atf_add_test_case gnutranslit2 + atf_add_test_case includes + atf_add_test_case m4wrap3 + atf_add_test_case patterns + atf_add_test_case quotes + atf_add_test_case redef + atf_add_test_case strangequotes + atf_add_test_case translit + atf_add_test_case translit2 +} diff --git a/usr.bin/m4/tests/regress.defn.out b/usr.bin/m4/tests/regress.defn.out new file mode 100644 index 000000000000..190a18037c64 --- /dev/null +++ b/usr.bin/m4/tests/regress.defn.out @@ -0,0 +1 @@ +123 diff --git a/usr.bin/m4/tests/regress.eval.out b/usr.bin/m4/tests/regress.eval.out index 7298b3f43840..b1bb211dcb64 100644 --- a/usr.bin/m4/tests/regress.eval.out +++ b/usr.bin/m4/tests/regress.eval.out @@ -1,3 +1,5 @@ 96 255 1 +00001 +-0001 diff --git a/usr.bin/m4/tests/regress.gnuprefix.err b/usr.bin/m4/tests/regress.gnuprefix.err new file mode 100644 index 000000000000..8939371e81f4 --- /dev/null +++ b/usr.bin/m4/tests/regress.gnuprefix.err @@ -0,0 +1,44 @@ +`m4_ifelse' `m4_ifelse' +`m4_dnl' `m4_dnl' +`m4_expr' `m4_expr' +`m4_builtin' `m4_builtin' +`m4_popdef' `m4_popdef' +`m4_eval' `m4_eval' +`m4_len' `m4_len' +`m4_indir' `m4_indir' +`m4_sinclude' `m4_sinclude' +`m4_index' `m4_index' +`m4_traceoff' `m4_traceoff' +`m4___file__' `m4___file__' +`m4_unix' `m4_unix' +`m4_mkstemp' `m4_mkstemp' +`m4_changecom' `m4_changecom' +`m4_defn' `m4_defn' +`m4_decr' `m4_decr' +`m4_translit' `m4_translit' +`m4_patsubst' `m4_patsubst' +`m4_dumpdef' `m4_dumpdef' +`m4___line__' `m4___line__' +`m4_esyscmd' `m4_esyscmd' +`m4_traceon' `m4_traceon' +`m4_incr' `m4_incr' +`m4_shift' `m4_shift' +`m4_syscmd' `m4_syscmd' +`m4_include' `m4_include' +`m4_pushdef' `m4_pushdef' +`m4_paste' `m4_paste' +`m4_regexp' `m4_regexp' +`m4_changequote' `m4_changequote' +`m4_undivert' `m4_undivert' +`m4_m4exit' `m4_m4exit' +`m4_substr' `m4_substr' +`m4_m4wrap' `m4_m4wrap' +`m4_ifdef' `m4_ifdef' +`m4_sysval' `m4_sysval' +`m4_divert' `m4_divert' +`m4_maketemp' `m4_maketemp' +`m4_spaste' `m4_spaste' +`m4_define' `m4_define' +`m4_undefine' `m4_undefine' +`m4_divnum' `m4_divnum' +`m4_errprint' `m4_errprint' diff --git a/usr.bin/m4/tests/regress.gnuprefix.out b/usr.bin/m4/tests/regress.gnuprefix.out index 186421d8650b..3e86f4db699c 100644 --- a/usr.bin/m4/tests/regress.gnuprefix.out +++ b/usr.bin/m4/tests/regress.gnuprefix.out @@ -1,46 +1,2 @@ -`m4_ifelse' `m4_ifelse' -`m4_dnl' `m4_dnl' -`m4_expr' `m4_expr' -`m4_builtin' `m4_builtin' -`m4_popdef' `m4_popdef' -`m4_eval' `m4_eval' -`m4_len' `m4_len' -`m4_indir' `m4_indir' -`m4_sinclude' `m4_sinclude' -`m4_index' `m4_index' -`m4_traceoff' `m4_traceoff' -`m4___file__' `m4___file__' -`m4_unix' `m4_unix' -`m4_mkstemp' `m4_mkstemp' -`m4_changecom' `m4_changecom' -`m4_defn' `m4_defn' -`m4_decr' `m4_decr' -`m4_translit' `m4_translit' -`m4_patsubst' `m4_patsubst' -`m4_dumpdef' `m4_dumpdef' -`m4___line__' `m4___line__' -`m4_esyscmd' `m4_esyscmd' -`m4_traceon' `m4_traceon' -`m4_incr' `m4_incr' -`m4_shift' `m4_shift' -`m4_syscmd' `m4_syscmd' -`m4_include' `m4_include' -`m4_pushdef' `m4_pushdef' -`m4_paste' `m4_paste' -`m4_regexp' `m4_regexp' -`m4_changequote' `m4_changequote' -`m4_undivert' `m4_undivert' -`m4_m4exit' `m4_m4exit' -`m4_substr' `m4_substr' -`m4_m4wrap' `m4_m4wrap' -`m4_ifdef' `m4_ifdef' -`m4_sysval' `m4_sysval' -`m4_divert' `m4_divert' -`m4_maketemp' `m4_maketemp' -`m4_spaste' `m4_spaste' -`m4_define' `m4_define' -`m4_undefine' `m4_undefine' -`m4_divnum' `m4_divnum' -`m4_errprint' `m4_errprint' dumpdef() diff --git a/usr.bin/m4/tests/regress.gnusofterror.err b/usr.bin/m4/tests/regress.gnusofterror.err new file mode 100644 index 000000000000..d34464e85791 --- /dev/null +++ b/usr.bin/m4/tests/regress.gnusofterror.err @@ -0,0 +1 @@ +m4: gnusofterror.m4 at line 2: include(hey I do not exit): No such file or directory diff --git a/usr.bin/m4/tests/regress.gnusofterror.out b/usr.bin/m4/tests/regress.gnusofterror.out index 5c23eb237b6c..8baef1b4abc4 100644 --- a/usr.bin/m4/tests/regress.gnusofterror.out +++ b/usr.bin/m4/tests/regress.gnusofterror.out @@ -1,2 +1 @@ -m4: gnusofterror.m4 at line 2: include(hey I do not exit): No such file or directory abc diff --git a/usr.bin/m4/tests/regress.quotes.err b/usr.bin/m4/tests/regress.quotes.err new file mode 100644 index 000000000000..50eb78ca62df --- /dev/null +++ b/usr.bin/m4/tests/regress.quotes.err @@ -0,0 +1,2 @@ +m4: unclosed quote: + quotes.m4 at line 54 diff --git a/usr.bin/m4/tests/regress.quotes.out b/usr.bin/m4/tests/regress.quotes.out index cf34ba42a8d0..df38b6e6cd4d 100644 --- a/usr.bin/m4/tests/regress.quotes.out +++ b/usr.bin/m4/tests/regress.quotes.out @@ -1,5 +1,3 @@ -m4: unclosed quote: - quotes.m4 at line 54 1: normal quoted string [quoted STRING] diff --git a/usr.bin/m4/tests/regress.sh b/usr.bin/m4/tests/regress.sh deleted file mode 100644 index 39c9103db8d9..000000000000 --- a/usr.bin/m4/tests/regress.sh +++ /dev/null @@ -1,32 +0,0 @@ - -echo 1..21 - -test_m4() { - m4 "${@}" 2>&1 | sed -e "s,${SRCDIR}/,,g" -} - -REGRESSION_START($1) - -REGRESSION_TEST(`args', `test_m4 ${SRCDIR}/args.m4') -REGRESSION_TEST(`args2', `test_m4 ${SRCDIR}/args2.m4') -REGRESSION_TEST(`comments', `test_m4 ${SRCDIR}/comments.m4') -REGRESSION_TEST(`esyscmd', `test_m4 ${SRCDIR}/esyscmd.m4') -REGRESSION_TEST(`eval', `test_m4 ${SRCDIR}/eval.m4') -REGRESSION_TEST(`ff_after_dnl', `uudecode -o /dev/stdout ${SRCDIR}/ff_after_dnl.m4.uu | m4') -REGRESSION_TEST(`gnueval', `test_m4 -g ${SRCDIR}/gnueval.m4') -REGRESSION_TEST(`gnuformat', `test_m4 -g ${SRCDIR}/gnuformat.m4') -REGRESSION_TEST(`gnupatterns', `test_m4 -g ${SRCDIR}/gnupatterns.m4') -REGRESSION_TEST(`gnupatterns2', `test_m4 -g ${SRCDIR}/gnupatterns2.m4') -REGRESSION_TEST(`gnuprefix', `test_m4 -P ${SRCDIR}/gnuprefix.m4 2>&1') -REGRESSION_TEST(`gnusofterror', `test_m4 -g ${SRCDIR}/gnusofterror.m4 2>&1') -REGRESSION_TEST(`gnutranslit2', `test_m4 -g ${SRCDIR}/translit2.m4') -REGRESSION_TEST(`includes', `test_m4 -I${SRCDIR} ${SRCDIR}/includes.m4') -REGRESSION_TEST(`m4wrap3', `test_m4 ${SRCDIR}/m4wrap3.m4') -REGRESSION_TEST(`patterns', `test_m4 ${SRCDIR}/patterns.m4') -REGRESSION_TEST(`quotes', `test_m4 ${SRCDIR}/quotes.m4 2>&1') -REGRESSION_TEST(`strangequotes', `uudecode -o /dev/stdout ${SRCDIR}/strangequotes.m4.uu | m4') -REGRESSION_TEST(`redef', `test_m4 ${SRCDIR}/redef.m4') -REGRESSION_TEST(`translit', `test_m4 ${SRCDIR}/translit.m4') -REGRESSION_TEST(`translit2', `test_m4 ${SRCDIR}/translit2.m4') - -REGRESSION_END() diff --git a/usr.bin/man/manpath.1 b/usr.bin/man/manpath.1 index ac9e3b2db5a7..ea01ce23333a 100644 --- a/usr.bin/man/manpath.1 +++ b/usr.bin/man/manpath.1 @@ -1,5 +1,5 @@ .\"- -.\" SPDX-License-Identifer: BSD-2-Clause +.\" SPDX-License-Identifier: BSD-2-Clause .\" .\" Copyright (c) 2010 Gordon Tetlow .\" All rights reserved. diff --git a/usr.bin/mkimg/apm.c b/usr.bin/mkimg/apm.c index 259a7533c27c..59776d18bc47 100644 --- a/usr.bin/mkimg/apm.c +++ b/usr.bin/mkimg/apm.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/bsd.c b/usr.bin/mkimg/bsd.c index 17933c01ac07..647e9ab0608c 100644 --- a/usr.bin/mkimg/bsd.c +++ b/usr.bin/mkimg/bsd.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/ebr.c b/usr.bin/mkimg/ebr.c index 4d6adbb3b8ba..20ade1ed88d1 100644 --- a/usr.bin/mkimg/ebr.c +++ b/usr.bin/mkimg/ebr.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/endian.h b/usr.bin/mkimg/endian.h index e9dc2b44b9b7..98e699bee855 100644 --- a/usr.bin/mkimg/endian.h +++ b/usr.bin/mkimg/endian.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2002 Thomas Moestl <tmm@FreeBSD.org> * All rights reserved. * diff --git a/usr.bin/mkimg/format.c b/usr.bin/mkimg/format.c index 6730c22ca153..97e580cd8ca2 100644 --- a/usr.bin/mkimg/format.c +++ b/usr.bin/mkimg/format.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/format.h b/usr.bin/mkimg/format.h index 304af4586da8..db1ea764ced2 100644 --- a/usr.bin/mkimg/format.h +++ b/usr.bin/mkimg/format.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/gpt.c b/usr.bin/mkimg/gpt.c index ed3f008c394f..ce817ea10ed2 100644 --- a/usr.bin/mkimg/gpt.c +++ b/usr.bin/mkimg/gpt.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/image.c b/usr.bin/mkimg/image.c index 07aaf1a6c0ea..90817206e317 100644 --- a/usr.bin/mkimg/image.c +++ b/usr.bin/mkimg/image.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/image.h b/usr.bin/mkimg/image.h index 53dd3dc2df8a..956fe3f27556 100644 --- a/usr.bin/mkimg/image.h +++ b/usr.bin/mkimg/image.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/mbr.c b/usr.bin/mkimg/mbr.c index 7bda01c72e6a..cc5bd51bd7e5 100644 --- a/usr.bin/mkimg/mbr.c +++ b/usr.bin/mkimg/mbr.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/mkimg.c b/usr.bin/mkimg/mkimg.c index 8f3a5d879bbb..c625b49dc29a 100644 --- a/usr.bin/mkimg/mkimg.c +++ b/usr.bin/mkimg/mkimg.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2013,2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/mkimg.h b/usr.bin/mkimg/mkimg.h index aa0ec2a8d944..13ca7aab36fb 100644 --- a/usr.bin/mkimg/mkimg.h +++ b/usr.bin/mkimg/mkimg.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/qcow.c b/usr.bin/mkimg/qcow.c index 2dc3e5498420..6e67cbaa0887 100644 --- a/usr.bin/mkimg/qcow.c +++ b/usr.bin/mkimg/qcow.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014 Marcel Moolenaar * All rights reserved. * diff --git a/usr.bin/mkimg/raw.c b/usr.bin/mkimg/raw.c index 2de674b908ac..b68c5f06b3c4 100644 --- a/usr.bin/mkimg/raw.c +++ b/usr.bin/mkimg/raw.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/scheme.c b/usr.bin/mkimg/scheme.c index 85ed94013e8d..80ff456a709f 100644 --- a/usr.bin/mkimg/scheme.c +++ b/usr.bin/mkimg/scheme.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2013,2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/scheme.h b/usr.bin/mkimg/scheme.h index 52614255595f..1c234b86d66c 100644 --- a/usr.bin/mkimg/scheme.h +++ b/usr.bin/mkimg/scheme.h @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2013,2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mkimg/uuid.c b/usr.bin/mkimg/uuid.c index 885a6c36b522..da99c33109e3 100644 --- a/usr.bin/mkimg/uuid.c +++ b/usr.bin/mkimg/uuid.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2016 Marcel Moolenaar * All rights reserved. * diff --git a/usr.bin/mkimg/vhd.c b/usr.bin/mkimg/vhd.c index c0fe45ab416e..09d3cfab4dcc 100644 --- a/usr.bin/mkimg/vhd.c +++ b/usr.bin/mkimg/vhd.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014, 2015 Marcel Moolenaar * All rights reserved. * diff --git a/usr.bin/mkimg/vhdx.c b/usr.bin/mkimg/vhdx.c index e280250bd964..6ecdfe8e13e9 100644 --- a/usr.bin/mkimg/vhdx.c +++ b/usr.bin/mkimg/vhdx.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2020 Oleksandr Tymoshenko <gonzo@FreeBSD.org> * * Redistribution and use in source and binary forms, with or without diff --git a/usr.bin/mkimg/vmdk.c b/usr.bin/mkimg/vmdk.c index 132eb801387a..79ef256df223 100644 --- a/usr.bin/mkimg/vmdk.c +++ b/usr.bin/mkimg/vmdk.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2014 Juniper Networks, Inc. * All rights reserved. * diff --git a/usr.bin/mt/mt.1 b/usr.bin/mt/mt.1 index 4cafdf4437c7..361c9ae65bda 100644 --- a/usr.bin/mt/mt.1 +++ b/usr.bin/mt/mt.1 @@ -26,7 +26,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 31, 2023 +.Dd March 2, 2026 .Dt MT 1 .Os .Sh NAME @@ -524,6 +524,8 @@ Value Width Tracks Density Code Type Reference Note 0x5D 12.7 (0.5) 5376 19,107 (485,318) C LTO-M8 14 0x5E 12.7 (0.5) 6656 20,669 (524,993) C LTO-8 0x60 12.7 (0.5) 8960 23,031 (584,987) C LTO-9 +0x62 12.7 (0.5)15104 21,657 (550,088) C LTO-10 15 +0x63 12.7 (0.5)15104 22,441 (570,001) C LTO-10P 15 0x71 12.7 (0.5) 512 11,800 (299,720) C 3592A1 (encrypted) 0x72 12.7 (0.5) 896 11,800 (299,720) C 3592A2 (encrypted) 0x73 12.7 (0.5) 1152 13,452 (341,681) C 3592A3 (encrypted) @@ -572,6 +574,11 @@ NOTES LTO-7 cartridge initialized with a higher density format by an LTO-8 drive. It cannot be read by an LTO-7 drive. Uncompressed capacity is 9TB, compared to 6TB for LTO-7 and 12TB for LTO-8. +15. LTO-10 Premium cartridges hold 40TB uncompressed vs. 30TB + uncompressed for standard LTO-10 cartridges due to slightly higher + density and stronger, thinner, longer tape. LTO-10 tape drives + are not backward compatible with previous generation LTO tape + cartridges. .Ed .Bd -literal -offset 2n NOTE ON QIC STREAMERS diff --git a/usr.bin/netstat/mroute.c b/usr.bin/netstat/mroute.c index 1577a6ae73ac..75c3c8477ea4 100644 --- a/usr.bin/netstat/mroute.c +++ b/usr.bin/netstat/mroute.c @@ -37,7 +37,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> /* * Print multicast routing structures and statistics. * @@ -157,7 +156,7 @@ print_bw_meter(struct bw_meter *bw_meter, int *banner_printed) } xo_emit(" {:remaining-time/%s}", s3); - xo_open_instance("bandwidth-meter"); + xo_close_instance("bandwidth-meter"); xo_emit("\n"); } @@ -186,9 +185,9 @@ print_mfc(struct mfc *m, int maxvif, int *banner_printed) } memcpy(&sin.sin_addr, &m->mfc_origin, sizeof(sin.sin_addr)); - xo_emit(" {:origin-address/%-15.15s}", routename(sa, numeric_addr)); + xo_emit(" {t:origin-address/%-*.15s}", 15, routename(sa, numeric_addr)); memcpy(&sin.sin_addr, &m->mfc_mcastgrp, sizeof(sin.sin_addr)); - xo_emit(" {:group-address/%-15.15s}", + xo_emit(" {t:group-address/%-15.15s}", routename(sa, numeric_addr)); xo_emit(" {:sent-packets/%9lu}", m->mfc_pkt_cnt); xo_emit(" {:parent/%3d} ", m->mfc_parent); @@ -303,12 +302,12 @@ mroutepr(void) xo_open_instance("vif"); memcpy(&sin.sin_addr, &v->v_lcl_addr, sizeof(sin.sin_addr)); - xo_emit(" {:vif/%2u} {:threshold/%6u} {:route/%-15.15s}", + xo_emit(" {:vif/%2u} {:threshold/%6u} {t:route/%-15.15s}", /* opposite math of add_vif() */ vifi, v->v_threshold, routename(sa, numeric_addr)); memcpy(&sin.sin_addr, &v->v_rmt_addr, sizeof(sin.sin_addr)); - xo_emit(" {:source/%-15.15s}", (v->v_flags & VIFF_TUNNEL) ? + xo_emit(" {t:source/%-15.15s}", (v->v_flags & VIFF_TUNNEL) ? routename(sa, numeric_addr) : ""); xo_emit(" {:received-packets/%9lu} {:sent-packets/%9lu}\n", diff --git a/usr.bin/netstat/mroute6.c b/usr.bin/netstat/mroute6.c index 0bb44b8292e7..5898791dcbe6 100644 --- a/usr.bin/netstat/mroute6.c +++ b/usr.bin/netstat/mroute6.c @@ -65,7 +65,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #ifdef INET6 #include <sys/param.h> #include <sys/queue.h> @@ -151,7 +150,7 @@ mroute6pr(void) xo_close_instance("multicast-interface"); } if (banner_printed) - xo_open_list("multicast-interface"); + xo_close_list("multicast-interface"); else xo_emit("\n{T:IPv6 Multicast Interface Table is empty}\n"); @@ -172,19 +171,19 @@ mroute6pr(void) xo_open_list("multicast-forwarding-cache"); xo_emit("\n" "{T:IPv6 Multicast Forwarding Cache}\n"); - xo_emit(" {T:%-*.*s} {T:%-*.*s} {T:%s}", + xo_emit(" {T:/%-*.*s} {T:/%-*.*s} {T:/%s}\n", WID_ORG, WID_ORG, "Origin", WID_GRP, WID_GRP, "Group", - " Packets Waits In-Mif Out-Mifs\n"); + " Packets Waits In-Mif Out-Mifs"); banner_printed = 1; } xo_open_instance("multicast-forwarding-cache"); - xo_emit(" {:origin/%-*.*s}", WID_ORG, WID_ORG, + xo_emit(" {t:origin/%-*.*s}", WID_ORG, WID_ORG, routename(sin6tosa(&mfc.mf6c_origin), numeric_addr)); - xo_emit(" {:group/%-*.*s}", WID_GRP, WID_GRP, + xo_emit(" {t:group/%-*.*s}", WID_GRP, WID_GRP, routename(sin6tosa(&mfc.mf6c_mcastgrp), numeric_addr)); xo_emit(" {:total-packets/%9ju}", @@ -205,7 +204,7 @@ mroute6pr(void) xo_open_list("mif"); for (mifi = 0; mifi <= maxmif; mifi++) { if (IF_ISSET(mifi, &mfc.mf6c_ifset)) - xo_emit(" {l:%u}", mifi); + xo_emit(" {l:/%u}", mifi); } xo_close_list("mif"); xo_emit("\n"); diff --git a/usr.bin/netstat/route_netlink.c b/usr.bin/netstat/route_netlink.c index e7b2a1964602..2c4b7a5c6b00 100644 --- a/usr.bin/netstat/route_netlink.c +++ b/usr.bin/netstat/route_netlink.c @@ -218,8 +218,8 @@ p_path(struct snl_parsed_route *rt, bool is_mpath) else xo_emit("{t:interface-name/%*.*s}", wid.iface, wid.iface, prettyname); - if (rt->rta_expires > 0) { - xo_emit(" {:expire-time/%*u}", wid.expire, rt->rta_expires); + if (rt->rta_expire > 0) { + xo_emit(" {:expire-time/%*u}", wid.expire, rt->rta_expire); } } @@ -244,6 +244,7 @@ p_rtentry_netlink(struct snl_state *ss, const char *name, struct nlmsghdr *hdr) rt.rtax_weight = nhop->rtnh_weight; rt.rta_rtflags = nhop->rta_rtflags ? nhop->rta_rtflags : orig_rtflags; rt.rtax_mtu = nhop->rtax_mtu ? nhop->rtax_mtu : orig_mtu; + rt.rta_expire = nhop->rta_expire; xo_open_instance(name); p_path(&rt, true); diff --git a/usr.bin/newgrp/newgrp.1 b/usr.bin/newgrp/newgrp.1 index d9701feef0d7..032aeb72616d 100644 --- a/usr.bin/newgrp/newgrp.1 +++ b/usr.bin/newgrp/newgrp.1 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd February 8, 2013 +.Dd February 6, 2025 .Dt NEWGRP 1 .Os .Sh NAME @@ -67,6 +67,21 @@ exits >0. Otherwise, the exit status of .Nm is the exit status of the shell. +.Sh EXAMPLES +Create a new group, +.Ar foo , +with +.Xr pw 8 : +.Pp +.Dl pw group add foo +.Pp +Set the group password: +.Pp +.Dl pw group mod foo -h 0 +.Pp +As a non-root user, switch to the group: +.Pp +.Dl newgrp foo .Sh SEE ALSO .Xr csh 1 , .Xr groups 1 , diff --git a/usr.bin/paste/Makefile b/usr.bin/paste/Makefile index e4f9e6d817b5..33fcb91db84d 100644 --- a/usr.bin/paste/Makefile +++ b/usr.bin/paste/Makefile @@ -1,3 +1,11 @@ +.include <src.opts.mk> + PROG= paste +.if ${MK_CASPER} != "no" && !defined(RESCUE) +LIBADD+= casper +LIBADD+= cap_fileargs +CFLAGS+= -DWITH_CASPER +.endif + .include <bsd.prog.mk> diff --git a/usr.bin/paste/paste.c b/usr.bin/paste/paste.c index 8114a85a869a..cc029e20ea9c 100644 --- a/usr.bin/paste/paste.c +++ b/usr.bin/paste/paste.c @@ -33,9 +33,13 @@ */ #include <sys/types.h> +#include <sys/queue.h> +#include <sys/capsicum.h> +#include <capsicum_helpers.h> #include <err.h> #include <errno.h> +#include <fcntl.h> #include <limits.h> #include <locale.h> #include <stdio.h> @@ -44,11 +48,14 @@ #include <unistd.h> #include <wchar.h> +#include <libcasper.h> +#include <casper/cap_fileargs.h> + static wchar_t *delim; static int delimcnt; -static int parallel(char **); -static int sequential(char **); +static int parallel(char **, fileargs_t *); +static int sequential(char **, fileargs_t *); static int tr(wchar_t *); static void usage(void) __dead2; @@ -61,6 +68,8 @@ main(int argc, char *argv[]) wchar_t *warg; const char *arg; size_t len; + fileargs_t *fa; + cap_rights_t rights; setlocale(LC_CTYPE, ""); @@ -98,51 +107,58 @@ main(int argc, char *argv[]) delim = tab; } - if (seq) - rval = sequential(argv); - else - rval = parallel(argv); + fa = fileargs_init(argc, argv, O_RDONLY, 0, + cap_rights_init(&rights, CAP_READ, CAP_FSTAT, CAP_FCNTL), FA_OPEN); + if (fa == NULL) + err(1, "unable to open system.fileargs service"); + + caph_cache_catpages(); + if (caph_enter_casper() < 0) + err(1, "unable to enter capability mode"); + + rval = seq ? sequential(argv, fa) : parallel(argv, fa); + + fileargs_free(fa); exit(rval); } typedef struct _list { - struct _list *next; + STAILQ_ENTRY(_list) entries; FILE *fp; int cnt; char *name; } LIST; +static STAILQ_HEAD(head, _list) lh; + static int -parallel(char **argv) +parallel(char **argv, fileargs_t *fa) { LIST *lp; int cnt; wint_t ich; wchar_t ch; char *p; - LIST *head, *tmp; int opencnt, output; - for (cnt = 0, head = tmp = NULL; (p = *argv); ++argv, ++cnt) { + STAILQ_INIT(&lh); + + for (cnt = 0; (p = *argv); ++argv, ++cnt) { if ((lp = malloc(sizeof(LIST))) == NULL) err(1, NULL); if (p[0] == '-' && !p[1]) lp->fp = stdin; - else if (!(lp->fp = fopen(p, "r"))) + else if (!(lp->fp = fileargs_fopen(fa, p, "r"))) err(1, "%s", p); - lp->next = NULL; lp->cnt = cnt; lp->name = p; - if (!head) - head = tmp = lp; - else { - tmp->next = lp; - tmp = lp; - } + + STAILQ_INSERT_TAIL(&lh, lp, entries); } for (opencnt = cnt; opencnt;) { - for (output = 0, lp = head; lp; lp = lp->next) { + output = 0; + STAILQ_FOREACH(lp, &lh, entries) { if (!lp->fp) { if (output && lp->cnt && (ch = delim[(lp->cnt - 1) % delimcnt])) @@ -183,7 +199,7 @@ parallel(char **argv) } static int -sequential(char **argv) +sequential(char **argv, fileargs_t *fa) { FILE *fp; int cnt, failed, needdelim; @@ -194,7 +210,7 @@ sequential(char **argv) for (; (p = *argv); ++argv) { if (p[0] == '-' && !p[1]) fp = stdin; - else if (!(fp = fopen(p, "r"))) { + else if (!(fp = fileargs_fopen(fa, p, "r"))) { warn("%s", p); failed = 1; continue; @@ -243,7 +259,8 @@ tr(wchar_t *arg) default: *arg = ch; break; - } else + } + else *arg = ch; if (!cnt) diff --git a/usr.bin/procstat/procstat_kqueue.c b/usr.bin/procstat/procstat_kqueue.c index ce9d2cb42fe2..b4d396e12d3a 100644 --- a/usr.bin/procstat/procstat_kqueue.c +++ b/usr.bin/procstat/procstat_kqueue.c @@ -135,8 +135,10 @@ procstat_kqueue_flags(const struct pk_elem *names, unsigned flags, bool commas) } } - if (strlen(res) == 0) - return (strdup("-")); + if (strlen(res) == 0) { + free(res); + res = strdup("-"); + } return (res); } diff --git a/usr.bin/resizewin/resizewin.c b/usr.bin/resizewin/resizewin.c index c6fefd79624c..89b91c219de8 100644 --- a/usr.bin/resizewin/resizewin.c +++ b/usr.bin/resizewin/resizewin.c @@ -1,4 +1,6 @@ /* + * SPDX-License-Identifier: BSD-2-Clause + * * resizewin * * Query terminal for size and inform the kernel diff --git a/usr.bin/rpcinfo/rpcinfo.c b/usr.bin/rpcinfo/rpcinfo.c index 5f2dd4433292..5156dd2db4e0 100644 --- a/usr.bin/rpcinfo/rpcinfo.c +++ b/usr.bin/rpcinfo/rpcinfo.c @@ -125,7 +125,8 @@ static void pmapdump(int, char **); static void get_inet_address(struct sockaddr_in *, char *); #endif -static bool_t reply_proc(void *, struct netbuf *, struct netconfig *); +static bool_t reply_proc(char *, const struct netbuf *, + const struct netconfig *); static void brdcst(int, char **); static void addrping(char *, char *, int, char **); static void progping(char *, int, char **); @@ -584,7 +585,8 @@ get_inet_address(struct sockaddr_in *addr, char *host) /*ARGSUSED*/ static bool_t -reply_proc(void *res, struct netbuf *who, struct netconfig *nconf) +reply_proc(char *res __unused, const struct netbuf *who, + const struct netconfig *nconf) /* void *res; Nothing comes back */ /* struct netbuf *who; Who sent us the reply */ /* struct netconfig *nconf; On which transport the reply came */ @@ -621,7 +623,7 @@ brdcst(int argc, char **argv) vers = getvers(argv[1]); rpc_stat = rpc_broadcast(prognum, vers, NULLPROC, (xdrproc_t) xdr_void, (char *)NULL, (xdrproc_t) xdr_void, - (char *)NULL, (resultproc_t) reply_proc, NULL); + (char *)NULL, reply_proc, NULL); if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) errx(1, "broadcast failed: %s", clnt_sperrno(rpc_stat)); exit(0); diff --git a/usr.bin/runat/runat.c b/usr.bin/runat/runat.c index 99437f3472f4..eb30ef87f2f9 100644 --- a/usr.bin/runat/runat.c +++ b/usr.bin/runat/runat.c @@ -8,17 +8,25 @@ #include <sys/wait.h> #include <err.h> #include <fcntl.h> +#include <getopt.h> #include <paths.h> #include <signal.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> +static struct option longopts[] = { + { "nofollow", no_argument, NULL, 'h' }, + { "-", no_argument, NULL, '-' }, + { NULL, 0, NULL, 0} +}; + static void usage(void) { - (void)fprintf(stderr, "usage: runat <file> " + (void)fprintf(stderr, "usage: runat [-h/--nofollow] [--] <file> " "<shell command>\n"); exit(1); } @@ -26,15 +34,28 @@ usage(void) int main(int argc, char *argv[]) { - int i, file_fd, nameddir_fd, outsiz; + int ch, file_fd, flags, i, longindex, nameddir_fd, outsiz; char *buf; long named_enabled; size_t pos, siz; + bool done_args; - if (argc <= 2) - usage(); - argv++; - argc--; + flags = O_RDONLY | O_CLOEXEC | O_PATH; + done_args = false; + while (!done_args && (ch = getopt_long(argc, argv, "h-", longopts, + &longindex)) != -1) + switch (ch) { + case 'h': + flags |= O_NOFOLLOW; + break; + case '-': + done_args = true; + break; + default: + usage(); + } + argv += optind; + argc -= optind; if (argc < 2) usage(); @@ -61,7 +82,7 @@ main(int argc, char *argv[]) } buf[pos - 1] = '\0'; - file_fd = open(argv[0], O_RDONLY | O_CLOEXEC, 0); + file_fd = open(argv[0], flags, 0); if (file_fd < 0) err(1, "Cannot open %s", argv[0]); nameddir_fd = openat(file_fd, ".", O_RDONLY | O_CLOEXEC | O_NAMEDATTR, diff --git a/usr.bin/rup/rup.c b/usr.bin/rup/rup.c index 5f605f55b413..d53d4ebcd28e 100644 --- a/usr.bin/rup/rup.c +++ b/usr.bin/rup/rup.c @@ -206,7 +206,7 @@ allhosts(void) clnt_stat = clnt_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS, (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_statstime, &host_stat, - (resultproc_t)rstat_reply); + (clnt_broadcast_resultproc_t)rstat_reply); if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) errx(1, "%s", clnt_sperrno(clnt_stat)); } diff --git a/usr.bin/rusers/rusers.c b/usr.bin/rusers/rusers.c index 413de53c304b..c23b79240fad 100644 --- a/usr.bin/rusers/rusers.c +++ b/usr.bin/rusers/rusers.c @@ -208,7 +208,7 @@ allhosts(void) clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_IDLE, RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_utmpidlearr, (char *)&up, - (resultproc_t)rusers_reply); + (clnt_broadcast_resultproc_t)rusers_reply); if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) errx(1, "%s", clnt_sperrno(clnt_stat)); } diff --git a/usr.bin/sockstat/main.c b/usr.bin/sockstat/main.c index 32b1ac1a8d20..ea4449300866 100644 --- a/usr.bin/sockstat/main.c +++ b/usr.bin/sockstat/main.c @@ -928,6 +928,7 @@ formataddr(struct sockaddr_storage *ss, char *buf, size_t bufsize) struct sockaddr_un *sun; int error, off, port = 0; char addrstr[NI_MAXHOST] = ""; + bool needs_ipv6_brackets = false; switch (ss->ss_family) { case AF_INET: @@ -938,6 +939,8 @@ formataddr(struct sockaddr_storage *ss, char *buf, size_t bufsize) case AF_INET6: if (IN6_IS_ADDR_UNSPECIFIED(&sstosin6(ss)->sin6_addr)) addrstr[0] = '*'; + else + needs_ipv6_brackets = true; port = ntohs(sstosin6(ss)->sin6_port); break; case AF_UNIX: @@ -946,7 +949,7 @@ formataddr(struct sockaddr_storage *ss, char *buf, size_t bufsize) if (is_xo_style_encoding) { xo_emit("{:path/%.*s}", sun->sun_len - off, sun->sun_path); - return 0; + return (0); } return snprintf(buf, bufsize, "%.*s", sun->sun_len - off, sun->sun_path); @@ -962,6 +965,11 @@ formataddr(struct sockaddr_storage *ss, char *buf, size_t bufsize) xo_emit("{:port/%d}", port); return (0); } + if (needs_ipv6_brackets) { + if (port == 0) + return (snprintf(buf, bufsize, "[%s]:*", addrstr)); + return (snprintf(buf, bufsize, "[%s]:%d", addrstr, port)); + } if (port == 0) return (snprintf(buf, bufsize, "%s:*", addrstr)); return (snprintf(buf, bufsize, "%s:%d", addrstr, port)); diff --git a/usr.bin/tar/tests/functional_test.sh b/usr.bin/tar/tests/functional_test.sh index 39a73abd0a79..11f3cb6dd122 100755 --- a/usr.bin/tar/tests/functional_test.sh +++ b/usr.bin/tar/tests/functional_test.sh @@ -25,9 +25,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -export BSDTAR=$(which tar) SRCDIR=$(atf_get_srcdir) TESTER="${SRCDIR}/bsdtar_test" +export BSDTAR=$(which tar) check() { @@ -41,7 +41,7 @@ atf_init_test_cases() # Redirect stderr to stdout for the usage message because if you don't # kyua list/kyua test will break: # https://github.com/jmmv/kyua/issues/149 - testcases=$(${TESTER} -h 2>&1 | awk 'p != 0 && $1 ~ /^[0-9]+:/ { print $NF } /Available tests:/ { p=1 }') + testcases=$(${TESTER} -l 2>&1 | awk '/^ [0-9]+: / { print $2 }') for testcase in ${testcases}; do atf_test_case ${testcase} eval "${testcase}_body() { check ${testcase}; }" diff --git a/usr.bin/touch/tests/touch_test.sh b/usr.bin/touch/tests/touch_test.sh index da39abef622e..811d74983020 100644 --- a/usr.bin/touch/tests/touch_test.sh +++ b/usr.bin/touch/tests/touch_test.sh @@ -12,6 +12,12 @@ atf_check_mtime() atf_check -o inline:"$((mtime))\n" stat -f%m "$filename" } +atf_check_atime() +{ + local atime=$1 filename=$2 + atf_check -o inline:"$((atime))\n" stat -f%a "$filename" +} + atf_test_case touch_none touch_none_head() { @@ -144,6 +150,61 @@ touch_nocreate_body() atf_check -s exit:1 test -f bar } +atf_test_case touch_symlink_h_flag +touch_symlink_h_flag_head() +{ + atf_set descr "Update time of symlink but not file pointed to" +} +touch_symlink_h_flag_body() +{ + atf_check touch -t 200406151337 pointed + atf_check ln -s pointed symlink + atf_check touch -t 197209071337 -h symlink + atf_check_mtime 1087306620 pointed + atf_check_mtime 84721020 symlink +} + +atf_test_case touch_symlink_no_h_flag +touch_symlink_no_h_flag_head() +{ + atf_set descr "Update time of file pointed to but not symlink" +} +touch_symlink_no_h_flag_body() +{ + atf_check touch -t 200406151337 pointed + atf_check ln -s pointed symlink + local orig_mtime=$(stat -f %m symlink) + atf_check touch -t 197209071337 symlink + atf_check_mtime 84721020 pointed + atf_check_mtime $orig_mtime symlink +} + +atf_test_case touch_just_atime +touch_just_atime_head() +{ + atf_set descr "Update just access time of file (-a)" +} +touch_just_atime_body() +{ + atf_check touch -t 200406151337 file + atf_check touch -at 197209071337 file + atf_check_mtime 1087306620 file + atf_check_atime 84721020 file +} + +atf_test_case touch_just_mtime +touch_just_mtime_head() +{ + atf_set descr "Update just modify time of file (-m)" +} +touch_just_mtime_body() +{ + atf_check touch -t 200406151337 file + atf_check touch -mt 197209071337 file + atf_check_mtime 84721020 file + atf_check_atime 1087306620 file +} + atf_init_test_cases() { atf_add_test_case touch_none @@ -153,5 +214,8 @@ atf_init_test_cases() atf_add_test_case touch_relative atf_add_test_case touch_copy atf_add_test_case touch_nocreate - # TODO: add test cases for -a, -h, -m + atf_add_test_case touch_symlink_h_flag + atf_add_test_case touch_symlink_no_h_flag + atf_add_test_case touch_just_atime + atf_add_test_case touch_just_mtime } diff --git a/usr.bin/touch/touch.c b/usr.bin/touch/touch.c index 70257e320a60..2be2e369596c 100644 --- a/usr.bin/touch/touch.c +++ b/usr.bin/touch/touch.c @@ -163,19 +163,14 @@ main(int argc, char *argv[]) /* Create the file. */ fd = open(*argv, O_WRONLY | O_CREAT, DEFFILEMODE); - if (fd == -1) { + if (fd < 0 || fstat(fd, &sb) < 0) { rval = 1; warn("%s", *argv); + if (fd >= 0) + (void)close(fd); continue; } - if (fstat(fd, &sb) < 0) { - warn("%s", *argv); - rval = 1; - } - if (close(fd) < 0) { - warn("%s", *argv); - rval = 1; - } + (void)close(fd); /* If using the current time, we're done. */ if (!timeset) diff --git a/usr.bin/tr/tr.c b/usr.bin/tr/tr.c index d31a51a73542..75b7cd8be7c0 100644 --- a/usr.bin/tr/tr.c +++ b/usr.bin/tr/tr.c @@ -242,6 +242,40 @@ main(int argc, char **argv) break; } while (s2.state == CCLASS_LOWER && s2.cnt > 1); goto again; + } else if (s1.state == CCLASS && + s2.state == CCLASS_UPPER && + s1.cnt == 1 && s2.cnt == 1) { + do { + ch = towupper(s1.lastch); + cmap_add(map, s1.lastch, ch); + if (sflag && iswupper(ch)) + cset_add(squeeze, ch); + if (!next(&s1)) + goto endloop; + } while (s1.state == CCLASS && s1.cnt > 1); + /* skip upper set */ + do { + if (!next(&s2)) + break; + } while (s2.state == CCLASS_UPPER && s2.cnt > 1); + goto again; + } else if (s1.state == CCLASS && + s2.state == CCLASS_LOWER && + s1.cnt == 1 && s2.cnt == 1) { + do { + ch = towlower(s1.lastch); + cmap_add(map, s1.lastch, ch); + if (sflag && iswlower(ch)) + cset_add(squeeze, ch); + if (!next(&s1)) + goto endloop; + } while (s1.state == CCLASS && s1.cnt > 1); + /* skip lower set */ + do { + if (!next(&s2)) + break; + } while (s2.state == CCLASS_LOWER && s2.cnt > 1); + goto again; } else { cmap_add(map, s1.lastch, s2.lastch); if (sflag) diff --git a/usr.bin/unzip/tests/functional_test.sh b/usr.bin/unzip/tests/functional_test.sh index e668453d8882..c6b25cfc2e7e 100755 --- a/usr.bin/unzip/tests/functional_test.sh +++ b/usr.bin/unzip/tests/functional_test.sh @@ -46,7 +46,7 @@ atf_init_test_cases() # Redirect stderr to stdout for the usage message because if you don't # kyua list/kyua test will break: # https://github.com/jmmv/kyua/issues/149 - testcases=$(${TESTER} -h 2>&1 | awk 'p != 0 && $1 ~ /^[0-9]+:/ { print $NF } /Available tests:/ { p=1 }') + testcases=$(${TESTER} -l 2>&1 | awk '/^ [0-9]+: / { print $2 }') for testcase in ${testcases}; do atf_test_case ${testcase} eval "${testcase}_body() { check ${testcase}; }" diff --git a/usr.bin/vtfontcvt/vtfontcvt.c b/usr.bin/vtfontcvt/vtfontcvt.c index 773072813d8a..1e388ef36276 100644 --- a/usr.bin/vtfontcvt/vtfontcvt.c +++ b/usr.bin/vtfontcvt/vtfontcvt.c @@ -1,4 +1,6 @@ /*- + * SPDX-License-Identifier: BSD-2-Clause + * * Copyright (c) 2009, 2014 The FreeBSD Foundation * * This software was developed by Ed Schouten under sponsorship from the diff --git a/usr.bin/xinstall/tests/install_test.sh b/usr.bin/xinstall/tests/install_test.sh index 0f1f93ab4c63..3cea648aa805 100755 --- a/usr.bin/xinstall/tests/install_test.sh +++ b/usr.bin/xinstall/tests/install_test.sh @@ -512,6 +512,42 @@ set_optional_exec_body() atf_check test ! -x testfile } +atf_test_case metalog +metalog_head() { + atf_set "descr" "Test metalog generation" +} +metalog_body() { + atf_check install -M metalog -D dst -m 0755 -d dst + echo ". type=dir mode=0755" >expect + atf_check install -M metalog -D dst -m 0705 -d dst/dir + echo "./dir type=dir mode=0705" >>expect + atf_check -o save:file echo "Hello, world!" + atf_check install -M metalog -D dst -m 0604 file dst/dir + echo "./dir/file type=file mode=0604 size=14" >>expect + atf_check install -M metalog -D dst -lrs dir/file dst/"li nk" + echo "./li\040nk type=link mode=0755 link=dir/file" >>expect + atf_check mtree -f expect -p dst + atf_check -o file:expect cat metalog +} + +atf_test_case digest +digest_head() { + atf_set "descr" "Compute digest while copying" +} +digest_body() { + atf_check mkdir src dst + atf_check -e ignore dd if=/dev/random of=src/file bs=1m count=1 + for alg in md5 rmd160 sha1 sha256 sha512 ; do + rm -f dst/file digest metalog + atf_check -o save:digest $alg -q src/file + atf_check install -M metalog -D dst -h $alg -m 0644 src/file dst + echo -n "./file type=file mode=0644 size=1048576 $alg=" >expect + cat digest >>expect + atf_check cmp src/file dst/file + atf_check -o file:expect cat metalog + done +} + atf_init_test_cases() { atf_add_test_case copy_to_empty atf_add_test_case copy_to_nonexistent @@ -557,4 +593,6 @@ atf_init_test_cases() { atf_add_test_case set_owner_group_mode atf_add_test_case set_owner_group_mode_unpriv atf_add_test_case set_optional_exec + atf_add_test_case metalog + atf_add_test_case digest } diff --git a/usr.bin/xinstall/xinstall.c b/usr.bin/xinstall/xinstall.c index 28b546bc80c2..1aed8c1b24e4 100644 --- a/usr.bin/xinstall/xinstall.c +++ b/usr.bin/xinstall/xinstall.c @@ -140,7 +140,7 @@ static char *destdir, *digest, *fflags, *metafile, *tags; static int compare(int, const char *, size_t, int, const char *, size_t, char **); -static char *copy(int, const char *, int, const char *, off_t); +static char *copy(int, const char *, int, const char *); static int create_tempfile(const char *, char *, size_t); static char *quiet_mktemp(char *template); static char *digest_file(const char *); @@ -877,7 +877,7 @@ install(const char *from_name, const char *to_name, u_long fset, u_int flags) } if (!stripped) { digestresult = copy(from_fd, from_name, to_fd, - tempfile, from_sb.st_size); + tempfile); } } } @@ -1175,8 +1175,7 @@ create_tempfile(const char *path, char *temp, size_t tsize) * copy from one file to another */ static char * -copy(int from_fd, const char *from_name, int to_fd, const char *to_name, - off_t size) +copy(int from_fd, const char *from_name, int to_fd, const char *to_name) { static char *buf = NULL; static size_t bufsize; @@ -1198,8 +1197,8 @@ copy(int from_fd, const char *from_name, int to_fd, const char *to_name, if (digesttype == DIGEST_NONE) { do { ret = copy_file_range(from_fd, NULL, to_fd, NULL, - (size_t)size, 0); - } while (ret > 0); + SSIZE_MAX, 0); + } while (ret > 0 || (ret < 0 && errno == EINTR)); if (ret == 0) goto done; if (errno != EINVAL) { @@ -1227,28 +1226,29 @@ copy(int from_fd, const char *from_name, int to_fd, const char *to_name, if (buf == NULL) err(1, "Not enough memory"); } - while ((nr = read(from_fd, buf, bufsize)) > 0) { - if ((nw = write(to_fd, buf, nr)) != nr) { + for (;;) { + if ((nr = read(from_fd, buf, bufsize)) < 0) { + if (errno == EINTR) + continue; serrno = errno; (void)unlink(to_name); - if (nw >= 0) { - errx(EX_OSERR, - "short write to %s: %jd bytes written, " - "%jd bytes asked to write", - to_name, (uintmax_t)nw, - (uintmax_t)size); - } else { + errno = serrno; + err(EX_OSERR, "%s", from_name); + } + if (nr <= 0) + break; + digest_update(&ctx, buf, nr); + while (nr > 0) { + if ((nw = write(to_fd, buf, nr)) < 0) { + if (errno == EINTR) + continue; + serrno = errno; + (void)unlink(to_name); errno = serrno; err(EX_OSERR, "%s", to_name); } + nr -= nw; } - digest_update(&ctx, buf, nr); - } - if (nr != 0) { - serrno = errno; - (void)unlink(to_name); - errno = serrno; - err(EX_OSERR, "%s", from_name); } #ifndef BOOTSTRAP_XINSTALL done: diff --git a/usr.bin/yes/Makefile b/usr.bin/yes/Makefile index b1d4075b5917..545c95d00624 100644 --- a/usr.bin/yes/Makefile +++ b/usr.bin/yes/Makefile @@ -1,3 +1,7 @@ +.include <src.opts.mk> + PROG= yes +HAS_TESTS= +SUBDIR.${MK_TESTS}= tests .include <bsd.prog.mk> diff --git a/usr.bin/yes/tests/Makefile b/usr.bin/yes/tests/Makefile new file mode 100644 index 000000000000..874a1bc21751 --- /dev/null +++ b/usr.bin/yes/tests/Makefile @@ -0,0 +1,4 @@ +PACKAGE= tests +ATF_TESTS_SH= yes_test + +.include <bsd.test.mk> diff --git a/usr.bin/yes/tests/yes_test.sh b/usr.bin/yes/tests/yes_test.sh new file mode 100644 index 000000000000..f4c04e186536 --- /dev/null +++ b/usr.bin/yes/tests/yes_test.sh @@ -0,0 +1,85 @@ +# +# Copyright (c) 2026 Klara, Inc. +# +# SPDX-License-Identifier: BSD-2-Clause +# + +atf_test_case none +none_head() +{ + atf_set "descr" "No arguments" +} +none_body() +{ + atf_check \ + -o inline:"y\ny\ny\ny\ny\n" \ + -x "yes | head -5" +} + +atf_test_case one +one_head() +{ + atf_set "descr" "One argument" +} +one_body() +{ + local y="Hello, world!" + atf_check \ + -o inline:"${y}\n${y}\n${y}\n${y}\n${y}\n" \ + -x "yes '${y}' | head -5" +} + +atf_test_case multi +multi_head() +{ + atf_set "descr" "Multiple arguments" +} +multi_body() +{ + set -- The Magic Words are Squeamish Ossifrage + local y="$*" + atf_check \ + -o inline:"${y}\n${y}\n${y}\n${y}\n${y}\n" \ + -x "yes $* | head -5" +} + +atf_test_case argv +argv_head() +{ + atf_set "descr" "Verify that argv is unmolested" +} +argv_body() +{ + yes y >/dev/null & + local pid=$! + atf_check -o inline:"yes y\n" ps -o args= $pid + kill $pid + wait +} + +atf_test_case stdout +stdout_head() +{ + atf_set descr "Error writing to stdout" +} +stdout_body() +{ + ( + trap "" PIPE + # Give true(1) some time to exit. + sleep 1 + yes 2>stderr + echo $? >result + ) | true + atf_check -o inline:"1\n" cat result + atf_check -o match:"stdout" cat stderr +} + +atf_init_test_cases() +{ + atf_add_test_case none + atf_add_test_case one + atf_add_test_case multi + atf_add_test_case argv + atf_add_test_case stdout +} diff --git a/usr.bin/yes/yes.1 b/usr.bin/yes/yes.1 index 8ed8beab0d28..689031345dc3 100644 --- a/usr.bin/yes/yes.1 +++ b/usr.bin/yes/yes.1 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 4, 2014 +.Dd March 2, 2026 .Dt YES 1 .Os .Sh NAME @@ -33,7 +33,7 @@ .Nd be repetitively affirmative .Sh SYNOPSIS .Nm -.Op Ar expletive +.Op Ar expletive ... .Sh DESCRIPTION The .Nm @@ -42,6 +42,8 @@ utility outputs or, by default, .Dq y , forever. +If multiple arguments are given, they are concatenated into a single +space-separated string. .Sh SEE ALSO .Xr jot 1 , .Xr seq 1 diff --git a/usr.bin/yes/yes.c b/usr.bin/yes/yes.c index d9e896b6ea27..86022c82f453 100644 --- a/usr.bin/yes/yes.c +++ b/usr.bin/yes/yes.c @@ -31,44 +31,76 @@ #include <capsicum_helpers.h> #include <err.h> +#include <limits.h> #include <stdio.h> #include <string.h> #include <unistd.h> +/* + * Default expletive + */ +#define EXP "y\n" +#define EXPLEN strlen(EXP) + +/* + * Optimum and maximum buffer size. The optimum is just a little less + * than the default value of kern.ipc.pipe_mindirect; writing more than + * that is significantly slower, but we want to get as close as possible + * to minimize the number of system calls. The maximum is enough for a + * maximal command line plus a newline and terminating NUL. + */ +#define OPTBUF 8190 +#define MAXBUF (ARG_MAX + 2) + int main(int argc, char **argv) { - char buf[8192]; - char y[2] = { 'y', '\n' }; - char * exp = y; - size_t buflen = 0; - size_t explen = sizeof(y); - size_t more; - ssize_t ret; + static char buf[MAXBUF] = EXP; + char *end = buf + sizeof(buf), *exp, *pos = buf + EXPLEN; + size_t buflen, explen = EXPLEN; + ssize_t wlen = 0; if (caph_limit_stdio() < 0 || caph_enter() < 0) err(1, "capsicum"); - if (argc > 1) { - exp = argv[1]; - explen = strlen(exp) + 1; - exp[explen - 1] = '\n'; - } + argc -= 1; + argv += 1; - if (explen <= sizeof(buf)) { - while (buflen < sizeof(buf) - explen) { - memcpy(buf + buflen, exp, explen); - buflen += explen; + /* Assemble the expletive */ + if (argc > 0) { + /* Copy positional arguments into expletive buffer */ + for (pos = buf, end = buf + sizeof(buf); + argc > 0 && pos < end; argc--, argv++) { + /* Separate with spaces */ + if (pos > buf) + *pos++ = ' '; + exp = *argv; + while (*exp != '\0' && pos < end) + *pos++ = *exp++; } - exp = buf; - explen = buflen; + /* This should not be possible, but check anyway */ + if (pos > end - 2) + pos = end - 2; + *pos++ = '\n'; + explen = pos - buf; } - more = explen; - while ((ret = write(STDOUT_FILENO, exp + (explen - more), more)) > 0) - if ((more -= ret) == 0) - more = explen; + /* + * Double until we're past OPTBUF, then reduce buflen to exactly + * OPTBUF. It doesn't matter if that's not a multiple of explen; + * the modulo operation in the write loop will take care of that. + */ + for (buflen = explen; buflen < OPTBUF; pos += buflen, buflen += buflen) + memcpy(pos, buf, buflen); + if (explen < OPTBUF && buflen > OPTBUF) + buflen = OPTBUF; + /* Dump it to stdout */ + end = (pos = buf) + buflen; + do { + pos = buf + (pos - buf + wlen) % explen; + wlen = write(STDOUT_FILENO, pos, end - pos); + } while (wlen > 0); err(1, "stdout"); /*NOTREACHED*/ } |
