Ejemplo n.º 1
0
/*
 * The default is to use fstype from cxt->fs, this could be overwritten by
 * @try_type argument.
 *
 * Returns: 0 on success,
 *         >0 in case of mount(2) error (returns syscall errno),
 *         <0 in case of other errors.
 */
static int do_mount(struct libmnt_context *cxt, const char *try_type)
{
	int rc = 0;
	const char *src, *target, *type;
	unsigned long flags;

	assert(cxt);
	assert(cxt->fs);
	assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));

	if (try_type && !cxt->helper) {
		rc = mnt_context_prepare_helper(cxt, "mount", try_type);
		if (!rc)
			return rc;
	}
	if (cxt->helper)
		return exec_helper(cxt);

	flags = cxt->mountflags;
	src = mnt_fs_get_srcpath(cxt->fs);
	target = mnt_fs_get_target(cxt->fs);

	if (!src || !target)
		return -EINVAL;

	type = try_type ? : mnt_fs_get_fstype(cxt->fs);

	if (!(flags & MS_MGC_MSK))
		flags |= MS_MGC_VAL;

	DBG(CXT, mnt_debug_h(cxt, "%smount(2) "
			"[source=%s, target=%s, type=%s, "
			" mountflags=0x%08lx, mountdata=%s]",
			(cxt->flags & MNT_FL_FAKE) ? "(FAKE) " : "",
			src, target, type,
			flags, cxt->mountdata ? "yes" : "<none>"));

	if (cxt->flags & MNT_FL_FAKE)
		cxt->syscall_status = 0;
	else {
		if (mount(src, target, type, flags, cxt->mountdata)) {
			cxt->syscall_status = -errno;
			DBG(CXT, mnt_debug_h(cxt, "mount(2) failed [errno=%d %m]",
							-cxt->syscall_status));
			return -cxt->syscall_status;
		}
		DBG(CXT, mnt_debug_h(cxt, "mount(2) success"));
		cxt->syscall_status = 0;
	}

	if (try_type && cxt->update) {
		struct libmnt_fs *fs = mnt_update_get_fs(cxt->update);
		if (fs)
			rc = mnt_fs_set_fstype(fs, try_type);
	}

	return rc;
}
Ejemplo n.º 2
0
static void fs_interpret_type(struct libmnt_fs *fs)
{
	const char *device;
	const char *type = mnt_fs_get_fstype(fs);

	if (type && strcmp(type, "auto") != 0)
		return;

	mnt_fs_set_fstype(fs, NULL);

	device = fs_get_device(fs);
	if (device) {
		int ambi = 0;

		type = mnt_get_fstype(device, &ambi, mnt_table_get_cache(fstab));
		if (!ambi)
			mnt_fs_set_fstype(fs, type);
	}
}
Ejemplo n.º 3
0
static int test_add(struct libmnt_test *ts, int argc, char *argv[])
{
	struct libmnt_fs *fs = mnt_new_fs();
	int rc;

	if (argc < 5 || !fs)
		return -1;
	mnt_fs_set_source(fs, argv[1]);
	mnt_fs_set_target(fs, argv[2]);
	mnt_fs_set_fstype(fs, argv[3]);
	mnt_fs_set_options(fs, argv[4]);

	rc = update(NULL, fs, 0);
	mnt_free_fs(fs);
	return rc;
}
Ejemplo n.º 4
0
/*
 * Parses one line from /proc/swaps
 */
