1 |
|
|
/* $OpenBSD: mount_tmpfs.c,v 1.6 2016/06/06 17:09:03 espie Exp $ */ |
2 |
|
|
/* $NetBSD: mount_tmpfs.c,v 1.24 2008/08/05 20:57:45 pooka Exp $ */ |
3 |
|
|
|
4 |
|
|
/* |
5 |
|
|
* Copyright (c) 2005, 2006 The NetBSD Foundation, Inc. |
6 |
|
|
* All rights reserved. |
7 |
|
|
* |
8 |
|
|
* This code is derived from software contributed to The NetBSD Foundation |
9 |
|
|
* by Julio M. Merino Vidal, developed as part of Google's Summer of Code |
10 |
|
|
* 2005 program. |
11 |
|
|
* |
12 |
|
|
* Redistribution and use in source and binary forms, with or without |
13 |
|
|
* modification, are permitted provided that the following conditions |
14 |
|
|
* are met: |
15 |
|
|
* 1. Redistributions of source code must retain the above copyright |
16 |
|
|
* notice, this list of conditions and the following disclaimer. |
17 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
18 |
|
|
* notice, this list of conditions and the following disclaimer in the |
19 |
|
|
* documentation and/or other materials provided with the distribution. |
20 |
|
|
* |
21 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
22 |
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
23 |
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
24 |
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
25 |
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 |
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 |
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 |
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 |
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 |
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
31 |
|
|
* POSSIBILITY OF SUCH DAMAGE. |
32 |
|
|
*/ |
33 |
|
|
|
34 |
|
|
#include <sys/types.h> |
35 |
|
|
#include <sys/mount.h> |
36 |
|
|
#include <sys/stat.h> |
37 |
|
|
|
38 |
|
|
#include <ctype.h> |
39 |
|
|
#include <err.h> |
40 |
|
|
#include <errno.h> |
41 |
|
|
#include <grp.h> |
42 |
|
|
#include <mntopts.h> |
43 |
|
|
#include <pwd.h> |
44 |
|
|
#include <stdio.h> |
45 |
|
|
#include <stdlib.h> |
46 |
|
|
#include <string.h> |
47 |
|
|
#include <unistd.h> |
48 |
|
|
#include <limits.h> |
49 |
|
|
#include <util.h> |
50 |
|
|
|
51 |
|
|
#include "mount_tmpfs.h" |
52 |
|
|
|
53 |
|
|
/* --------------------------------------------------------------------- */ |
54 |
|
|
|
55 |
|
|
static const struct mntopt mopts[] = { |
56 |
|
|
MOPT_STDOPTS, |
57 |
|
|
MOPT_WXALLOWED, |
58 |
|
|
MOPT_UPDATE, |
59 |
|
|
{ NULL }, |
60 |
|
|
}; |
61 |
|
|
|
62 |
|
|
/* --------------------------------------------------------------------- */ |
63 |
|
|
|
64 |
|
|
static void usage(void) __dead; |
65 |
|
|
static uid_t a_uid(const char *); |
66 |
|
|
static gid_t a_gid(const char *); |
67 |
|
|
static uid_t a_gid(const char *); |
68 |
|
|
static int a_num(const char *, const char *); |
69 |
|
|
static mode_t a_mask(const char *); |
70 |
|
|
static void pathadj(const char *, char *); |
71 |
|
|
|
72 |
|
|
/* --------------------------------------------------------------------- */ |
73 |
|
|
|
74 |
|
|
void |
75 |
|
|
mount_tmpfs_parseargs(int argc, char *argv[], |
76 |
|
|
struct tmpfs_args *args, int *mntflags, |
77 |
|
|
char *canon_dev, char *canon_dir) |
78 |
|
|
{ |
79 |
|
|
int gidset, modeset, uidset; /* Ought to be 'bool'. */ |
80 |
|
|
int ch; |
81 |
|
|
gid_t gid; |
82 |
|
|
uid_t uid; |
83 |
|
|
mode_t mode; |
84 |
|
|
int64_t tmpnumber; |
85 |
|
|
struct stat sb; |
86 |
|
|
|
87 |
|
|
/* Set default values for mount point arguments. */ |
88 |
|
|
memset(args, 0, sizeof(*args)); |
89 |
|
|
args->ta_version = TMPFS_ARGS_VERSION; |
90 |
|
|
args->ta_size_max = 0; |
91 |
|
|
args->ta_nodes_max = 0; |
92 |
|
|
*mntflags = 0; |
93 |
|
|
|
94 |
|
|
gidset = 0; gid = 0; |
95 |
|
|
uidset = 0; uid = 0; |
96 |
|
|
modeset = 0; mode = 0; |
97 |
|
|
|
98 |
|
|
optind = optreset = 1; |
99 |
|
|
while ((ch = getopt(argc, argv, "g:m:n:o:s:u:")) != -1 ) { |
100 |
|
|
switch (ch) { |
101 |
|
|
case 'g': |
102 |
|
|
gid = a_gid(optarg); |
103 |
|
|
gidset = 1; |
104 |
|
|
break; |
105 |
|
|
|
106 |
|
|
case 'm': |
107 |
|
|
mode = a_mask(optarg); |
108 |
|
|
modeset = 1; |
109 |
|
|
break; |
110 |
|
|
|
111 |
|
|
case 'n': |
112 |
|
|
|
113 |
|
|
if (scan_scaled(optarg, &tmpnumber) == -1) |
114 |
|
|
err(EXIT_FAILURE, "failed to parse nodes `%s'", |
115 |
|
|
optarg); |
116 |
|
|
args->ta_nodes_max = tmpnumber; |
117 |
|
|
break; |
118 |
|
|
|
119 |
|
|
case 'o': |
120 |
|
|
getmntopts(optarg, mopts, mntflags); |
121 |
|
|
break; |
122 |
|
|
|
123 |
|
|
case 's': |
124 |
|
|
if (scan_scaled(optarg, &tmpnumber) == -1) |
125 |
|
|
err(EXIT_FAILURE, "failed to parse size `%s'", |
126 |
|
|
optarg); |
127 |
|
|
args->ta_size_max = tmpnumber; |
128 |
|
|
break; |
129 |
|
|
|
130 |
|
|
case 'u': |
131 |
|
|
uid = a_uid(optarg); |
132 |
|
|
uidset = 1; |
133 |
|
|
break; |
134 |
|
|
|
135 |
|
|
case '?': |
136 |
|
|
default: |
137 |
|
|
usage(); |
138 |
|
|
} |
139 |
|
|
} |
140 |
|
|
argc -= optind; |
141 |
|
|
argv += optind; |
142 |
|
|
|
143 |
|
|
if (argc != 2) |
144 |
|
|
usage(); |
145 |
|
|
|
146 |
|
|
strlcpy(canon_dev, argv[0], PATH_MAX); |
147 |
|
|
pathadj(argv[1], canon_dir); |
148 |
|
|
|
149 |
|
|
if (stat(canon_dir, &sb) == -1) |
150 |
|
|
err(EXIT_FAILURE, "cannot stat `%s'", canon_dir); |
151 |
|
|
|
152 |
|
|
args->ta_root_uid = uidset ? uid : sb.st_uid; |
153 |
|
|
args->ta_root_gid = gidset ? gid : sb.st_gid; |
154 |
|
|
args->ta_root_mode = modeset ? mode : sb.st_mode; |
155 |
|
|
} |
156 |
|
|
|
157 |
|
|
/* --------------------------------------------------------------------- */ |
158 |
|
|
|
159 |
|
|
static void |
160 |
|
|
usage(void) |
161 |
|
|
{ |
162 |
|
|
extern char *__progname; |
163 |
|
|
(void)fprintf(stderr, |
164 |
|
|
"usage: %s [-g group] [-m mode] [-n nodes] [-o options] [-s size]\n" |
165 |
|
|
" [-u user] tmpfs mount_point\n", __progname); |
166 |
|
|
exit(1); |
167 |
|
|
} |
168 |
|
|
|
169 |
|
|
/* --------------------------------------------------------------------- */ |
170 |
|
|
|
171 |
|
|
int |
172 |
|
|
mount_tmpfs(int argc, char *argv[]) |
173 |
|
|
{ |
174 |
|
|
struct tmpfs_args args; |
175 |
|
|
char canon_dev[PATH_MAX], canon_dir[PATH_MAX]; |
176 |
|
|
int mntflags; |
177 |
|
|
|
178 |
|
|
mount_tmpfs_parseargs(argc, argv, &args, &mntflags, |
179 |
|
|
canon_dev, canon_dir); |
180 |
|
|
|
181 |
|
|
if (mount(MOUNT_TMPFS, canon_dir, mntflags, &args) == -1) |
182 |
|
|
err(EXIT_FAILURE, "tmpfs on %s", canon_dir); |
183 |
|
|
|
184 |
|
|
return EXIT_SUCCESS; |
185 |
|
|
} |
186 |
|
|
|
187 |
|
|
int |
188 |
|
|
main(int argc, char *argv[]) |
189 |
|
|
{ |
190 |
|
|
|
191 |
|
|
/* setprogname(argv[0]); */ |
192 |
|
|
return mount_tmpfs(argc, argv); |
193 |
|
|
} |
194 |
|
|
|
195 |
|
|
static uid_t |
196 |
|
|
a_uid(const char *s) |
197 |
|
|
{ |
198 |
|
|
struct passwd *pw; |
199 |
|
|
|
200 |
|
|
if ((pw = getpwnam(s)) != NULL) |
201 |
|
|
return pw->pw_uid; |
202 |
|
|
return a_num(s, "user"); |
203 |
|
|
} |
204 |
|
|
|
205 |
|
|
static gid_t |
206 |
|
|
a_gid(const char *s) |
207 |
|
|
{ |
208 |
|
|
struct group *gr; |
209 |
|
|
|
210 |
|
|
if ((gr = getgrnam(s)) != NULL) |
211 |
|
|
return gr->gr_gid; |
212 |
|
|
return a_num(s, "group"); |
213 |
|
|
} |
214 |
|
|
|
215 |
|
|
static int |
216 |
|
|
a_num(const char *s, const char *id_type) |
217 |
|
|
{ |
218 |
|
|
int id; |
219 |
|
|
char *ep; |
220 |
|
|
|
221 |
|
|
id = strtol(s, &ep, 0); |
222 |
|
|
if (*ep || s == ep || id < 0) |
223 |
|
|
errx(1, "unknown %s id: %s", id_type, s); |
224 |
|
|
return id; |
225 |
|
|
} |
226 |
|
|
|
227 |
|
|
static mode_t |
228 |
|
|
a_mask(const char *s) |
229 |
|
|
{ |
230 |
|
|
int rv; |
231 |
|
|
char *ep; |
232 |
|
|
|
233 |
|
|
rv = strtol(s, &ep, 8); |
234 |
|
|
if (s == ep || *ep || rv < 0) |
235 |
|
|
errx(1, "invalid file mode: %s", s); |
236 |
|
|
return rv; |
237 |
|
|
} |
238 |
|
|
|
239 |
|
|
static void |
240 |
|
|
pathadj(const char *input, char *adjusted) |
241 |
|
|
{ |
242 |
|
|
|
243 |
|
|
if (realpath(input, adjusted) == NULL) |
244 |
|
|
warn("Warning: realpath %s", input); |
245 |
|
|
if (strncmp(input, adjusted, PATH_MAX)) { |
246 |
|
|
warnx("\"%s\" is a non-resolved or relative path.", input); |
247 |
|
|
warnx("using \"%s\" instead.", adjusted); |
248 |
|
|
} |
249 |
|
|
} |