コード例 #1
0
static int unmount_fuse_locked(const char *mnt, int quiet, int lazy)
{
	int res;
	char *copy;
	const char *last;
	int umount_flags = lazy ? UMOUNT_DETACH : 0;

	if (getuid() != 0) {
		res = may_unmount(mnt, quiet);
		if (res == -1)
			return -1;
	}

	copy = strdup(mnt);
	if (copy == NULL) {
		fprintf(stderr, "%s: failed to allocate memory\n", progname);
		return -1;
	}

	res = chdir_to_parent(copy, &last);
	if (res == -1)
		goto out;

	if (umount_nofollow_support()) {
		umount_flags |= UMOUNT_NOFOLLOW;
	} else {
		res = check_is_mount(last, mnt);
		if (res == -1)
			goto out;
	}

	res = umount2(last, umount_flags);
	if (res == -1 && !quiet) {
		fprintf(stderr, "%s: failed to unmount %s: %s\n",
			progname, mnt, strerror(errno));
	}

out:
	if (res == -1)
		return -1;

	res = chdir("/");
	if (res == -1) {
		fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
		return -1;
	}

	return fuse_mnt_remove_mount(progname, mnt);
}
コード例 #2
0
ファイル: context_umount.c プロジェクト: efarrer/util-linux
static int do_umount(struct libmnt_context *cxt)
{
	int rc = 0, flags = 0;
	const char *src, *target;
	char *tgtbuf = NULL;

	assert(cxt);
	assert(cxt->fs);
	assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));
	assert(cxt->syscall_status == 1);

	if (cxt->helper)
		return exec_helper(cxt);

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

	if (!target)
		return -EINVAL;

	DBG(CXT, mnt_debug_h(cxt, "do umount"));

	if (cxt->restricted && !mnt_context_is_fake(cxt)) {
		/*
		 * extra paranoia for non-root users
		 * -- chdir to the parent of the mountpoint and use NOFOLLOW
		 *    flag to avoid races and symlink attacks.
		 */
		if (umount_nofollow_support())
			flags |= UMOUNT_NOFOLLOW;

		rc = mnt_chdir_to_parent(target, &tgtbuf);
		if (rc)
			return rc;
		target = tgtbuf;
	}

	if (mnt_context_is_lazy(cxt))
		flags |= MNT_DETACH;

	else if (mnt_context_is_force(cxt))
		flags |= MNT_FORCE;

	DBG(CXT, mnt_debug_h(cxt, "umount(2) [target='%s', flags=0x%08x]%s",
				target, flags,
				mnt_context_is_fake(cxt) ? " (FAKE)" : ""));

	if (mnt_context_is_fake(cxt))
		rc = 0;
	else {
		rc = flags ? umount2(target, flags) : umount(target);
		if (rc < 0)
			cxt->syscall_status = -errno;
		free(tgtbuf);
	}

	/*
	 * try remount read-only
	 */
	if (rc < 0
	    && cxt->syscall_status == -EBUSY
	    && mnt_context_is_rdonly_umount(cxt)
	    && src) {

		mnt_context_set_mflags(cxt, (cxt->mountflags |
					     MS_REMOUNT | MS_RDONLY));
		mnt_context_enable_loopdel(cxt, FALSE);

		DBG(CXT, mnt_debug_h(cxt,
			"umount(2) failed [errno=%d] -- trying to remount read-only",
			-cxt->syscall_status));

		rc = mount(src, mnt_fs_get_target(cxt->fs), NULL,
			    MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
		if (rc < 0) {
			cxt->syscall_status = -errno;
			DBG(CXT, mnt_debug_h(cxt,
				"read-only re-mount(2) failed [errno=%d]",
				-cxt->syscall_status));

			return -cxt->syscall_status;
		}
		cxt->syscall_status = 0;
		DBG(CXT, mnt_debug_h(cxt, "read-only re-mount(2) success"));
		return 0;
	}

	if (rc < 0) {
		DBG(CXT, mnt_debug_h(cxt, "umount(2) failed [errno=%d]",
			-cxt->syscall_status));
		return -cxt->syscall_status;
	}

	cxt->syscall_status = 0;
	DBG(CXT, mnt_debug_h(cxt, "umount(2) success"));
	return 0;
}