Exemple #1
0
static int
be_do_mount(int argc, char **argv)
{
	nvlist_t	*be_attrs;
	boolean_t	shared_fs = B_FALSE;
	int		err = 1;
	int		c;
	int		mount_flags = 0;
	char		*obe_name;
	char		*mountpoint;
	char		*tmp_mp = NULL;

	while ((c = getopt(argc, argv, "s:v")) != -1) {
		switch (c) {
		case 's':
			shared_fs = B_TRUE;

			mount_flags |= BE_MOUNT_FLAG_SHARED_FS;

			if (strcmp(optarg, "rw") == 0) {
				mount_flags |= BE_MOUNT_FLAG_SHARED_RW;
			} else if (strcmp(optarg, "ro") != 0) {
				(void) fprintf(stderr, _("The -s flag "
				    "requires an argument [ rw | ro ]\n"));
				usage();
				return (1);
			}

			break;
		case 'v':
			libbe_print_errors(B_TRUE);
			break;
		default:
			usage();
			return (1);
		}
	}

	argc -= optind;
	argv += optind;

	if (argc < 1 || argc > 2) {
		usage();
		return (1);
	}

	obe_name = argv[0];

	if (argc == 2) {
		mountpoint = argv[1];
		if (mountpoint[0] != '/') {
			(void) fprintf(stderr, _("Invalid mount point %s. "
			    "Mount point must start with a /.\n"), mountpoint);
			return (1);
		}
	} else {
		const char *tmpdir = getenv("TMPDIR");
		const char *tmpname = "tmp.XXXXXX";
		int sz;

		if (tmpdir == NULL)
			tmpdir = "/tmp";

		sz = asprintf(&tmp_mp, "%s/%s", tmpdir, tmpname);
		if (sz < 0) {
			(void) fprintf(stderr, _("internal error: "
			    "out of memory\n"));
			return (1);
		}

		mountpoint = mkdtemp(tmp_mp);
	}

	if (be_nvl_alloc(&be_attrs) != 0)
		return (1);

	if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name) != 0)
		goto out;

	if (be_nvl_add_string(be_attrs, BE_ATTR_MOUNTPOINT, mountpoint) != 0)
		goto out;

	if (shared_fs && be_nvl_add_uint16(be_attrs, BE_ATTR_MOUNT_FLAGS,
	    mount_flags) != 0)
		goto out;

	err = be_mount(be_attrs);

	switch (err) {
	case BE_SUCCESS:
		(void) printf(_("Mounted successfully on: '%s'\n"), mountpoint);
		break;
	case BE_ERR_BE_NOENT:
		(void) fprintf(stderr, _("%s does not exist or appear "
		    "to be a valid BE.\nPlease check that the name of "
		    "the BE provided is correct.\n"), obe_name);
		break;
	case BE_ERR_MOUNTED:
		(void) fprintf(stderr, _("%s is already mounted.\n"
		    "Please unmount the BE before mounting it again.\n"),
		    obe_name);
		break;
	case BE_ERR_PERM:
	case BE_ERR_ACCESS:
		(void) fprintf(stderr, _("Unable to mount %s.\n"), obe_name);
		(void) fprintf(stderr, _("You have insufficient privileges to "
		    "execute this command.\n"));
		break;
	case BE_ERR_NO_MOUNTED_ZONE:
		(void) fprintf(stderr, _("Mounted on '%s'.\nUnable to mount "
		    "one of %s's zone BE's.\n"), mountpoint, obe_name);
		break;
	default:
		(void) fprintf(stderr, _("Unable to mount %s.\n"), obe_name);
		(void) fprintf(stderr, "%s\n", be_err_to_str(err));
	}

out:
	if (tmp_mp != NULL)
		free(tmp_mp);
	nvlist_free(be_attrs);
	return (err);
}
int
bectl_cmd_jail(int argc, char *argv[])
{
	char *bootenv, **jargv, *mountpoint;
	int i, jid, mntflags, opt, ret;
	bool default_hostname, interactive, unjail;
	pid_t pid;


	/* XXX TODO: Allow shallow */
	mntflags = BE_MNT_DEEP;
	default_hostname = interactive = unjail = true;

	if ((nvlist_alloc(&jailparams, NV_UNIQUE_NAME, 0)) != 0) {
		fprintf(stderr, "nvlist_alloc() failed\n");
		return (1);
	}

	jailparam_add("persist", "true");
	jailparam_add("allow.mount", "true");
	jailparam_add("allow.mount.devfs", "true");
	jailparam_add("enforce_statfs", "1");

	while ((opt = getopt(argc, argv, "bo:Uu:")) != -1) {
		switch (opt) {
		case 'b':
			interactive = false;
			break;
		case 'o':
			if (jailparam_addarg(optarg)) {
				/*
				 * optarg has been modified to null terminate
				 * at the assignment operator.
				 */
				if (strcmp(optarg, "host.hostname") == 0)
					default_hostname = false;
			} else {
				return (1);
			}
			break;
		case 'U':
			unjail = false;
			break;
		case 'u':
			if ((ret = jailparam_delarg(optarg)) == 0) {
				if (strcmp(optarg, "host.hostname") == 0)
					default_hostname = true;
			} else if (ret != ENOENT) {
				fprintf(stderr,
				    "bectl jail: error unsetting \"%s\"\n",
				    optarg);
				return (ret);
			}
			break;
		default:
			fprintf(stderr, "bectl jail: unknown option '-%c'\n",
			    optopt);
			return (usage(false));
		}
	}

	argc -= optind;
	argv += optind;

	if (argc < 1) {
		fprintf(stderr, "bectl jail: missing boot environment name\n");
		return (usage(false));
	}

	bootenv = argv[0];
	argc--;
	argv++;

	/*
	 * XXX TODO: if its already mounted, perhaps there should be a flag to
	 * indicate its okay to proceed??
	 */
	if (*mnt_loc == '\0')
		mountpoint = NULL;
	else
		mountpoint = mnt_loc;
	if (be_mount(be, bootenv, mountpoint, mntflags, mnt_loc) != BE_ERR_SUCCESS) {
		fprintf(stderr, "could not mount bootenv\n");
		return (1);
	}

	if (default_hostname)
		jailparam_add("host.hostname", bootenv);

	/*
	 * This is our indicator that path was not set by the user, so we'll use
	 * the path that libbe generated for us.
	 */
	if (mountpoint == NULL) {
		jailparam_add("path", mnt_loc);
		mountpoint = mnt_loc;
	}

	if ((build_jailcmd(&jargv, interactive, argc, argv)) != 0) {
		fprintf(stderr, "unable to build argument list for jail command\n");
		return (1);
	}

	pid = fork();

	switch (pid) {
	case -1:
		perror("fork");
		return (1);
	case 0:
		execv("/usr/sbin/jail", jargv);
		fprintf(stderr, "bectl jail: failed to execute\n");
	default:
		waitpid(pid, NULL, 0);
	}

	for (i = 0; jargv[i] != NULL; i++) {
		free(jargv[i]);
	}
	free(jargv);

	if (!interactive)
		return (0);

	if (unjail) {
		/*
		 *  We're not checking the jail id result here because in the
		 *  case of invalid param, or last command in jail was an error
		 *  the jail will not exist upon exit. bectl_jail_cleanup will
		 *  only jail_remove if the jid is >= 0.
		 */
		jid = bectl_locate_jail(bootenv);
		bectl_jail_cleanup(mountpoint, jid);
		be_unmount(be, bootenv, 0);
	}

	return (0);
}