be_access.c revision 336668
1/*
2 * be_access.c
3 *
4 * Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include "be.h"
30#include "be_impl.h"
31
32/*
33 * usage
34 */
35int
36be_mount(libbe_handle_t *lbh, char *bootenv, char *mountpoint, int flags,
37    char *result_loc)
38{
39	char be[BE_MAXPATHLEN];
40	char mnt_temp[BE_MAXPATHLEN];
41	zfs_handle_t *zfs_hdl;
42	char *path;
43	int mntflags;
44	int err;
45
46	if (err = be_root_concat(lbh, bootenv, be)) {
47		return (set_error(lbh, err));
48	}
49
50	if (!be_exists(lbh, bootenv)) {
51		return (set_error(lbh, BE_ERR_NOENT));
52	}
53
54	if (is_mounted(lbh->lzh, be, &path)) {
55		return (set_error(lbh, BE_ERR_MOUNTED));
56	}
57
58
59	mntflags = (flags & BE_MNT_FORCE) ? MNT_FORCE : 0;
60
61	/* Create mountpoint if it is not specified */
62	if (mountpoint == NULL) {
63		strcpy(mnt_temp, "/tmp/be_mount.XXXX");
64		if (mkdtemp(mnt_temp) == NULL) {
65			// TODO: create error for this
66			return (set_error(lbh, BE_ERR_UNKNOWN));
67		}
68	}
69
70	char opt = '\0';
71	if (err = zmount(be, (mountpoint == NULL) ? mnt_temp : mountpoint,
72	    mntflags, MNTTYPE_ZFS, NULL, 0, &opt, 1)) {
73		// TODO: zmount returns the nmount error, look into what kind of
74		// errors we can report from that
75		return (set_error(lbh, BE_ERR_UNKNOWN));
76	}
77
78	if (result_loc != NULL) {
79		strcpy(result_loc, mountpoint == NULL ? mnt_temp : mountpoint);
80	}
81
82	return (BE_ERR_SUCCESS);
83}
84
85
86/*
87 * usage
88 */
89int
90be_unmount(libbe_handle_t *lbh, char *bootenv, int flags)
91{
92	int err, mntflags;
93	char be[BE_MAXPATHLEN];
94	struct statfs *mntbuf;
95	int mntsize;
96	char *mntpath;
97
98	if (err = be_root_concat(lbh, bootenv, be)) {
99		return (set_error(lbh, err));
100	}
101
102	if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) {
103		// TODO correct error
104		return (set_error(lbh, BE_ERR_NOMOUNT));
105	}
106
107	mntpath = NULL;
108	for (int i = 0; i < mntsize; ++i) {
109		/* 0x000000de is the type number of zfs */
110		if (mntbuf[i].f_type != 0x000000de) {
111			continue;
112		}
113
114		if (strcmp(mntbuf[i].f_mntfromname, be) == 0) {
115			mntpath = mntbuf[i].f_mntonname;
116			break;
117		}
118	}
119
120	if (mntpath == NULL) {
121		return (set_error(lbh, BE_ERR_NOMOUNT));
122	}
123
124	mntflags = (flags & BE_MNT_FORCE) ? MNT_FORCE : 0;
125
126	if (err = unmount(mntpath, mntflags)) {
127		// TODO correct error
128		return (set_error(lbh, BE_ERR_NOMOUNT));
129	}
130
131	return (set_error(lbh, BE_ERR_SUCCESS));
132}
133