}
// 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, "-");
// 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;
}
} 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.
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);
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);
}
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);
}
return;
}
+ toys.exitval = 0;
+
for (;;) {
len1 = readall(TT.fd, toybuf, size);
len2 = readall(fd, buf2, size);
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;
}
}
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);
}
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;
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);
}
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);
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;
// 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;