Example #1
0
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();
}
Example #2
0
int
mtab_is_writable() {
	int fd;

	/* Should we write to /etc/mtab upon an update?
	   Probably not if it is a symlink to /proc/mounts, since that
	   would create a file /proc/mounts in case the proc filesystem
	   is not mounted. */
	if (mtab_is_a_symlink())
		return 0;

	fd = open(MOUNTED, O_RDWR | O_CREAT, 0644);
	if (fd >= 0) {
		close(fd);
		return 1;
	} else
		return 0;
}
Example #3
0
static FILE *
open_locked_mtab(const char *mnttabname, char *mode, char *fs)
{
  FILE *mfp = NULL;

  if (mnt_file) {
    dlog("Forced close on %s in read_mtab", mnttabname);
    endmntent(mnt_file);
    mnt_file = NULL;
  }

  if (!mtab_is_a_symlink() &&
      !lock_mtab()) {
    plog(XLOG_ERROR, "Couldn't lock mtab");
    return 0;
  }

  mfp = setmntent((char *)mnttabname, mode);
  if (!mfp) {
    plog(XLOG_ERROR, "setmntent(\"%s\", \"%s\"): %m", mnttabname, mode);
    return 0;
  }
  return mfp;
}
Example #4
0
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)
		if (chown (MOUNTED_TEMP, sbuf.st_uid, sbuf.st_gid) < 0) {
			int errsv = errno;
			fprintf(stderr, _("error changing ownership of %s: %s\n"),
				MOUNTED_TEMP, strerror (errsv));
		}
	}

	/* 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();
}