aboutsummaryrefslogtreecommitdiff
path: root/toys
diff options
context:
space:
mode:
Diffstat (limited to 'toys')
-rw-r--r--toys/posix/tail.c94
1 files changed, 32 insertions, 62 deletions
diff --git a/toys/posix/tail.c b/toys/posix/tail.c
index c2f71cbd..a00bfa0c 100644
--- a/toys/posix/tail.c
+++ b/toys/posix/tail.c
@@ -29,21 +29,13 @@ config TAIL_SEEK
#define FOR_tail
#include "toys.h"
-
#include <sys/inotify.h>
-struct file_info {
- int fd;
- int wd;
- const char* path;
-};
-
GLOBALS(
long lines;
long bytes;
- int file_no;
- struct file_info *files;
+ int file_no, ffd, *files;
)
struct line_list {
@@ -143,16 +135,21 @@ static void do_tail(int fd, char *name)
long bytes = TT.bytes, lines = TT.lines;
int linepop = 1;
+ if (toys.optflags & FLAG_f) {
+ int f = TT.file_no*2;
+ char *s = name;
+
+ if (!fd) sprintf(s = toybuf, "/proc/self/fd/%d", fd);
+ TT.files[f++] = fd;
+ if (0 > (TT.files[f] = inotify_add_watch(TT.ffd, s, IN_MODIFY)))
+ perror_msg("bad -f on '%s'", name);
+ }
+
if (toys.optc > 1) {
- if (TT.file_no > 0) xputc('\n');
+ if (TT.file_no++) xputc('\n');
xprintf("==> %s <==\n", name);
}
- // -f support: cache name/descriptor
- TT.files[TT.file_no].fd = dup(fd);
- TT.files[TT.file_no].path = strdup(name);
- ++TT.file_no;
-
// Are we measuring from the end of the file?
if (bytes<0 || lines<0) {
@@ -240,60 +237,33 @@ void tail_main(void)
TT.lines = -10;
}
- TT.files = xmalloc(toys.optc * sizeof(struct file_info));
- loopfiles(args, do_tail);
+ // Allocate 2 ints per optarg for -f
+ if (toys.optflags&FLAG_f) {
+ 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);
- // do -f stuff
if (toys.optflags & FLAG_f) {
- int infd, last_wd, i;
-
- infd = inotify_init();
- if (infd < 0) {
- perror_exit("failed to create inotify fd");
- }
-
- for (i = 0; i < TT.file_no; ++i) {
- #define STR(x) #x
- char path[sizeof("/proc/self/fd/" STR(INT_MIN))];
+ int len, last_fd = TT.files[(TT.file_no-1)*2], i, fd;
+ struct inotify_event ev;
- snprintf(path, sizeof(path), "/proc/self/fd/%d", TT.files[i].fd);
-
- TT.files[i].wd = inotify_add_watch(infd, path, IN_MODIFY);
- if (TT.files[i].wd < 0) {
- perror_msg("failed to add inotify watch for %s", TT.files[i].path);
- continue;
- }
- }
-
- last_wd = TT.files[TT.file_no - 1].wd;
-
- while (1) {
- struct inotify_event ev;
- int len;
+ for (;;) {
+ if (sizeof(ev)!=read(TT.ffd, &ev, sizeof(ev))) perror_exit("inotify");
- len = read(infd, &ev, sizeof(ev));
- if (len < 0) {
- perror_exit("inotify read failed");
- }
+ for (i = 0; i<TT.file_no && ev.wd!=TT.files[(i*2)+1]; i++);
+ if (i==TT.file_no) continue;
+ fd = TT.files[i*2];
- for (i = 0; i < TT.file_no; ++i) {
- if (ev.wd != TT.files[i].wd) {
- continue;
+ // Read new data.
+ while ((len = read(fd, toybuf, sizeof(toybuf)))>0) {
+ if (last_fd != fd) {
+ last_fd = fd;
+ xprintf("\n==> %s <==\n", args[i]);
}
- // Read until we hit the end.
- while (1) {
- len = read(TT.files[i].fd, toybuf, sizeof(toybuf));
- if (len <= 0) break;
-
- if (last_wd != TT.files[i].wd) {
- last_wd = TT.files[i].wd;
- xprintf("\n==> %s <==\n", TT.files[i].path);
- }
-
- xwrite(1, toybuf, len);
- }
- break;
+ xwrite(1, toybuf, len);
}
}
}