1 /* $NetBSD: mount_tmpfs.c,v 1.20 2007/12/15 19:44:46 perry 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.20 2007/12/15 19:44:46 perry 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[0]); 156 157 if (strncmp(argv[1], canon_dir, MAXPATHLEN) != 0) { 158 warnx("\"%s\" is a relative path", argv[0]); 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