summaryrefslogtreecommitdiffstats
path: root/usr.sbin/fstyp/fstyp.c
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2015-01-20 20:39:29 +0000
committertrasz <trasz@FreeBSD.org>2015-01-20 20:39:29 +0000
commit0638ccbfc6cc8bfa31852aa15bc3c7e15bc40406 (patch)
tree8f48ce245679198d9b1f16d6c998c0b60806e91d /usr.sbin/fstyp/fstyp.c
parenta20136a3031bbdcb96276992b5f185c751668636 (diff)
downloadFreeBSD-src-0638ccbfc6cc8bfa31852aa15bc3c7e15bc40406.zip
FreeBSD-src-0638ccbfc6cc8bfa31852aa15bc3c7e15bc40406.tar.gz
MFC r275680:
Add fstyp(8). This utility, named after its SVR4 counterpart, detects filesystems. It differs from file(1) in that it gives machine-parseable output, it outputs filesystem labels, doesn't get confused by other formats metadata, and runs in Capsicum sandbox. Differential Revision: https://reviews.freebsd.org/D1255 Relnotes: yes Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'usr.sbin/fstyp/fstyp.c')
-rw-r--r--usr.sbin/fstyp/fstyp.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/usr.sbin/fstyp/fstyp.c b/usr.sbin/fstyp/fstyp.c
new file mode 100644
index 0000000..b3bdcde
--- /dev/null
+++ b/usr.sbin/fstyp/fstyp.c
@@ -0,0 +1,210 @@
+/*-
+ * Copyright (c) 2014 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Edward Tomasz Napierala under sponsorship
+ * from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/capability.h>
+#include <sys/disk.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <vis.h>
+
+#include "fstyp.h"
+
+#define LABEL_LEN 256
+
+typedef int (*fstyp_function)(FILE *, char *, size_t);
+
+static struct {
+ const char *name;
+ fstyp_function function;
+} fstypes[] = {
+ { "cd9660", &fstyp_cd9660 },
+ { "ext2fs", &fstyp_ext2fs },
+ { "msdosfs", &fstyp_msdosfs },
+ { "ntfs", &fstyp_ntfs },
+ { "ufs", &fstyp_ufs },
+ { NULL, NULL }
+};
+
+void *
+read_buf(FILE *fp, off_t off, size_t len)
+{
+ int error;
+ size_t nread;
+ void *buf;
+
+ error = fseek(fp, off, SEEK_SET);
+ if (error != 0) {
+ warn("cannot seek to %jd", (uintmax_t)off);
+ return (NULL);
+ }
+
+ buf = malloc(len);
+ if (buf == 0) {
+ warn("cannot malloc %zd bytes of memory", len);
+ return (NULL);
+ }
+
+ nread = fread(buf, len, 1, fp);
+ if (nread != 1) {
+ free(buf);
+ if (feof(fp) == 0)
+ warn("fread");
+ return (NULL);
+ }
+
+ return (buf);
+}
+
+char *
+checked_strdup(const char *s)
+{
+ char *c;
+
+ c = strdup(s);
+ if (c == NULL)
+ err(1, "strdup");
+ return (c);
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: fstyp [-l][-s] special\n");
+ exit(1);
+}
+
+static void
+type_check(const char *path, FILE *fp)
+{
+ int error, fd;
+ off_t mediasize;
+ struct stat sb;
+
+ fd = fileno(fp);
+
+ error = fstat(fd, &sb);
+ if (error != 0)
+ err(1, "%s: fstat", path);
+
+ if (S_ISREG(sb.st_mode))
+ return;
+
+ error = ioctl(fd, DIOCGMEDIASIZE, &mediasize);
+ if (error != 0)
+ errx(1, "%s: not a disk", path);
+}
+
+int
+main(int argc, char **argv)
+{
+ int ch, error, i, nbytes;
+ bool ignore_type = false, show_label = false;
+ char label[LABEL_LEN + 1], strvised[LABEL_LEN * 4 + 1];
+ char *path;
+ FILE *fp;
+ fstyp_function fstyp_f;
+
+ while ((ch = getopt(argc, argv, "ls")) != -1) {
+ switch (ch) {
+ case 'l':
+ show_label = true;
+ break;
+ case 's':
+ ignore_type = true;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+ if (argc != 1)
+ usage();
+
+ path = argv[0];
+
+ fp = fopen(path, "r");
+ if (fp == NULL)
+ err(1, "%s", path);
+
+ error = cap_enter();
+ if (error != 0 && errno != ENOSYS)
+ err(1, "cap_enter");
+
+ if (ignore_type == false)
+ type_check(path, fp);
+
+ memset(label, '\0', sizeof(label));
+
+ for (i = 0;; i++) {
+ fstyp_f = fstypes[i].function;
+ if (fstyp_f == NULL)
+ break;
+
+ error = fstyp_f(fp, label, sizeof(label));
+ if (error == 0)
+ break;
+ }
+
+ if (fstypes[i].name == NULL) {
+ warnx("%s: filesystem not recognized", path);
+ return (1);
+ }
+
+ if (show_label && label[0] != '\0') {
+ /*
+ * XXX: I'd prefer VIS_HTTPSTYLE, but it unconditionally
+ * encodes spaces.
+ */
+ nbytes = strsnvis(strvised, sizeof(strvised), label,
+ VIS_GLOB | VIS_NL, "\"'$");
+ if (nbytes == -1)
+ err(1, "strsnvis");
+
+ printf("%s %s\n", fstypes[i].name, strvised);
+ } else {
+ printf("%s\n", fstypes[i].name);
+ }
+
+ return (0);
+}
OpenPOWER on IntegriCloud