From 7528a9628443b2d8e57b7bece698a5a6a0a3fe18 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 3 Sep 2016 15:41:55 -0500 Subject: Move genericish function to lib. --- lib/lib.c | 21 +++++++++++++++++++++ lib/lib.h | 1 + toys/posix/sed.c | 24 ------------------------ 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/lib/lib.c b/lib/lib.c index 8f8b4a3b..a6cb0ec3 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -1207,3 +1207,24 @@ char *getgroupname(gid_t gid) return gr ? gr->gr_name : gnum; } +// Iterate over lines in file, calling function. Function can write 0 to +// the line pointer if they want to keep it, or 1 to terminate processing, +// otherwise line is freed. Passed file descriptor is closed at the end. +void do_lines(int fd, void (*call)(char **pline, long len)) +{ + FILE *fp = fd ? xfdopen(fd, "r") : stdin; + + for (;;) { + char *line = 0; + ssize_t len; + + len = getline(&line, (void *)&len, fp); + if (len > 0) { + call(&line, len); + if (line == (void *)1) break; + free(line); + } else break; + } + + if (fd) fclose(fp); +} diff --git a/lib/lib.h b/lib/lib.h index 43d6b1ff..5cd991c9 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -225,6 +225,7 @@ int regexec0(regex_t *preg, char *string, long len, int nmatch, regmatch_t pmatch[], int eflags); char *getusername(uid_t uid); char *getgroupname(gid_t gid); +void do_lines(int fd, void (*call)(char **pline, long len)); #define HR_SPACE 1 // Space between number and units #define HR_B 2 // Use "B" for single byte units diff --git a/toys/posix/sed.c b/toys/posix/sed.c index 71988248..c62d2d10 100644 --- a/toys/posix/sed.c +++ b/toys/posix/sed.c @@ -621,30 +621,6 @@ done: free(line); } -// Genericish function, can probably get moved to lib.c - -// Iterate over lines in file, calling function. Function can write 0 to -// the line pointer if they want to keep it, or 1 to terminate processing, -// otherwise line is freed. Passed file descriptor is closed at the end. -static void do_lines(int fd, void (*call)(char **pline, long len)) -{ - FILE *fp = fd ? xfdopen(fd, "r") : stdin; - - for (;;) { - char *line = 0; - ssize_t len; - - len = getline(&line, (void *)&len, fp); - if (len > 0) { - call(&line, len); - if (line == (void *)1) break; - free(line); - } else break; - } - - if (fd) fclose(fp); -} - // Callback called on each input file static void do_sed(int fd, char *name) { -- cgit v1.2.3 From 0c8a66ea44eae5eec4d0398a1f2a6d93a54b0fb0 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 4 Sep 2016 17:18:31 -0500 Subject: Switch help.c from #ifdef to if() --- lib/help.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/help.c b/lib/help.c index 87a3df94..d0185678 100644 --- a/lib/help.c +++ b/lib/help.c @@ -2,9 +2,6 @@ #include "toys.h" -#if !CFG_TOYBOX_HELP -void show_help(FILE *out) {;} -#else #include "generated/help.h" #undef NEWTOY @@ -24,14 +21,15 @@ void show_help(FILE *out) int i = toys.which-toy_list; char *s; - for (;;) { - s = help_data; - while (i--) s += strlen(s) + 1; - // If it's an alias, restart search for real name - if (*s != 255) break; - i = toy_find(++s)-toy_list; - } + if (CFG_TOYBOX_HELP) { + for (;;) { + s = help_data; + while (i--) s += strlen(s) + 1; + // If it's an alias, restart search for real name + if (*s != 255) break; + i = toy_find(++s)-toy_list; + } - fprintf(out, "%s", s); + fprintf(out, "%s", s); + } } -#endif -- cgit v1.2.3 From 299d43879d70de33f84eafab78fcd78d7befd827 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 4 Sep 2016 17:26:34 -0500 Subject: Add openro() and WARN_ONLY flag so xopen() and friends can warn without exiting. --- lib/lib.h | 6 ++++++ lib/xwrap.c | 20 +++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/lib.h b/lib/lib.h index 5cd991c9..3c5adb43 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -102,6 +102,11 @@ struct dirtree *dirtree_read(char *path, int (*callback)(struct dirtree *node)); void show_help(FILE *out); +// Tell xopen and friends to print warnings but return -1 as necessary +// The largest O_BLAH flag so far is arch/alpha's O_PATH at 0x800000 so +// plenty of headroom. +#define WARN_ONLY (1<<31) + // xwrap.c void xstrncpy(char *dest, char *src, size_t size); void xstrncat(char *dest, char *src, size_t size); @@ -132,6 +137,7 @@ int xcreate(char *path, int flags, int mode); int xopen(char *path, int flags); int xcreate_stdio(char *path, int flags, int mode); int xopen_stdio(char *path, int flags); +int openro(char *path, int flags); int xopenro(char *path); void xpipe(int *pp); void xclose(int fd); diff --git a/lib/xwrap.c b/lib/xwrap.c index 48e02965..89488acf 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -318,11 +318,13 @@ void xunlink(char *path) } // Die unless we can open/create a file, returning file descriptor. +// The meaning of O_CLOEXEC is reversed (it defaults on, pass it to disable) +// and WARN_ONLY tells us not to exit. int xcreate_stdio(char *path, int flags, int mode) { - int fd = open(path, flags^O_CLOEXEC, mode); + int fd = open(path, (flags^O_CLOEXEC)&~WARN_ONLY, mode); - if (fd == -1) perror_exit_raw(path); + if (fd == -1) ((mode&WARN_ONLY) ? perror_msg_raw : perror_exit_raw)(path); return fd; } @@ -378,12 +380,18 @@ int xopen(char *path, int flags) return notstdio(xopen_stdio(path, flags)); } -// Open read only, treating "-" as a synonym for stdin. -int xopenro(char *path) +// Open read only, treating "-" as a synonym for stdin, defaulting to warn only +int openro(char *path, int flags) { if (!strcmp(path, "-")) return 0; - return xopen(path, O_RDONLY); + return xopen(path, flags^WARN_ONLY); +} + +// Open read only, treating "-" as a synonym for stdin. +int xopenro(char *path) +{ + return openro(path, O_RDONLY|WARN_ONLY); } FILE *xfdopen(int fd, char *mode) @@ -674,6 +682,8 @@ char *xreadfile(char *name, char *buf, off_t len) return buf; } +// The data argument to ioctl() is actually long, but it's usually used as +// a pointer. If you need to feed in a number, do (void *)(long) typecast. int xioctl(int fd, int request, void *data) { int rc; -- cgit v1.2.3 From 7fc7db1332c801ab0c1834d6eda80496908292d8 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 4 Sep 2016 17:42:32 -0500 Subject: Remove a chunk of copied header that hasn't been upated in a while. --- www/code.html | 61 ++++++++++------------------------------------------------- 1 file changed, 10 insertions(+), 51 deletions(-) diff --git a/www/code.html b/www/code.html index c0566b4c..77b0b211 100644 --- a/www/code.html +++ b/www/code.html @@ -743,12 +743,8 @@ away in libc.

  • struct passwd *xgetpwuid(uid_t uid)
    struct group *xgetgrgid(gid_t gid)
    struct passwd *xgetpwnam(char *name)

    - -

  • - -
  • void xsetuser(struct passwd *pwd)
  • char *xreadlink(char *name)
  • char *xreadfile(char *name, char *buf, off_t len)
  • @@ -760,53 +756,7 @@ struct passwd *xgetpwnam(char *name)

    lib/lib.c

    -

    Eight gazillion common functions:

    - -
      -
    • void verror_msg(char *msg, int err, va_list va)
    • -
    • void error_msg(char *msg, ...)
    • -
    • void perror_msg(char *msg, ...)
    • -
    • void error_exit(char *msg, ...)
    • -
    • void perror_exit(char *msg, ...)
    • -
    • ssize_t readall(int fd, void *buf, size_t len)
    • -
    • ssize_t writeall(int fd, void *buf, size_t len)
    • -
    • off_t lskip(int fd, off_t offset)
    • -
    • int mkpathat(int atfd, char *dir, mode_t lastmode, int flags)
    • -
    • struct string_list **splitpath(char *path, struct string_list **list)
    • -
    • struct string_list *find_in_path(char *path, char *filename)
    • -
    • long atolx(char *numstr)
    • -
    • long atolx_range(char *numstr, long low, long high)
    • -
    • int numlen(long l)
    • -
    • int stridx(char *haystack, char needle)
    • -
    • int strstart(char **a, char *b)
    • -
    • off_t fdlength(int fd)
    • -
    • char *readfile(char *name, char *ibuf, off_t len)
    • -
    • void msleep(long miliseconds)
    • -
    • int64_t peek_le(void *ptr, unsigned size)
    • -
    • int64_t peek_be(void *ptr, unsigned size)
    • -
    • int64_t peek(void *ptr, unsigned size)
    • -
    • void poke(void *ptr, uint64_t val, int size)
    • -
    • void loopfiles_rw(char **argv, int flags, int permissions, int failok,
    • -
    • void loopfiles(char **argv, void (*function)(int fd, char *name))
    • -
    • char *get_rawline(int fd, long *plen, char end)
    • -
    • char *get_line(int fd)
    • -
    • int wfchmodat(int fd, char *name, mode_t mode)
    • -
    • static void tempfile_handler(int i)
    • -
    • int copy_tempfile(int fdin, char *name, char **tempname)
    • -
    • void delete_tempfile(int fdin, int fdout, char **tempname)
    • -
    • void replace_tempfile(int fdin, int fdout, char **tempname)
    • -
    • void crc_init(unsigned int *crc_table, int little_endian)
    • -
    • int terminal_size(unsigned *xx, unsigned *yy)
    • -
    • int yesno(char *prompt, int def)
    • -
    • void generic_signal(int sig)
    • -
    • void sigatexit(void *handler)
    • -
    • int sig_to_num(char *pidstr)
    • -
    • char *num_to_sig(int sig)
    • -
    • mode_t string_to_mode(char *modestr, mode_t mode)
    • -
    • void mode_to_string(mode_t mode, char *buf)
    • -
    • void names_to_pid(char **names, int (*callback)(pid_t pid, char *name))
    • -
    • int human_readable(char *buf, unsigned long long num)
    • -
    +

    Eight gazillion common functions, see lib/lib.h for the moment:

    lib/portability.h

    @@ -1087,6 +1037,15 @@ in the same order they're declared, and that padding won't be inserted between consecutive variables of register size. Thus the first few entries can be longs or pointers corresponding to the saved arguments.

    +

    The main downside is that numeric arguments ("#" and "-" format) +are limited to +- 2 billion on 32 bit platforms (the "truncate -s 8G" +problem), because long is only 64 bits on 64 bit hosts, so the capabilities +of some tools differ when built in 32 bit vs 64 bit mode. Fixing this +kind of ugly and even embedded designs are slowly moving to 64 bits, +so our current plan is to document the problem and wait it out. (If +"x32 mode" and similar becomes popular enough, we may revisit this +decision.)

    +

    See toys/example/*.c for longer examples of parsing options into the GLOBALS block.

    -- cgit v1.2.3 From 8cc325d55ca2984dbf2a29dbc48ed483de979740 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 4 Sep 2016 18:07:12 -0500 Subject: Add comment so I don't undo and then redo a thing again. --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 711d6247..6c5dd0d4 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,7 @@ change: clean:: rm -rf toybox generated change .singleconfig* +# If singlemake was in generated/ "make clean; make test_ls" wouldn't work. distclean: clean rm -f toybox_old .config* .singlemake -- cgit v1.2.3 From 8361fbd8ea9c6f29602982d31f67351f42f736b0 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 4 Sep 2016 19:13:31 -0500 Subject: make test_cmp caused the make invocation to exit with an error because the last test exited with nonzero status and the script preserved it. In the current context, that's counterproductive. --- scripts/runtest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/runtest.sh b/scripts/runtest.sh index 13b82f14..6e94d945 100644 --- a/scripts/runtest.sh +++ b/scripts/runtest.sh @@ -109,7 +109,7 @@ testing() [ -n "$DEBUG" ] && set +x - return $RETVAL + return 0 } # Recursively grab an executable and all the libraries needed to run it. -- cgit v1.2.3 From 19394faadb511c6f5ed015d63f6e5ba32c4fc4ca Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 5 Sep 2016 00:32:38 -0500 Subject: Fluff up cmp tests. --- tests/cmp.test | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/cmp.test b/tests/cmp.test index c3e8f5be..3b2dd1b2 100755 --- a/tests/cmp.test +++ b/tests/cmp.test @@ -22,12 +22,14 @@ testing "EOF, return code" "cmp input input2 2>/dev/null || echo yes" "yes\n" "a testing "diff, stdout" "cmp input input2" "input input2 differ: char 4, line 2\n" "ab\nx\nx" "" testing "diff, return code" "cmp input input2 > /dev/null || echo yes" "yes\n" "ab\nx\nx" "" -testing "-s EOF, return code" "cmp -s input input2 || echo yes" "yes\n" "ab\nc\nx" "" -testing "-s diff, return code" "cmp -s input input2 || echo yes" "yes\n" "ab\nx\nx" "" +testing "-s EOF, return code" "cmp -s input input2 2>&1 || echo yes" "yes\n" "ab\nc\nx" "" +testing "-s diff, return code" "cmp -s input input2 2>&1 || echo yes" "yes\n" "ab\nx\nx" "" testing "-l EOF, stderr" "cmp -l input input2 2>&1" "cmp: EOF on input2\n" "ab\nc\nx" "" testing "-l diff and EOF, stdout and stderr" "cmp -l input input2 2>&1 | sort" "4 170 143\ncmp: EOF on input2\n" "ab\nx\nx" "" +testing "-s not exist" "cmp -s input doesnotexist 2>&1 || echo yes" "yes\n" "" "" + rm input2 testing "stdin and file" "cmp input -" "input - differ: char 4, line 2\n" "ab\nc\n" "ab\nx\n" -- cgit v1.2.3 From 7f7907f53ecaeabb00929feb0ede85a456683ddc Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 5 Sep 2016 00:52:44 -0500 Subject: Export notstdio() wrapper. --- lib/lib.h | 1 + lib/xwrap.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/lib/lib.h b/lib/lib.h index 3c5adb43..647f5328 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -142,6 +142,7 @@ int xopenro(char *path); void xpipe(int *pp); void xclose(int fd); int xdup(int fd); +int notstdio(int fd); FILE *xfdopen(int fd, char *mode); FILE *xfopen(char *path, char *mode); size_t xread(int fd, void *buf, size_t len); diff --git a/lib/xwrap.c b/lib/xwrap.c index 89488acf..66972f2b 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -357,6 +357,8 @@ int xdup(int fd) // old one. (We should never be called with stdin/stdout/stderr closed, but...) int notstdio(int fd) { + if (fd<0) return fd; + while (fd<3) { int fd2 = xdup(fd); -- cgit v1.2.3 From eed9ed41aa73023af8f79cd5353b96b80585490f Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Mon, 5 Sep 2016 00:55:24 -0500 Subject: Replace loopfiles' failok with WARN_ONLY open flag. --- lib/lib.c | 22 +++++++++++++--------- lib/lib.h | 2 +- toys/other/fsync.c | 4 ++-- toys/other/truncate.c | 6 +++--- toys/posix/cmp.c | 10 ++++++---- toys/posix/grep.c | 9 ++------- toys/posix/sed.c | 4 ++-- toys/posix/tail.c | 4 ++-- toys/posix/tee.c | 4 ++-- 9 files changed, 33 insertions(+), 32 deletions(-) diff --git a/lib/lib.c b/lib/lib.c index a6cb0ec3..fe85cbed 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -547,16 +547,20 @@ void poke(void *ptr, uint64_t val, int size) } // Iterate through an array of files, opening each one and calling a function -// on that filehandle and name. The special filename "-" means stdin if -// flags is O_RDONLY, stdout otherwise. An empty argument list calls +// on that filehandle and name. The special filename "-" means stdin if +// flags is O_RDONLY, stdout otherwise. An empty argument list calls // function() on just stdin/stdout. // // Note: pass O_CLOEXEC to automatically close filehandles when function() -// returns, otherwise filehandles must be closed by function() -void loopfiles_rw(char **argv, int flags, int permissions, int failok, +// returns, otherwise filehandles must be closed by function(). +// pass WARN_ONLY to produce warning messages about files it couldn't +// open/create, and skip them. Otherwise function is called with fd -1. +void loopfiles_rw(char **argv, int flags, int permissions, void (*function)(int fd, char *name)) { - int fd; + int fd, failok = !(flags&WARN_ONLY); + + flags &= ~WARN_ONLY; // If no arguments, read from stdin. if (!*argv) function((flags & O_ACCMODE) != O_RDONLY ? 1 : 0, "-"); @@ -564,8 +568,8 @@ void loopfiles_rw(char **argv, int flags, int permissions, int failok, // Filename "-" means read from stdin. // Inability to open a file prints a warning, but doesn't exit. - if (!strcmp(*argv, "-")) fd=0; - else if (0>(fd = open(*argv, flags, permissions)) && !failok) { + if (!strcmp(*argv, "-")) fd = 0; + else if (0>(fd = notstdio(open(*argv, flags, permissions))) && !failok) { perror_msg_raw(*argv); continue; } @@ -574,10 +578,10 @@ void loopfiles_rw(char **argv, int flags, int permissions, int failok, } while (*++argv); } -// Call loopfiles_rw with O_RDONLY|O_CLOEXEC and !failok (common case). +// Call loopfiles_rw with O_RDONLY|O_CLOEXEC|WARN_ONLY (common case) void loopfiles(char **argv, void (*function)(int fd, char *name)) { - loopfiles_rw(argv, O_RDONLY|O_CLOEXEC, 0, 0, function); + loopfiles_rw(argv, O_RDONLY|O_CLOEXEC|WARN_ONLY, 0, function); } // Slow, but small. diff --git a/lib/lib.h b/lib/lib.h index 647f5328..69692b73 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -205,7 +205,7 @@ char *chomp(char *s); int unescape(char c); int strstart(char **a, char *b); off_t fdlength(int fd); -void loopfiles_rw(char **argv, int flags, int permissions, int failok, +void loopfiles_rw(char **argv, int flags, int permissions, void (*function)(int fd, char *name)); void loopfiles(char **argv, void (*function)(int fd, char *name)); void xsendfile(int in, int out); diff --git a/toys/other/fsync.c b/toys/other/fsync.c index e6f6c8d9..bd73f398 100644 --- a/toys/other/fsync.c +++ b/toys/other/fsync.c @@ -28,6 +28,6 @@ static void do_fsync(int fd, char *name) void fsync_main(void) { - loopfiles_rw(toys.optargs, O_RDONLY|O_NOATIME|O_NOCTTY|O_CLOEXEC, - 0, 0, do_fsync); + loopfiles_rw(toys.optargs, O_RDONLY|O_NOATIME|O_NOCTTY|O_CLOEXEC|WARN_ONLY, + 0, do_fsync); } diff --git a/toys/other/truncate.c b/toys/other/truncate.c index bfe1f10c..6092d5a9 100644 --- a/toys/other/truncate.c +++ b/toys/other/truncate.c @@ -53,13 +53,13 @@ static void do_truncate(int fd, char *name) void truncate_main(void) { - int cr = !(toys.optflags&1); + int cr = !(toys.optflags&FLAG_c); if (-1 != (TT.type = stridx("+-<>/%", *TT.s))) TT.s++; TT.size = atolx(TT.s); // Create files with mask rwrwrw. // Nonexistent files are only an error if we're supposed to create them. - loopfiles_rw(toys.optargs, O_WRONLY|O_CLOEXEC|(cr ? O_CREAT : 0), 0666, cr, - do_truncate); + loopfiles_rw(toys.optargs, O_WRONLY|O_CLOEXEC|(cr ? O_CREAT|WARN_ONLY : 0), + 0666, do_truncate); } diff --git a/toys/posix/cmp.c b/toys/posix/cmp.c index 527fbfda..f4c34091 100644 --- a/toys/posix/cmp.c +++ b/toys/posix/cmp.c @@ -43,6 +43,8 @@ static void do_cmp(int fd, char *name) return; } + toys.exitval = 0; + for (;;) { len1 = readall(TT.fd, toybuf, size); len2 = readall(fd, buf2, size); @@ -54,11 +56,9 @@ static void do_cmp(int fd, char *name) if (toys.optflags & FLAG_l) printf("%ld %o %o\n", byte_no, toybuf[i], buf2[i]); else { - if (!(toys.optflags & FLAG_s)) { + if (!(toys.optflags & FLAG_s)) printf("%s %s differ: char %ld, line %ld\n", TT.name, name, byte_no, line_no); - toys.exitval++; - } goto out; } } @@ -79,6 +79,8 @@ out: void cmp_main(void) { - loopfiles_rw(toys.optargs, O_CLOEXEC, 0, toys.optflags&FLAG_s, do_cmp); + toys.exitval = 2; + loopfiles_rw(toys.optargs, O_CLOEXEC|(WARN_ONLY*!(toys.optflags&FLAG_s)), 0, + do_cmp); } diff --git a/toys/posix/grep.c b/toys/posix/grep.c index 6423ea6b..2fe6ac27 100644 --- a/toys/posix/grep.c +++ b/toys/posix/grep.c @@ -81,17 +81,12 @@ static void outline(char *line, char dash, char *name, long lcount, long bcount, static void do_grep(int fd, char *name) { struct double_list *dlb = 0; - FILE *file = fdopen(fd, "r"); + FILE *file = xfdopen(fd, "r"); long lcount = 0, mcount = 0, offset = 0, after = 0, before = 0; char *bars = 0; if (!fd) name = "(standard input)"; - if (!file) { - perror_msg_raw(name); - return; - } - // Loop through lines of input for (;;) { char *line = 0, *start; @@ -368,5 +363,5 @@ void grep_main(void) if (!strcmp(*ss, "-")) do_grep(0, *ss); else dirtree_read(*ss, do_grep_r); } - } else loopfiles_rw(ss, O_RDONLY, 0, 1, do_grep); + } else loopfiles_rw(ss, O_RDONLY|WARN_ONLY, 0, do_grep); } diff --git a/toys/posix/sed.c b/toys/posix/sed.c index c62d2d10..744edf7b 100644 --- a/toys/posix/sed.c +++ b/toys/posix/sed.c @@ -1010,8 +1010,8 @@ void sed_main(void) TT.fdout = 1; TT.remember = xstrdup(""); - // Inflict pattern upon input files - loopfiles_rw(args, O_RDONLY, 0, 0, do_sed); + // Inflict pattern upon input files. Long version because !O_CLOEXEC + loopfiles_rw(args, O_RDONLY|WARN_ONLY, 0, do_sed); if (!(toys.optflags & FLAG_i)) process_line(0, 0); diff --git a/toys/posix/tail.c b/toys/posix/tail.c index 787e116e..22b5ac6d 100644 --- a/toys/posix/tail.c +++ b/toys/posix/tail.c @@ -242,8 +242,8 @@ void tail_main(void) if ((TT.ffd = inotify_init()) < 0) perror_exit("inotify_init"); TT.files = xmalloc(toys.optc*8); } - loopfiles_rw(args, O_RDONLY|(O_CLOEXEC*!(toys.optflags&FLAG_f)), - 0, 0, do_tail); + loopfiles_rw(args, O_RDONLY|WARN_ONLY|(O_CLOEXEC*!(toys.optflags&FLAG_f)), + 0, do_tail); if ((toys.optflags & FLAG_f) && TT.file_no) { int len, last_fd = TT.files[(TT.file_no-1)*2], i, fd; diff --git a/toys/posix/tee.c b/toys/posix/tee.c index d5591b67..6167c8ad 100644 --- a/toys/posix/tee.c +++ b/toys/posix/tee.c @@ -49,8 +49,8 @@ void tee_main(void) // Open output files loopfiles_rw(toys.optargs, - O_RDWR|O_CREAT|((toys.optflags & FLAG_a)?O_APPEND:O_TRUNC), - 0666, 0, do_tee_open); + O_RDWR|O_CREAT|WARN_ONLY|((toys.optflags & FLAG_a)?O_APPEND:O_TRUNC), + 0666, do_tee_open); for (;;) { struct fd_list *fdl; -- cgit v1.2.3 From 337c072ac09a94a4a47d81cb214b3b8e55eee621 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Tue, 6 Sep 2016 00:14:24 -0500 Subject: Teach sed s/// how to handle [:space:] type sequences. Or more accurately, s@[[:space:]@]@replace@ which can't treat the @ in [] as a delimiter but has to know about nested [[]] to make that decision. --- tests/sed.test | 2 ++ toys/posix/sed.c | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/sed.test b/tests/sed.test index d25148ed..f48b73e6 100755 --- a/tests/sed.test +++ b/tests/sed.test @@ -57,6 +57,8 @@ testing 'multiple regex address match' 'sed -n /on/,/off/p' \ 'zap\nbone\nturtle\scoff\nfred\ntron\nlurid\noffer\nbecause\n' testing 'regex address overlap' 'sed -n /on/,/off/p' "on\nzap\noffon\n" "" \ 'on\nzap\noffon\nping\noff\n' +testing 'getdelim with nested [:blah:]' 'sed -n "sa\a[a[:space:]bc]*aXXagp"' \ + "ABXXCDXXEFXXGHXXIXX" "" "ABaaCDa EFaa aGHa a Ia " # gGhHlnNpPqrstwxy:= # s///#comment diff --git a/toys/posix/sed.c b/toys/posix/sed.c index 744edf7b..31268ece 100644 --- a/toys/posix/sed.c +++ b/toys/posix/sed.c @@ -657,6 +657,7 @@ static char *unescape_delimited_string(char **pstr, char *delim) { char *to, *from, mode = 0, d; + // Grab leading delimiter (if necessary), allocate space for new string from = *pstr; if (!delim || !*delim) { if (!(d = *(from++))) return 0; @@ -670,13 +671,23 @@ static char *unescape_delimited_string(char **pstr, char *delim) if (!*from) return 0; // delimiter in regex character range doesn't count - if (!mode && *from == '[') { - mode = '['; - if (from[1]=='-' || from[1]==']') *(to++) = *(from++); - } else if (mode && *from == ']') mode = 0; + if (*from == '[') { + if (!mode) { + mode = ']'; + if (from[1]=='-' || from[1]==']') *(to++) = *(from++); + } else if (mode == ']' && strchr(".=:", from[1])) { + *(to++) = *(from++); + mode = *from; + } + } else if (*from == mode) { + if (mode == ']') mode = 0; + else { + *(to++) = *(from++); + mode = ']'; + } // Length 1 range (X-X with same X) is "undefined" and makes regcomp err, // but the perl build does it, so we need to filter it out. - else if (mode && *from == '-' && from[-1] == from[1]) { + } else if (mode && *from == '-' && from[-1] == from[1]) { from+=2; continue; } else if (*from == '\\') { -- cgit v1.2.3 From 9f42e832a186bb3f5320581a3a713d0a8a9c8384 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 11 Sep 2016 23:55:36 -0500 Subject: Izabera pointed out that "file -" was inconsistent (calling stat on "-" but then reading from stdin if it detected a file). Fixed it so "-" always means stdin and you have to say ./- to look at a local "-". Did some whitespace tweaks while I was there... --- toys/posix/file.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/toys/posix/file.c b/toys/posix/file.c index 0cd9047c..27b4c0c2 100644 --- a/toys/posix/file.c +++ b/toys/posix/file.c @@ -221,24 +221,20 @@ static void do_regular_file(int fd, char *name, struct stat *sb) else if (toybuf[5] == '1') cpioformat = "SVR4 with no CRC"; else if (toybuf[5] == '2') cpioformat = "SVR4 with CRC"; xprintf("ASCII cpio archive (%s)\n", cpioformat); - } - else if (len>33 && (magic=peek(&s,2), magic==0143561 || magic==070707)) { + } else if (len>33 && (magic=peek(&s,2), magic==0143561 || magic==070707)) { if (magic == 0143561) printf("byte-swapped "); xprintf("cpio archive\n"); - } // tar archive (ustar/pax or gnu) - else if (len>500 && !strncmp(s+257, "ustar", 5)) { + } else if (len>500 && !strncmp(s+257, "ustar", 5)) { xprintf("POSIX tar archive%s\n", strncmp(s+262," ",2)?"":" (GNU)"); - } // zip/jar/apk archive, ODF/OOXML document, or such - else if (len>5 && strstart(&s, "PK\03\04")) { + } else if (len>5 && strstart(&s, "PK\03\04")) { int ver = (int)(char)(toybuf[4]); xprintf("Zip archive data"); if (ver) xprintf(", requires at least v%d.%d to extract", ver/10, ver%10); xputc('\n'); - } - else { + } else { char *what = 0; int i, bytes; @@ -279,23 +275,22 @@ void file_main(void) // Can't use loopfiles here because it doesn't call function when can't open for (arg = toys.optargs; *arg; arg++) { - struct stat sb; char *name = *arg, *what = "cannot open"; + struct stat sb; + int fd = !strcmp(name, "-"); xprintf("%s: %*s", name, (int)(TT.max_name_len - strlen(name)), ""); - if (!lstat(name, &sb)) { - if (S_ISFIFO(sb.st_mode)) what = "fifo"; - else if (S_ISREG(sb.st_mode)) { - int fd = !strcmp(name, "-") ? 0 : open(name, O_RDONLY); - - if (fd!=-1) { - if (!sb.st_size) what = "empty"; - else do_regular_file(fd, name, &sb); + if (fd || !lstat(name, &sb)) { + if (fd || S_ISREG(sb.st_mode)) { + if (!sb.st_size) what = "empty"; + else if ((fd = openro(name, O_RDONLY)) != -1) { + do_regular_file(fd, name, &sb); if (fd) close(fd); - if (sb.st_size) continue; + continue; } - } else if (S_ISBLK(sb.st_mode)) what = "block special"; + } else if (S_ISFIFO(sb.st_mode)) what = "fifo"; + else if (S_ISBLK(sb.st_mode)) what = "block special"; else if (S_ISCHR(sb.st_mode)) what = "character special"; else if (S_ISDIR(sb.st_mode)) what = "directory"; else if (S_ISSOCK(sb.st_mode)) what = "socket"; -- cgit v1.2.3