1 /* $NetBSD: mount_tmpfs.c,v 1.23 2008/07/28 12:42:12 pooka 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 * 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. 31 */ 32 33 #include <sys/cdefs.h> 34 #ifndef lint 35 __RCSID("$NetBSD: mount_tmpfs.c,v 1.23 2008/07/28 12:42:12 pooka Exp $"); 36 #endif /* not lint */ 37 38 #include <sys/param.h> 39 #include <sys/mount.h> 40 #include <sys/stat.h> 41 42 #include <fs/tmpfs/tmpfs_args.h> 43 44 #include <ctype.h> 45 #include <err.h> 46 #include <errno.h> 47 #include <grp.h> 48 #include <mntopts.h> 49 #include <pwd.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 #include <unistd.h> 54 #include "fattr.h" 55 56 /* --------------------------------------------------------------------- */ 57 58 static const struct mntopt mopts[] = { 59 MOPT_STDOPTS, 60 MOPT_GETARGS, 61 MOPT_NULL, 62 }; 63 64 /* --------------------------------------------------------------------- */ 65 66 static int mount_tmpfs(int argc, char **argv); 67 static void usage(void) __dead; 68 69 /* --------------------------------------------------------------------- */ 70 71 int 72 mount_tmpfs(int argc, char *argv[]) 73 { 74 char canon_dir[MAXPATHLEN]; 75 int gidset, modeset, uidset; /* Ought to be 'bool'. */ 76 int ch, mntflags; 77 gid_t gid; 78 uid_t uid; 79 mode_t mode; 80 int64_t tmpnumber; 81 mntoptparse_t mp; 82 struct tmpfs_args args; 83 struct stat sb; 84 85 setprogname(argv[0]); 86 87 /* Set default values for mount point arguments. */ 88 args.ta_version = TMPFS_ARGS_VERSION; 89 args.ta_size_max = 0; 90 args.ta_nodes_max = 0; 91 mntflags = 0; 92 93 gidset = 0; gid = 0; 94 uidset = 0; uid = 0; 95 modeset = 0; mode = 0; 96 97 optind = optreset = 1; 98 while ((ch = getopt(argc, argv, "g:m:n:o:s:u:")) != -1 ) { 99 switch (ch) { 100 case 'g': 101 gid = a_gid(optarg); 102 gidset = 1; 103 break; 104 105 case 'm': 106 mode = a_mask(optarg); 107 modeset = 1; 108 break; 109 110 case 'n': 111 if (dehumanize_number(optarg, &tmpnumber) == -1) 112 err(EXIT_FAILURE, "failed to parse nodes `%s'", 113 optarg); 114 args.ta_nodes_max = tmpnumber; 115 break; 116 117 case 'o': 118 mp = getmntopts(optarg, mopts, &mntflags, 0); 119 if (mp == NULL) 120 err(EXIT_FAILURE, "getmntopts"); 121 freemntopts(mp); 122 break; 123 124 case 's': 125 if (dehumanize_number(optarg, &tmpnumber) == -1) 126 err(EXIT_FAILURE, "failed to parse size `%s'", 127 optarg); 128 args.ta_size_max = tmpnumber; 129 break; 130 131 case 'u': 132 uid = a_uid(optarg); 133 uidset = 1; 134 break; 135 136 case '?': 137 default: 138 usage(); 139 } 140 } 141 argc -= optind; 142 argv += optind; 143 144 if (argc != 2) 145 usage(); 146 147 if (realpath(argv[1], canon_dir) == NULL) 148 err(EXIT_FAILURE, "realpath %s", argv[1]); 149 150 if (strncmp(argv[1], canon_dir, MAXPATHLEN) != 0) { 151 warnx("\"%s\" is a relative path", argv[1]); 152 warnx("using \"%s\" instead", canon_dir); 153 } 154 155 if (stat(canon_dir, &sb) == -1) 156 err(EXIT_FAILURE, "cannot stat `%s'", canon_dir); 157 158 args.ta_root_uid = uidset ? uid : sb.st_uid; 159 args.ta_root_gid = gidset ? gid : sb.st_gid; 160 args.ta_root_mode = modeset ? mode : sb.st_mode; 161 162 if (mount(MOUNT_TMPFS, canon_dir, mntflags, &args, sizeof args) == -1) 163 err(EXIT_FAILURE, "tmpfs on %s", canon_dir); 164 165 if (mntflags & MNT_GETARGS) { 166 struct passwd *pw; 167 struct group *gr; 168 169 (void)printf("version=%d, ", args.ta_version); 170 (void)printf("size_max=%" PRIuMAX ", ", 171 (uintmax_t)args.ta_size_max); 172 (void)printf("nodes_max=%" PRIuMAX ", ", 173 (uintmax_t)args.ta_nodes_max); 174 175 pw = getpwuid(args.ta_root_uid); 176 if (pw == NULL) 177 (void)printf("root_uid=%" PRIuMAX ", ", 178 (uintmax_t)args.ta_root_uid); 179 else 180 (void)printf("root_uid=%s, ", pw->pw_name); 181 182 gr = getgrgid(args.ta_root_gid); 183 if (gr == NULL) 184 (void)printf("root_gid=%" PRIuMAX ", ", 185 (uintmax_t)args.ta_root_gid); 186 else 187 (void)printf("root_gid=%s, ", gr->gr_name); 188 189 (void)printf("root_mode=%o\n", args.ta_root_mode); 190 } 191 192 return EXIT_SUCCESS; 193 } 194 195 /* --------------------------------------------------------------------- */ 196 197 static void 198 usage(void) 199 { 200 (void)fprintf(stderr, 201 "Usage: %s [-g group] [-m mode] [-n nodes] [-o options] [-s size]\n" 202 " [-u user] tmpfs mountpoint\n", getprogname()); 203 exit(1); 204 } 205 206 /* --------------------------------------------------------------------- */ 207 208 #ifndef MOUNT_NOMAIN 209 int 210 main(int argc, char *argv[]) 211 { 212 213 return mount_tmpfs(argc, argv); 214 } 215 #endif 216