mount_tmpfs.c revision 1.21 1 /* $NetBSD: mount_tmpfs.c,v 1.21 2008/02/13 14:24:12 rillig Exp $ */
2
3 /*
4 * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
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
9 * 2005 program.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
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.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 #include <sys/cdefs.h>
41 #ifndef lint
42 __RCSID("$NetBSD: mount_tmpfs.c,v 1.21 2008/02/13 14:24:12 rillig Exp $");
43 #endif /* not lint */
44
45 #include <sys/param.h>
46 #include <sys/mount.h>
47 #include <sys/stat.h>
48
49 #include <fs/tmpfs/tmpfs.h>
50
51 #include <ctype.h>
52 #include <err.h>
53 #include <errno.h>
54 #include <grp.h>
55 #include <mntopts.h>
56 #include <pwd.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <unistd.h>
61 #include "fattr.h"
62
63 /* --------------------------------------------------------------------- */
64
65 static const struct mntopt mopts[] = {
66 MOPT_STDOPTS,
67 MOPT_GETARGS,
68 MOPT_NULL,
69 };
70
71 /* --------------------------------------------------------------------- */
72
73 static int mount_tmpfs(int argc, char **argv);
74 static void usage(void) __dead;
75
76 /* --------------------------------------------------------------------- */
77
78 int
79 mount_tmpfs(int argc, char *argv[])
80 {
81 char canon_dir[MAXPATHLEN];
82 int gidset, modeset, uidset; /* Ought to be 'bool'. */
83 int ch, mntflags;
84 gid_t gid;
85 uid_t uid;
86 mode_t mode;
87 int64_t tmpnumber;
88 mntoptparse_t mp;
89 struct tmpfs_args args;
90 struct stat sb;
91
92 setprogname(argv[0]);
93
94 /* Set default values for mount point arguments. */
95 args.ta_version = TMPFS_ARGS_VERSION;
96 args.ta_size_max = 0;
97 args.ta_nodes_max = 0;
98 mntflags = 0;
99
100 gidset = 0; gid = 0;
101 uidset = 0; uid = 0;
102 modeset = 0; mode = 0;
103
104 optind = optreset = 1;
105 while ((ch = getopt(argc, argv, "g:m:n:o:s:u:")) != -1 ) {
106 switch (ch) {
107 case 'g':
108 gid = a_gid(optarg);
109 gidset = 1;
110 break;
111
112 case 'm':
113 mode = a_mask(optarg);
114 modeset = 1;
115 break;
116
117 case 'n':
118 if (dehumanize_number(optarg, &tmpnumber) == -1)
119 err(EXIT_FAILURE, "failed to parse nodes `%s'",
120 optarg);
121 args.ta_nodes_max = tmpnumber;
122 break;
123
124 case 'o':
125 mp = getmntopts(optarg, mopts, &mntflags, 0);
126 if (mp == NULL)
127 err(EXIT_FAILURE, "getmntopts");
128 freemntopts(mp);
129 break;
130
131 case 's':
132 if (dehumanize_number(optarg, &tmpnumber) == -1)
133 err(EXIT_FAILURE, "failed to parse size `%s'",
134 optarg);
135 args.ta_size_max = tmpnumber;
136 break;
137
138 case 'u':
139 uid = a_uid(optarg);
140 uidset = 1;
141 break;
142
143 case '?':
144 default:
145 usage();
146 }
147 }
148 argc -= optind;
149 argv += optind;
150
151 if (argc != 2)
152 usage();
153
154 if (realpath(argv[1], canon_dir) == NULL)
155 err(EXIT_FAILURE, "realpath %s", argv[1]);
156
157 if (strncmp(argv[1], canon_dir, MAXPATHLEN) != 0) {
158 warnx("\"%s\" is a relative path", argv[1]);
159 warnx("using \"%s\" instead", canon_dir);
160 }
161
162 if (stat(canon_dir, &sb) == -1)
163 err(EXIT_FAILURE, "cannot stat `%s'", canon_dir);
164
165 args.ta_root_uid = uidset ? uid : sb.st_uid;
166 args.ta_root_gid = gidset ? gid : sb.st_gid;
167 args.ta_root_mode = modeset ? mode : sb.st_mode;
168
169 if (mount(MOUNT_TMPFS, canon_dir, mntflags, &args, sizeof args) == -1)
170 err(EXIT_FAILURE, "tmpfs on %s", canon_dir);
171
172 if (mntflags & MNT_GETARGS) {
173 struct passwd *pw;
174 struct group *gr;
175
176 (void)printf("version=%d, ", args.ta_version);
177 (void)printf("size_max=%" PRIuMAX ", ",
178 (uintmax_t)args.ta_size_max);
179 (void)printf("nodes_max=%" PRIuMAX ", ",
180 (uintmax_t)args.ta_nodes_max);
181
182 pw = getpwuid(args.ta_root_uid);
183 if (pw == NULL)
184 (void)printf("root_uid=%" PRIuMAX ", ",
185 (uintmax_t)args.ta_root_uid);
186 else
187 (void)printf("root_uid=%s, ", pw->pw_name);
188
189 gr = getgrgid(args.ta_root_gid);
190 if (gr == NULL)
191 (void)printf("root_gid=%" PRIuMAX ", ",
192 (uintmax_t)args.ta_root_gid);
193 else
194 (void)printf("root_gid=%s, ", gr->gr_name);
195
196 (void)printf("root_mode=%o\n", args.ta_root_mode);
197 }
198
199 return EXIT_SUCCESS;
200 }
201
202 /* --------------------------------------------------------------------- */
203
204 static void
205 usage(void)
206 {
207 (void)fprintf(stderr,
208 "Usage: %s [-g group] [-m mode] [-n nodes] [-o options] [-s size]\n"
209 " [-u user] tmpfs mountpoint\n", getprogname());
210 exit(1);
211 }
212
213 /* --------------------------------------------------------------------- */
214
215 #ifndef MOUNT_NOMAIN
216 int
217 main(int argc, char *argv[])
218 {
219
220 return mount_tmpfs(argc, argv);
221 }
222 #endif
223