svn commit: r193488 - head/usr.bin/tail

Brian Somers brian at FreeBSD.org
Fri Jun 5 09:08:55 UTC 2009


Author: brian
Date: Fri Jun  5 09:08:53 2009
New Revision: 193488
URL: http://svn.freebsd.org/changeset/base/193488

Log:
  Change the behaviour of -F slightly; it now persists (forever) in
  trying to open files rather than giving up when it encounters an
  error.  ENOENT errors are not reported.
  
  As a result, files that are moved away then recreated are not at
  risk of being 'lost' to tail.  Files that are recreated and
  temporarily have unreadable permissions will be shown when they
  are fixed.
  
  This behaviour is consistent with the GNU version of tail but
  without the verbiage that goes with the GNU version.
  
  This change also fixes error messages accompanying -f and -F.
  They no longer report problems with (null)!
  
  MFC after:	3 weeks

Modified:
  head/usr.bin/tail/extern.h
  head/usr.bin/tail/forward.c
  head/usr.bin/tail/misc.c
  head/usr.bin/tail/read.c
  head/usr.bin/tail/reverse.c
  head/usr.bin/tail/tail.1
  head/usr.bin/tail/tail.c

Modified: head/usr.bin/tail/extern.h
==============================================================================
--- head/usr.bin/tail/extern.h	Fri Jun  5 08:37:11 2009	(r193487)
+++ head/usr.bin/tail/extern.h	Fri Jun  5 09:08:53 2009	(r193488)
@@ -61,16 +61,15 @@ typedef struct file_info file_info_t;
 enum STYLE { NOTSET = 0, FBYTES, FLINES, RBYTES, RLINES, REVERSE };
 
 void follow(file_info_t *, enum STYLE, off_t);
-void forward(FILE *, enum STYLE, off_t, struct stat *);
-void reverse(FILE *, enum STYLE, off_t, struct stat *);
+void forward(FILE *, const char *, enum STYLE, off_t, struct stat *);
+void reverse(FILE *, const char *, enum STYLE, off_t, struct stat *);
 
-int bytes(FILE *, off_t);
-int lines(FILE *, off_t);
+int bytes(FILE *, const char *, off_t);
+int lines(FILE *, const char *, off_t);
 
-void ierr(void);
+void ierr(const char *);
 void oerr(void);
 int mapprint(struct mapinfo *, off_t, off_t);
 int maparound(struct mapinfo *, off_t);
 
 extern int Fflag, fflag, qflag, rflag, rval, no_files;
-extern const char *fname;

Modified: head/usr.bin/tail/forward.c
==============================================================================
--- head/usr.bin/tail/forward.c	Fri Jun  5 08:37:11 2009	(r193487)
+++ head/usr.bin/tail/forward.c	Fri Jun  5 09:08:53 2009	(r193488)
@@ -61,8 +61,8 @@ static const char sccsid[] = "@(#)forwar
 
 #include "extern.h"
 
-static void rlines(FILE *, off_t, struct stat *);
-static void show(file_info_t *);
+static void rlines(FILE *, const char *fn, off_t, struct stat *);
+static int show(file_info_t *);
 static void set_events(file_info_t *files);
 
 /* defines for inner loop actions */
@@ -99,7 +99,7 @@ static const file_info_t *last;
  *	NOREG	cyclically read lines into a wrap-around array of buffers
  */
 void
