From 53a3c31df8dd719c8c4eac4ccdf7d47dff336535 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 31 Dec 2017 22:22:57 +0000 Subject: [PATCH] utils: Make mount/umount do all the right things Now uses mntent, does proper locking and correctly allows mount and umount -a --- Applications/util/mount.c | 173 +++++++++++++++++++++++------------- Applications/util/prtroot.c | 2 +- Applications/util/umount.c | 75 ++++++---------- 3 files changed, 141 insertions(+), 109 deletions(-) diff --git a/Applications/util/mount.c b/Applications/util/mount.c index 01b6c168..b07f8c3d 100644 --- a/Applications/util/mount.c +++ b/Applications/util/mount.c @@ -1,93 +1,144 @@ #include #include #include +#include +#include -/* Assumed length of a line in /etc/mtab */ -#define MTAB_LINE 160 +static int err = 0; +static int all = 0; +static char *fstype = "fuzix"; -int lsmtab(void) +static void usage(void) +{ + fputs("Usage: mount [-a] [-t type] name [path].\n", stderr); + exit(1); +} + +static int lsmtab(void) { FILE *f; - char tmp[MTAB_LINE]; - char* dev; - char* mntpt; - char* fstype; - char* rwflag; + struct mntent *mnt; - f = fopen("/etc/mtab", "r"); + f = setmntent("/etc/mtab", "r"); if (f) { - while (fgets(tmp, sizeof(tmp), f)) { - dev = strtok(tmp, " "); - mntpt = strtok(NULL, " "); - fstype = strtok(NULL, " "); - rwflag = strtok(NULL, "\n"); - if (strcmp(fstype, "swap") == 0) - printf("%s is swapspace\n", dev); + while (mnt = getmntent(f)) { + if (strcmp(mnt->mnt_type, "swap") == 0) + printf("%s is swapspace\n", mnt->mnt_fsname); else - printf("%s mounted on %s read-%s\n", dev, mntpt, - (strcmp(rwflag, "ro") == 0) ? "only" : "write"); + printf("%s mounted on %s read-%s\n", + mnt->mnt_fsname, + mnt->mnt_dir, + hasmntopt(mnt, "ro") ? "only" : "write"); } - fclose(f); - } + endmntent(f); + } else + err = 1; return 0; } -int add2mtab(char *dev, char *mntpt, char *fstype, char *rwflag) +static void add2mtab(struct mntent *mnt) { - FILE *inpf, *outf; - char *tmp_fname; - int c; + FILE *f; - if ((tmp_fname = tmpnam(NULL)) == NULL) { - perror("Error getting temporary file name"); - exit(1); - } - inpf = fopen("/etc/mtab", "r"); - outf = fopen(tmp_fname, "w"); - if (!outf) { - perror("Can't create temporary file"); + f = setmntent("/etc/mtab", "a"); + if (f == NULL) { + perror("/etc/mtab"); exit(1); } - if (inpf) { - for (;;) { - c = fgetc(inpf); - if (c == EOF) - break; - fputc(c, outf); + addmntent(f, mnt); + endmntent(f); +} + +static int flagsof(struct mntent *mnt) +{ + int f = 0; + if (hasmntopt(mnt, "ro")) + f |= MS_RDONLY; + if (hasmntopt(mnt, "nosuid")) + f |= MS_NOSUID; + return f; +} + +static int is_mounted(struct mntent *ent) +{ + FILE *f = setmntent("/etc/mtab", "r"); + struct mntent mnt; + static char buf[_MAX_MNTLEN]; + + while(getmntent_r(f, &mnt, buf, _MAX_MNTLEN)) { + if (strcmp(mnt.mnt_fsname, ent->mnt_fsname) == 0) { + endmntent(f); + return 1; } - fclose(inpf); } - fprintf(outf, "%s %s %s %s\n", dev, mntpt, fstype, rwflag); - fclose(outf); - if (inpf && unlink("/etc/mtab") < 0) { - perror("Can't delete old /etc/mtab file"); - exit(1); + endmntent(f); + return 0; +} + +static void do_mount(struct mntent *mnt) +{ + if (strcmp(mnt->mnt_type, "swap") == 0) + return; + if (mount(mnt->mnt_fsname, mnt->mnt_dir, flagsof(mnt)) == -1) { + err = errno; + perror(mnt->mnt_fsname); + return; } - if (rename(tmp_fname, "/etc/mtab") < 0) { - perror("Error installing /etc/mtab"); - exit(1); + add2mtab(mnt); +} + +static void automount(char *match) +{ + FILE *f = setmntent("/etc/fstab", "r"); + struct mntent *mnt; + + while (mnt = getmntent(f)) { + /* Warning - mnt contents go invalid if we do work on mtab so + be careful here and use getmntent_r in is_mounted */ + if (is_mounted(mnt)) + continue; + if (match == NULL || strcmp(mnt->mnt_fsname, match) == 0 || + strcmp(mnt->mnt_dir, match) == 0) + do_mount(mnt); + if (err) + break; } - return 0; + endmntent(f); } int main(int argc, char *argv[]) { - if (argc == 1) { - lsmtab(); - return 0; - } + int opt; - if (argc != 3) { - printf("usage: mount device path\n"); - return 1; + while((opt = getopt(argc, argv, "at:")) != -1) { + if (opt == 'a') + all = 1; + else if (opt == 't') + fstype = optarg; + else + usage(); } - if (mount(argv[1], argv[2], 0) == 0) { - add2mtab(argv[1], argv[2], "uzi", "rw"); - } else { - perror("mount"); - return 1; + if (optind >= argc) { + if (all) + automount(NULL); + else + lsmtab(); + return err; } - return 0; + if (optind == argc - 1) + automount(argv[optind]); + else if (optind <= argc - 2) { + static struct mntent mnt; + mnt.mnt_fsname = argv[optind++]; + mnt.mnt_dir = argv[optind++]; + mnt.mnt_type = fstype; + if (optind != argc) + mnt.mnt_opts = argv[optind++]; + if (optind != argc) + usage(); + do_mount(&mnt); + } + return err; } diff --git a/Applications/util/prtroot.c b/Applications/util/prtroot.c index 6be4b66a..34e7b779 100644 --- a/Applications/util/prtroot.c +++ b/Applications/util/prtroot.c @@ -27,7 +27,7 @@ #include #define DEV_PATH "/dev/" -#define MESSAGE " / fuzix rw\n" +#define MESSAGE " / fuzix rw 0 0\n" #define UNKNOWN_DEV "/dev/unknown" #define ROOT "/" diff --git a/Applications/util/umount.c b/Applications/util/umount.c index 77ac925e..cee0c54e 100644 --- a/Applications/util/umount.c +++ b/Applications/util/umount.c @@ -2,49 +2,35 @@ #include #include #include +#include /* Assumed length of a line in /etc/mtab */ +/* FIXME */ #define MTAB_LINE 160 #define MAXFS 16 static char *devlist[MAXFS]; static char **devp = &devlist[0]; -static char tmp[MTAB_LINE]; - -const char *readmtab(FILE *fp) -{ - char *dev; - while (fgets(tmp, sizeof(tmp), fp) != NULL) { - dev = strtok(tmp, " \t"); - if (dev == NULL || *tmp == '#') - continue; - return dev; - } - return NULL; -} - -char *getdev(char *arg) +static char *getdev(char *arg) { FILE *f; - const char *dev; - char* mntpt; + struct mntent *mnt; - f = fopen("/etc/mtab", "r"); + f = setmntent("/etc/mtab", "r"); if (f) { - while ((dev = readmtab(f)) != NULL) { - mntpt = strtok(NULL, " \t"); - if ((strcmp(dev, arg) == 0) || (strcmp(mntpt, arg) == 0)) { - fclose(f); - return strdup(dev); + while (mnt = getmntent(f)) { + if ((strcmp(mnt->mnt_fsname, arg) == 0) || (strcmp(mnt->mnt_dir, arg) == 0)) { + endmntent(f); + return strdup(mnt->mnt_fsname); } } - fclose(f); + endmntent(f); } return NULL; } -int deleted(const char *p) +static int deleted(const char *p) { char **d = &devlist[0]; @@ -65,35 +51,30 @@ static void queue_rm_mtab(const char *p) } /* FIXME: error checking, atomicity */ -int rewrite_mtab(void) +static int rewrite_mtab(void) { FILE *inpf, *outf; - char *tmp_fname; - static char tmp[MTAB_LINE]; - static char tmp2[MTAB_LINE]; - char* dev; + struct mntent *mnt; - inpf = fopen("/etc/mtab", "r"); + inpf = setmntent("/etc/mtab", "r"); if (!inpf) { perror("Can't open /etc/mtab"); exit(1); } - outf = fopen("/etc/mtab.new", "w"); + outf = setmntent("/etc/mtab.new", "w"); if (!outf) { perror("Can't create temporary file"); exit(1); } - while (fgets(tmp, sizeof(tmp), inpf)) { - strncpy( tmp2, tmp, MTAB_LINE ); - dev = strtok(tmp, " \t"); - if (dev && deleted(dev)) { + while (mnt = getmntent(inpf)) { + /* FIXME: should we check device and dir ? */ + if (deleted(mnt->mnt_fsname)) continue; - } else { - fputs(tmp2, outf); - } + else + addmntent(outf, mnt); } - fclose(inpf); - fclose(outf); + endmntent(inpf); + endmntent(outf); if (rename("/etc/mtab.new", "/etc/mtab") < 0) { perror("Error installing /etc/mtab"); exit(1); @@ -103,6 +84,7 @@ int rewrite_mtab(void) int main(int argc, char *argv[]) { + struct mntent *mnt; const char *dev; char **dp; FILE *f; @@ -117,18 +99,17 @@ int main(int argc, char *argv[]) if (strcmp(argv[1], "-a") == 0) { /* We need to umount things in reverse order if we have mounts on mounts */ - f = fopen("/etc/mtab", "r"); + f = setmntent("/etc/mtab", "r"); if (f == NULL) { perror("mtab"); exit(1); } - while((dev = readmtab(f)) != NULL) { - char *mntpt = strtok(NULL, " \t"); + while(mnt = getmntent(f)) { /* We can't unmount / */ - if (strcmp(mntpt, "/")) - queue_rm_mtab(dev); + if (strcmp(mnt->mnt_dir, "/")) + queue_rm_mtab(mnt->mnt_fsname); } - fclose(f); + endmntent(f); dp = devp; /* Unmount in reverse order of mounting */ while(--dp >= devlist) { -- 2.34.1