static int mnt_parse_swaps_line(struct libmnt_fs *fs, char *s)
{
	uintmax_t fsz, usz;
	int rc;
	char *src = NULL;

	rc = sscanf(s,	UL_SCNsA" "	/* (1) source */
			UL_SCNsA" "	/* (2) type */
			"%jd"		/* (3) size */
			"%jd"		/* (4) used */
			"%d",		/* priority */

			&src,
			&fs->swaptype,
			&fsz,
			&usz,
			&fs->priority);

	if (rc == 5) {
		size_t sz;

		fs->size = fsz;
		fs->usedsize = usz;

		unmangle_string(src);

		/* remove "(deleted)" suffix */
		sz = strlen(src);
		if (sz > PATH_DELETED_SUFFIX_SZ) {
			char *p = src + (sz - PATH_DELETED_SUFFIX_SZ);
			if (strcmp(p, PATH_DELETED_SUFFIX) == 0)
				*p = '\0';
		}

		rc = mnt_fs_set_source(fs, src);
		if (!rc)
			mnt_fs_set_fstype(fs, "swap");
		free(src);
	} else {
		DBG(TAB, mnt_debug("tab parse error: [sscanf rc=%d]: '%s'", rc, s));
		rc = -EINVAL;
	}

	return rc;
}
Ejemplo n.º 5
0
/*
 * Sets fs-root and fs-type to @upd->fs according to the @fs template and
 * @mountfalgs. For MS_BIND mountflag it reads information about source
 * filesystem from /proc/self/mountinfo.
 */
static int set_fs_root(struct libmnt_update *upd, struct libmnt_fs *fs,
		       unsigned long mountflags)
{
	struct libmnt_fs *src_fs;
	char *fsroot = NULL;
	const char *src;
	int rc = 0;

	DBG(UPDATE, mnt_debug("setting FS root"));

	assert(upd);
	assert(upd->fs);
	assert(fs);

	if (mountflags & MS_BIND) {
		if (!upd->mountinfo)
			upd->mountinfo = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO);

		src = mnt_fs_get_srcpath(fs);
		if (src) {
			 rc = mnt_fs_set_bindsrc(upd->fs, src);
			 if (rc)
				 goto err;
		}
	}

	src_fs = mnt_table_get_fs_root(upd->mountinfo, fs,
					mountflags, &fsroot);
	if (src_fs) {
		src = mnt_fs_get_srcpath(src_fs);
		rc = mnt_fs_set_source(upd->fs, src);
		if (rc)
			goto err;

		mnt_fs_set_fstype(upd->fs, mnt_fs_get_fstype(src_fs));
	}

	upd->fs->root = fsroot;
	return 0;
err:
	free(fsroot);
	return rc;
}
Ejemplo n.º 6
0
/* this is umount replacement to mnt_context_apply_fstab(), use
 * mnt_context_tab_applied() to check result.
 */
