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 55#include "mountprog.h" 56#include "mount_tmpfs.h" 57 58/* --------------------------------------------------------------------- */ 59 60static const struct mntopt mopts[] = { 61 MOPT_STDOPTS, 62 MOPT_GETARGS, 63 MOPT_NULL, 64}; 65 66/* --------------------------------------------------------------------- */ 67 68static void usage(void) __dead; 69 70/* --------------------------------------------------------------------- */ 71 72void 73mount_tmpfs_parseargs(int argc, char *argv[], 74 struct tmpfs_args *args, int *mntflags, 75 char *canon_dev, char *canon_dir) 76{ 77 int gidset, modeset, uidset; /* Ought to be 'bool'. */ 78 int ch; 79 gid_t gid; 80 uid_t uid; 81 mode_t mode; 82 int64_t tmpnumber; 83 mntoptparse_t mp; 84 struct stat sb; 85 86 /* Set default values for mount point arguments. */ 87 memset(args, 0, sizeof(*args)); 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 strlcpy(canon_dev, argv[0], MAXPATHLEN); 148 pathadj(argv[1], canon_dir); 149 150 if (stat(canon_dir, &sb) == -1) 151 err(EXIT_FAILURE, "cannot stat `%s'", canon_dir); 152 153 args->ta_root_uid = uidset ? uid : sb.st_uid; 154 args->ta_root_gid = gidset ? gid : sb.st_gid; 155 args->ta_root_mode = modeset ? mode : sb.st_mode; 156} 157 158/* --------------------------------------------------------------------- */ 159 160static void 161usage(void) 162{ 163 (void)fprintf(stderr, 164 "Usage: %s [-g group] [-m mode] [-n nodes] [-o options] [-s size]\n" 165 " [-u user] tmpfs mountpoint\n", getprogname()); 166 exit(1); 167} 168 169/* --------------------------------------------------------------------- */ 170 171int 172mount_tmpfs(int argc, char *argv[]) 173{ 174 struct tmpfs_args args; 175 char canon_dev[MAXPATHLEN], canon_dir[MAXPATHLEN]; 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, sizeof args) == -1) 182 err(EXIT_FAILURE, "tmpfs on %s", canon_dir); 183 184 if (mntflags & MNT_GETARGS) { 185 struct passwd *pw; 186 struct group *gr; 187 188 (void)printf("version=%d, ", args.ta_version); 189 (void)printf("size_max=%" PRIuMAX ", ", 190 (uintmax_t)args.ta_size_max); 191 (void)printf("nodes_max=%" PRIuMAX ", ", 192 (uintmax_t)args.ta_nodes_max); 193 194 pw = getpwuid(args.ta_root_uid); 195 if (pw == NULL) 196 (void)printf("root_uid=%" PRIuMAX ", ", 197 (uintmax_t)args.ta_root_uid); 198 else 199 (void)printf("root_uid=%s, ", pw->pw_name); 200 201 gr = getgrgid(args.ta_root_gid); 202 if (gr == NULL) 203 (void)printf("root_gid=%" PRIuMAX ", ", 204 (uintmax_t)args.ta_root_gid); 205 else 206 (void)printf("root_gid=%s, ", gr->gr_name); 207 208 (void)printf("root_mode=%o\n", args.ta_root_mode); 209 } 210 211 return EXIT_SUCCESS; 212} 213 214#ifndef MOUNT_NOMAIN 215int 216main(int argc, char *argv[]) 217{ 218 219 setprogname(argv[0]); 220 return mount_tmpfs(argc, argv); 221} 222#endif 223