logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git/
commit: 00afd8cbb84b80cbddb6ea7a225e01fbd5c2b8ab
parent d0ea89a5b18bf63f4a3dbf1516d1605137399559
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Wed, 25 Jun 2025 02:54:10 +0200

Move libs for libutils.a into libutils

And keep header-only and ones used by a single-command into lib/
to avoid needlessly invalidating libutils.a

Note:  Technically libutils/humanize is only used by cmd/df but it
will also have to be used by cmd/du, cmd/ls, … when they land.

Diffstat:

M.gitignore4+++-
MMakefile135++++++++++++++++++++++++++++++++++++++++---------------------------------------
Mcheck-libs.sh2+-
Mcmd/base64.c2+-
Mcmd/basename.c2+-
Mcmd/cat.c4++--
Mcmd/chmod.c4++--
Mcmd/chown.c6+++---
Mcmd/cmp.c2+-
Mcmd/cut.c2+-
Mcmd/date.1.in2+-
Mcmd/date.c4++--
Mcmd/df.c4++--
Mcmd/env.c2+-
Mcmd/expr.y4++--
Mcmd/getconf.c2+-
Mcmd/head.c6+++---
Mcmd/id.c2+-
Mcmd/install.c10+++++-----
Mcmd/join.c5+++--
Mcmd/ln.c2+-
Mcmd/mkdir.c6+++---
Mcmd/mkfifo.c4++--
Mcmd/mknod.c4++--
Mcmd/mktemp.c2+-
Mcmd/mv.c6+++---
Mcmd/nice.c2+-
Mcmd/nproc.c2+-
Mcmd/paste.c4++--
Mcmd/pathchk.c2+-
Mcmd/pwd.c2+-
Mcmd/realpath.c4++--
Mcmd/renice.c2+-
Mcmd/rm.c4++--
Mcmd/rmdir.c2+-
Mcmd/seq.c2+-
Mcmd/sha1sum.c2+-
Mcmd/sha256sum.c2+-
Mcmd/sha512sum.c2+-
Mcmd/shuf.c2+-
Mcmd/sleep.c2+-
Mcmd/split.c6+++---
Mcmd/strings.c2+-
Mcmd/sync.c2+-
Mcmd/tee.c2+-
Mcmd/time.c2+-
Mcmd/timeout.c4++--
Mcmd/touch.1.in2+-
Mcmd/touch.c4++--
Mcmd/tr.c4++--
Mcmd/truncate.c4++--
Mcmd/uname.c2+-
Mcmd/uniq.c2+-
Mcmd/wc.c2+-
Mcmd/which.c4++--
Mcmd/whoami.c2+-
Mcommon.mk12++++++------
Mconfigure4++--
Dlib/humanize.c41-----------------------------------------
Dlib/mode.c312-------------------------------------------------------------------------------
Dlib/symbolize_mode.c65-----------------------------------------------------------------
Mlib/tr_str.c2+-
Rlib/consent.c -> libutils/consent.c0
Rlib/consent.h -> libutils/consent.h0
Rlib/datetime_parse.c -> libutils/datetime_parse.c0
Rlib/datetime_parse.h -> libutils/datetime_parse.h0
Rlib/datetime_parse.mdoc -> libutils/datetime_parse.mdoc0
Rlib/err.c -> libutils/err.c0
Rlib/err.h -> libutils/err.h0
Rlib/fs.c -> libutils/fs.c0
Rlib/fs.h -> libutils/fs.h0
Rlib/getopt_nolong.c -> libutils/getopt_nolong.c0
Rlib/getopt_nolong.h -> libutils/getopt_nolong.h0
Alibutils/humanize.c41+++++++++++++++++++++++++++++++++++++++++
Rlib/humanize.h -> libutils/humanize.h0
Rlib/lib_mkdir.c -> libutils/lib_mkdir.c0
Rlib/lib_mkdir.h -> libutils/lib_mkdir.h0
Alibutils/mode.c312+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rlib/mode.h -> libutils/mode.h0
Rlib/offline_realpath.c -> libutils/offline_realpath.c0
Rlib/strchrnul.c -> libutils/strchrnul.c0
Rlib/strchrnul.h -> libutils/strchrnul.h0
Rlib/strtodur.c -> libutils/strtodur.c0
Rlib/strtodur.h -> libutils/strtodur.h0
Alibutils/symbolize_mode.c65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rlib/truncation.c -> libutils/truncation.c0
Rlib/truncation.h -> libutils/truncation.h0
Rlib/user_group_parse.c -> libutils/user_group_parse.c0
Rlib/user_group_parse.h -> libutils/user_group_parse.h0
Dtest-lib/t_humanize.c78------------------------------------------------------------------------------
Dtest-lib/t_mode.c325-------------------------------------------------------------------------------
Dtest-lib/t_strtodur.c83-------------------------------------------------------------------------------
Dtest-lib/t_symbolize_mode.c47-----------------------------------------------
Dtest-lib/t_truncation.c80-------------------------------------------------------------------------------
Atest-libutils/t_humanize.c78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest-libutils/t_mode.c325+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest-libutils/t_strtodur.c83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest-libutils/t_symbolize_mode.c47+++++++++++++++++++++++++++++++++++++++++++++++
Atest-libutils/t_truncation.c80+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
99 files changed, 1196 insertions(+), 1192 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -17,9 +17,11 @@ /build/ /test-lib/* -!/test-lib/Kuafile !/test-lib/*.c !/test-lib/*.h +/test-libutils/* +!/test-libutils/*.c +!/test-libutils/*.h /test-cmd/pathchk-getlimits diff --git a/Makefile b/Makefile @@ -32,7 +32,7 @@ selfcheck-cmds: $(EXE) $(TEST_CMDS) LDSTATIC="$(LDSTATIC)" ./check-cmds.sh .PHONY: selfcheck-libs -TEST_LIBS = test-lib/t_mode test-lib/t_strtodur test-lib/t_symbolize_mode test-lib/t_truncation test-lib/t_sha1 test-lib/t_sha256 test-lib/t_sha512 test-lib/t_humanize +TEST_LIBS = test-libutils/t_mode test-libutils/t_strtodur test-libutils/t_symbolize_mode test-libutils/t_truncation test-lib/t_sha1 test-lib/t_sha256 test-lib/t_sha512 test-libutils/t_humanize selfcheck-libs: $(TEST_LIBS) LDSTATIC="$(LDSTATIC)" ./check-libs.sh $(TEST_LIBS) @@ -61,7 +61,7 @@ lint: $(MAN1SO) .PHONY: clean clean: - $(RM) -fr $(EXE) ${EXE:=.c.gcov} ${EXE:=.gcda} ${EXE:=.gcno} cmd/expr.tab.c $(MAN1SO) $(TEST_CMDS) $(TEST_LIBS) ${LIBUTILS_O} build + $(RM) -fr $(EXE) ${EXE:=.c.gcov} ${EXE:=.gcda} ${EXE:=.gcno} cmd/expr.tab.c $(MAN1SO) $(TEST_CMDS) $(TEST_LIBS) lib/*.o libutils/*.o libutils/libutils.a build install: all mkdir -p ${DESTDIR}${BINDIR}/ @@ -73,7 +73,7 @@ install: all coverage: $(GCOV) -b $(EXE) -C_SOURCES = cmd/*.c lib/*.h lib/*.c test-lib/*.c configure.d/*.c +C_SOURCES = cmd/*.c lib/*.h lib/*.c libutils/*.c libutils/*.h test-libutils/*.c configure.d/*.c format: $(C_SOURCES) clang-format -style=file -assume-filename=.clang-format -i $(C_SOURCES) @@ -83,14 +83,14 @@ build/sys_signame.c: lib/sys_signame.sh cmd/cat cmd/printf cmd/mkdir lib/sys_signame.sh >|build/sys_signame.c LIBUTILS_O = ${LIBUTILS_C:.c=.o} -lib/utils.a: ${LIBUTILS_O} ${LIBUTILS_H} config.mk config.h Makefile - ${AR} rc ${ARFLAGS} lib/utils.a ${LIBUTILS_O} +libutils/libutils.a: ${LIBUTILS_O} ${LIBUTILS_H} config.mk config.h Makefile + ${AR} rc ${ARFLAGS} libutils/libutils.a ${LIBUTILS_O} -build/cmd/date.1: cmd/date.1.in lib/datetime_parse.mdoc cmd/mkdir +build/cmd/date.1: cmd/date.1.in libutils/datetime_parse.mdoc cmd/mkdir mkdir -p build/cmd $(M4) cmd/date.1.in > build/cmd/date.1 -build/cmd/touch.1: cmd/touch.1.in lib/datetime_parse.mdoc cmd/mkdir +build/cmd/touch.1: cmd/touch.1.in libutils/datetime_parse.mdoc cmd/mkdir mkdir -p build/cmd $(M4) cmd/touch.1.in > build/cmd/touch.1 @@ -98,81 +98,82 @@ cmd/expr.tab.c: cmd/expr.y Makefile $(YACC) -b cmd/expr cmd/expr.y # Needs -D_POSIX_C_SOURCE=200809L due to OpenBSD yacc -cmd/expr: cmd/expr.tab.c lib/utils.a +cmd/expr: cmd/expr.tab.c libutils/libutils.a $(RM) -f cmd/expr.tab.c.gcov cmd/expr.tab.o.gcda cmd/expr.tab.o.gcno - $(CC) -std=c99 $(CFLAGS) -D_POSIX_C_SOURCE=200809L -o cmd/expr cmd/expr.tab.c lib/utils.a $(LDFLAGS) $(LDSTATIC) + $(CC) -std=c99 $(CFLAGS) -D_POSIX_C_SOURCE=200809L -o cmd/expr cmd/expr.tab.c libutils/libutils.a $(LDFLAGS) $(LDSTATIC) # Needs -lm -cmd/seq: cmd/seq.c Makefile lib/utils.a +cmd/seq: cmd/seq.c Makefile libutils/libutils.a $(RM) -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno} - $(CC) -std=c99 $(CFLAGS) -o $@ cmd/seq.c lib/utils.a -lm $(LDFLAGS) $(LDSTATIC) + $(CC) -std=c99 $(CFLAGS) -o $@ cmd/seq.c libutils/libutils.a -lm $(LDFLAGS) $(LDSTATIC) cmd/getconf_vars.h: cmd/getconf_vars.m4 $(M4) cmd/getconf_vars.m4 > cmd/getconf_vars.h # cmd/getconf_vars.h needs to invalidate cmd/getconf but not be in command -cmd/getconf: cmd/getconf.c cmd/getconf_vars.h lib/utils.a +cmd/getconf: cmd/getconf.c cmd/getconf_vars.h libutils/libutils.a $(RM) -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno} - $(CC) -std=c99 $(CFLAGS) -o cmd/getconf cmd/getconf.c lib/utils.a $(LDFLAGS) $(LDSTATIC) - -cmd/base64: cmd/base64.c lib/utils.a -cmd/basename: cmd/basename.c lib/utils.a -cmd/chmod: cmd/chmod.c lib/utils.a -cmd/chown: cmd/chown.c lib/utils.a -cmd/cmp: cmd/cmp.c lib/utils.a -cmd/cut: cmd/cut.c lib/utils.a -cmd/date: cmd/date.c lib/utils.a -cmd/df: cmd/df.c lib/utils.a -cmd/env: cmd/env.c lib/utils.a -cmd/head: cmd/head.c lib/utils.a -cmd/id: cmd/id.c lib/utils.a -cmd/install: cmd/install.c lib/utils.a -cmd/join: cmd/join.c lib/utils.a -cmd/ln: cmd/ln.c lib/utils.a -cmd/mkdir: cmd/mkdir.c lib/utils.a -cmd/mkfifo: cmd/mkfifo.c lib/utils.a -cmd/mknod: cmd/mknod.c lib/utils.a -cmd/mktemp: cmd/mktemp.c lib/utils.a -cmd/mv: cmd/mv.c lib/utils.a -cmd/nice: cmd/nice.c lib/utils.a -cmd/nproc: cmd/nproc.c lib/utils.a -cmd/od: cmd/od.c lib/utils.a -cmd/paste: cmd/paste.c lib/utils.a -cmd/pathchk: cmd/pathchk.c lib/utils.a -cmd/pwd: cmd/pwd.c lib/utils.a -cmd/realpath: cmd/realpath.c lib/utils.a -cmd/renice: cmd/renice.c lib/utils.a -cmd/rmdir: cmd/rmdir.c lib/utils.a -cmd/sha1sum: cmd/sha1sum.c lib/utils.a -cmd/sha256sum: cmd/sha256sum.c lib/utils.a -cmd/sha512sum: cmd/sha512sum.c lib/utils.a -cmd/shuf: cmd/shuf.c lib/utils.a -cmd/sleep: cmd/sleep.c lib/utils.a -cmd/split: cmd/split.c lib/utils.a -cmd/strings: cmd/strings.c lib/utils.a -cmd/sync: cmd/sync.c lib/utils.a -cmd/tee: cmd/tee.c lib/utils.a -cmd/time: cmd/time.c lib/utils.a -cmd/timeout: cmd/timeout.c build/sys_signame.c lib/utils.a -cmd/touch: cmd/touch.c lib/utils.a -cmd/truncate: cmd/truncate.c lib/utils.a -cmd/uname: cmd/uname.c lib/utils.a -cmd/uniq: cmd/uniq.c lib/utils.a -cmd/wc: cmd/wc.c lib/utils.a -cmd/which: cmd/which.c lib/utils.a -cmd/whoami: cmd/whoami.c lib/utils.a - -lib/mode.o: lib/mode.c lib/mode.h + $(CC) -std=c99 $(CFLAGS) -o cmd/getconf cmd/getconf.c libutils/libutils.a $(LDFLAGS) $(LDSTATIC) + +cmd/base64: cmd/base64.c libutils/libutils.a +cmd/basename: cmd/basename.c libutils/libutils.a +cmd/chmod: cmd/chmod.c libutils/libutils.a +cmd/chown: cmd/chown.c libutils/libutils.a +cmd/cmp: cmd/cmp.c libutils/libutils.a +cmd/cut: cmd/cut.c libutils/libutils.a +cmd/date: cmd/date.c libutils/libutils.a +cmd/df: cmd/df.c libutils/libutils.a +cmd/env: cmd/env.c libutils/libutils.a +cmd/head: cmd/head.c libutils/libutils.a +cmd/id: cmd/id.c libutils/libutils.a +cmd/install: cmd/install.c libutils/libutils.a +cmd/join: cmd/join.c libutils/libutils.a +cmd/ln: cmd/ln.c libutils/libutils.a +cmd/mkdir: cmd/mkdir.c libutils/libutils.a +cmd/mkfifo: cmd/mkfifo.c libutils/libutils.a +cmd/mknod: cmd/mknod.c libutils/libutils.a +cmd/mktemp: cmd/mktemp.c libutils/libutils.a +cmd/mv: cmd/mv.c libutils/libutils.a +cmd/nice: cmd/nice.c libutils/libutils.a +cmd/nproc: cmd/nproc.c libutils/libutils.a +cmd/od: cmd/od.c libutils/libutils.a +cmd/paste: cmd/paste.c libutils/libutils.a +cmd/pathchk: cmd/pathchk.c libutils/libutils.a +cmd/pwd: cmd/pwd.c libutils/libutils.a +cmd/realpath: cmd/realpath.c libutils/libutils.a +cmd/renice: cmd/renice.c libutils/libutils.a +cmd/rmdir: cmd/rmdir.c libutils/libutils.a +cmd/sha1sum: cmd/sha1sum.c libutils/libutils.a lib/bytes2hex.o lib/sha1.o +cmd/sha256sum: cmd/sha256sum.c libutils/libutils.a lib/bytes2hex.o lib/sha256.o +cmd/sha512sum: cmd/sha512sum.c libutils/libutils.a lib/bytes2hex.o lib/sha512.o +cmd/shuf: cmd/shuf.c libutils/libutils.a +cmd/sleep: cmd/sleep.c libutils/libutils.a +cmd/split: cmd/split.c libutils/libutils.a +cmd/strings: cmd/strings.c libutils/libutils.a +cmd/sync: cmd/sync.c libutils/libutils.a +cmd/tee: cmd/tee.c libutils/libutils.a +cmd/time: cmd/time.c libutils/libutils.a +cmd/timeout: cmd/timeout.c build/sys_signame.c libutils/libutils.a +cmd/touch: cmd/touch.c libutils/libutils.a +cmd/truncate: cmd/truncate.c libutils/libutils.a +cmd/uname: cmd/uname.c libutils/libutils.a +cmd/uniq: cmd/uniq.c libutils/libutils.a +cmd/wc: cmd/wc.c libutils/libutils.a +cmd/which: cmd/which.c libutils/libutils.a +cmd/whoami: cmd/whoami.c libutils/libutils.a + +libutils/mode.o: libutils/mode.c libutils/mode.h + lib/sha1.o: lib/sha1.c lib/sha1.h lib/sha256.o: lib/sha256.c lib/sha256.h lib/sha512.o: lib/sha512.c lib/sha512.h lib/bytes2hex.o: lib/bytes2hex.c lib/strconv.h -test-lib/t_humanize: test-lib/t_humanize.c lib/humanize.o -test-lib/t_mode: test-lib/t_mode.c lib/mode.o test-lib/t_sha1: test-lib/t_sha1.c lib/sha1.c lib/bytes2hex.o test-lib/t_sha256: test-lib/t_sha256.c lib/sha256.c lib/bytes2hex.o test-lib/t_sha512: test-lib/t_sha512.c lib/sha512.c lib/bytes2hex.o -test-lib/t_strtodur: test-lib/t_strtodur.c lib/strtodur.o -test-lib/t_symbolize_mode: test-lib/t_symbolize_mode.c lib/symbolize_mode.o -test-lib/t_truncation: test-lib/t_truncation.c lib/truncation.o +test-libutils/t_humanize: test-libutils/t_humanize.c libutils/humanize.o +test-libutils/t_mode: test-libutils/t_mode.c libutils/mode.o +test-libutils/t_strtodur: test-libutils/t_strtodur.c libutils/strtodur.o +test-libutils/t_symbolize_mode: test-libutils/t_symbolize_mode.c libutils/symbolize_mode.o +test-libutils/t_truncation: test-libutils/t_truncation.c libutils/truncation.o diff --git a/check-libs.sh b/check-libs.sh @@ -20,7 +20,7 @@ then wrap_test "$runner" done else - for src in test-lib/*.c + for src in test-lib/*.c test-libutils/*.c do runner="${src%.c}" wrap_test "$runner" diff --git a/cmd/base64.c b/cmd/base64.c @@ -4,7 +4,7 @@ // SPDX-License-Identifier: MPL-2.0 AND BSD-2-Clause #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <assert.h> /* assert */ #include <ctype.h> /* isspace */ diff --git a/cmd/basename.c b/cmd/basename.c @@ -4,7 +4,7 @@ #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <libgen.h> // basename #include <stdbool.h> diff --git a/cmd/cat.c b/cmd/cat.c @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/fs.h" -#include "../lib/getopt_nolong.h" +#include "../libutils/fs.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> #include <fcntl.h> // open, O_RDONLY diff --git a/cmd/chmod.c b/cmd/chmod.c @@ -10,8 +10,8 @@ #endif #include "../config.h" // HAS_* -#include "../lib/getopt_nolong.h" -#include "../lib/mode.h" +#include "../libutils/getopt_nolong.h" +#include "../libutils/mode.h" #include <dirent.h> // fdopendir, readdir, closedir #include <errno.h> diff --git a/cmd/chown.c b/cmd/chown.c @@ -10,9 +10,9 @@ #endif #include "../config.h" // HAS_* -#include "../lib/fs.h" -#include "../lib/getopt_nolong.h" -#include "../lib/user_group_parse.h" +#include "../libutils/fs.h" +#include "../libutils/getopt_nolong.h" +#include "../libutils/user_group_parse.h" #include <dirent.h> // fdopendir, readdir, closedir #include <errno.h> diff --git a/cmd/cmp.c b/cmd/cmp.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <assert.h> #include <errno.h> diff --git a/cmd/cut.c b/cmd/cut.c @@ -4,7 +4,7 @@ #define _POSIX_C_SOURCE 202405L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include "../lib/reallocarray.h" #include <assert.h> diff --git a/cmd/date.1.in b/cmd/date.1.in @@ -36,7 +36,7 @@ will print the datetime in a user-defined way. Use .Ar datetime instead of current datetime. -include(lib/datetime_parse.mdoc) +include(libutils/datetime_parse.mdoc) .It Fl f Ar now_format Use .Ar now_format diff --git a/cmd/date.c b/cmd/date.c @@ -6,8 +6,8 @@ #define _POSIX_C_SOURCE 200809L #define _XOPEN_SOURCE 700 // strptime is in XSI -#include "../lib/datetime_parse.h" /* datetime_parse */ -#include "../lib/getopt_nolong.h" +#include "../libutils/datetime_parse.h" /* datetime_parse */ +#include "../libutils/getopt_nolong.h" #include <assert.h> #include <errno.h> diff --git a/cmd/df.c b/cmd/df.c @@ -5,8 +5,8 @@ #define _POSIX_C_SOURCE 200809L #define _DEFAULT_SOURCE // mntent in glibc 2.19+ -#include "../lib/getopt_nolong.h" -#include "../lib/humanize.h" +#include "../libutils/getopt_nolong.h" +#include "../libutils/humanize.h" #include <ctype.h> // iscntrl, isspace #include <errno.h> // errno diff --git a/cmd/env.c b/cmd/env.c @@ -6,7 +6,7 @@ #define _XOPEN_SOURCE 800 // wordexp #include "../config.h" // HAS_* -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <assert.h> // assert #include <errno.h> // errno diff --git a/cmd/expr.y b/cmd/expr.y @@ -18,8 +18,8 @@ #include <assert.h> #include <sys/types.h> #include <ctype.h> -#include "../lib/err.h" -#include "../lib/getopt_nolong.h" +#include "../libutils/err.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> #include <inttypes.h> #include <limits.h> diff --git a/cmd/getconf.c b/cmd/getconf.c @@ -4,7 +4,7 @@ #define _POSIX_C_SOURCE 202405L #define _XOPEN_SOURCE 800 -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <assert.h> #include <errno.h> diff --git a/cmd/head.c b/cmd/head.c @@ -4,9 +4,9 @@ #define _POSIX_C_SOURCE 200809L -#include "../lib/fs.h" // auto_fd_copy -#include "../lib/getopt_nolong.h" -#include "../lib/truncation.h" // apply_size_suffix +#include "../libutils/fs.h" // auto_fd_copy +#include "../libutils/getopt_nolong.h" +#include "../libutils/truncation.h" // apply_size_suffix #include <ctype.h> // isdigit #include <errno.h> diff --git a/cmd/id.c b/cmd/id.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _DEFAULT_SOURCE // getgrouplist (4.4BSD+) -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <grp.h> // getgrgid, getgroups, getgrouplist(glibc) #include <pwd.h> // getpwuid diff --git a/cmd/install.c b/cmd/install.c @@ -7,11 +7,11 @@ #define _DEFAULT_SOURCE // FreeBSD #include "../config.h" // HAS_* -#include "../lib/fs.h" -#include "../lib/getopt_nolong.h" -#include "../lib/lib_mkdir.h" -#include "../lib/mode.h" -#include "../lib/user_group_parse.h" +#include "../libutils/fs.h" +#include "../libutils/getopt_nolong.h" +#include "../libutils/lib_mkdir.h" +#include "../libutils/mode.h" +#include "../libutils/user_group_parse.h" #include <assert.h> #include <errno.h> diff --git a/cmd/join.c b/cmd/join.c @@ -33,11 +33,12 @@ * SUCH DAMAGE. */ +#define _POSIX_C_SOURCE 202405L #define _BSD_SOURCE // fgetln, strsep #include "../lib/reallocarray.h" -#include "../lib/err.h" -#include "../lib/getopt_nolong.h" +#include "../libutils/err.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> #include <limits.h> diff --git a/cmd/ln.c b/cmd/ln.c @@ -5,7 +5,7 @@ #define _POSIX_C_SOURCE 200809L #include "../lib/bitmasks.h" -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" // NetBSD (9.3 and 10) hides symlink behind _XOPEN_SOURCE / _NETBSD_SOURCE #ifdef __NetBSD__ diff --git a/cmd/mkdir.c b/cmd/mkdir.c @@ -4,9 +4,9 @@ #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" -#include "../lib/lib_mkdir.h" -#include "../lib/mode.h" +#include "../libutils/getopt_nolong.h" +#include "../libutils/lib_mkdir.h" +#include "../libutils/mode.h" #include <errno.h> #include <stdbool.h> diff --git a/cmd/mkfifo.c b/cmd/mkfifo.c @@ -4,8 +4,8 @@ #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" -#include "../lib/mode.h" +#include "../libutils/getopt_nolong.h" +#include "../libutils/mode.h" #include <errno.h> #include <stdio.h> // fprintf diff --git a/cmd/mknod.c b/cmd/mknod.c @@ -5,8 +5,8 @@ #define _POSIX_C_SOURCE 200809L #define _XOPEN_SOURCE 700 // mknod is in XSI -#include "../lib/getopt_nolong.h" -#include "../lib/mode.h" +#include "../libutils/getopt_nolong.h" +#include "../libutils/mode.h" #include <errno.h> #include <stdio.h> // fprintf diff --git a/cmd/mktemp.c b/cmd/mktemp.c @@ -5,7 +5,7 @@ // getentropy got in POSIX.1-2024 but defining _POSIX_C_SOURCE causes too much side-effects #define _DEFAULT_SOURCE // getentropy #include "../config.h" // HAS_* -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> #include <limits.h> // PATH_MAX diff --git a/cmd/mv.c b/cmd/mv.c @@ -11,9 +11,9 @@ #define _NETBSD_SOURCE #endif -#include "../lib/consent.h" -#include "../lib/fs.h" -#include "../lib/getopt_nolong.h" +#include "../libutils/consent.h" +#include "../libutils/fs.h" +#include "../libutils/getopt_nolong.h" #include <dirent.h> // fdopendir #include <errno.h> diff --git a/cmd/nice.c b/cmd/nice.c @@ -4,7 +4,7 @@ #define _POSIX_C_SOURCE 200809L #define _XOPEN_SOURCE 700 // nice() is in XSI -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <assert.h> #include <errno.h> diff --git a/cmd/nproc.c b/cmd/nproc.c @@ -9,7 +9,7 @@ // Sadly {Free,Net}BSD hides _SC_NPROCESSORS_{CONF,ONLN} if _POSIX_C_SOURCE is defined *sigh* // #define _POSIX_C_SOURCE 202405L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> #include <stdio.h> // printf diff --git a/cmd/paste.c b/cmd/paste.c @@ -34,8 +34,8 @@ #define _POSIX_C_SOURCE 200809L -#include "../lib/err.h" -#include "../lib/getopt_nolong.h" +#include "../libutils/err.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> #include <limits.h> diff --git a/cmd/pathchk.c b/cmd/pathchk.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> #include <limits.h> // PATH_MAX diff --git a/cmd/pwd.c b/cmd/pwd.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <limits.h> // PATH_MAX #include <stdbool.h> diff --git a/cmd/realpath.c b/cmd/realpath.c @@ -5,8 +5,8 @@ #define _POSIX_C_SOURCE 200809L #define _XOPEN_SOURCE 700 // realpath is in XSI -#include "../lib/fs.h" -#include "../lib/getopt_nolong.h" +#include "../libutils/fs.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> #include <limits.h> // PATH_MAX diff --git a/cmd/renice.c b/cmd/renice.c @@ -5,7 +5,7 @@ #define _POSIX_C_SOURCE 200809L #define _XOPEN_SOURCE 700 // getpriority, setpriority -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> #include <stdio.h> // fprintf diff --git a/cmd/rm.c b/cmd/rm.c @@ -9,8 +9,8 @@ #define _NETBSD_SOURCE #endif -#include "../lib/consent.h" -#include "../lib/getopt_nolong.h" +#include "../libutils/consent.h" +#include "../libutils/getopt_nolong.h" #include <ctype.h> // isprint #include <dirent.h> // fdopendir, readdir, closedir diff --git a/cmd/rmdir.c b/cmd/rmdir.c @@ -4,7 +4,7 @@ #define _POSIX_C_SOURCE 200809L #include "../config.h" // HAS_* -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> #include <stdbool.h> diff --git a/cmd/seq.c b/cmd/seq.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <ctype.h> // isdigit #include <errno.h> // errno diff --git a/cmd/sha1sum.c b/cmd/sha1sum.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include "../lib/sha1.h" // sha1_* #include "../lib/strconv.h" // bytes2hex diff --git a/cmd/sha256sum.c b/cmd/sha256sum.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include "../lib/sha256.h" // sha256_* #include "../lib/strconv.h" // bytes2hex diff --git a/cmd/sha512sum.c b/cmd/sha512sum.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include "../lib/sha512.h" // sha512_* #include "../lib/strconv.h" // bytes2hex diff --git a/cmd/shuf.c b/cmd/shuf.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> #include <stdbool.h> diff --git a/cmd/sleep.c b/cmd/sleep.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/strtodur.h" +#include "../libutils/strtodur.h" #include <errno.h> // errno #include <stdio.h> // fprintf, perror diff --git a/cmd/split.c b/cmd/split.c @@ -4,9 +4,9 @@ #define _POSIX_C_SOURCE 200809L -#include "../lib/fs.h" // auto_file_copy -#include "../lib/getopt_nolong.h" -#include "../lib/truncation.h" // apply_size_suffix +#include "../libutils/fs.h" // auto_file_copy +#include "../libutils/getopt_nolong.h" +#include "../libutils/truncation.h" // apply_size_suffix #include <errno.h> #include <fcntl.h> // open diff --git a/cmd/strings.c b/cmd/strings.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <ctype.h> /* isprint() */ #include <errno.h> /* errno */ diff --git a/cmd/sync.c b/cmd/sync.c @@ -7,7 +7,7 @@ #define _XOPEN_SOURCE 700 // sync #include "../config.h" // HAS_* -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> #include <fcntl.h> // open, O_* diff --git a/cmd/tee.c b/cmd/tee.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <assert.h> /* assert() */ #include <errno.h> /* errno */ diff --git a/cmd/time.c b/cmd/time.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> // errno #include <stdio.h> // perror, fprintf diff --git a/cmd/timeout.c b/cmd/timeout.c @@ -4,8 +4,8 @@ #define _POSIX_C_SOURCE 200809L #define _DEFAULT_SOURCE // For NSIG in sys_signame.h, thanks glibc -#include "../lib/getopt_nolong.h" -#include "../lib/strtodur.h" +#include "../libutils/getopt_nolong.h" +#include "../libutils/strtodur.h" #include "../lib/sys_signame.h" #include <ctype.h> diff --git a/cmd/touch.1.in b/cmd/touch.1.in @@ -36,7 +36,7 @@ in 2011, in 2012. .\" Let's not publicly document too much that illumos still supports it .It Fl d Ar isotime -include(lib/datetime_parse.mdoc) +include(libutils/datetime_parse.mdoc) .It Fl h Do not follow symlinks. .It Fl m diff --git a/cmd/touch.c b/cmd/touch.c @@ -7,8 +7,8 @@ #define _POSIX_C_SOURCE 200809L // O_NOFOLLOW, st_atim/st_mtim #include "../lib/bitmasks.h" /* FIELD_* */ -#include "../lib/datetime_parse.h" /* datetime_parse */ -#include "../lib/getopt_nolong.h" +#include "../libutils/datetime_parse.h" /* datetime_parse */ +#include "../libutils/getopt_nolong.h" #include <assert.h> #include <errno.h> /* errno */ diff --git a/cmd/tr.c b/cmd/tr.c @@ -32,8 +32,8 @@ #define _DEFAULT_SOURCE -#include "../lib/err.h" -#include "../lib/getopt_nolong.h" +#include "../libutils/err.h" +#include "../libutils/getopt_nolong.h" #include "../lib/tr_str.h" #include <stdio.h> diff --git a/cmd/truncate.c b/cmd/truncate.c @@ -5,8 +5,8 @@ #define _POSIX_C_SOURCE 200809L #include "../lib/bitmasks.h" // FIELD_CLR -#include "../lib/getopt_nolong.h" -#include "../lib/truncation.h" // parse_size +#include "../libutils/getopt_nolong.h" +#include "../libutils/truncation.h" // parse_size #include <errno.h> #include <fcntl.h> // open diff --git a/cmd/uname.c b/cmd/uname.c @@ -4,7 +4,7 @@ #define _POSIX_C_SOURCE 200809L #include "../lib/bitmasks.h" -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <errno.h> #include <stdio.h> // printf diff --git a/cmd/uniq.c b/cmd/uniq.c @@ -3,7 +3,7 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <ctype.h> // isblank #include <errno.h> diff --git a/cmd/wc.c b/cmd/wc.c @@ -5,7 +5,7 @@ #define _POSIX_C_SOURCE 200809L #include "../config.h" // HAS_* #include "../lib/bitmasks.h" -#include "../lib/getopt_nolong.h" +#include "../libutils/getopt_nolong.h" #include <ctype.h> // isspace #include <errno.h> diff --git a/cmd/which.c b/cmd/which.c @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include "../lib/getopt_nolong.h" -#include "../lib/strchrnul.h" +#include "../libutils/getopt_nolong.h" +#include "../libutils/strchrnul.h" #include <errno.h> #include <limits.h> // PATH_MAX diff --git a/cmd/whoami.c b/cmd/whoami.c @@ -4,7 +4,7 @@ #define _POSIX_C_SOURCE 200809L -#include "../lib/err.h" +#include "../libutils/err.h" #include <errno.h> #include <pwd.h> // getpwuid diff --git a/common.mk b/common.mk @@ -2,11 +2,11 @@ # SPDX-License-Identifier: MPL-2.0 # bootstrap.mk targets should be kept simple -lib/fs.o: lib/fs.c lib/fs.h config.h -lib/err.o: lib/err.c lib/err.h -lib/consent.o: lib/consent.c lib/consent.h +libutils/fs.o: libutils/fs.c libutils/fs.h config.h +libutils/err.o: libutils/err.c libutils/err.h +libutils/consent.o: libutils/consent.c libutils/consent.h lib/tr_str.o: lib/tr_str.c lib/tr_str.h -cmd/cat: cmd/cat.c lib/fs.o lib/getopt_nolong.o +cmd/cat: cmd/cat.c libutils/fs.o libutils/getopt_nolong.o cmd/printf: cmd/printf.c -cmd/rm: cmd/rm.c lib/consent.o lib/getopt_nolong.o -cmd/tr: cmd/tr.c lib/tr_str.o lib/err.o lib/getopt_nolong.o +cmd/rm: cmd/rm.c libutils/consent.o libutils/getopt_nolong.o +cmd/tr: cmd/tr.c lib/tr_str.o libutils/err.o libutils/getopt_nolong.o diff --git a/configure b/configure @@ -73,11 +73,11 @@ gen_targets() { echo printf 'LIBUTILS_C = ' - echo lib/*.c + echo libutils/*.c echo printf 'LIBUTILS_H = ' - echo lib/*.h + echo libutils/*.h echo } diff --git a/lib/humanize.c b/lib/humanize.c @@ -1,41 +0,0 @@ -// utils-std: Collection of commonly available Unix tools -// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> -// SPDX-License-Identifier: MPL-2.0 - -#define _POSIX_C_SOURCE 200809L - -#include "../lib/humanize.h" - -#include <math.h> // fabs -#include <stdio.h> // snprintf - -struct si_scale -dtosi(double num, bool iec) -{ -#define PFX 11 - const char *si_prefixes[PFX] = {"", "k", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q"}; - const char *iec_prefixes[PFX] = { - "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "RiB", "QiB"}; - - int div = iec ? 1024 : 1000; - const char **prefixes = iec ? iec_prefixes : si_prefixes; - bool neg = num < 0; - - struct si_scale ret = { - .number = fabs(num), - .prefix = "", - .exponent = 0, - }; - - while(ret.number > div && ret.exponent < (PFX - 1)) - { - ret.number /= div; - ret.exponent += 1; - } - - ret.prefix = prefixes[ret.exponent]; - - if(neg) ret.number = -ret.number; - - return ret; -} diff --git a/lib/mode.c b/lib/mode.c @@ -1,312 +0,0 @@ -// Collection of Unix tools, comparable to coreutils -// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> -// SPDX-License-Identifier: MPL-2.0 - -#define _POSIX_C_SOURCE 200809L -#define _XOPEN_SOURCE 700 // S_ISVTX -#include "mode.h" - -#include "bitmasks.h" - -#include <errno.h> -#include <stdbool.h> -#include <stdint.h> // int8_t -#include <stdio.h> // strtol -#include <stdlib.h> // abort -#include <string.h> // strlen -#include <sys/stat.h> // umask - -enum perm_who_e -{ - WHO_RST = 0, // 0b000 - WHO_USER = 1, // 0b001 - WHO_GROUP = 2, // 0b010 - WHO_OTHER = 4, // 0b100 - WHO_ALL = 7, // 0b111 -}; - -enum operation_e -{ - OP_RST, - OP_ADD, - OP_DEL, - OP_SET, -}; - -struct modes -{ - int8_t set; - int8_t user; - int8_t group; - int8_t other; -}; - -struct modes_meta -{ - enum perm_who_e dest; - enum operation_e op; - struct modes new_modes; -}; - -static void -apply(struct modes_meta *meta, int8_t mode) -{ - // get old, then reset to old. Yay to POSIX nonsense - mode_t mask = umask(0); - umask(mask); - - // negate to get a normal bitmask - mask ^= 0777; - - switch(meta->op) - { - case OP_ADD: - if(meta->dest == WHO_RST) - { - FIELD_SET(meta->new_modes.user, mode & ((mask >> 6) & 07)); - FIELD_SET(meta->new_modes.group, mode & ((mask >> 3) & 07)); - FIELD_SET(meta->new_modes.other, mode & ((mask >> 0) & 07)); - } - if(FIELD_MATCH(meta->dest, WHO_USER)) FIELD_SET(meta->new_modes.user, mode); - if(FIELD_MATCH(meta->dest, WHO_GROUP)) FIELD_SET(meta->new_modes.group, mode); - if(FIELD_MATCH(meta->dest, WHO_OTHER)) FIELD_SET(meta->new_modes.other, mode); - break; - case OP_DEL: - if(meta->dest == WHO_RST) - { - FIELD_CLR(meta->new_modes.user, mode & ((mask >> 6) & 07)); - FIELD_CLR(meta->new_modes.group, mode & ((mask >> 3) & 07)); - FIELD_CLR(meta->new_modes.other, mode & ((mask >> 0) & 07)); - } - if(FIELD_MATCH(meta->dest, WHO_USER)) FIELD_CLR(meta->new_modes.user, mode); - if(FIELD_MATCH(meta->dest, WHO_GROUP)) FIELD_CLR(meta->new_modes.group, mode); - if(FIELD_MATCH(meta->dest, WHO_OTHER)) FIELD_CLR(meta->new_modes.other, mode); - break; - case OP_SET: - if(meta->dest == WHO_RST) - { - meta->new_modes.user = mode & ((mask >> 6) & 07); - meta->new_modes.group = mode & ((mask >> 3) & 07); - meta->new_modes.other = mode & ((mask >> 0) & 07); - } - if(FIELD_MATCH(meta->dest, WHO_USER)) meta->new_modes.user = mode; - if(FIELD_MATCH(meta->dest, WHO_GROUP)) meta->new_modes.group = mode; - if(FIELD_MATCH(meta->dest, WHO_OTHER)) meta->new_modes.other = mode; - - // So a=rw is a=r+w rather than a=r,a=w - meta->op = OP_ADD; - break; - default: - abort(); - } -} - -mode_t -new_mode(const char *mode, mode_t old, const char **errstr) -{ - // NULL? Then nothing to change :) - if(mode == NULL) return old; - - size_t mode_len = strlen(mode); - - if(mode_len == 0) return old; - - bool symbolic = false; - for(size_t i = 0; i < mode_len; i++) - { - if(mode[i] < '0' || mode[i] > '7') - { - if(mode[i] == '8' || mode[i] == '9') - { - *errstr = "contains digit outside of [0-7]"; - return old; - } - symbolic = true; - break; - } - } - - if(!symbolic) - { - char *endptr = NULL; - - long new = strtol(mode, &endptr, 8); - - if(errno != 0) - { - *errstr = strerror(errno); - errno = 0; - return old; - } - - if(new < 0) - { - *errstr = "can't be negative"; - return old; - } - - if(new > 07777) - { - *errstr = "can't be higher than 0o7777"; - return old; - } - - return (old & 0770000) | new; - } - - // ((^|,)[ugoa]*([+-=]|[ugo]|[rwxXst]+)+)+ - struct modes_meta meta = {.dest = WHO_RST, - .op = OP_RST, - .new_modes = { - .set = (old & 07000) >> 9, - .user = (old & 00700) >> 6, - .group = (old & 00070) >> 3, - .other = (old & 00007) >> 0, - }}; - - for(size_t i = 0; i < mode_len; i++) - { - char m = mode[i]; - - switch(m) - { - // separator - case ',': - meta.dest = WHO_RST; - meta.op = OP_RST; - break; - - // who - case 'u': - if(meta.op == OP_RST) - FIELD_SET(meta.dest, WHO_USER); - else - apply(&meta, meta.new_modes.user); - break; - case 'g': - if(meta.op == OP_RST) - FIELD_SET(meta.dest, WHO_GROUP); - else - apply(&meta, meta.new_modes.group); - break; - case 'o': - if(meta.op == OP_RST) - FIELD_SET(meta.dest, WHO_OTHER); - else - apply(&meta, meta.new_modes.other); - break; - case 'a': - if(meta.op == OP_RST) FIELD_SET(meta.dest, WHO_ALL); - // ignore =a, POSIX doesn't allows "a" in permcopy (would be a noop anyway) - break; - - // op - // Implementation-note: When another operator was set, override it - case '+': - meta.op = OP_ADD; - break; - case '-': - meta.op = OP_DEL; - break; - case '=': - meta.op = OP_SET; - apply(&meta, 00); - break; - - // perm - case 'r': - if(meta.op == OP_RST) - { - *errstr = "perm 'r' given without operator"; - return 0; - } - apply(&meta, 04); - break; - case 'w': - if(meta.op == OP_RST) - { - *errstr = "perm 'w' given without operator"; - return 0; - } - apply(&meta, 02); - break; - case 'x': - if(meta.op == OP_RST) - { - *errstr = "perm 'x' given without operator"; - return 0; - } - apply(&meta, 01); - break; - case 'X': - if(meta.op == OP_RST) - { - *errstr = "perm 'X' given without operator"; - return 0; - } - if(S_ISDIR(old)) apply(&meta, 01); - break; - case 's': - { - if(meta.op == OP_RST) - { - *errstr = "perm 's' given without operator"; - return 0; - } - mode_t set_id = S_ISUID >> 9; - if(FIELD_MATCH(meta.dest, WHO_GROUP)) set_id = S_ISGID >> 9; - - switch(meta.op) - { - case OP_ADD: - FIELD_SET(meta.new_modes.set, set_id); - break; - case OP_DEL: - FIELD_CLR(meta.new_modes.set, set_id); - break; - case OP_SET: - meta.new_modes.set = set_id; - break; - default: - abort(); - } - break; - } - case 't': - // Implementation defined behavior outside of directories and !(WHO_ALL|WHO_RST) - switch(meta.op) - { - case OP_RST: - *errstr = "perm 't' given without operator"; - return 0; - case OP_ADD: - FIELD_SET(meta.new_modes.set, S_ISVTX >> 9); - break; - case OP_DEL: - FIELD_CLR(meta.new_modes.set, S_ISVTX >> 9); - break; - case OP_SET: - meta.new_modes.set = S_ISVTX >> 9; - break; - default: - abort(); - } - break; - - default: - // Would need to either be non-thread-safe with a shared read-write buffer - // or only allocate in this situation, meaning a memory leak. - *errstr = "syntax error, got invalid character"; - - return 0; - } - } - - // clang-format off - return (old & 0770000) - | ((meta.new_modes.set & 07) << 9) - | ((meta.new_modes.user & 07) << 6) - | ((meta.new_modes.group & 07) << 3) - | ((meta.new_modes.other & 07) << 0); - // clang-format on -} diff --git a/lib/symbolize_mode.c b/lib/symbolize_mode.c @@ -1,65 +0,0 @@ -// Collection of Unix tools, comparable to coreutils -// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> -// SPDX-License-Identifier: MPL-2.0 - -#define _POSIX_C_SOURCE 200809L -#define _XOPEN_SOURCE 700 // S_ISVTX, S_IFMT, S_IFDIR, … -#include "bitmasks.h" -#include "mode.h" - -#include <sys/stat.h> - -void -symbolize_mode(mode_t mode, char str[11]) -{ - switch(mode & S_IFMT) - { - case S_IFDIR: - str[0] = 'd'; - break; - case S_IFCHR: - str[0] = 'c'; - break; - case S_IFBLK: - str[0] = 'b'; - break; - case S_IFREG: - str[0] = '-'; - break; - case S_IFIFO: - str[0] = 'f'; - break; - case S_IFLNK: - str[0] = 'l'; - break; - case S_IFSOCK: - str[0] = 's'; - break; - default: - str[0] = '?'; - break; - } - - str[1] = FIELD_MATCH(mode, S_IRUSR) ? 'r' : '-'; - str[2] = FIELD_MATCH(mode, S_IWUSR) ? 'w' : '-'; - if(FIELD_MATCH(mode, S_ISUID)) - str[3] = FIELD_MATCH(mode, S_IXUSR) ? 's' : 'S'; - else - str[3] = FIELD_MATCH(mode, S_IXUSR) ? 'x' : '-'; - - str[4] = FIELD_MATCH(mode, S_IRGRP) ? 'r' : '-'; - str[5] = FIELD_MATCH(mode, S_IWGRP) ? 'w' : '-'; - if(FIELD_MATCH(mode, S_ISGID)) - str[6] = FIELD_MATCH(mode, S_IXGRP) ? 's' : 'S'; - else - str[6] = FIELD_MATCH(mode, S_IXGRP) ? 'x' : '-'; - - str[7] = FIELD_MATCH(mode, S_IROTH) ? 'r' : '-'; - str[8] = FIELD_MATCH(mode, S_IWOTH) ? 'w' : '-'; - if(FIELD_MATCH(mode, S_ISVTX)) - str[9] = FIELD_MATCH(mode, S_IXOTH) ? 't' : 'T'; - else - str[9] = FIELD_MATCH(mode, S_IXOTH) ? 'x' : '-'; - - str[10] = '\0'; -} diff --git a/lib/tr_str.c b/lib/tr_str.c @@ -39,7 +39,7 @@ #include "./tr_str.h" // clang-format on -#include "./err.h" +#include "../libutils/err.h" #include <assert.h> #include <ctype.h> diff --git a/lib/consent.c b/libutils/consent.c diff --git a/lib/consent.h b/libutils/consent.h diff --git a/lib/datetime_parse.c b/libutils/datetime_parse.c diff --git a/lib/datetime_parse.h b/libutils/datetime_parse.h diff --git a/lib/datetime_parse.mdoc b/libutils/datetime_parse.mdoc diff --git a/lib/err.c b/libutils/err.c diff --git a/lib/err.h b/libutils/err.h diff --git a/lib/fs.c b/libutils/fs.c diff --git a/lib/fs.h b/libutils/fs.h diff --git a/lib/getopt_nolong.c b/libutils/getopt_nolong.c diff --git a/lib/getopt_nolong.h b/libutils/getopt_nolong.h diff --git a/libutils/humanize.c b/libutils/humanize.c @@ -0,0 +1,41 @@ +// utils-std: Collection of commonly available Unix tools +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#define _POSIX_C_SOURCE 200809L + +#include "../libutils/humanize.h" + +#include <math.h> // fabs +#include <stdio.h> // snprintf + +struct si_scale +dtosi(double num, bool iec) +{ +#define PFX 11 + const char *si_prefixes[PFX] = {"", "k", "M", "G", "T", "P", "E", "Z", "Y", "R", "Q"}; + const char *iec_prefixes[PFX] = { + "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB", "RiB", "QiB"}; + + int div = iec ? 1024 : 1000; + const char **prefixes = iec ? iec_prefixes : si_prefixes; + bool neg = num < 0; + + struct si_scale ret = { + .number = fabs(num), + .prefix = "", + .exponent = 0, + }; + + while(ret.number > div && ret.exponent < (PFX - 1)) + { + ret.number /= div; + ret.exponent += 1; + } + + ret.prefix = prefixes[ret.exponent]; + + if(neg) ret.number = -ret.number; + + return ret; +} diff --git a/lib/humanize.h b/libutils/humanize.h diff --git a/lib/lib_mkdir.c b/libutils/lib_mkdir.c diff --git a/lib/lib_mkdir.h b/libutils/lib_mkdir.h diff --git a/libutils/mode.c b/libutils/mode.c @@ -0,0 +1,312 @@ +// Collection of Unix tools, comparable to coreutils +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#define _POSIX_C_SOURCE 200809L +#define _XOPEN_SOURCE 700 // S_ISVTX +#include "mode.h" + +#include "../lib/bitmasks.h" + +#include <errno.h> +#include <stdbool.h> +#include <stdint.h> // int8_t +#include <stdio.h> // strtol +#include <stdlib.h> // abort +#include <string.h> // strlen +#include <sys/stat.h> // umask + +enum perm_who_e +{ + WHO_RST = 0, // 0b000 + WHO_USER = 1, // 0b001 + WHO_GROUP = 2, // 0b010 + WHO_OTHER = 4, // 0b100 + WHO_ALL = 7, // 0b111 +}; + +enum operation_e +{ + OP_RST, + OP_ADD, + OP_DEL, + OP_SET, +}; + +struct modes +{ + int8_t set; + int8_t user; + int8_t group; + int8_t other; +}; + +struct modes_meta +{ + enum perm_who_e dest; + enum operation_e op; + struct modes new_modes; +}; + +static void +apply(struct modes_meta *meta, int8_t mode) +{ + // get old, then reset to old. Yay to POSIX nonsense + mode_t mask = umask(0); + umask(mask); + + // negate to get a normal bitmask + mask ^= 0777; + + switch(meta->op) + { + case OP_ADD: + if(meta->dest == WHO_RST) + { + FIELD_SET(meta->new_modes.user, mode & ((mask >> 6) & 07)); + FIELD_SET(meta->new_modes.group, mode & ((mask >> 3) & 07)); + FIELD_SET(meta->new_modes.other, mode & ((mask >> 0) & 07)); + } + if(FIELD_MATCH(meta->dest, WHO_USER)) FIELD_SET(meta->new_modes.user, mode); + if(FIELD_MATCH(meta->dest, WHO_GROUP)) FIELD_SET(meta->new_modes.group, mode); + if(FIELD_MATCH(meta->dest, WHO_OTHER)) FIELD_SET(meta->new_modes.other, mode); + break; + case OP_DEL: + if(meta->dest == WHO_RST) + { + FIELD_CLR(meta->new_modes.user, mode & ((mask >> 6) & 07)); + FIELD_CLR(meta->new_modes.group, mode & ((mask >> 3) & 07)); + FIELD_CLR(meta->new_modes.other, mode & ((mask >> 0) & 07)); + } + if(FIELD_MATCH(meta->dest, WHO_USER)) FIELD_CLR(meta->new_modes.user, mode); + if(FIELD_MATCH(meta->dest, WHO_GROUP)) FIELD_CLR(meta->new_modes.group, mode); + if(FIELD_MATCH(meta->dest, WHO_OTHER)) FIELD_CLR(meta->new_modes.other, mode); + break; + case OP_SET: + if(meta->dest == WHO_RST) + { + meta->new_modes.user = mode & ((mask >> 6) & 07); + meta->new_modes.group = mode & ((mask >> 3) & 07); + meta->new_modes.other = mode & ((mask >> 0) & 07); + } + if(FIELD_MATCH(meta->dest, WHO_USER)) meta->new_modes.user = mode; + if(FIELD_MATCH(meta->dest, WHO_GROUP)) meta->new_modes.group = mode; + if(FIELD_MATCH(meta->dest, WHO_OTHER)) meta->new_modes.other = mode; + + // So a=rw is a=r+w rather than a=r,a=w + meta->op = OP_ADD; + break; + default: + abort(); + } +} + +mode_t +new_mode(const char *mode, mode_t old, const char **errstr) +{ + // NULL? Then nothing to change :) + if(mode == NULL) return old; + + size_t mode_len = strlen(mode); + + if(mode_len == 0) return old; + + bool symbolic = false; + for(size_t i = 0; i < mode_len; i++) + { + if(mode[i] < '0' || mode[i] > '7') + { + if(mode[i] == '8' || mode[i] == '9') + { + *errstr = "contains digit outside of [0-7]"; + return old; + } + symbolic = true; + break; + } + } + + if(!symbolic) + { + char *endptr = NULL; + + long new = strtol(mode, &endptr, 8); + + if(errno != 0) + { + *errstr = strerror(errno); + errno = 0; + return old; + } + + if(new < 0) + { + *errstr = "can't be negative"; + return old; + } + + if(new > 07777) + { + *errstr = "can't be higher than 0o7777"; + return old; + } + + return (old & 0770000) | new; + } + + // ((^|,)[ugoa]*([+-=]|[ugo]|[rwxXst]+)+)+ + struct modes_meta meta = {.dest = WHO_RST, + .op = OP_RST, + .new_modes = { + .set = (old & 07000) >> 9, + .user = (old & 00700) >> 6, + .group = (old & 00070) >> 3, + .other = (old & 00007) >> 0, + }}; + + for(size_t i = 0; i < mode_len; i++) + { + char m = mode[i]; + + switch(m) + { + // separator + case ',': + meta.dest = WHO_RST; + meta.op = OP_RST; + break; + + // who + case 'u': + if(meta.op == OP_RST) + FIELD_SET(meta.dest, WHO_USER); + else + apply(&meta, meta.new_modes.user); + break; + case 'g': + if(meta.op == OP_RST) + FIELD_SET(meta.dest, WHO_GROUP); + else + apply(&meta, meta.new_modes.group); + break; + case 'o': + if(meta.op == OP_RST) + FIELD_SET(meta.dest, WHO_OTHER); + else + apply(&meta, meta.new_modes.other); + break; + case 'a': + if(meta.op == OP_RST) FIELD_SET(meta.dest, WHO_ALL); + // ignore =a, POSIX doesn't allows "a" in permcopy (would be a noop anyway) + break; + + // op + // Implementation-note: When another operator was set, override it + case '+': + meta.op = OP_ADD; + break; + case '-': + meta.op = OP_DEL; + break; + case '=': + meta.op = OP_SET; + apply(&meta, 00); + break; + + // perm + case 'r': + if(meta.op == OP_RST) + { + *errstr = "perm 'r' given without operator"; + return 0; + } + apply(&meta, 04); + break; + case 'w': + if(meta.op == OP_RST) + { + *errstr = "perm 'w' given without operator"; + return 0; + } + apply(&meta, 02); + break; + case 'x': + if(meta.op == OP_RST) + { + *errstr = "perm 'x' given without operator"; + return 0; + } + apply(&meta, 01); + break; + case 'X': + if(meta.op == OP_RST) + { + *errstr = "perm 'X' given without operator"; + return 0; + } + if(S_ISDIR(old)) apply(&meta, 01); + break; + case 's': + { + if(meta.op == OP_RST) + { + *errstr = "perm 's' given without operator"; + return 0; + } + mode_t set_id = S_ISUID >> 9; + if(FIELD_MATCH(meta.dest, WHO_GROUP)) set_id = S_ISGID >> 9; + + switch(meta.op) + { + case OP_ADD: + FIELD_SET(meta.new_modes.set, set_id); + break; + case OP_DEL: + FIELD_CLR(meta.new_modes.set, set_id); + break; + case OP_SET: + meta.new_modes.set = set_id; + break; + default: + abort(); + } + break; + } + case 't': + // Implementation defined behavior outside of directories and !(WHO_ALL|WHO_RST) + switch(meta.op) + { + case OP_RST: + *errstr = "perm 't' given without operator"; + return 0; + case OP_ADD: + FIELD_SET(meta.new_modes.set, S_ISVTX >> 9); + break; + case OP_DEL: + FIELD_CLR(meta.new_modes.set, S_ISVTX >> 9); + break; + case OP_SET: + meta.new_modes.set = S_ISVTX >> 9; + break; + default: + abort(); + } + break; + + default: + // Would need to either be non-thread-safe with a shared read-write buffer + // or only allocate in this situation, meaning a memory leak. + *errstr = "syntax error, got invalid character"; + + return 0; + } + } + + // clang-format off + return (old & 0770000) + | ((meta.new_modes.set & 07) << 9) + | ((meta.new_modes.user & 07) << 6) + | ((meta.new_modes.group & 07) << 3) + | ((meta.new_modes.other & 07) << 0); + // clang-format on +} diff --git a/lib/mode.h b/libutils/mode.h diff --git a/lib/offline_realpath.c b/libutils/offline_realpath.c diff --git a/lib/strchrnul.c b/libutils/strchrnul.c diff --git a/lib/strchrnul.h b/libutils/strchrnul.h diff --git a/lib/strtodur.c b/libutils/strtodur.c diff --git a/lib/strtodur.h b/libutils/strtodur.h diff --git a/libutils/symbolize_mode.c b/libutils/symbolize_mode.c @@ -0,0 +1,65 @@ +// Collection of Unix tools, comparable to coreutils +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#define _POSIX_C_SOURCE 200809L +#define _XOPEN_SOURCE 700 // S_ISVTX, S_IFMT, S_IFDIR, … +#include "../lib/bitmasks.h" +#include "mode.h" + +#include <sys/stat.h> + +void +symbolize_mode(mode_t mode, char str[11]) +{ + switch(mode & S_IFMT) + { + case S_IFDIR: + str[0] = 'd'; + break; + case S_IFCHR: + str[0] = 'c'; + break; + case S_IFBLK: + str[0] = 'b'; + break; + case S_IFREG: + str[0] = '-'; + break; + case S_IFIFO: + str[0] = 'f'; + break; + case S_IFLNK: + str[0] = 'l'; + break; + case S_IFSOCK: + str[0] = 's'; + break; + default: + str[0] = '?'; + break; + } + + str[1] = FIELD_MATCH(mode, S_IRUSR) ? 'r' : '-'; + str[2] = FIELD_MATCH(mode, S_IWUSR) ? 'w' : '-'; + if(FIELD_MATCH(mode, S_ISUID)) + str[3] = FIELD_MATCH(mode, S_IXUSR) ? 's' : 'S'; + else + str[3] = FIELD_MATCH(mode, S_IXUSR) ? 'x' : '-'; + + str[4] = FIELD_MATCH(mode, S_IRGRP) ? 'r' : '-'; + str[5] = FIELD_MATCH(mode, S_IWGRP) ? 'w' : '-'; + if(FIELD_MATCH(mode, S_ISGID)) + str[6] = FIELD_MATCH(mode, S_IXGRP) ? 's' : 'S'; + else + str[6] = FIELD_MATCH(mode, S_IXGRP) ? 'x' : '-'; + + str[7] = FIELD_MATCH(mode, S_IROTH) ? 'r' : '-'; + str[8] = FIELD_MATCH(mode, S_IWOTH) ? 'w' : '-'; + if(FIELD_MATCH(mode, S_ISVTX)) + str[9] = FIELD_MATCH(mode, S_IXOTH) ? 't' : 'T'; + else + str[9] = FIELD_MATCH(mode, S_IXOTH) ? 'x' : '-'; + + str[10] = '\0'; +} diff --git a/lib/truncation.c b/libutils/truncation.c diff --git a/lib/truncation.h b/libutils/truncation.h diff --git a/lib/user_group_parse.c b/libutils/user_group_parse.c diff --git a/lib/user_group_parse.h b/libutils/user_group_parse.h diff --git a/test-lib/t_humanize.c b/test-lib/t_humanize.c @@ -1,78 +0,0 @@ -// utils-std: Collection of commonly available Unix tools -// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> -// SPDX-License-Identifier: MPL-2.0 - -#define _POSIX_C_SOURCE 200809L -#include "../lib/humanize.h" - -#include <assert.h> -#include <stdio.h> // printf - -const char *argv0 = "t_humanize"; -int counter = 0; -int err = 0; - -static void -t_dtosi(double in, bool iec, double out, unsigned exponent) -{ - int id = ++counter; - - struct si_scale ret = dtosi(in, iec); - - if(ret.number == out && ret.exponent == exponent) - { - printf("ok %d - dtosi(%f, %d) => {.number = %g, .exponent = %d}\n", - id, - in, - iec, - ret.number, - ret.exponent); - return; - } - - err = 1; - printf("not ok %d - dtosi(%f, %d) => {.number = %g, .exponent = %d}\n", - id, - in, - iec, - ret.number, - ret.exponent); - printf("# Expected: {.number = %g, .exponent = %d}\n", out, exponent); -} - -int -main(void) -{ - int plan = 18; - printf("1..%d\n", plan); - - t_dtosi(0, false, 0, 0); - t_dtosi(0, true, 0, 0); - - t_dtosi(1000, false, 1000, 0); - t_dtosi(10000, false, 10, 1); - - t_dtosi(-1000, false, -1000, 0); - t_dtosi(-10000, false, -10, 1); - - t_dtosi(1024, true, 1024, 0); - t_dtosi(10240, true, 10240 / 1024, 1); - - t_dtosi(-1024, true, -1024, 0); - t_dtosi(-10240, true, -10240 / 1024, 1); - -#define IEC_QiB 1267650600228229401496703205376.0 /* 1024^10 */ - t_dtosi(1024 * IEC_QiB, true, 1024, 10); - t_dtosi(-1024 * IEC_QiB, true, -1024, 10); - t_dtosi(1024 * 1024 * IEC_QiB, true, 1024 * 1024, 10); - t_dtosi(-1024 * 1024 * IEC_QiB, true, -1024 * 1024, 10); - -#define SI_Q 1000000000000000000000000000000.0 /* 1000^10 */ - t_dtosi(1000 * SI_Q, false, 1000, 10); - t_dtosi(-1000 * SI_Q, false, -1000, 10); - t_dtosi(1000 * 1000 * SI_Q, false, 1000 * 1000, 10); - t_dtosi(-1000 * 1000 * SI_Q, false, -1000 * 1000, 10); - - assert(counter == plan); - return err; -} diff --git a/test-lib/t_mode.c b/test-lib/t_mode.c @@ -1,325 +0,0 @@ -// utils-std: Collection of commonly available Unix tools -// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> -// SPDX-License-Identifier: MPL-2.0 - -#define _POSIX_C_SOURCE 200809L -#include "../lib/mode.h" - -#include <assert.h> -#include <stdio.h> // printf -#include <string.h> // strcmp -#include <sys/stat.h> // umask - -int counter = 0; -int t_err = 0; - -static void -t_mode(const char *str, mode_t old, mode_t expect) -{ - int id = ++counter; - const char *errstr = NULL; - mode_t got = new_mode(str, old, &errstr); - if(got == expect && errstr == NULL) - { - printf("ok %d - new_mode(\"%s\", 0%06o) == 0%06o\n", id, str, old, expect); - return; - } - - t_err = 1; - printf("not ok %d - new_mode(\"%s\", 0%06o) == 0%06o\n", id, str, old, expect); - if(got != expect) printf("# Got: 0%06o\n", got); - if(errstr != NULL) printf("# Errstr: \"%s\"\n", errstr); -} - -static void -t_mode_errstr(const char *str, mode_t old, const char *expect_errstr) -{ - assert(expect_errstr != NULL); - - int id = ++counter; - const char *errstr = NULL; - (void)new_mode(str, old, &errstr); - - if(errstr != NULL && strcmp(errstr, expect_errstr) == 0) - { - printf("ok %d - new_mode(\"%s\", 0%06o) -> %s\n", id, str, old, expect_errstr); - } - else - { - printf("not ok %d - new_mode(\"%s\", 0%06o) -> %s\n", id, str, old, expect_errstr); - printf("# Got errstr: \"%s\"\n", errstr); - t_err = 1; - } -} - -static void -add_read(void) -{ - printf("# => add_read\n"); - umask(0044); - - t_mode("+r", 0, 00400); - t_mode("a+r", 0, 00444); - t_mode("u+r", 0, 00400); - t_mode("g+r", 0, 00040); - t_mode("o+r", 0, 00004); - t_mode("ug+r", 0, 00440); - t_mode("go+r", 0, 00044); - t_mode("uo+r", 0, 00404); - t_mode("u+r,g+r", 0, 00440); - t_mode("g+r,o+r", 0, 00044); - t_mode("u+r,o+r", 0, 00404); - - t_mode("+r", 00777, 00777); - t_mode("a+r", 00777, 00777); - t_mode("u+r", 00777, 00777); - t_mode("g+r", 00777, 00777); - t_mode("o+r", 00777, 00777); - t_mode("ug+r", 00777, 00777); - t_mode("go+r", 00777, 00777); - t_mode("uo+r", 00777, 00777); - t_mode("u+r,g+r", 00777, 00777); - t_mode("g+r,o+r", 00777, 00777); - t_mode("u+r,o+r", 00777, 00777); -} - -static void -set_read(void) -{ - printf("# => set_read\n"); - umask(0044); - - t_mode("=r", 0, 00400); - t_mode("a=r", 0, 00444); - t_mode("u=r", 0, 00400); - t_mode("g=r", 0, 00040); - t_mode("o=r", 0, 00004); - t_mode("ug=r", 0, 00440); - t_mode("go=r", 0, 00044); - t_mode("uo=r", 0, 00404); - t_mode("u=r,g=r", 0, 00440); - t_mode("g=r,o=r", 0, 00044); - t_mode("u=r,o=r", 0, 00404); - - t_mode("go=,u=xr", 0, 00500); - t_mode("go=,u=xr", 00777, 00500); - - t_mode("=r", 00777, 00400); - t_mode("a=r", 00777, 00444); - t_mode("u=r", 00777, 00477); - t_mode("g=r", 00777, 00747); - t_mode("o=r", 00777, 00774); - t_mode("ug=r", 00777, 00447); - t_mode("go=r", 00777, 00744); - t_mode("uo=r", 00777, 00474); - t_mode("u=r,g=r", 00777, 00447); - t_mode("g=r,o=r", 00777, 00744); - t_mode("u=r,o=r", 00777, 00474); -} - -static void -del_read(void) -{ - printf("# => del_read\n"); - umask(0044); - - t_mode("-r", 0, 0); - t_mode("a-r", 0, 0); - t_mode("u-r", 0, 0); - t_mode("g-r", 0, 0); - t_mode("o-r", 0, 0); - t_mode("ug-r", 0, 0); - t_mode("go-r", 0, 0); - t_mode("uo-r", 0, 0); - t_mode("u-r,g-r", 0, 0); - t_mode("g-r,o-r", 0, 0); - t_mode("u-r,o-r", 0, 0); - - t_mode("-r", 00777, 00377); - t_mode("a-r", 00777, 00333); - t_mode("u-r", 00777, 00377); - t_mode("g-r", 00777, 00737); - t_mode("o-r", 00777, 00773); - t_mode("ug-r", 00777, 00337); - t_mode("go-r", 00777, 00733); - t_mode("uo-r", 00777, 00373); - t_mode("u-r,g-r", 00777, 00337); - t_mode("g-r,o-r", 00777, 00733); - t_mode("u-r,o-r", 00777, 00373); -} - -static void -search(void) -{ - printf("# => search\n"); - t_mode("-X", 0, 0); - t_mode("a-X", 0, 0); - t_mode("u-X", 0, 0); - t_mode("g-X", 0, 0); - t_mode("o-X", 0, 0); - - t_mode("+X", 0, 0); - t_mode("a+X", 0, 0); - t_mode("u+X", 0, 0); - t_mode("g+X", 0, 0); - t_mode("o+X", 0, 0); - - t_mode("=X", 0, 0); - t_mode("a=X", 0, 0); - t_mode("u=X", 0, 0); - t_mode("g=X", 0, 0); - t_mode("o=X", 0, 0); - - // S_IFDIR = 0040000 - t_mode("-X", 0040777, 0040666); - t_mode("a-X", 0040777, 0040666); - t_mode("u-X", 0040777, 0040677); - t_mode("g-X", 0040777, 0040767); - t_mode("o-X", 0040777, 0040776); - - t_mode("+X", 0040777, 0040777); - t_mode("a+X", 0040777, 0040777); - t_mode("u+X", 0040777, 0040777); - t_mode("g+X", 0040777, 0040777); - t_mode("o+X", 0040777, 0040777); - - t_mode("=X", 0040777, 0040111); - t_mode("a=X", 0040777, 0040111); - t_mode("u=X", 0040777, 0040177); - t_mode("g=X", 0040777, 0040717); - t_mode("o=X", 0040777, 0040771); - - t_mode("-X", 0040000, 0040000); - t_mode("a-X", 0040000, 0040000); - t_mode("u-X", 0040000, 0040000); - t_mode("g-X", 0040000, 0040000); - t_mode("o-X", 0040000, 0040000); - - t_mode("+X", 0040000, 0040111); - t_mode("a+X", 0040000, 0040111); - t_mode("u+X", 0040000, 0040100); - t_mode("g+X", 0040000, 0040010); - t_mode("o+X", 0040000, 0040001); - - t_mode("=X", 0040000, 0040111); - t_mode("a=X", 0040000, 0040111); - t_mode("u=X", 0040000, 0040100); - t_mode("g=X", 0040000, 0040010); - t_mode("o=X", 0040000, 0040001); -} - -static void -syntax(void) -{ - printf("# => syntax\n"); - - t_mode("=", 0, 0); - t_mode("=", 0040777, 0040000); - - t_mode("-", 0, 0); - t_mode("-", 0040777, 0040777); - - t_mode("+", 0, 0); - t_mode("+", 0040777, 0040777); - - t_mode_errstr("/", 0, "syntax error, got invalid character"); - - t_mode_errstr("foo", 0, "syntax error, got invalid character"); - - t_mode_errstr("77777", 0, "can't be higher than 0o7777"); - - t_mode_errstr("-0", 0, "syntax error, got invalid character"); -} - -static void -posix_examples(void) -{ - // Examples as given by POSIX in chmod(1p) - printf("# => posix_examples\n"); - - // clears all file mode bits. - t_mode("a+=", 0040777, 0040000); - t_mode("a+=", 0040000, 0040000); - - // clears group and other write bits - t_mode("go+-w", 0040777, 0040755); - t_mode("go+-w", 0040000, 0040000); - - // sets group bit to match other bits and then clears group write bit. - t_mode("g=o-w", 0040777, 0040757); - t_mode("g=o-w", 0040642, 0040602); - t_mode("g=o-w", 0040246, 0040246); - t_mode("g=o-w", 0040000, 0040000); - - // clears group read bit and sets group write bit. - t_mode("g-r+w", 0040777, 0040737); - t_mode("g-r+w", 0040000, 0040020); - - // Sets owner bits to match group bits and sets other bits to match group bits. - t_mode("uo=g", 0040777, 0040777); - t_mode("uo=g", 0040642, 0040444); - t_mode("uo=g", 0040000, 0040000); -} - -static void -non_symbolic(void) -{ - printf("# => non_symbolic\n"); - - t_mode("0", 0, 0); - t_mode("0", 0040777, 0040000); - - t_mode("7", 0, 07); - t_mode("7", 0040777, 0040007); - - t_mode("77", 0, 077); - t_mode("77", 0040777, 0040077); - - t_mode("777", 0, 0777); - t_mode("777", 0040777, 0040777); - - t_mode("700", 0, 0700); - t_mode("700", 0040777, 0040700); - - t_mode("7777", 0, 07777); - t_mode("7777", 0040777, 0047777); -} - -int -main(void) -{ - int plan = 161; - printf("1..%d\n", plan); - - t_mode(NULL, 0, 0); - t_mode(NULL, 00777, 00777); - t_mode("", 0, 0); - t_mode("", 00777, 00777); - t_mode(",", 0, 0); - t_mode(",", 00777, 00777); - - t_mode("-w,+x", 00666, 00577); - - t_mode("a-wx,u+x,u+s", 00666, 04544); - t_mode("a-wx,ug+x,g+s", 00666, 02554); - t_mode("a-wx,ug+x,+t", 00666, 01554); - - t_mode("-s", 04544, 00544); - t_mode("g-s", 02544, 00544); - t_mode("-t", 01544, 00544); - - add_read(); - set_read(); - del_read(); - - search(); - - posix_examples(); - - syntax(); - - non_symbolic(); - - assert(counter == plan); - return t_err; -} diff --git a/test-lib/t_strtodur.c b/test-lib/t_strtodur.c @@ -1,83 +0,0 @@ -// utils-std: Collection of commonly available Unix tools -// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> -// SPDX-License-Identifier: MPL-2.0 - -#define _POSIX_C_SOURCE 200809L -#include "../lib/strtodur.h" - -#include <assert.h> -#include <stdio.h> // printf - -const char *argv0 = "t_strtodur"; -int counter = 0; -int err = 0; - -static void -t_strtodur(char *str, time_t ex_sec, long ex_nsec) -{ - int id = ++counter; - - struct timespec dur = {.tv_sec = 0, .tv_nsec = 0}; - int ret = strtodur(str, &dur); - - if(dur.tv_sec == ex_sec && dur.tv_nsec == ex_nsec && ret == 0) - { - printf("ok %d - strtodur(\"%s\", _) -> {.tv_sec = %ld, .tv_nsec = %ld}\n", - id, - str, - dur.tv_sec, - dur.tv_nsec); - return; - } - - err = 1; - printf("not ok %d - strtodur(\"%s\", _) -> {.tv_sec = %ld, .tv_nsec = %ld}\n", - id, - str, - dur.tv_sec, - dur.tv_nsec); - if(dur.tv_sec != ex_sec || dur.tv_nsec != ex_nsec) - printf("# Expected: {.tv_sec = %ld, .tv_nsec = %ld}\n", ex_sec, ex_nsec); - if(ret != 0) printf("# Exit status: %d\n", ret); -} - -int -main(void) -{ - int plan = 18; - printf("1..%d\n", plan); - - // TODO: Capture errors, say with open_memstream(3) - -#define T_NSEC 1000000000 -#define T_MIN 60 -#define T_HOUR 60 * T_MIN -#define T_DAY 24 * T_HOUR - - t_strtodur(NULL, 0, 0); - t_strtodur((char *)"", 0, 0); - t_strtodur((char *)",", 0, 0); - - t_strtodur((char *)"1", 1, 0); - t_strtodur((char *)"1.", 1, 0); - t_strtodur((char *)"1,", 1, 0); - - t_strtodur((char *)".1", 0, T_NSEC * 0.1); - t_strtodur((char *)"0.1", 0, T_NSEC * 0.1); - - t_strtodur((char *)"1s", 1, 0); - t_strtodur((char *)"1m", T_MIN, 0); - t_strtodur((char *)"1h", 1 * T_HOUR, 0); - t_strtodur((char *)"1d", 1 * T_DAY, 0); - t_strtodur((char *)"1d1h1m1s", (1 * T_DAY) + (1 * T_HOUR) + (1 * T_MIN) + 1, 0); - - t_strtodur((char *)"1.5s", 1, T_NSEC * 0.5); - t_strtodur((char *)"1.5m", 1.5 * T_MIN, 0); - t_strtodur((char *)"1.5h", 1.5 * T_HOUR, 0); - t_strtodur((char *)"1.5d", 1.5 * T_DAY, 0); - t_strtodur( - (char *)"1.5d1.5h1.5m1.5s", (1.5 * T_DAY) + (1.5 * T_HOUR) + (1.5 * T_MIN) + 1, T_NSEC * 0.5); - - assert(counter == plan); - return err; -} diff --git a/test-lib/t_symbolize_mode.c b/test-lib/t_symbolize_mode.c @@ -1,47 +0,0 @@ -// utils-std: Collection of commonly available Unix tools -// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> -// SPDX-License-Identifier: MPL-2.0 - -#define _POSIX_C_SOURCE 200809L -#include "../lib/mode.h" - -#include <assert.h> -#include <stdio.h> // printf -#include <string.h> // strcmp - -int counter = 0; -int err = 0; - -static void -t_symbolize_mode(mode_t mode, const char *expected) -{ - char str[11] = ""; - symbolize_mode(mode, str); - if(strcmp(str, expected) == 0) - { - printf("ok %d - %7o -> %s\n", ++counter, mode, expected); - return; - } - - err = 1; - printf("not ok %d - %7o -> %s\n", ++counter, mode, expected); - printf("# Got: %s\n", str); -} - -int -main(void) -{ - int plan = 6; - printf("1..%d\n", plan); - - t_symbolize_mode(0040000, "d---------"); - t_symbolize_mode(0040755, "drwxr-xr-x"); - t_symbolize_mode(0020644, "crw-r--r--"); - - t_symbolize_mode(0024644, "crwSr--r--"); - t_symbolize_mode(0022774, "crwxrwsr--"); - t_symbolize_mode(0021744, "crwxr--r-T"); - - assert(counter == plan); - return err; -} diff --git a/test-lib/t_truncation.c b/test-lib/t_truncation.c @@ -1,80 +0,0 @@ -// utils-std: Collection of commonly available Unix tools -// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> -// SPDX-License-Identifier: MPL-2.0 - -#define _POSIX_C_SOURCE 200809L -#include "../lib/truncation.h" - -#include <assert.h> -#include <stdio.h> // printf - -const char *argv0 = "test-lib/truncation"; - -int counter = 0; -int err = 0; - -static void -t_parse_size(const char *str, off_t size, enum operation_e op) -{ - int id = ++counter; - - struct truncation tr; - int ret = parse_size(str, &tr); - if(ret == 0 && tr.size == size && tr.op == op) - { - printf("ok %d - parse_size(\"%s\", _) -> {.size = %ld, .op = %d}\n", id, str, tr.size, tr.op); - return; - } - - err = 1; - printf("not ok %d - parse_size(\"%s\", _) -> {.size = %ld, .op = %d}\n", id, str, tr.size, tr.op); - if(tr.size != size || tr.op != op) printf("# Expected: {.size = %ld, .op = %d}\n", size, op); - if(ret != 0) printf("# Exit status: %d\n", ret); -} - -static void -set(void) -{ - t_parse_size("0", 0L, OP_SET); - t_parse_size("666", 666L, OP_SET); - t_parse_size("666M", 666 * 1024 * 1024L, OP_SET); - t_parse_size("666MB", 666 * 1000 * 1000L, OP_SET); - t_parse_size("666MiB", 666 * 1024 * 1024L, OP_SET); -} - -static void -inc(void) -{ - t_parse_size("+0", 0L, OP_INC); - t_parse_size("+666", 666L, OP_INC); - t_parse_size("+666M", 666 * 1024 * 1024L, OP_INC); - t_parse_size("+666MB", 666 * 1000 * 1000L, OP_INC); - t_parse_size("+666MiB", 666 * 1024 * 1024L, OP_INC); -} - -static void -dec(void) -{ - t_parse_size("-0", 0L, OP_DEC); - t_parse_size("-666", 666L, OP_DEC); - t_parse_size("-666M", 666 * 1024 * 1024L, OP_DEC); - t_parse_size("-666MB", 666 * 1000 * 1000L, OP_DEC); - t_parse_size("-666MiB", 666 * 1024 * 1024L, OP_DEC); -} - -int -main(void) -{ - int plan = 15; - printf("1..%d\n", plan); - - // needs standard error capture - //t_parse_size("", 0, OP_SET); - - set(); - inc(); - dec(); - - assert(counter == plan); - return err; -} diff --git a/test-libutils/t_humanize.c b/test-libutils/t_humanize.c @@ -0,0 +1,78 @@ +// utils-std: Collection of commonly available Unix tools +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#define _POSIX_C_SOURCE 200809L +#include "../libutils/humanize.h" + +#include <assert.h> +#include <stdio.h> // printf + +const char *argv0 = "t_humanize"; +int counter = 0; +int err = 0; + +static void +t_dtosi(double in, bool iec, double out, unsigned exponent) +{ + int id = ++counter; + + struct si_scale ret = dtosi(in, iec); + + if(ret.number == out && ret.exponent == exponent) + { + printf("ok %d - dtosi(%f, %d) => {.number = %g, .exponent = %d}\n", + id, + in, + iec, + ret.number, + ret.exponent); + return; + } + + err = 1; + printf("not ok %d - dtosi(%f, %d) => {.number = %g, .exponent = %d}\n", + id, + in, + iec, + ret.number, + ret.exponent); + printf("# Expected: {.number = %g, .exponent = %d}\n", out, exponent); +} + +int +main(void) +{ + int plan = 18; + printf("1..%d\n", plan); + + t_dtosi(0, false, 0, 0); + t_dtosi(0, true, 0, 0); + + t_dtosi(1000, false, 1000, 0); + t_dtosi(10000, false, 10, 1); + + t_dtosi(-1000, false, -1000, 0); + t_dtosi(-10000, false, -10, 1); + + t_dtosi(1024, true, 1024, 0); + t_dtosi(10240, true, 10240 / 1024, 1); + + t_dtosi(-1024, true, -1024, 0); + t_dtosi(-10240, true, -10240 / 1024, 1); + +#define IEC_QiB 1267650600228229401496703205376.0 /* 1024^10 */ + t_dtosi(1024 * IEC_QiB, true, 1024, 10); + t_dtosi(-1024 * IEC_QiB, true, -1024, 10); + t_dtosi(1024 * 1024 * IEC_QiB, true, 1024 * 1024, 10); + t_dtosi(-1024 * 1024 * IEC_QiB, true, -1024 * 1024, 10); + +#define SI_Q 1000000000000000000000000000000.0 /* 1000^10 */ + t_dtosi(1000 * SI_Q, false, 1000, 10); + t_dtosi(-1000 * SI_Q, false, -1000, 10); + t_dtosi(1000 * 1000 * SI_Q, false, 1000 * 1000, 10); + t_dtosi(-1000 * 1000 * SI_Q, false, -1000 * 1000, 10); + + assert(counter == plan); + return err; +} diff --git a/test-libutils/t_mode.c b/test-libutils/t_mode.c @@ -0,0 +1,325 @@ +// utils-std: Collection of commonly available Unix tools +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#define _POSIX_C_SOURCE 200809L +#include "../libutils/mode.h" + +#include <assert.h> +#include <stdio.h> // printf +#include <string.h> // strcmp +#include <sys/stat.h> // umask + +int counter = 0; +int t_err = 0; + +static void +t_mode(const char *str, mode_t old, mode_t expect) +{ + int id = ++counter; + const char *errstr = NULL; + mode_t got = new_mode(str, old, &errstr); + if(got == expect && errstr == NULL) + { + printf("ok %d - new_mode(\"%s\", 0%06o) == 0%06o\n", id, str, old, expect); + return; + } + + t_err = 1; + printf("not ok %d - new_mode(\"%s\", 0%06o) == 0%06o\n", id, str, old, expect); + if(got != expect) printf("# Got: 0%06o\n", got); + if(errstr != NULL) printf("# Errstr: \"%s\"\n", errstr); +} + +static void +t_mode_errstr(const char *str, mode_t old, const char *expect_errstr) +{ + assert(expect_errstr != NULL); + + int id = ++counter; + const char *errstr = NULL; + (void)new_mode(str, old, &errstr); + + if(errstr != NULL && strcmp(errstr, expect_errstr) == 0) + { + printf("ok %d - new_mode(\"%s\", 0%06o) -> %s\n", id, str, old, expect_errstr); + } + else + { + printf("not ok %d - new_mode(\"%s\", 0%06o) -> %s\n", id, str, old, expect_errstr); + printf("# Got errstr: \"%s\"\n", errstr); + t_err = 1; + } +} + +static void +add_read(void) +{ + printf("# => add_read\n"); + umask(0044); + + t_mode("+r", 0, 00400); + t_mode("a+r", 0, 00444); + t_mode("u+r", 0, 00400); + t_mode("g+r", 0, 00040); + t_mode("o+r", 0, 00004); + t_mode("ug+r", 0, 00440); + t_mode("go+r", 0, 00044); + t_mode("uo+r", 0, 00404); + t_mode("u+r,g+r", 0, 00440); + t_mode("g+r,o+r", 0, 00044); + t_mode("u+r,o+r", 0, 00404); + + t_mode("+r", 00777, 00777); + t_mode("a+r", 00777, 00777); + t_mode("u+r", 00777, 00777); + t_mode("g+r", 00777, 00777); + t_mode("o+r", 00777, 00777); + t_mode("ug+r", 00777, 00777); + t_mode("go+r", 00777, 00777); + t_mode("uo+r", 00777, 00777); + t_mode("u+r,g+r", 00777, 00777); + t_mode("g+r,o+r", 00777, 00777); + t_mode("u+r,o+r", 00777, 00777); +} + +static void +set_read(void) +{ + printf("# => set_read\n"); + umask(0044); + + t_mode("=r", 0, 00400); + t_mode("a=r", 0, 00444); + t_mode("u=r", 0, 00400); + t_mode("g=r", 0, 00040); + t_mode("o=r", 0, 00004); + t_mode("ug=r", 0, 00440); + t_mode("go=r", 0, 00044); + t_mode("uo=r", 0, 00404); + t_mode("u=r,g=r", 0, 00440); + t_mode("g=r,o=r", 0, 00044); + t_mode("u=r,o=r", 0, 00404); + + t_mode("go=,u=xr", 0, 00500); + t_mode("go=,u=xr", 00777, 00500); + + t_mode("=r", 00777, 00400); + t_mode("a=r", 00777, 00444); + t_mode("u=r", 00777, 00477); + t_mode("g=r", 00777, 00747); + t_mode("o=r", 00777, 00774); + t_mode("ug=r", 00777, 00447); + t_mode("go=r", 00777, 00744); + t_mode("uo=r", 00777, 00474); + t_mode("u=r,g=r", 00777, 00447); + t_mode("g=r,o=r", 00777, 00744); + t_mode("u=r,o=r", 00777, 00474); +} + +static void +del_read(void) +{ + printf("# => del_read\n"); + umask(0044); + + t_mode("-r", 0, 0); + t_mode("a-r", 0, 0); + t_mode("u-r", 0, 0); + t_mode("g-r", 0, 0); + t_mode("o-r", 0, 0); + t_mode("ug-r", 0, 0); + t_mode("go-r", 0, 0); + t_mode("uo-r", 0, 0); + t_mode("u-r,g-r", 0, 0); + t_mode("g-r,o-r", 0, 0); + t_mode("u-r,o-r", 0, 0); + + t_mode("-r", 00777, 00377); + t_mode("a-r", 00777, 00333); + t_mode("u-r", 00777, 00377); + t_mode("g-r", 00777, 00737); + t_mode("o-r", 00777, 00773); + t_mode("ug-r", 00777, 00337); + t_mode("go-r", 00777, 00733); + t_mode("uo-r", 00777, 00373); + t_mode("u-r,g-r", 00777, 00337); + t_mode("g-r,o-r", 00777, 00733); + t_mode("u-r,o-r", 00777, 00373); +} + +static void +search(void) +{ + printf("# => search\n"); + t_mode("-X", 0, 0); + t_mode("a-X", 0, 0); + t_mode("u-X", 0, 0); + t_mode("g-X", 0, 0); + t_mode("o-X", 0, 0); + + t_mode("+X", 0, 0); + t_mode("a+X", 0, 0); + t_mode("u+X", 0, 0); + t_mode("g+X", 0, 0); + t_mode("o+X", 0, 0); + + t_mode("=X", 0, 0); + t_mode("a=X", 0, 0); + t_mode("u=X", 0, 0); + t_mode("g=X", 0, 0); + t_mode("o=X", 0, 0); + + // S_IFDIR = 0040000 + t_mode("-X", 0040777, 0040666); + t_mode("a-X", 0040777, 0040666); + t_mode("u-X", 0040777, 0040677); + t_mode("g-X", 0040777, 0040767); + t_mode("o-X", 0040777, 0040776); + + t_mode("+X", 0040777, 0040777); + t_mode("a+X", 0040777, 0040777); + t_mode("u+X", 0040777, 0040777); + t_mode("g+X", 0040777, 0040777); + t_mode("o+X", 0040777, 0040777); + + t_mode("=X", 0040777, 0040111); + t_mode("a=X", 0040777, 0040111); + t_mode("u=X", 0040777, 0040177); + t_mode("g=X", 0040777, 0040717); + t_mode("o=X", 0040777, 0040771); + + t_mode("-X", 0040000, 0040000); + t_mode("a-X", 0040000, 0040000); + t_mode("u-X", 0040000, 0040000); + t_mode("g-X", 0040000, 0040000); + t_mode("o-X", 0040000, 0040000); + + t_mode("+X", 0040000, 0040111); + t_mode("a+X", 0040000, 0040111); + t_mode("u+X", 0040000, 0040100); + t_mode("g+X", 0040000, 0040010); + t_mode("o+X", 0040000, 0040001); + + t_mode("=X", 0040000, 0040111); + t_mode("a=X", 0040000, 0040111); + t_mode("u=X", 0040000, 0040100); + t_mode("g=X", 0040000, 0040010); + t_mode("o=X", 0040000, 0040001); +} + +static void +syntax(void) +{ + printf("# => syntax\n"); + + t_mode("=", 0, 0); + t_mode("=", 0040777, 0040000); + + t_mode("-", 0, 0); + t_mode("-", 0040777, 0040777); + + t_mode("+", 0, 0); + t_mode("+", 0040777, 0040777); + + t_mode_errstr("/", 0, "syntax error, got invalid character"); + + t_mode_errstr("foo", 0, "syntax error, got invalid character"); + + t_mode_errstr("77777", 0, "can't be higher than 0o7777"); + + t_mode_errstr("-0", 0, "syntax error, got invalid character"); +} + +static void +posix_examples(void) +{ + // Examples as given by POSIX in chmod(1p) + printf("# => posix_examples\n"); + + // clears all file mode bits. + t_mode("a+=", 0040777, 0040000); + t_mode("a+=", 0040000, 0040000); + + // clears group and other write bits + t_mode("go+-w", 0040777, 0040755); + t_mode("go+-w", 0040000, 0040000); + + // sets group bit to match other bits and then clears group write bit. + t_mode("g=o-w", 0040777, 0040757); + t_mode("g=o-w", 0040642, 0040602); + t_mode("g=o-w", 0040246, 0040246); + t_mode("g=o-w", 0040000, 0040000); + + // clears group read bit and sets group write bit. + t_mode("g-r+w", 0040777, 0040737); + t_mode("g-r+w", 0040000, 0040020); + + // Sets owner bits to match group bits and sets other bits to match group bits. + t_mode("uo=g", 0040777, 0040777); + t_mode("uo=g", 0040642, 0040444); + t_mode("uo=g", 0040000, 0040000); +} + +static void +non_symbolic(void) +{ + printf("# => non_symbolic\n"); + + t_mode("0", 0, 0); + t_mode("0", 0040777, 0040000); + + t_mode("7", 0, 07); + t_mode("7", 0040777, 0040007); + + t_mode("77", 0, 077); + t_mode("77", 0040777, 0040077); + + t_mode("777", 0, 0777); + t_mode("777", 0040777, 0040777); + + t_mode("700", 0, 0700); + t_mode("700", 0040777, 0040700); + + t_mode("7777", 0, 07777); + t_mode("7777", 0040777, 0047777); +} + +int +main(void) +{ + int plan = 161; + printf("1..%d\n", plan); + + t_mode(NULL, 0, 0); + t_mode(NULL, 00777, 00777); + t_mode("", 0, 0); + t_mode("", 00777, 00777); + t_mode(",", 0, 0); + t_mode(",", 00777, 00777); + + t_mode("-w,+x", 00666, 00577); + + t_mode("a-wx,u+x,u+s", 00666, 04544); + t_mode("a-wx,ug+x,g+s", 00666, 02554); + t_mode("a-wx,ug+x,+t", 00666, 01554); + + t_mode("-s", 04544, 00544); + t_mode("g-s", 02544, 00544); + t_mode("-t", 01544, 00544); + + add_read(); + set_read(); + del_read(); + + search(); + + posix_examples(); + + syntax(); + + non_symbolic(); + + assert(counter == plan); + return t_err; +} diff --git a/test-libutils/t_strtodur.c b/test-libutils/t_strtodur.c @@ -0,0 +1,83 @@ +// utils-std: Collection of commonly available Unix tools +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#define _POSIX_C_SOURCE 200809L +#include "../libutils/strtodur.h" + +#include <assert.h> +#include <stdio.h> // printf + +const char *argv0 = "t_strtodur"; +int counter = 0; +int err = 0; + +static void +t_strtodur(char *str, time_t ex_sec, long ex_nsec) +{ + int id = ++counter; + + struct timespec dur = {.tv_sec = 0, .tv_nsec = 0}; + int ret = strtodur(str, &dur); + + if(dur.tv_sec == ex_sec && dur.tv_nsec == ex_nsec && ret == 0) + { + printf("ok %d - strtodur(\"%s\", _) -> {.tv_sec = %ld, .tv_nsec = %ld}\n", + id, + str, + dur.tv_sec, + dur.tv_nsec); + return; + } + + err = 1; + printf("not ok %d - strtodur(\"%s\", _) -> {.tv_sec = %ld, .tv_nsec = %ld}\n", + id, + str, + dur.tv_sec, + dur.tv_nsec); + if(dur.tv_sec != ex_sec || dur.tv_nsec != ex_nsec) + printf("# Expected: {.tv_sec = %ld, .tv_nsec = %ld}\n", ex_sec, ex_nsec); + if(ret != 0) printf("# Exit status: %d\n", ret); +} + +int +main(void) +{ + int plan = 18; + printf("1..%d\n", plan); + + // TODO: Capture errors, say with open_memstream(3) + +#define T_NSEC 1000000000 +#define T_MIN 60 +#define T_HOUR 60 * T_MIN +#define T_DAY 24 * T_HOUR + + t_strtodur(NULL, 0, 0); + t_strtodur((char *)"", 0, 0); + t_strtodur((char *)",", 0, 0); + + t_strtodur((char *)"1", 1, 0); + t_strtodur((char *)"1.", 1, 0); + t_strtodur((char *)"1,", 1, 0); + + t_strtodur((char *)".1", 0, T_NSEC * 0.1); + t_strtodur((char *)"0.1", 0, T_NSEC * 0.1); + + t_strtodur((char *)"1s", 1, 0); + t_strtodur((char *)"1m", T_MIN, 0); + t_strtodur((char *)"1h", 1 * T_HOUR, 0); + t_strtodur((char *)"1d", 1 * T_DAY, 0); + t_strtodur((char *)"1d1h1m1s", (1 * T_DAY) + (1 * T_HOUR) + (1 * T_MIN) + 1, 0); + + t_strtodur((char *)"1.5s", 1, T_NSEC * 0.5); + t_strtodur((char *)"1.5m", 1.5 * T_MIN, 0); + t_strtodur((char *)"1.5h", 1.5 * T_HOUR, 0); + t_strtodur((char *)"1.5d", 1.5 * T_DAY, 0); + t_strtodur( + (char *)"1.5d1.5h1.5m1.5s", (1.5 * T_DAY) + (1.5 * T_HOUR) + (1.5 * T_MIN) + 1, T_NSEC * 0.5); + + assert(counter == plan); + return err; +} diff --git a/test-libutils/t_symbolize_mode.c b/test-libutils/t_symbolize_mode.c @@ -0,0 +1,47 @@ +// utils-std: Collection of commonly available Unix tools +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#define _POSIX_C_SOURCE 200809L +#include "../libutils/mode.h" + +#include <assert.h> +#include <stdio.h> // printf +#include <string.h> // strcmp + +int counter = 0; +int err = 0; + +static void +t_symbolize_mode(mode_t mode, const char *expected) +{ + char str[11] = ""; + symbolize_mode(mode, str); + if(strcmp(str, expected) == 0) + { + printf("ok %d - %7o -> %s\n", ++counter, mode, expected); + return; + } + + err = 1; + printf("not ok %d - %7o -> %s\n", ++counter, mode, expected); + printf("# Got: %s\n", str); +} + +int +main(void) +{ + int plan = 6; + printf("1..%d\n", plan); + + t_symbolize_mode(0040000, "d---------"); + t_symbolize_mode(0040755, "drwxr-xr-x"); + t_symbolize_mode(0020644, "crw-r--r--"); + + t_symbolize_mode(0024644, "crwSr--r--"); + t_symbolize_mode(0022774, "crwxrwsr--"); + t_symbolize_mode(0021744, "crwxr--r-T"); + + assert(counter == plan); + return err; +} diff --git a/test-libutils/t_truncation.c b/test-libutils/t_truncation.c @@ -0,0 +1,80 @@ +// utils-std: Collection of commonly available Unix tools +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#define _POSIX_C_SOURCE 200809L +#include "../libutils/truncation.h" + +#include <assert.h> +#include <stdio.h> // printf + +const char *argv0 = "test-lib/truncation"; + +int counter = 0; +int err = 0; + +static void +t_parse_size(const char *str, off_t size, enum operation_e op) +{ + int id = ++counter; + + struct truncation tr; + int ret = parse_size(str, &tr); + if(ret == 0 && tr.size == size && tr.op == op) + { + printf("ok %d - parse_size(\"%s\", _) -> {.size = %ld, .op = %d}\n", id, str, tr.size, tr.op); + return; + } + + err = 1; + printf("not ok %d - parse_size(\"%s\", _) -> {.size = %ld, .op = %d}\n", id, str, tr.size, tr.op); + if(tr.size != size || tr.op != op) printf("# Expected: {.size = %ld, .op = %d}\n", size, op); + if(ret != 0) printf("# Exit status: %d\n", ret); +} + +static void +set(void) +{ + t_parse_size("0", 0L, OP_SET); + t_parse_size("666", 666L, OP_SET); + t_parse_size("666M", 666 * 1024 * 1024L, OP_SET); + t_parse_size("666MB", 666 * 1000 * 1000L, OP_SET); + t_parse_size("666MiB", 666 * 1024 * 1024L, OP_SET); +} + +static void +inc(void) +{ + t_parse_size("+0", 0L, OP_INC); + t_parse_size("+666", 666L, OP_INC); + t_parse_size("+666M", 666 * 1024 * 1024L, OP_INC); + t_parse_size("+666MB", 666 * 1000 * 1000L, OP_INC); + t_parse_size("+666MiB", 666 * 1024 * 1024L, OP_INC); +} + +static void +dec(void) +{ + t_parse_size("-0", 0L, OP_DEC); + t_parse_size("-666", 666L, OP_DEC); + t_parse_size("-666M", 666 * 1024 * 1024L, OP_DEC); + t_parse_size("-666MB", 666 * 1000 * 1000L, OP_DEC); + t_parse_size("-666MiB", 666 * 1024 * 1024L, OP_DEC); +} + +int +main(void) +{ + int plan = 15; + printf("1..%d\n", plan); + + // needs standard error capture + //t_parse_size("", 0, OP_SET); + + set(); + inc(); + dec(); + + assert(counter == plan); + return err; +}