/* todo: there are some cases which options are not changed */ static void update_mtab(FILE *fp, char *mntpnt, int do_remount, int do_verbose) { int err; long pos; FILE *ofp; struct mntent ent, *p; /* prohibit updating mount options for this mntpnt */ au_plink_maint(mntpnt); err = au_proc_getmntent(mntpnt, &ent); if (err) AuFin("no such mount point"); ofp = setmntent(MTab, "r"); if (!ofp) AuFin(MTab); if (do_remount) { /* find the last one */ pos = -1; while ((p = getmntent(ofp))) { if (!strcmp(p->mnt_dir, mntpnt)) pos = ftell(ofp); } rewind(ofp); if (pos > 0) { while ((p = getmntent(ofp))) { if (ftell(ofp) == pos) { /* replace the line */ p = &ent; pos = -1; } err = addmntent(fp, p); if (err) AuFin("addmntent"); } if (pos > 0) AuFin("internal error"); } else append_mtab(fp, ofp, &ent); } else append_mtab(fp, ofp, &ent); endmntent(ofp); /* ignore */ au_plink_maint(NULL); if (do_verbose) au_print_ent(&ent); }
int main(int argc, char *argv[]) { int err, c, status; pid_t pid; unsigned char flags[LastOpt]; struct mntent ent; char *dev, *mntpnt, *opts, *cwd; DIR *cur; if (argc < 3) { errno = EINVAL; AuFin(NULL); } memset(flags, 0, sizeof(flags)); flags[Update] = 1; opts = NULL; /* mount(8) always passes the arguments in this order */ dev = argv[1]; mntpnt = argv[2]; while ((c = getopt(argc - 2, argv + 2, "nvo:")) != -1) { switch (c) { case 'n': flags[Update] = 0; break; case 'v': flags[Verbose] = 1; break; case 'o': opts = optarg; break; case '?': case ':': errno = EINVAL; AuFin("internal error"); } } cur = opendir("."); if (!cur) AuFin("."); err = chdir(mntpnt); if (err) AuFin(mntpnt); cwd = getcwd(NULL, 0); /* glibc */ if (!cwd) AuFin("getcwd"); err = fchdir(dirfd(cur)); if (err) AuFin("fchdir"); closedir(cur); /* ignore */ if (opts) test_opts(opts, flags); if (!flags[Bind] && flags[Update]) { err = access(MTab, R_OK | W_OK); if (err) AuFin(MTab); } if (flags[Remount]) { errno = EINVAL; if (flags[Bind]) AuFin("both of remount and bind are specified"); flags[AuFlush] = test_flush(opts); if (flags[AuFlush]) { err = au_plink(cwd, AuPlink_FLUSH, 1, 1); if (err) AuFin(NULL); } } pid = fork(); if (!pid) { /* actual mount operation */ do_mount(dev, mntpnt, argc, argv, flags); return 0; } else if (pid < 0) AuFin("fork"); err = waitpid(pid, &status, 0); if (err < 0) AuFin("child process"); err = !WIFEXITED(status); if (!err) err = WEXITSTATUS(status); if (!err && !flags[Bind]) { if (flags[Update]) err = au_update_mtab(cwd, flags[Remount], flags[Verbose]); else if (flags[Verbose]) { /* withoug blocking plink */ err = au_proc_getmntent(cwd, &ent); if (!err) au_print_ent(&ent); else AuFin("internal error"); } } return err; }