Bug 19536

Summary: patch to prevent head'ing directories
Product: Base System Reporter: kbyanc <kbyanc>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.0-STABLE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description kbyanc 2000-06-27 01:50:00 UTC
	Similar to my previous PR (19514), except this patch affects
	head(1) rather than tail(1). Otherwise it is identical. This patch
	is made again -current head.c.

How-To-Repeat: 
	head .
Comment 1 kbyanc 2000-06-27 06:34:47 UTC
  Attached is a more correct patch, please apply it instead. Thanks,

  Kelly

Index: usr.bin/head/head.c
===================================================================
RCS file: /home/cvs/src/usr.bin/head/head.c,v
retrieving revision 1.10
diff -u -r1.10 head.c
--- usr.bin/head/head.c	1999/08/28 01:01:58	1.10
+++ usr.bin/head/head.c	2000/06/27 05:25:44
@@ -45,6 +45,7 @@
   "$FreeBSD: src/usr.bin/head/head.c,v 1.10 1999/08/28 01:01:58 peter Exp $";
 #endif /* not lint */
 
+#include <sys/stat.h>
 #include <sys/types.h>
 
 #include <ctype.h>
@@ -73,6 +74,7 @@
 	char *argv[];
 {
 	register int ch;
+	struct stat sb;
 	FILE *fp;
 	int first, linecnt = -1, bytecnt = -1;
 	char *ep;
@@ -103,11 +105,22 @@
 		linecnt = 10;
 	if (*argv) {
 		for (first = 1; *argv; ++argv) {
-			if ((fp = fopen(*argv, "r")) == NULL) {
+			if ((fp = fopen(*argv, "r")) == NULL ||
+			    fstat(fileno(fp), &sb)) {
 				warn("%s", *argv);
 				eval = 1;
 				continue;
 			}
+			if (S_ISDIR(sb.st_mode))
+				errx(1, "%s is a directory", *argv);
+			if (S_ISLNK(sb.st_mode))
+				/* This should transparently be resolved and
+				 * thus never happen.
+				 */
+				errx(1, "%s is a symlink", *argv);
+			if (S_ISWHT(sb.st_mode))
+				/* This should never happen. */
+				errx(1, "%s is a whiteout entry", *argv);
 			if (argc > 1) {
 				(void)printf("%s==> %s <==\n",
 				    first ? "" : "\n", *argv);
Comment 2 kbyanc 2000-06-29 00:41:47 UTC
  Update to patch in response to comments from BDE.

  -Kelly

Index: usr.bin/head/head.c
===================================================================
RCS file: /home/cvs/src/usr.bin/head/head.c,v
retrieving revision 1.10
diff -u -r1.10 head.c
--- usr.bin/head/head.c	1999/08/28 01:01:58	1.10
+++ usr.bin/head/head.c	2000/06/28 23:36:45
@@ -45,6 +45,7 @@
   "$FreeBSD: src/usr.bin/head/head.c,v 1.10 1999/08/28 01:01:58 peter Exp $";
 #endif /* not lint */
 
+#include <sys/stat.h>
 #include <sys/types.h>
 
 #include <ctype.h>
@@ -73,8 +74,9 @@
 	char *argv[];
 {
 	register int ch;
+        struct stat sb;
 	FILE *fp;
-	int first, linecnt = -1, bytecnt = -1;
+	int first, linecnt = -1, bytecnt = -1, num = 0;
 	char *ep;
 
 	obsolete(argv);
@@ -103,12 +105,24 @@
 		linecnt = 10;
 	if (*argv) {
 		for (first = 1; *argv; ++argv) {
-			if ((fp = fopen(*argv, "r")) == NULL) {
+			if ((fp = fopen(*argv, "r")) == NULL ||
+			    fstat(fileno(fp), &sb)) {
 				warn("%s", *argv);
 				eval = 1;
 				continue;
 			}
-			if (argc > 1) {
+			if (S_ISDIR(sb.st_mode)) {
+				warnx("%s is a directory", *argv);
+				continue;
+			} else if (S_ISLNK(sb.st_mode)) {
+				warnx("%s is a symlink", *argv);
+				continue;
+			} else if (S_ISWHT(sb.st_mode)) {
+				warnx("%s is a whiteout entry", *argv);
+				continue;
+			}
+			num++;
+			if (num > 1) {
 				(void)printf("%s==> %s <==\n",
 				    first ? "" : "\n", *argv);
 				first = 0;
Comment 3 Jens Schweikhardt freebsd_committer freebsd_triage 2001-06-14 14:11:18 UTC
State Changed
From-To: open->closed

We think that it's better to stick to the WYGIWYAF principle 
(what you get is what you asked for). As bde points out, 
why should "tail /" not do the same thing as "cat / | tail"?