int main(int argc, char *argv[]) { struct fstab *fs; int i, rval = 0; char *vfstype = NULL; char *p, globopt[3]; struct rlimit rl; /* Increase our data size to the max */ if (getrlimit(RLIMIT_DATA, &rl) == 0) { if (geteuid() == 0) rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; else rl.rlim_cur = rl.rlim_max; if (setrlimit(RLIMIT_DATA, &rl) < 0) warn("Can't get resource limit to max data size"); } else warn("Can't get resource limit for data size"); globopt[0] = '-'; globopt[2] = '\0'; TAILQ_INIT(&selhead); TAILQ_INIT(&opthead); while ((i = getopt(argc, argv, "dvpfnyb:l:T:t:")) != -1) switch (i) { case 'd': flags |= CHECK_DEBUG; break; case 'v': flags |= CHECK_VERBOSE; break; case 'p': flags |= CHECK_PREEN; /*FALLTHROUGH*/ case 'n': case 'f': case 'y': globopt[1] = i; options = catopt(options, globopt, 1); break; case 'b': if (asprintf(&p, "-b %s", optarg) == -1) err(1, "malloc failed"); options = catopt(options, p, 1); free(p); break; case 'l': maxrun = atoi(optarg); break; case 'T': if (*optarg) addoption(optarg); break; case 't': if (!TAILQ_EMPTY(&selhead)) errx(1, "only one -t option may be specified."); maketypelist(optarg); vfstype = optarg; break; case '?': default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; if (argc == 0) return checkfstab(flags, maxrun, isok, checkfs); #define BADTYPE(type) \ (strcmp(type, FSTAB_RO) && \ strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) for (; argc--; argv++) { char *spec, *type; if ((strncmp(*argv, "/dev/", 5) == 0 || isduid(*argv, 0)) && (type = readlabelfs(*argv, 0))) { spec = *argv; } else if ((fs = getfsfile(*argv)) == NULL && (fs = getfsspec(*argv)) == NULL) { if (vfstype == NULL) errx(1, "%s: unknown special file or file system.", *argv); spec = *argv; type = vfstype; } else { spec = fs->fs_spec; type = fs->fs_vfstype; if (BADTYPE(fs->fs_type)) errx(1, "%s has unknown file system type.", *argv); } rval |= checkfs(type, blockcheck(spec), *argv, NULL, NULL); } return rval; }
/* * This routine is a generic rewrite of the original code found in * disklabel(8). */ int opendev(const char *path, int oflags, int dflags, char **realpath) { static char namebuf[PATH_MAX]; struct dk_diskmap dm; char *slash, *prefix; int fd; /* Initial state */ fd = -1; errno = ENOENT; if (dflags & OPENDEV_BLCK) prefix = ""; /* block device */ else prefix = "r"; /* character device */ if ((slash = strchr(path, '/'))) { strlcpy(namebuf, path, sizeof(namebuf)); fd = open(namebuf, oflags); } else if (isduid(path, dflags)) { strlcpy(namebuf, path, sizeof(namebuf)); if ((fd = open("/dev/diskmap", oflags)) != -1) { bzero(&dm, sizeof(struct dk_diskmap)); dm.device = namebuf; dm.fd = fd; if (dflags & OPENDEV_PART) dm.flags |= DM_OPENPART; if (dflags & OPENDEV_BLCK) dm.flags |= DM_OPENBLCK; if (ioctl(fd, DIOCMAP, &dm) == -1) { close(fd); fd = -1; errno = ENOENT; } } } if (!slash && fd == -1 && errno == ENOENT) { if (dflags & OPENDEV_PART) { /* * First try raw partition (for removable drives) */ if (snprintf(namebuf, sizeof(namebuf), "%s%s%s%c", _PATH_DEV, prefix, path, 'a' + getrawpartition()) < sizeof(namebuf)) { fd = open(namebuf, oflags); } else errno = ENAMETOOLONG; } if (fd == -1 && errno == ENOENT) { if (snprintf(namebuf, sizeof(namebuf), "%s%s%s", _PATH_DEV, prefix, path) < sizeof(namebuf)) { fd = open(namebuf, oflags); } else errno = ENAMETOOLONG; } } if (realpath) *realpath = namebuf; return (fd); }
/* * Try to get a disklabel for the specified device, and return mount_xxx * style filesystem type name for the specified partition. */ char * readlabelfs(char *device, int verbose) { char rpath[MAXPATHLEN]; struct dk_diskmap dm; struct disklabel dk; char part, *type; struct stat sbuf; int fd = -1; /* Perform disk mapping if device is given as a DUID. */ if (isduid(device, 0)) { if ((fd = open("/dev/diskmap", O_RDONLY)) != -1) { bzero(&dm, sizeof(struct dk_diskmap)); strlcpy(rpath, device, sizeof(rpath)); part = rpath[strlen(rpath) - 1]; dm.device = rpath; dm.fd = fd; dm.flags = DM_OPENPART; if (ioctl(fd, DIOCMAP, &dm) == -1) close(fd); else goto disklabel; } } /* Assuming device is of the form /dev/??p, build a raw partition. */ if (stat(device, &sbuf) < 0) { if (verbose) warn("%s", device); return (NULL); } switch (sbuf.st_mode & S_IFMT) { case S_IFCHR: /* Ok... already a raw device. Hmm. */ strlcpy(rpath, device, sizeof(rpath)); /* Change partition name. */ part = rpath[strlen(rpath) - 1]; rpath[strlen(rpath) - 1] = 'a' + getrawpartition(); break; case S_IFBLK: if (strlen(device) > sizeof(_PATH_DEV) - 1) { snprintf(rpath, sizeof(rpath), "%sr%s", _PATH_DEV, &device[sizeof(_PATH_DEV) - 1]); /* Change partition name. */ part = rpath[strlen(rpath) - 1]; rpath[strlen(rpath) - 1] = 'a' + getrawpartition(); break; } /* FALLTHROUGH */ default: if (verbose) warnx("%s: not a device node", device); return (NULL); } /* If rpath doesn't exist, change that partition back. */ fd = open(rpath, O_RDONLY); if (fd < 0) { if (errno == ENOENT) { rpath[strlen(rpath) - 1] = part; fd = open(rpath, O_RDONLY); if (fd < 0) { if (verbose) warn("%s", rpath); return (NULL); } } else { if (verbose) warn("%s", rpath); return (NULL); } } disklabel: if (ioctl(fd, DIOCGDINFO, &dk) < 0) { if (verbose) warn("%s: couldn't read disklabel", rpath); close(fd); return (NULL); } close(fd); if (dk.d_partitions[part - 'a'].p_fstype >= FSMAXTYPES) { if (verbose) warnx("%s: bad filesystem type in label", rpath); return (NULL); } type = fstypesnames[dk.d_partitions[part - 'a'].p_fstype]; return ((type[0] == '\0') ? NULL : type); }
void do_fstab(void) { struct fstab *fp; char *s; long priority; struct stat st; mode_t rejecttype; int gotone = 0; /* * Select which mount point types to reject, depending on the * value of the -t parameter. */ if (tflag != NULL) { if (strcmp(tflag, "blk") == 0) rejecttype = S_IFREG; else if (strcmp(tflag, "noblk") == 0) rejecttype = S_IFBLK; } else rejecttype = 0; #define PRIORITYEQ "priority=" #define NFSMNTPT "nfsmntpt=" #define PATH_MOUNT "/sbin/mount_nfs" while ((fp = getfsent()) != NULL) { const char *spec; if (strcmp(fp->fs_type, "sw") != 0) continue; spec = fp->fs_spec; if ((s = strstr(fp->fs_mntops, PRIORITYEQ)) != NULL) { s += sizeof(PRIORITYEQ) - 1; priority = atol(s); } else priority = pri; if ((s = strstr(fp->fs_mntops, NFSMNTPT)) != NULL) { char *t, cmd[sizeof(PATH_MOUNT)+PATH_MAX+1+PATH_MAX+1]; int l; /* * Skip this song and dance if we're only * doing block devices. */ if (rejecttype == S_IFREG) continue; t = strpbrk(s, ","); if (t != 0) *t = '\0'; spec = strdup(s + strlen(NFSMNTPT)); if (spec == NULL) err(1, "strdup"); if (t != 0) *t = ','; if (strlen(spec) == 0) { warnx("empty mountpoint"); free((char *)spec); continue; } l = snprintf(cmd, sizeof(cmd), "%s %s %s", PATH_MOUNT, fp->fs_spec, spec); if (l == -1 || l >= sizeof(cmd)) errx(1, "path too long"); if (system(cmd) != 0) { warnx("%s: mount failed", fp->fs_spec); free((char *)spec); continue; } } else if (isduid(spec, 0)) { if (rejecttype == S_IFBLK) continue; } else { /* * Determine blk-ness. Don't even consider a * mountpoint outside /dev as a block device. */ if (rejecttype == S_IFREG) { if (strncmp("/dev/", spec, 5) != 0) continue; } if (stat(spec, &st) < 0) { warn("%s", spec); continue; } if ((st.st_mode & S_IFMT) == rejecttype) continue; /* * Do not allow fancy objects to be swap areas. */ if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode)) continue; } if (swapctl(SWAP_ON, spec, (int)priority) < 0) { if (errno != EBUSY) warn("%s", spec); } else { gotone = 1; printf("%s: adding %s as swap device at priority %d\n", __progname, fp->fs_spec, (int)priority); } if (spec != fp->fs_spec) free((char *)spec); } if (gotone == 0) exit(1); }