From 128fddab7306e4ffba80133d49468e39cbd5a6ef Mon Sep 17 00:00:00 2001
From: Reuben Thomas <rrt@sc3d.org>
Date: Fri, 25 Jul 2008 23:59:01 +0000
Subject: [PATCH] Have finer-grained pseudo-MIME types for non-regular files.

---
 src/fsmagic.c | 130 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 84 insertions(+), 46 deletions(-)

diff --git a/src/fsmagic.c b/src/fsmagic.c
index 4bb62dc0..4b94baf3 100644
--- a/src/fsmagic.c
+++ b/src/fsmagic.c
@@ -57,23 +57,30 @@
 #undef HAVE_MAJOR
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: fsmagic.c,v 1.50 2008/02/12 17:22:54 rrt Exp $")
+FILE_RCSID("@(#)$File: fsmagic.c,v 1.51 2008/05/09 14:20:28 christos Exp $")
 #endif	/* lint */
 
 private int
 bad_link(struct magic_set *ms, int err, char *buf)
 {
 	const char *errfmt;
-	if (err == ELOOP)
-		errfmt = "symbolic link in a loop";
-	else
-		errfmt = "broken symbolic link to `%s'";
-	if (ms->flags & MAGIC_ERROR) {
-		file_error(ms, err, errfmt, buf);
-		return -1;
-	} 
-	if (file_printf(ms, errfmt, buf) == -1)
+	int mime = ms->flags & MAGIC_MIME;
+	if ((mime & MAGIC_MIME_TYPE) &&
+	    file_printf(ms, "application/x-symlink")
+	    == -1)
 		return -1;
+	else if (!mime) {
+		if (err == ELOOP)
+			errfmt = "symbolic link in a loop";
+		else
+			errfmt = "broken symbolic link to `%s'";
+		if (ms->flags & MAGIC_ERROR) {
+			file_error(ms, err, errfmt, buf);
+			return -1;
+		} 
+		if (file_printf(ms, errfmt, buf) == -1)
+			return -1;
+	}
 	return 1;
 }
 
@@ -113,16 +120,7 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
 		return 1;
 	}
 
