diff --git a/usr.bin/tail/forward.c b/usr.bin/tail/forward.c --- a/usr.bin/tail/forward.c +++ b/usr.bin/tail/forward.c @@ -275,7 +275,7 @@ action = USE_KQUEUE; for (i = 0, file = files; i < no_files; i++, file++) { - if (! file->fp) + if (!file->fp) continue; if (fstatfs(fileno(file->fp), &sf) == 0 && @@ -307,27 +307,21 @@ void follow(file_info_t *files, enum STYLE style, off_t off) { - int active, ev_change, i, n = -1; + int active, ev_change, i, n; struct stat sb2; file_info_t *file; FILE *ftmp; struct timespec ts; /* Position each of the files */ - - file = files; active = 0; - n = 0; - for (i = 0; i < no_files; i++, file++) { - if (file->fp) { - active = 1; - n++; - if (vflag || (qflag == 0 && no_files > 1)) - printfn(file->file_name, 1); - forward(file->fp, file->file_name, style, off, &file->st); - if (Fflag && fileno(file->fp) != STDIN_FILENO) - n++; - } + for (i = 0, file = files; i < no_files; i++, file++) { + if (!file->fp) + continue; + active = 1; + if (vflag || (qflag == 0 && no_files > 1)) + printfn(file->file_name, 1); + forward(file->fp, file->file_name, style, off, &file->st); } if (!Fflag && !active) return; @@ -337,9 +331,14 @@ kq = kqueue(); if (kq < 0) err(1, "kqueue"); - ev = malloc(n * sizeof(struct kevent)); - if (! ev) - err(1, "Couldn't allocate memory for kevents."); + /* + * The number of kqueue events we track may vary over time and may + * even grow past its initial value in the -F case, but it will + * never exceed two per file, so just preallocate that. + */ + ev = malloc(no_files * 2 * sizeof(struct kevent)); + if (ev == NULL) + err(1, "Couldn't allocate memory for kevents."); set_events(files); for (;;) { @@ -413,9 +412,7 @@ */ do { n = kevent(kq, NULL, 0, ev, 1, Fflag ? &ts : NULL); - if (n < 0 && errno == EINTR) - continue; - if (n < 0) + if (n < 0 && errno != EINTR) err(1, "kevent"); } while (n < 0); if (n == 0) { diff --git a/usr.bin/tail/tests/tail_test.sh b/usr.bin/tail/tests/tail_test.sh --- a/usr.bin/tail/tests/tail_test.sh +++ b/usr.bin/tail/tests/tail_test.sh @@ -329,10 +329,28 @@ atf_check kill $pid } +atf_test_case follow_create +follow_create_head() +{ + atf_set "descr" "Verify that -F works when a file is created" +} +follow_create_body() +{ + local pid + + rm -f infile + tail -F infile > outfile & + pid=$! + seq 1 5 >infile + sleep 2 + atf_check cmp infile outfile + atf_check kill $pid +} + atf_test_case follow_rename follow_rename_head() { - atf_set "descr" "Verify that -F works" + atf_set "descr" "Verify that -F works when a file is replaced" } follow_rename_body() { @@ -424,6 +442,7 @@ atf_add_test_case stdin atf_add_test_case follow atf_add_test_case follow_stdin + atf_add_test_case follow_create atf_add_test_case follow_rename atf_add_test_case silent_header atf_add_test_case verbose_header