void update_mtab(const char *dir, struct mntent *instead) { struct mntent *mnt; struct mntent *next; struct mntent remnt; int added = 0; mntFILE *mfp, *mftmp; if (mtab_does_not_exist() || mtab_is_a_symlink()) return; lock_mtab(); mfp = my_setmntent(MOUNTED, "r"); if (mfp == NULL || mfp->mntent_fp == NULL) { error("cannot open %s (%s) - mtab not updated", MOUNTED, strerror(errno)); goto leave; } mftmp = my_setmntent(MOUNTED_TEMP, "w"); if (mftmp == NULL || mftmp->mntent_fp == NULL) { error("can't open %s (%s) - mtab not updated", MOUNTED_TEMP, strerror(errno)); goto leave; } while ((mnt = my_getmntent(mfp))) { if (streq(mnt->mnt_dir, dir)) { added++; if (instead) { /* a remount */ remnt = *instead; next = &remnt; remnt.mnt_fsname = mnt->mnt_fsname; remnt.mnt_type = mnt->mnt_type; if (instead->mnt_fsname && !streq(mnt->mnt_fsname, instead->mnt_fsname)) printf("mount: warning: cannot change " "mounted device with a remount\n"); else if (instead->mnt_type && !streq(instead->mnt_type, "unknown") && !streq(mnt->mnt_type, instead->mnt_type)) printf("mount: warning: cannot change " "filesystem type with a remount\n"); } else next = NULL; } else next = mnt; if (next && my_addmntent(mftmp, next) == 1) die(EX_FILEIO, "error writing %s: %s", MOUNTED_TEMP, strerror(errno)); } if (instead && !added && my_addmntent(mftmp, instead) == 1) die(EX_FILEIO, "error writing %s: %s", MOUNTED_TEMP, strerror(errno)); my_endmntent(mfp); if (fchmod(fileno(mftmp->mntent_fp), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) fprintf(stderr, "error changing mode of %s: %s\n", MOUNTED_TEMP, strerror(errno)); my_endmntent(mftmp); if (rename(MOUNTED_TEMP, MOUNTED) < 0) fprintf(stderr, "can't rename %s to %s: %s\n", MOUNTED_TEMP, MOUNTED, strerror(errno)); leave: unlock_mtab(); }
void update_mtab (const char *dir, struct mntent *instead) { mntFILE *mfp, *mftmp; const char *fnam = MOUNTED; struct mntentchn mtabhead; /* dummy */ struct mntentchn *mc, *mc0, *absent = NULL; if (mtab_does_not_exist() || !mtab_is_writable()) return; lock_mtab(); /* having locked mtab, read it again */ mc0 = mc = &mtabhead; mc->nxt = mc->prev = NULL; mfp = nfs_setmntent(fnam, "r"); if (mfp == NULL || mfp->mntent_fp == NULL) { int errsv = errno; nfs_error (_("cannot open %s (%s) - mtab not updated"), fnam, strerror (errsv)); goto leave; } read_mntentchn(mfp, fnam, mc); /* find last occurrence of dir */ for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev) if (streq(mc->m.mnt_dir, dir)) break; if (mc && mc != mc0) { if (instead == NULL) { /* An umount - remove entry */ if (mc && mc != mc0) { mc->prev->nxt = mc->nxt; mc->nxt->prev = mc->prev; free(mc); } } else { /* A remount */ mc->m.mnt_opts = instead->mnt_opts; } } else if (instead) { /* not found, add a new entry */ absent = xmalloc(sizeof(*absent)); absent->m = *instead; absent->nxt = mc0; absent->prev = mc0->prev; mc0->prev = absent; if (mc0->nxt == NULL) mc0->nxt = absent; } /* write chain to mtemp */ mftmp = nfs_setmntent (MOUNTED_TEMP, "w"); if (mftmp == NULL || mftmp->mntent_fp == NULL) { int errsv = errno; nfs_error (_("cannot open %s (%s) - mtab not updated"), MOUNTED_TEMP, strerror (errsv)); goto leave; } for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) { if (nfs_addmntent(mftmp, &(mc->m)) == 1) { int errsv = errno; die (EX_FILEIO, _("error writing %s: %s"), MOUNTED_TEMP, strerror (errsv)); } } #if 0 /* the chain might have strings copied from 'instead', * so we cannot safely free it. * And there is no need anyway because we are going to exit * shortly. So just don't call discard_mntentchn.... */ discard_mntentchn(mc0); #endif if (fchmod (fileno (mftmp->mntent_fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { int errsv = errno; nfs_error(_("%s: error changing mode of %s: %s"), progname, MOUNTED_TEMP, strerror (errsv)); } nfs_endmntent (mftmp); { /* * If mount is setuid and some non-root user mounts sth, * then mtab.tmp might get the group of this user. Copy uid/gid * from the present mtab before renaming. */ struct stat sbuf; if (stat (MOUNTED, &sbuf) == 0) { if (chown (MOUNTED_TEMP, sbuf.st_uid, sbuf.st_gid) < 0) { nfs_error(_("%s: error changing owner of %s: %s"), progname, MOUNTED_TEMP, strerror (errno)); } } } /* rename mtemp to mtab */ if (rename (MOUNTED_TEMP, MOUNTED) < 0) { int errsv = errno; nfs_error(_("%s: can't rename %s to %s: %s\n"), progname, MOUNTED_TEMP, MOUNTED, strerror(errsv)); } leave: unlock_mtab(); }
void update_mtab (const char *dir, struct my_mntent *instead) { mntFILE *mfp, *mftmp; const char *fnam = MOUNTED; struct mntentchn mtabhead; /* dummy */ struct mntentchn *mc, *mc0, *absent = NULL; if (mtab_does_not_exist() || mtab_is_a_symlink()) return; lock_mtab(); /* having locked mtab, read it again */ mc0 = mc = &mtabhead; mc->nxt = mc->prev = NULL; mfp = my_setmntent(fnam, "r"); if (mfp == NULL || mfp->mntent_fp == NULL) { int errsv = errno; error (_("cannot open %s (%s) - mtab not updated"), fnam, strerror (errsv)); goto leave; } read_mntentchn(mfp, fnam, mc); /* find last occurrence of dir */ for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev) if (streq(mc->m.mnt_dir, dir)) break; if (mc && mc != mc0) { if (instead == NULL) { /* An umount - remove entry */ if (mc && mc != mc0) { mc->prev->nxt = mc->nxt; mc->nxt->prev = mc->prev; free(mc); } } else { /* A remount */ mc->m.mnt_opts = instead->mnt_opts; } } else if (instead) { /* not found, add a new entry */ absent = xmalloc(sizeof(*absent)); absent->m = *instead; absent->nxt = mc0; absent->prev = mc0->prev; mc0->prev = absent; if (mc0->nxt == NULL) mc0->nxt = absent; } /* write chain to mtemp */ mftmp = my_setmntent (MOUNTED_TEMP, "w"); if (mftmp == NULL || mftmp->mntent_fp == NULL) { int errsv = errno; error (_("cannot open %s (%s) - mtab not updated"), MOUNTED_TEMP, strerror (errsv)); goto leave; } for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) { if (my_addmntent(mftmp, &(mc->m)) == 1) { int errsv = errno; die (EX_FILEIO, _("error writing %s: %s"), MOUNTED_TEMP, strerror (errsv)); } } discard_mntentchn(mc0); if (fchmod (fileno (mftmp->mntent_fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { int errsv = errno; fprintf(stderr, _("error changing mode of %s: %s\n"), MOUNTED_TEMP, strerror (errsv)); } my_endmntent (mftmp); { /* * If mount is setuid and some non-root user mounts sth, * then mtab.tmp might get the group of this user. Copy uid/gid * from the present mtab before renaming. */ struct stat sbuf; if (stat (MOUNTED, &sbuf) == 0) chown (MOUNTED_TEMP, sbuf.st_uid, sbuf.st_gid); } /* rename mtemp to mtab */ if (rename (MOUNTED_TEMP, MOUNTED) < 0) { int errsv = errno; fprintf(stderr, _("can't rename %s to %s: %s\n"), MOUNTED_TEMP, MOUNTED, strerror(errsv)); } leave: unlock_mtab(); }
int main(int argc, char *argv[]) { struct mount_options *opts = &options; char *device, *mntdir; int res = 0; if (argc > 0) { char *cp = strrchr(argv[0], '/'); progname = (cp ? cp + 1 : argv[0]); } nilfs_cleaner_logger = nilfs_mount_logger; parse_options(argc, argv, opts); umask(022); if (optind >= argc || !argv[optind]) die(EX_USAGE, _("No device specified")); device = argv[optind++]; if (optind >= argc || !argv[optind]) die(EX_USAGE, _("No mountpoint specified")); mntdir = argv[optind++]; if (opts->fstype && strncmp(opts->fstype, fstype, strlen(fstype))) die(EX_USAGE, _("Unknown filesystem (%s)"), opts->fstype); if (getuid() != geteuid()) die(EX_USAGE, _("%s: mount by non-root user is not supported yet"), progname); if (!nomtab && mtab_does_not_exist()) die(EX_USAGE, _("%s: no %s found - aborting"), progname, MOUNTED); if (!(opts->flags & MS_RDONLY) && !(opts->flags & MS_BIND)) { res = device_is_readonly(device, &devro); if (res) die(EX_USAGE, _("%s: device %s not accessible: %s"), progname, device, strerror(res)); } if (signal(SIGTERM, handle_signal) == SIG_ERR) die(EX_SYSERR, _("Could not set SIGTERM")); if (signal(SIGINT, handle_signal) == SIG_ERR) die(EX_SYSERR, _("Could not set SIGINT")); block_signals(SIG_BLOCK); res = mount_one(device, mntdir, opts); block_signals(SIG_UNBLOCK); my_free(opts->opts); my_free(opts->extra_opts); return res; }