-	if (mime) {
-		if ((sb->st_mode & S_IFMT) != S_IFREG) {
-			if ((mime & MAGIC_MIME_TYPE) &&
-			    file_printf(ms, "application/x-not-regular-file")
-			    == -1)
-				    return -1;
-			return 1;
-		}
-	}
-	else {
+	if (!mime) {
 #ifdef S_ISUID
 		if (sb->st_mode & S_ISUID) 
 			if (file_printf(ms, "setuid ") == -1)
@@ -142,7 +140,11 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
 	
 	switch (sb->st_mode & S_IFMT) {
 	case S_IFDIR:
-		if (file_printf(ms, "directory") == -1)
+		if ((mime & MAGIC_MIME_TYPE) &&
+		    file_printf(ms, "application/x-directory")
+		    == -1)
+			return -1;
+		if (!mime && file_printf(ms, "directory") == -1)
 			return -1;
 		return 1;
 #ifdef S_IFCHR
@@ -154,21 +156,27 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
 		 */
 		if ((ms->flags & MAGIC_DEVICES) != 0)
 			break;
+		if ((mime & MAGIC_MIME_TYPE) &&
+		    file_printf(ms, "application/x-character-device")
+		    == -1)
+			return -1;
+		if (!mime) {
 #ifdef HAVE_STAT_ST_RDEV
 # ifdef dv_unit
-		if (file_printf(ms, "character special (%d/%d/%d)",
-		    major(sb->st_rdev), dv_unit(sb->st_rdev),
-		    dv_subunit(sb->st_rdev)) == -1)
-			return -1;
+			if (file_printf(ms, "character special (%d/%d/%d)",
+					major(sb->st_rdev), dv_unit(sb->st_rdev),
+					dv_subunit(sb->st_rdev)) == -1)
+				return -1;
 # else
-		if (file_printf(ms, "character special (%ld/%ld)",
-		    (long) major(sb->st_rdev), (long) minor(sb->st_rdev)) == -1)
-			return -1;
+			if (file_printf(ms, "character special (%ld/%ld)",
+					(long) major(sb->st_rdev), (long) minor(sb->st_rdev)) == -1)
+				return -1;
 # endif
 #else
-		if (file_printf(ms, "character special") == -1)
-			return -1;
+			if (file_printf(ms, "character special") == -1)
+				return -1;
 #endif
+		}
 		return 1;
 #endif
 #ifdef S_IFBLK
@@ -180,21 +188,27 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
 		 */
 		if ((ms->flags & MAGIC_DEVICES) != 0)
 			break;
+		if ((mime & MAGIC_MIME_TYPE) &&
+		    file_printf(ms, "application/x-block-device")
+		    == -1)
+			return -1;
+		if (!mime) {
 #ifdef HAVE_STAT_ST_RDEV
 # ifdef dv_unit
-		if (file_printf(ms, "block special (%d/%d/%d)",
-		    major(sb->st_rdev), dv_unit(sb->st_rdev),
-		    dv_subunit(sb->st_rdev)) == -1)
-			return -1;
+			if (file_printf(ms, "block special (%d/%d/%d)",
+					major(sb->st_rdev), dv_unit(sb->st_rdev),
+					dv_subunit(sb->st_rdev)) == -1)
+				return -1;
 # else
-		if (file_printf(ms, "block special (%ld/%ld)",
-		    (long)major(sb->st_rdev), (long)minor(sb->st_rdev)) == -1)
-			return -1;
+			if (file_printf(ms, "block special (%ld/%ld)",
+					(long)major(sb->st_rdev), (long)minor(sb->st_rdev)) == -1)
+				return -1;
 # endif
 #else
-		if (file_printf(ms, "block special") == -1)
-			return -1;
+			if (file_printf(ms, "block special") == -1)
+				return -1;
 #endif
+		}
 		return 1;
 #endif
 	/* TODO add code to handle V7 MUX and Blit MUX files */
@@ -202,13 +216,21 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
 	case S_IFIFO:
 		if((ms->flags & MAGIC_DEVICES) != 0)
 			break;
-		if (file_printf(ms, "fifo (named pipe)") == -1)
+		if ((mime & MAGIC_MIME_TYPE) &&
+		    file_printf(ms, "application/x-fifo")
+		    == -1)
+			return -1;
+		if (!mime && file_printf(ms, "fifo (named pipe)") == -1)
 			return -1;
 		return 1;
 #endif
 #ifdef	S_IFDOOR
 	case S_IFDOOR:
-		if (file_printf(ms, "door") == -1)
+		if ((mime & MAGIC_MIME_TYPE) &&
+		    file_printf(ms, "application/x-door")
+		    == -1)
+			return -1;
+		if (!mime && file_printf(ms, "door") == -1)
 			return -1;
 		return 1;
 #endif
@@ -220,7 +242,11 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
 				fn);
 			    return -1;
 			}
-			if (file_printf(ms,
+			if ((mime & MAGIC_MIME_TYPE) &&
+			    file_printf(ms, "application/x-symlink")
+			    == -1)
+				return -1;
+			if (!mime && file_printf(ms,
 			    "unreadable symlink `%s' (%s)", fn,
 			    strerror(errno)) == -1)
 				return -1;
@@ -245,7 +271,11 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
 						    "path too long: `%s'", buf);
 						return -1;
 					}
-					if (file_printf(ms,
+					if ((mime & MAGIC_MIME_TYPE) &&
+					    file_printf(ms, "application/x-path-too-long")
+					    == -1)
+						return -1;
+					if (!mime && file_printf(ms,
 					    "path too long: `%s'", fn) == -1)
 						return -1;
 					return 1;
@@ -267,16 +297,24 @@ file_fsmagic(struct magic_set *ms, const char *fn, struct stat *sb)
 			ms->flags |= MAGIC_SYMLINK;
 			return p != NULL ? 1 : -1;
 		} else { /* just print what it points to */
-			if (file_printf(ms, "symbolic link to `%s'",
+			if ((mime & MAGIC_MIME_TYPE) &&
+			    file_printf(ms, "application/x-symlink")
+			    == -1)
+				return -1;
+			if (!mime && file_printf(ms, "symbolic link to `%s'",
 			    buf) == -1)
 				return -1;
 		}
-	return 1;
+		return 1;
 #endif
 #ifdef	S_IFSOCK
 #ifndef __COHERENT__
 	case S_IFSOCK:
-		if (file_printf(ms, "socket") == -1)
+		if ((mime & MAGIC_MIME_TYPE) &&
+		    file_printf(ms, "application/x-socket")
+		    == -1)
+			return -1;
+		if (!mime && file_printf(ms, "socket") == -1)
 			return -1;
 		return 1;
 #endif
-- 
2.40.0