-forward(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
+forward(FILE *fp, const char *fn, enum STYLE style, off_t off, struct stat *sbp)
 {
 	int ch;
 
@@ -111,13 +111,13 @@ forward(FILE *fp, enum STYLE style, off_
 			if (sbp->st_size < off)
 				off = sbp->st_size;
 			if (fseeko(fp, off, SEEK_SET) == -1) {
-				ierr();
+				ierr(fn);
 				return;
 			}
 		} else while (off--)
 			if ((ch = getc(fp)) == EOF) {
 				if (ferror(fp)) {
-					ierr();
+					ierr(fn);
 					return;
 				}
 				break;
@@ -129,7 +129,7 @@ forward(FILE *fp, enum STYLE style, off_
 		for (;;) {
 			if ((ch = getc(fp)) == EOF) {
 				if (ferror(fp)) {
-					ierr();
+					ierr(fn);
 					return;
 				}
 				break;
@@ -142,36 +142,36 @@ forward(FILE *fp, enum STYLE style, off_
 		if (S_ISREG(sbp->st_mode)) {
 			if (sbp->st_size >= off &&
 			    fseeko(fp, -off, SEEK_END) == -1) {
-				ierr();
+				ierr(fn);
 				return;
 			}
 		} else if (off == 0) {
 			while (getc(fp) != EOF);
 			if (ferror(fp)) {
-				ierr();
+				ierr(fn);
 				return;
 			}
 		} else
-			if (bytes(fp, off))
+			if (bytes(fp, fn, off))
 				return;
 		break;
 	case RLINES:
 		if (S_ISREG(sbp->st_mode))
 			if (!off) {
 				if (fseeko(fp, (off_t)0, SEEK_END) == -1) {
-					ierr();
+					ierr(fn);
 					return;
 				}
 			} else
-				rlines(fp, off, sbp);
+				rlines(fp, fn, off, sbp);
 		else if (off == 0) {
 			while (getc(fp) != EOF);
 			if (ferror(fp)) {
-				ierr();
+				ierr(fn);
 				return;
 			}
 		} else
-			if (lines(fp, off))
+			if (lines(fp, fn, off))
 				return;
 		break;
 	default:
@@ -182,7 +182,7 @@ forward(FILE *fp, enum STYLE style, off_
 		if (putchar(ch) == EOF)
 			oerr();
 	if (ferror(fp)) {
-		ierr();
+		ierr(fn);
 		return;
 	}
 	(void)fflush(stdout);
@@ -192,10 +192,7 @@ forward(FILE *fp, enum STYLE style, off_
  * rlines -- display the last offset lines of the file.
  */
 static void
-rlines(fp, off, sbp)
-	FILE *fp;
-	off_t off;
-	struct stat *sbp;
+rlines(FILE *fp, const char *fn, off_t off, struct stat *sbp)
 {
 	struct mapinfo map;
 	off_t curoff, size;
@@ -214,7 +211,7 @@ rlines(fp, off, sbp)
 	curoff = size - 2;
 	while (curoff >= 0) {
 		if (curoff < map.mapoff && maparound(&map, curoff) != 0) {
-			ierr();
+			ierr(fn);
 			return;
 		}
 		for (i = curoff - map.mapoff; i >= 0; i--)
@@ -227,41 +224,44 @@ rlines(fp, off, sbp)
 	}
 	curoff++;
 	if (mapprint(&map, curoff, size - curoff) != 0) {
-		ierr();
+		ierr(fn);
 		exit(1);
 	}
 
 	/* Set the file pointer to reflect the length displayed. */
 	if (fseeko(fp, sbp->st_size, SEEK_SET) == -1) {
-		ierr();
+		ierr(fn);
 		return;
 	}
 	if (map.start != NULL && munmap(map.start, map.maplen)) {
-		ierr();
+		ierr(fn);
 		return;
 	}
 }
 
-static void
+static int
 show(file_info_t *file)
 {
-    int ch;
+	int ch;
 
-    while ((ch = getc(file->fp)) != EOF) {
-	if (last != file && no_files > 1) {
-		if (!qflag)
-			(void)printf("\n==> %s <==\n", file->file_name);
-		last = file;
-	}
-	if (putchar(ch) == EOF)
-		oerr();
-    }
-    (void)fflush(stdout);
-    if (ferror(file->fp)) {
-	    file->fp = NULL;
-	    ierr();
-    } else
-	    clearerr(file->fp);
+	while ((ch = getc(file->fp)) != EOF) {
+		if (last != file && no_files > 1) {
+			if (!qflag)
+				(void)printf("\n==> %s <==\n", file->file_name);
+			last = file;
+		}
+		if (putchar(ch) == EOF)
+			oerr();
+	}
+	(void)fflush(stdout);
+	if (ferror(file->fp)) {
+		fclose(file->fp);
+		file->fp = NULL;
+		ierr(file->file_name);
+		return 0;
+	}
+	clearerr(file->fp);
+	return 1;
 }
 
 static void
@@ -309,7 +309,7 @@ set_events(file_info_t *files)
 void
 follow(file_info_t *files, enum STYLE style, off_t off)
 {
-	int active, i, n = -1;
+	int active, ev_change, i, n = -1;
 	struct stat sb2;
 	file_info_t *file;
 	struct timespec ts;
@@ -325,12 +325,12 @@ follow(file_info_t *files, enum STYLE st
 			n++;
 			if (no_files > 1 && !qflag)
 				(void)printf("\n==> %s <==\n", file->file_name);
-			forward(file->fp, style, off, &file->st);
+			forward(file->fp, file->file_name, style, off, &file->st);
 			if (Fflag && fileno(file->fp) != STDIN_FILENO)
-			    n++;
+				n++;
 		}
 	}
-	if (! active)
+	if (!Fflag && !active)
 		return;
 
 	last = --file;
@@ -344,28 +344,56 @@ follow(file_info_t *files, enum STYLE st
 	set_events(files);
 
 	for (;;) {
-		for (i = 0, file = files; i < no_files; i++, file++) {
-			if (! file->fp)
-				continue;
-			if (Fflag && file->fp && fileno(file->fp) != STDIN_FILENO) {
-				if (stat(file->file_name, &sb2) == 0 &&
-				    (sb2.st_ino != file->st.st_ino ||
-				     sb2.st_dev != file->st.st_dev ||
-				     sb2.st_nlink == 0)) {
-					show(file);
-					file->fp = freopen(file->file_name, "r", file->fp);
-					if (file->fp == NULL) {
-						ierr();
-						continue;
-					} else {
-						memcpy(&file->st, &sb2, sizeof(struct stat));
-						set_events(files);
+		ev_change = 0;
+		if (Fflag) {
+			for (i = 0, file = files; i < no_files; i++, file++) {
+				if (!file->fp) {
+					file->fp = fopen(file->file_name, "r");
+					if (file->fp != NULL &&
+					    fstat(fileno(file->fp), &file->st)
+					    == -1) {
+						fclose(file->fp);
+						file->fp = NULL;
 					}
+					if (file->fp != NULL)
+						ev_change++;
+					continue;
+				}
+				if (fileno(file->fp) == STDIN_FILENO)
+					continue;
+				if (stat(file->file_name, &sb2) == -1) {
+					if (errno != ENOENT)
+						ierr(file->file_name);
+					show(file);
+					fclose(file->fp);
+					file->fp = NULL;
+					ev_change++;
+					continue;
+				}
+
+				if (sb2.st_ino != file->st.st_ino ||
+				    sb2.st_dev != file->st.st_dev ||
+				    sb2.st_nlink == 0) {
+					show(file);
+					file->fp = freopen(file->file_name, "r",
+					    file->fp);
+					if (file->fp != NULL)
+						memcpy(&file->st, &sb2,
+						    sizeof(struct stat));
+					else if (errno != ENOENT)
+						ierr(file->file_name);
+					ev_change++;
 				}
 			}
-			show(file);
 		}
 
+		for (i = 0, file = files; i < no_files; i++, file++)
+			if (file->fp && !show(file))
+				ev_change++;
+
+		if (ev_change)
+			set_events(files);
+
 		switch (action) {
 		case USE_KQUEUE:
 			ts.tv_sec = 1;
@@ -381,9 +409,9 @@ follow(file_info_t *files, enum STYLE st
 				/* timeout */
 				break;
 			} else if (ev->filter == EVFILT_READ && ev->data < 0) {
-				 /* file shrank, reposition to end */
+				/* file shrank, reposition to end */
 				if (lseek(ev->ident, (off_t)0, SEEK_END) == -1) {
-					ierr();
+					ierr(file->file_name);
 					continue;
 				}
 			}

Modified: head/usr.bin/tail/misc.c
==============================================================================
--- head/usr.bin/tail/misc.c	Fri Jun  5 08:37:11 2009	(r193487)
+++ head/usr.bin/tail/misc.c	Fri Jun  5 09:08:53 2009	(r193488)
@@ -56,7 +56,7 @@ static const char sccsid[] = "@(#)misc.c
 #include "extern.h"
 
 void
-ierr()
+ierr(const char *fname)
 {
 	warn("%s", fname);
 	rval = 1;

Modified: head/usr.bin/tail/read.c
==============================================================================
--- head/usr.bin/tail/read.c	Fri Jun  5 08:37:11 2009	(r193487)
+++ head/usr.bin/tail/read.c	Fri Jun  5 09:08:53 2009	(r193488)
@@ -66,7 +66,7 @@ static const char sccsid[] = "@(#)read.c
  * the end.
  */
 int
-bytes(FILE *fp, off_t off)
+bytes(FILE *fp, const char *fn, off_t off)
 {
 	int ch, len, tlen;
 	char *ep, *p, *t;
@@ -84,7 +84,7 @@ bytes(FILE *fp, off_t off)
 		}
 	}
 	if (ferror(fp)) {
-		ierr();
+		ierr(fn);
 		free(sp);
 		return 1;
 	}
@@ -136,7 +136,7 @@ bytes(FILE *fp, off_t off)
  * the end.
  */
 int
-lines(FILE *fp, off_t off)
+lines(FILE *fp, const char *fn, off_t off)
 {
 	struct {
 		int blen;
@@ -178,7 +178,7 @@ lines(FILE *fp, off_t off)
 		}
 	}
 	if (ferror(fp)) {
-		ierr();
+		ierr(fn);
 		rc = 1;
 		goto done;
 	}

Modified: head/usr.bin/tail/reverse.c
==============================================================================
--- head/usr.bin/tail/reverse.c	Fri Jun  5 08:37:11 2009	(r193487)
+++ head/usr.bin/tail/reverse.c	Fri Jun  5 09:08:53 2009	(r193488)
@@ -58,8 +58,8 @@ __FBSDID("$FreeBSD$");
 
 #include "extern.h"
 
-static void r_buf(FILE *);
-static void r_reg(FILE *, enum STYLE, off_t, struct stat *);
+static void r_buf(FILE *, const char *);
+static void r_reg(FILE *, const char *, enum STYLE, off_t, struct stat *);
 
 /*
  * reverse -- display input in reverse order by line.
@@ -80,25 +80,25 @@ static void r_reg(FILE *, enum STYLE, of
  *	NOREG	cyclically read input into a linked list of buffers
  */
 void
-reverse(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
+reverse(FILE *fp, const char *fn, enum STYLE style, off_t off, struct stat *sbp)
 {
 	if (style != REVERSE && off == 0)
 		return;
 
 	if (S_ISREG(sbp->st_mode))
-		r_reg(fp, style, off, sbp);
+		r_reg(fp, fn, style, off, sbp);
 	else
 		switch(style) {
 		case FBYTES:
 		case RBYTES:
-			bytes(fp, off);
+			bytes(fp, fn, off);
 			break;
 		case FLINES:
 		case RLINES:
-			lines(fp, off);
+			lines(fp, fn, off);
 			break;
 		case REVERSE:
-			r_buf(fp);
+			r_buf(fp, fn);
 			break;
 		default:
 			break;
@@ -109,7 +109,7 @@ reverse(FILE *fp, enum STYLE style, off_
  * r_reg -- display a regular file in reverse order by line.
  */
 static void
-r_reg(FILE *fp, enum STYLE style, off_t off, struct stat *sbp)
+r_reg(FILE *fp, const char *fn, enum STYLE style, off_t off, struct stat *sbp)
 {
 	struct mapinfo map;
 	off_t curoff, size, lineend;
@@ -132,7 +132,7 @@ r_reg(FILE *fp, enum STYLE style, off_t 
 		if (curoff < map.mapoff ||
 		    curoff >= map.mapoff + (off_t)map.maplen) {
 			if (maparound(&map, curoff) != 0) {
-				ierr();
+				ierr(fn);
 				return;
 			}
 		}
@@ -149,7 +149,7 @@ r_reg(FILE *fp, enum STYLE style, off_t 
 
 		/* Print the line and update offsets. */
 		if (mapprint(&map, curoff + 1, lineend - curoff - 1) != 0) {
-			ierr();
+			ierr(fn);
 			return;
 		}
 		lineend = curoff + 1;
@@ -165,11 +165,11 @@ r_reg(FILE *fp, enum STYLE style, off_t 
 		}
 	}
 	if (curoff < 0 && mapprint(&map, 0, lineend) != 0) {
-		ierr();
+		ierr(fn);
 		return;
 	}
 	if (map.start != NULL && munmap(map.start, map.maplen))
-		ierr();
+		ierr(fn);
 }
 
 typedef struct bf {
@@ -190,7 +190,7 @@ typedef struct bf {
  * user warned).
  */
 static void
-r_buf(FILE *fp)
+r_buf(FILE *fp, const char *fn)
 {
 	BF *mark, *tl, *tr;
 	int ch, len, llen;
@@ -227,7 +227,7 @@ r_buf(FILE *fp)
 			*p++ = ch;
 
 		if (ferror(fp)) {
-			ierr();
+			ierr(fn);
 			return;
 		}
 

Modified: head/usr.bin/tail/tail.1
==============================================================================
--- head/usr.bin/tail/tail.1	Fri Jun  5 08:37:11 2009	(r193487)
+++ head/usr.bin/tail/tail.1	Fri Jun  5 09:08:53 2009	(r193488)
@@ -35,7 +35,7 @@
 .\"	@(#)tail.1	8.1 (Berkeley) 6/6/93
 .\" $FreeBSD$
 .\"
-.Dd June 29, 2006
+.Dd June 05, 2009
 .Dt TAIL 1
 .Os
 .Sh NAME
@@ -106,9 +106,16 @@ will also check to see if the file being
 The file is closed and reopened when
 .Nm
 detects that the filename being read from has a new inode number.
+.Pp
+If the file being followed does not (yet) exist or if it is removed, tail
+will keep looking and will display the file from the beginning if and when
+it is created.
+.Pp
 The
 .Fl F
-option is ignored if reading from standard input rather than a file.
+option is the same as the
+.Fl f
+option if reading from standard input rather than a file.
 .It Fl n Ar number
 The location is
 .Ar number

Modified: head/usr.bin/tail/tail.c
==============================================================================
--- head/usr.bin/tail/tail.c	Fri Jun  5 08:37:11 2009	(r193487)
+++ head/usr.bin/tail/tail.c	Fri Jun  5 09:08:53 2009	(r193488)
@@ -61,7 +61,6 @@ static const char sccsid[] = "@(#)tail.c
 #include "extern.h"
 
 int Fflag, fflag, qflag, rflag, rval, no_files;
-const char *fname;
 
 file_info_t *files;
 
@@ -72,6 +71,7 @@ int
 main(int argc, char *argv[])
 {
 	struct stat sb;
+	const char *fn;
 	FILE *fp;
 	off_t off;
 	enum STYLE style;
@@ -175,20 +175,23 @@ main(int argc, char *argv[])
 	}
 
 	if (*argv && fflag) {
-		files = (struct file_info *) malloc(no_files * sizeof(struct file_info));
-		if (! files)
+		files = (struct file_info *) malloc(no_files *
+		    sizeof(struct file_info));
+		if (!files)
 			err(1, "Couldn't malloc space for file descriptors.");
 
-		for (file = files; (fname = *argv++); file++) {
-			file->file_name = malloc(strlen(fname)+1);
+		for (file = files; (fn = *argv++); file++) {
+			file->file_name = strdup(fn);
 			if (! file->file_name)
 				errx(1, "Couldn't malloc space for file name.");
-			strncpy(file->file_name, fname, strlen(fname)+1);
 			if ((file->fp = fopen(file->file_name, "r")) == NULL ||
 			    fstat(fileno(file->fp), &file->st)) {
-				file->fp = NULL;
-				ierr();
-				continue;
+				if (file->fp != NULL) {
+					fclose(file->fp);
+					file->fp = NULL;
+				}
+				if (!Fflag || errno != ENOENT)
+					ierr(file->file_name);
 			}
 		}
 		follow(files, style, off);
@@ -197,29 +200,29 @@ main(int argc, char *argv[])
 		}
 		free(files);
 	} else if (*argv) {
-		for (first = 1; (fname = *argv++);) {
-			if ((fp = fopen(fname, "r")) == NULL ||
+		for (first = 1; (fn = *argv++);) {
+			if ((fp = fopen(fn, "r")) == NULL ||
 			    fstat(fileno(fp), &sb)) {
-				ierr();
+				ierr(fn);
 				continue;
 			}
 			if (argc > 1 && !qflag) {
 				(void)printf("%s==> %s <==\n",
-				    first ? "" : "\n", fname);
+				    first ? "" : "\n", fn);
 				first = 0;
 				(void)fflush(stdout);
 			}
 
 			if (rflag)
-				reverse(fp, style, off, &sb);
+				reverse(fp, fn, style, off, &sb);
 			else
-				forward(fp, style, off, &sb);
+				forward(fp, fn, style, off, &sb);
 		}
 	} else {
-		fname = "stdin";
+		fn = "stdin";
 
 		if (fstat(fileno(stdin), &sb)) {
-			ierr();
+			ierr(fn);
 			exit(1);
 		}
 
@@ -234,9 +237,9 @@ main(int argc, char *argv[])
 		}
 
 		if (rflag)
-			reverse(stdin, style, off, &sb);
+			reverse(stdin, fn, style, off, &sb);
 		else
-			forward(stdin, style, off, &sb);
+			forward(stdin, fn, style, off, &sb);
 	}
 	exit(rval);
 }


More information about the svn-src-head mailing list