1 /* $NetBSD: mount_tmpfs.c,v 1.24 2008/08/05 20:57:45 pooka Exp $ */
4 * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Julio M. Merino Vidal, developed as part of Google's Summer of Code
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/param.h>
34 #include <sys/mount.h>
37 #include <vfs/tmpfs/tmpfs_mount.h>
54 #include "mount_tmpfs.h"
56 /* --------------------------------------------------------------------- */
58 #define MOPT_TMPFSOPTS \
59 { "gid=", 0, MNT_GID, 1}, \
60 { "uid=", 0, MNT_UID, 1}, \
61 { "mode=", 0, MNT_MODE, 1}, \
62 { "inodes=", 0, MNT_INODES, 1}, \
63 { "size=", 0, MNT_SIZE, 1}, \
64 { "maxfilesize=", 0, MNT_MAXFSIZE, 1}
67 static const struct mntopt mopts
[] = {
75 /* --------------------------------------------------------------------- */
77 static gid_t
a_gid(char *);
78 static uid_t
a_uid(char *);
79 static mode_t
a_mask(char *);
80 static int64_t a_number(char *s
);
81 static void usage(void) __dead2
;
83 /* --------------------------------------------------------------------- */
86 mount_tmpfs_parseargs(int argc
, char *argv
[],
87 struct tmpfs_mount_info
*args
, int *mntflags
,
88 char *canon_dev
, char *canon_dir
)
90 int gidset
, modeset
, uidset
; /* Ought to be 'bool'. */
99 /* Set default values for mount point arguments. */
100 memset(args
, 0, sizeof(*args
));
101 args
->ta_version
= TMPFS_ARGS_VERSION
;
102 args
->ta_size_max
= 0;
103 args
->ta_nodes_max
= 0;
104 args
->ta_maxfsize_max
= 0;
109 modeset
= 0; mode
= 0;
111 optind
= optreset
= 1;
112 while ((ch
= getopt(argc
, argv
, "Cf:g:m:n:o:s:u:")) != -1 ) {
118 args
->ta_maxfsize_max
= a_number(optarg
);
127 mode
= a_mask(optarg
);
132 args
->ta_nodes_max
= a_number(optarg
);
136 getmntopts(optarg
, mopts
, mntflags
, &extend_flags
);
137 if (extend_flags
& MNT_GID
) {
138 ptr
= strstr(optarg
, "gid=");
140 delim
= strstr(ptr
, ",");
143 gid
= a_gid(ptr
+ 4);
146 gid
= a_gid(ptr
+ 4);
149 extend_flags
^= MNT_GID
;
151 if (extend_flags
& MNT_UID
) {
152 ptr
= strstr(optarg
, "uid=");
154 delim
= strstr(ptr
, ",");
157 uid
= a_uid(ptr
+ 4);
160 uid
= a_uid(ptr
+ 4);
163 extend_flags
^= MNT_UID
;
165 if (extend_flags
& MNT_MODE
) {
166 ptr
= strstr(optarg
, "mode=");
168 delim
= strstr(ptr
, ",");
171 mode
= a_mask(ptr
+ 5);
174 mode
= a_mask(ptr
+ 5);
177 extend_flags
^= MNT_MODE
;
179 if (extend_flags
& MNT_INODES
) {
180 ptr
= strstr(optarg
, "inodes=");
182 delim
= strstr(ptr
, ",");
185 args
->ta_nodes_max
= a_number(ptr
+ 7);
188 args
->ta_nodes_max
= a_number(ptr
+ 7);
190 extend_flags
^= MNT_INODES
;
192 if (extend_flags
& MNT_SIZE
) {
193 ptr
= strstr(optarg
, "size=");
195 delim
= strstr(ptr
, ",");
198 args
->ta_size_max
= a_number(ptr
+ 5);
201 args
->ta_size_max
= a_number(ptr
+ 5);
203 extend_flags
^= MNT_SIZE
;
205 if (extend_flags
& MNT_MAXFSIZE
) {
206 ptr
= strstr(optarg
, "maxfilesize=");
208 delim
= strstr(ptr
, ",");
211 args
->ta_maxfsize_max
= a_number(ptr
+ 12);
214 args
->ta_maxfsize_max
= a_number(ptr
+ 12);
216 extend_flags
^= MNT_MAXFSIZE
;
221 args
->ta_size_max
= a_number(optarg
);
240 strlcpy(canon_dev
, argv
[0], MAXPATHLEN
);
241 strlcpy(canon_dir
, argv
[1], MAXPATHLEN
);
243 if (stat(canon_dir
, &sb
) == -1)
244 err(EXIT_FAILURE
, "cannot stat `%s'", canon_dir
);
246 args
->ta_root_uid
= uidset
? uid
: sb
.st_uid
;
247 args
->ta_root_gid
= gidset
? gid
: sb
.st_gid
;
248 args
->ta_root_mode
= modeset
? mode
: sb
.st_mode
;
251 /* --------------------------------------------------------------------- */
260 if ((gr
= getgrnam(s
)) != NULL
)
263 for (gname
= s
; *s
&& isdigit(*s
); ++s
);
267 errx(EX_NOUSER
, "unknown group id: %s", gname
);
279 if ((pw
= getpwnam(s
)) != NULL
)
282 for (uname
= s
; *s
&& isdigit(*s
); ++s
);
286 errx(EX_NOUSER
, "unknown user id: %s", uname
);
298 if (*s
>= '0' && *s
<= '7') {
300 rv
= strtol(s
, &ep
, 8);
302 if (!done
|| rv
< 0 || *ep
)
303 errx(EX_USAGE
, "invalid file mode: %s", s
);
312 if (dehumanize_number(s
, &rv
) < 0 || rv
< 0)
313 errx(EX_USAGE
, "bad number for option: %s", s
);
321 "Usage: %s [-C] [-g group] [-m mode] [-n nodes] [-o options] [-s size]\n"
322 " [-u user] [-f maxfilesize] tmpfs mountpoint\n", getprogname());
326 /* --------------------------------------------------------------------- */
329 mount_tmpfs(int argc
, char *argv
[])
331 struct tmpfs_mount_info args
;
332 char canon_dev
[MAXPATHLEN
], canon_dir
[MAXPATHLEN
];
336 fsnode_t copyroot
= NULL
;
337 fsnode_t copyhlinks
= NULL
;
339 mount_tmpfs_parseargs(argc
, argv
, &args
, &mntflags
,
340 canon_dev
, canon_dir
);
342 error
= getvfsbyname("tmpfs", &vfc
);
343 if (error
&& vfsisloadable("tmpfs")) {
345 err(EX_OSERR
, "vfsload(%s)", "tmpfs");
347 error
= getvfsbyname("tmpfs", &vfc
);
350 errx(EX_OSERR
, "%s filesystem not available", "tmpfs");
353 copyroot
= FSCopy(©hlinks
, canon_dir
);
355 if (mount(vfc
.vfc_name
, canon_dir
, mntflags
, &args
) == -1)
356 err(EXIT_FAILURE
, "tmpfs on %s", canon_dir
);
359 FSPaste(canon_dir
, copyroot
, copyhlinks
);
366 main(int argc
, char *argv
[])
368 setprogname(argv
[0]);
369 return mount_tmpfs(argc
, argv
);