static int lookup_umount_fs(struct libmnt_context *cxt)
{
	const char *tgt;
	struct stat st;
	struct libmnt_fs *fs = NULL;
	int rc = 0;

	assert(cxt);
	assert(cxt->fs);

	tgt = mnt_fs_get_target(cxt->fs);
	if (!tgt) {
		DBG(CXT, ul_debugobj(cxt, "umount: undefined target"));
		return -EINVAL;
	}

	/*
	 * Let's try to avoid mountinfo usage at all to minimize performance
	 * degradation. Don't forget that kernel has to compose *whole*
	 * mountinfo about all mountpoints although we look for only one entry.
	 *
	 * All we need is fstype and to check if there is no userspace mount
	 * options for the target (e.g. helper=udisks to call /sbin/umount.udisks).
	 *
	 * So, let's use statfs() if possible (it's bad idea for --lazy/--force
	 * umounts as target is probably unreachable NFS, also for --detach-loop
	 * as this additionally needs to know the name of the loop device).
	 */
	if (!mnt_context_is_restricted(cxt)
	    && *tgt == '/'
	    && !(cxt->flags & MNT_FL_HELPER)
	    && !mnt_context_mtab_writable(cxt)
	    && !mnt_context_is_force(cxt)
	    && !mnt_context_is_lazy(cxt)
	    && !mnt_context_is_loopdel(cxt)
	    && mnt_stat_mountpoint(tgt, &st) == 0 && S_ISDIR(st.st_mode)
	    && !has_utab_entry(cxt, tgt)) {

		const char *type = mnt_fs_get_fstype(cxt->fs);

		/* !mnt_context_mtab_writable(cxt) && has_utab_entry() verified that there
		 * is no stuff in utab, so disable all mtab/utab related actions */
		mnt_context_disable_mtab(cxt, TRUE);

		if (!type) {
			struct statfs vfs;
			if (statfs(tgt, &vfs) == 0)
				type = mnt_statfs_get_fstype(&vfs);
			if (type) {
				rc = mnt_fs_set_fstype(cxt->fs, type);
				if (rc)
					return rc;
			}
		}
		if (type) {
			DBG(CXT, ul_debugobj(cxt,
				"umount: mountinfo unnecessary [type=%s]", type));
			return 0;
		}
	}

	rc = mnt_context_find_umount_fs(cxt, tgt, &fs);
	if (rc < 0)
		return rc;

	if (rc == 1 || !fs) {
		DBG(CXT, ul_debugobj(cxt, "umount: cannot find '%s' in mtab", tgt));
		return 0;	/* this is correct! */
	}

	if (fs != cxt->fs) {
		/* copy from mtab to our FS description
		 */
		mnt_fs_set_source(cxt->fs, NULL);
		mnt_fs_set_target(cxt->fs, NULL);

		if (!mnt_copy_fs(cxt->fs, fs)) {
			DBG(CXT, ul_debugobj(cxt, "umount: failed to copy FS"));
			return -errno;
		}
		DBG(CXT, ul_debugobj(cxt, "umount: mtab applied"));
	}

	cxt->flags |= MNT_FL_TAB_APPLIED;
	return rc;
}
Ejemplo n.º 7
0
/*
 * The default is to use fstype from cxt->fs, this could be overwritten by
 * @try_type argument.
 *
 * Returns: 0 on success,
 *         >0 in case of mount(2) error (returns syscall errno),
 *         <0 in case of other errors.
 */
static int do_mount(struct libmnt_context *cxt, const char *try_type)
{
	int rc = 0;
	const char *src, *target, *type;
	unsigned long flags;

	assert(cxt);
	assert(cxt->fs);
	assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));

	if (try_type && !cxt->helper) {
		rc = mnt_context_prepare_helper(cxt, "mount", try_type);
		if (rc)
			return rc;
	}
	if (cxt->helper)
		return exec_helper(cxt);

	flags = cxt->mountflags;
	src = mnt_fs_get_srcpath(cxt->fs);
	target = mnt_fs_get_target(cxt->fs);

	if (!target)
		return -EINVAL;
	if (!src) {
		/* unnecessary, should be already resolved in
		 * mnt_context_prepare_srcpath(), but for sure... */
		DBG(CXT, mnt_debug_h(cxt, "WARNING: source is NULL -- using \"none\"!"));
		src = "none";
	}
	type = try_type ? : mnt_fs_get_fstype(cxt->fs);

	if (!(flags & MS_MGC_MSK))
		flags |= MS_MGC_VAL;

	DBG(CXT, mnt_debug_h(cxt, "%smount(2) "
			"[source=%s, target=%s, type=%s, "
			" mountflags=0x%08lx, mountdata=%s]",
			mnt_context_is_fake(cxt) ? "(FAKE) " : "",
			src, target, type,
			flags, cxt->mountdata ? "yes" : "<none>"));

	if (mnt_context_is_fake(cxt))
		cxt->syscall_status = 0;
	else {
		if (mount(src, target, type, flags, cxt->mountdata)) {
			cxt->syscall_status = -errno;
			DBG(CXT, mnt_debug_h(cxt, "mount(2) failed [errno=%d %m]",
							-cxt->syscall_status));
			return -cxt->syscall_status;
		}
		DBG(CXT, mnt_debug_h(cxt, "mount(2) success"));
		cxt->syscall_status = 0;
	}

	if (try_type && cxt->update) {
		struct libmnt_fs *fs = mnt_update_get_fs(cxt->update);
		if (fs)
			rc = mnt_fs_set_fstype(fs, try_type);
	}

	return rc;
}