14d7de91fSDima Dorfman /* 2d69f5deeSDima Dorfman * Copyright (c) 2001 Dima Dorfman. 34d7de91fSDima Dorfman * All rights reserved. 44d7de91fSDima Dorfman * 54d7de91fSDima Dorfman * Redistribution and use in source and binary forms, with or without 64d7de91fSDima Dorfman * modification, are permitted provided that the following conditions 74d7de91fSDima Dorfman * are met: 84d7de91fSDima Dorfman * 1. Redistributions of source code must retain the above copyright 94d7de91fSDima Dorfman * notice, this list of conditions and the following disclaimer. 104d7de91fSDima Dorfman * 2. Redistributions in binary form must reproduce the above copyright 114d7de91fSDima Dorfman * notice, this list of conditions and the following disclaimer in the 124d7de91fSDima Dorfman * documentation and/or other materials provided with the distribution. 134d7de91fSDima Dorfman * 144d7de91fSDima Dorfman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 154d7de91fSDima Dorfman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 164d7de91fSDima Dorfman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 174d7de91fSDima Dorfman * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 184d7de91fSDima Dorfman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 194d7de91fSDima Dorfman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 204d7de91fSDima Dorfman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 214d7de91fSDima Dorfman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 224d7de91fSDima Dorfman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 234d7de91fSDima Dorfman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 244d7de91fSDima Dorfman * SUCH DAMAGE. 254d7de91fSDima Dorfman */ 264d7de91fSDima Dorfman 274d7de91fSDima Dorfman /* 284d7de91fSDima Dorfman * mdmfs (md/MFS) is a wrapper around mdconfig(8), disklabel(8), 294d7de91fSDima Dorfman * newfs(8), and mount(8) that mimics the command line option set of 304d7de91fSDima Dorfman * the deprecated mount_mfs(8). 314d7de91fSDima Dorfman */ 324d7de91fSDima Dorfman 334d7de91fSDima Dorfman #ifndef lint 344d7de91fSDima Dorfman static const char rcsid[] = 354d7de91fSDima Dorfman "$FreeBSD$"; 364d7de91fSDima Dorfman #endif /* not lint */ 374d7de91fSDima Dorfman 384d7de91fSDima Dorfman #include <sys/param.h> 394d7de91fSDima Dorfman #include <sys/mdioctl.h> 404d7de91fSDima Dorfman #include <sys/stat.h> 414d7de91fSDima Dorfman #include <sys/wait.h> 424d7de91fSDima Dorfman 434d7de91fSDima Dorfman #include <assert.h> 444d7de91fSDima Dorfman #include <err.h> 454d7de91fSDima Dorfman #include <fcntl.h> 464d7de91fSDima Dorfman #include <grp.h> 474d7de91fSDima Dorfman #include <paths.h> 484d7de91fSDima Dorfman #include <pwd.h> 494d7de91fSDima Dorfman #include <stdarg.h> 504d7de91fSDima Dorfman #include <stdio.h> 514d7de91fSDima Dorfman #include <stdlib.h> 524d7de91fSDima Dorfman #include <string.h> 534d7de91fSDima Dorfman #include <unistd.h> 544d7de91fSDima Dorfman 554d7de91fSDima Dorfman #include "pathnames.h" 564d7de91fSDima Dorfman 574d7de91fSDima Dorfman typedef enum { false, true } bool; 584d7de91fSDima Dorfman 594d7de91fSDima Dorfman struct mtpt_info { 604d7de91fSDima Dorfman uid_t mi_uid; 614d7de91fSDima Dorfman bool mi_have_uid; 624d7de91fSDima Dorfman gid_t mi_gid; 634d7de91fSDima Dorfman bool mi_have_gid; 644d7de91fSDima Dorfman mode_t mi_mode; 654d7de91fSDima Dorfman bool mi_have_mode; 664d7de91fSDima Dorfman }; 674d7de91fSDima Dorfman 684d7de91fSDima Dorfman static bool debug; /* Emit debugging information? */ 694d7de91fSDima Dorfman static bool loudsubs; /* Suppress output from helper programs? */ 704d7de91fSDima Dorfman static bool norun; /* Actually run the helper programs? */ 714d7de91fSDima Dorfman static int unit; /* The unit we're working with. */ 724d7de91fSDima Dorfman static const char *mdname; /* Name of memory disk device (e.g., "md"). */ 734d7de91fSDima Dorfman static size_t mdnamelen; /* Length of mdname. */ 744d7de91fSDima Dorfman 75bc56b93aSKris Kennaway static void argappend(char **, const char *, ...) __printflike(2, 3); 76bc56b93aSKris Kennaway static void debugprintf(const char *, ...) __printflike(1, 2); 774d7de91fSDima Dorfman static void do_disklabel(void); 784d7de91fSDima Dorfman static void do_mdconfig_attach(const char *, const enum md_types); 794d7de91fSDima Dorfman static void do_mdconfig_attach_au(const char *, const enum md_types); 804d7de91fSDima Dorfman static void do_mdconfig_detach(void); 814d7de91fSDima Dorfman static void do_mount(const char *, const char *); 824d7de91fSDima Dorfman static void do_mtptsetup(const char *, struct mtpt_info *); 834d7de91fSDima Dorfman static void do_newfs(const char *); 844d7de91fSDima Dorfman static void extract_ugid(const char *, struct mtpt_info *); 85bc56b93aSKris Kennaway static int run(int *, const char *, ...) __printflike(2, 3); 864d7de91fSDima Dorfman static void usage(void); 874d7de91fSDima Dorfman 884d7de91fSDima Dorfman int 8994ddc5afSDavid E. O'Brien main(int argc, char **argv) 904d7de91fSDima Dorfman { 914d7de91fSDima Dorfman struct mtpt_info mi; /* Mountpoint info. */ 924d7de91fSDima Dorfman char *mdconfig_arg, *newfs_arg, /* Args to helper programs. */ 934d7de91fSDima Dorfman *mount_arg; 944d7de91fSDima Dorfman enum md_types mdtype; /* The type of our memory disk. */ 954d7de91fSDima Dorfman bool have_mdtype; 964d7de91fSDima Dorfman bool detach, softdep, autounit; 974d7de91fSDima Dorfman char *mtpoint, *unitstr; 984d7de91fSDima Dorfman char ch, *p; 994d7de91fSDima Dorfman 1004d7de91fSDima Dorfman /* Misc. initialization. */ 1014d7de91fSDima Dorfman (void)memset(&mi, '\0', sizeof(mi)); 1024d7de91fSDima Dorfman detach = true; 1034d7de91fSDima Dorfman softdep = true; 1044d7de91fSDima Dorfman autounit = false; 1054d7de91fSDima Dorfman have_mdtype = false; 1064d7de91fSDima Dorfman mdname = MD_NAME; 1074d7de91fSDima Dorfman mdnamelen = strlen(mdname); 1084d7de91fSDima Dorfman /* 1094d7de91fSDima Dorfman * Can't set these to NULL. They may be passed to the 1104d7de91fSDima Dorfman * respective programs without modification. I.e., we may not 1114d7de91fSDima Dorfman * receive any command-line options which will caused them to 1124d7de91fSDima Dorfman * be modified. 1134d7de91fSDima Dorfman */ 1144d7de91fSDima Dorfman mdconfig_arg = strdup(""); 1154d7de91fSDima Dorfman newfs_arg = strdup(""); 1164d7de91fSDima Dorfman mount_arg = strdup(""); 1174d7de91fSDima Dorfman 11894ddc5afSDavid E. O'Brien while ((ch = getopt(argc, argv, 1194d7de91fSDima Dorfman "a:b:c:Dd:e:F:f:hi:LMm:Nn:O:o:p:Ss:t:w:X")) != -1) 1204d7de91fSDima Dorfman switch (ch) { 1214d7de91fSDima Dorfman case 'a': 1224d7de91fSDima Dorfman argappend(&newfs_arg, "-a %s", optarg); 1234d7de91fSDima Dorfman break; 1244d7de91fSDima Dorfman case 'b': 1254d7de91fSDima Dorfman argappend(&newfs_arg, "-b %s", optarg); 1264d7de91fSDima Dorfman break; 1274d7de91fSDima Dorfman case 'c': 1284d7de91fSDima Dorfman argappend(&newfs_arg, "-c %s", optarg); 1294d7de91fSDima Dorfman break; 1304d7de91fSDima Dorfman case 'D': 1314d7de91fSDima Dorfman detach = false; 1324d7de91fSDima Dorfman break; 1334d7de91fSDima Dorfman case 'd': 1344d7de91fSDima Dorfman argappend(&newfs_arg, "-d %s", optarg); 1354d7de91fSDima Dorfman break; 1364d7de91fSDima Dorfman case 'e': 1374d7de91fSDima Dorfman argappend(&newfs_arg, "-e %s", optarg); 1384d7de91fSDima Dorfman break; 1394d7de91fSDima Dorfman case 'F': 1404d7de91fSDima Dorfman if (have_mdtype) 1414d7de91fSDima Dorfman usage(); 1424d7de91fSDima Dorfman mdtype = MD_VNODE; 1434d7de91fSDima Dorfman have_mdtype = true; 1444d7de91fSDima Dorfman argappend(&mdconfig_arg, "-f %s", optarg); 1454d7de91fSDima Dorfman break; 1464d7de91fSDima Dorfman case 'f': 1474d7de91fSDima Dorfman argappend(&newfs_arg, "-f %s", optarg); 1484d7de91fSDima Dorfman break; 1494d7de91fSDima Dorfman case 'h': 1504d7de91fSDima Dorfman usage(); 1514d7de91fSDima Dorfman break; 1524d7de91fSDima Dorfman case 'i': 1534d7de91fSDima Dorfman argappend(&newfs_arg, "-i %s", optarg); 1544d7de91fSDima Dorfman break; 1554d7de91fSDima Dorfman case 'L': 1564d7de91fSDima Dorfman loudsubs = true; 1574d7de91fSDima Dorfman break; 1584d7de91fSDima Dorfman case 'M': 1594d7de91fSDima Dorfman if (have_mdtype) 1604d7de91fSDima Dorfman usage(); 1614d7de91fSDima Dorfman mdtype = MD_MALLOC; 1624d7de91fSDima Dorfman have_mdtype = true; 1634d7de91fSDima Dorfman break; 1644d7de91fSDima Dorfman case 'm': 1654d7de91fSDima Dorfman argappend(&newfs_arg, "-m %s", optarg); 1664d7de91fSDima Dorfman break; 1674d7de91fSDima Dorfman case 'N': 1684d7de91fSDima Dorfman norun = true; 1694d7de91fSDima Dorfman break; 1704d7de91fSDima Dorfman case 'n': 1714d7de91fSDima Dorfman argappend(&newfs_arg, "-n %s", optarg); 1724d7de91fSDima Dorfman break; 1734d7de91fSDima Dorfman case 'O': 1744d7de91fSDima Dorfman argappend(&newfs_arg, "-o %s", optarg); 1754d7de91fSDima Dorfman break; 1764d7de91fSDima Dorfman case 'o': 1774d7de91fSDima Dorfman argappend(&mount_arg, "-o %s", optarg); 1784d7de91fSDima Dorfman break; 1794d7de91fSDima Dorfman case 'p': 1804d7de91fSDima Dorfman if (*optarg >= '0' && *optarg <= '7') 1814d7de91fSDima Dorfman mi.mi_mode = strtol(optarg, NULL, 8); 1824d7de91fSDima Dorfman if ((mi.mi_mode & ~07777) != 0) 1834d7de91fSDima Dorfman usage(); 1844d7de91fSDima Dorfman mi.mi_have_mode = true; 1854d7de91fSDima Dorfman break; 1864d7de91fSDima Dorfman case 'S': 1874d7de91fSDima Dorfman softdep = false; 1884d7de91fSDima Dorfman break; 1894d7de91fSDima Dorfman case 's': 1904d7de91fSDima Dorfman argappend(&mdconfig_arg, "-s %s", optarg); 1914d7de91fSDima Dorfman break; 1924d7de91fSDima Dorfman case 'w': 1934d7de91fSDima Dorfman extract_ugid(optarg, &mi); 1944d7de91fSDima Dorfman break; 1954d7de91fSDima Dorfman case 'X': 1964d7de91fSDima Dorfman debug = true; 1974d7de91fSDima Dorfman break; 1984d7de91fSDima Dorfman default: 1994d7de91fSDima Dorfman usage(); 2004d7de91fSDima Dorfman } 20194ddc5afSDavid E. O'Brien argc -= optind; 20294ddc5afSDavid E. O'Brien argv += optind; 20394ddc5afSDavid E. O'Brien if (argc < 2) 2044d7de91fSDima Dorfman usage(); 2054d7de91fSDima Dorfman 2064d7de91fSDima Dorfman /* Derive 'unit' (global). */ 20794ddc5afSDavid E. O'Brien unitstr = argv[0]; 2084d7de91fSDima Dorfman if (strncmp(unitstr, "/dev/", 5) == 0) 2094d7de91fSDima Dorfman unitstr += 5; 2104d7de91fSDima Dorfman if (strncmp(unitstr, mdname, mdnamelen) == 0) 2114d7de91fSDima Dorfman unitstr += mdnamelen; 2124d7de91fSDima Dorfman if (*unitstr == '\0') { 2134d7de91fSDima Dorfman autounit = true; 2144d7de91fSDima Dorfman unit = -1; 2154d7de91fSDima Dorfman } else { 2164d7de91fSDima Dorfman unit = strtoul(unitstr, &p, 10); 2174d7de91fSDima Dorfman if ((unsigned)unit == ULONG_MAX || *p != '\0') 2184d7de91fSDima Dorfman errx(1, "bad device unit: %s", unitstr); 2194d7de91fSDima Dorfman } 2204d7de91fSDima Dorfman 22194ddc5afSDavid E. O'Brien mtpoint = argv[1]; 2224d7de91fSDima Dorfman if (!have_mdtype) 2234d7de91fSDima Dorfman mdtype = MD_SWAP; 2244d7de91fSDima Dorfman if (softdep) 2254d7de91fSDima Dorfman argappend(&newfs_arg, "-U"); 2264d7de91fSDima Dorfman 2274d7de91fSDima Dorfman /* Do the work. */ 2284d7de91fSDima Dorfman if (detach && !autounit) 2294d7de91fSDima Dorfman do_mdconfig_detach(); 2304d7de91fSDima Dorfman if (autounit) 2314d7de91fSDima Dorfman do_mdconfig_attach_au(mdconfig_arg, mdtype); 2324d7de91fSDima Dorfman else 2334d7de91fSDima Dorfman do_mdconfig_attach(mdconfig_arg, mdtype); 2344d7de91fSDima Dorfman do_disklabel(); 2354d7de91fSDima Dorfman do_newfs(newfs_arg); 2364d7de91fSDima Dorfman do_mount(mount_arg, mtpoint); 2374d7de91fSDima Dorfman do_mtptsetup(mtpoint, &mi); 2384d7de91fSDima Dorfman 2394d7de91fSDima Dorfman return (0); 2404d7de91fSDima Dorfman } 2414d7de91fSDima Dorfman 2424d7de91fSDima Dorfman /* 2434d7de91fSDima Dorfman * Append the expansion of 'fmt' to the buffer pointed to by '*dstp'; 2444d7de91fSDima Dorfman * reallocate as required. 2454d7de91fSDima Dorfman */ 2464d7de91fSDima Dorfman static void 2474d7de91fSDima Dorfman argappend(char **dstp, const char *fmt, ...) 2484d7de91fSDima Dorfman { 2494d7de91fSDima Dorfman char *old, *new; 2504d7de91fSDima Dorfman va_list ap; 2514d7de91fSDima Dorfman 2524d7de91fSDima Dorfman old = *dstp; 2534d7de91fSDima Dorfman assert(old != NULL); 2544d7de91fSDima Dorfman 2554d7de91fSDima Dorfman va_start(ap, fmt); 2564d7de91fSDima Dorfman if (vasprintf(&new, fmt,ap) == -1) 2574d7de91fSDima Dorfman errx(1, "vasprintf"); 2584d7de91fSDima Dorfman va_end(ap); 2594d7de91fSDima Dorfman 2604d7de91fSDima Dorfman *dstp = new; 2614d7de91fSDima Dorfman if (asprintf(&new, "%s %s", old, new) == -1) 2624d7de91fSDima Dorfman errx(1, "asprintf"); 2634d7de91fSDima Dorfman free(*dstp); 2644d7de91fSDima Dorfman free(old); 2654d7de91fSDima Dorfman 2664d7de91fSDima Dorfman *dstp = new; 2674d7de91fSDima Dorfman } 2684d7de91fSDima Dorfman 2694d7de91fSDima Dorfman /* 2704d7de91fSDima Dorfman * If run-time debugging is enabled, print the expansion of 'fmt'. 2714d7de91fSDima Dorfman * Otherwise, do nothing. 2724d7de91fSDima Dorfman */ 2734d7de91fSDima Dorfman static void 2744d7de91fSDima Dorfman debugprintf(const char *fmt, ...) 2754d7de91fSDima Dorfman { 2764d7de91fSDima Dorfman va_list ap; 2774d7de91fSDima Dorfman 2784d7de91fSDima Dorfman if (!debug) 2794d7de91fSDima Dorfman return; 2804d7de91fSDima Dorfman fprintf(stderr, "DEBUG: "); 2814d7de91fSDima Dorfman va_start(ap, fmt); 2824d7de91fSDima Dorfman vfprintf(stderr, fmt, ap); 2834d7de91fSDima Dorfman va_end(ap); 2844d7de91fSDima Dorfman fprintf(stderr, "\n"); 2854d7de91fSDima Dorfman fflush(stderr); 2864d7de91fSDima Dorfman } 2874d7de91fSDima Dorfman 2884d7de91fSDima Dorfman /* 2894d7de91fSDima Dorfman * Label the memory disk. 2904d7de91fSDima Dorfman */ 2914d7de91fSDima Dorfman static void 2924d7de91fSDima Dorfman do_disklabel(void) 2934d7de91fSDima Dorfman { 2944d7de91fSDima Dorfman int rv; 2954d7de91fSDima Dorfman 2964d7de91fSDima Dorfman rv = run(NULL, "%s -r -w %s%d auto", PATH_DISKLABEL, mdname, unit); 2974d7de91fSDima Dorfman if (rv) 2984d7de91fSDima Dorfman errx(1, "disklabel exited with error code %d", rv); 2994d7de91fSDima Dorfman } 3004d7de91fSDima Dorfman 3014d7de91fSDima Dorfman /* 3024d7de91fSDima Dorfman * Attach a memory disk with a known unit. 3034d7de91fSDima Dorfman */ 3044d7de91fSDima Dorfman static void 3054d7de91fSDima Dorfman do_mdconfig_attach(const char *args, const enum md_types mdtype) 3064d7de91fSDima Dorfman { 3074d7de91fSDima Dorfman int rv; 3084d7de91fSDima Dorfman const char *ta; /* Type arg. */ 3094d7de91fSDima Dorfman 3104d7de91fSDima Dorfman switch (mdtype) { 3114d7de91fSDima Dorfman case MD_SWAP: 3124d7de91fSDima Dorfman ta = "-t swap"; 3134d7de91fSDima Dorfman break; 3144d7de91fSDima Dorfman case MD_VNODE: 3154d7de91fSDima Dorfman ta = "-t vnode"; 3164d7de91fSDima Dorfman break; 3174d7de91fSDima Dorfman case MD_MALLOC: 3184d7de91fSDima Dorfman ta = "-t malloc"; 3194d7de91fSDima Dorfman break; 3204d7de91fSDima Dorfman default: 3214d7de91fSDima Dorfman abort(); 3224d7de91fSDima Dorfman } 3234d7de91fSDima Dorfman rv = run(NULL, "%s -a %s%s -u %s%d", PATH_MDCONFIG, ta, args, 3244d7de91fSDima Dorfman mdname, unit); 3254d7de91fSDima Dorfman if (rv) 3264d7de91fSDima Dorfman errx(1, "mdconfig (attach) exited with error code %d", rv); 3274d7de91fSDima Dorfman } 3284d7de91fSDima Dorfman 3294d7de91fSDima Dorfman /* 3304d7de91fSDima Dorfman * Attach a memory disk with an unknown unit; use autounit. 3314d7de91fSDima Dorfman */ 3324d7de91fSDima Dorfman static void 3334d7de91fSDima Dorfman do_mdconfig_attach_au(const char *args, const enum md_types mdtype) 3344d7de91fSDima Dorfman { 3354d7de91fSDima Dorfman const char *ta; /* Type arg. */ 3364d7de91fSDima Dorfman char *linep, *linebuf; /* Line pointer, line buffer. */ 3374d7de91fSDima Dorfman int fd; /* Standard output of mdconfig invocation. */ 3384d7de91fSDima Dorfman FILE *sfd; 3394d7de91fSDima Dorfman int rv; 3404d7de91fSDima Dorfman char *p; 3414d7de91fSDima Dorfman size_t linelen; 3424d7de91fSDima Dorfman 3434d7de91fSDima Dorfman switch (mdtype) { 3444d7de91fSDima Dorfman case MD_SWAP: 3454d7de91fSDima Dorfman ta = "-t swap"; 3464d7de91fSDima Dorfman break; 3474d7de91fSDima Dorfman case MD_VNODE: 3484d7de91fSDima Dorfman ta = "-t vnode"; 3494d7de91fSDima Dorfman break; 3504d7de91fSDima Dorfman case MD_MALLOC: 3514d7de91fSDima Dorfman ta = "-t malloc"; 3524d7de91fSDima Dorfman break; 3534d7de91fSDima Dorfman default: 3544d7de91fSDima Dorfman abort(); 3554d7de91fSDima Dorfman } 3564d7de91fSDima Dorfman rv = run(&fd, "%s -a %s%s", PATH_MDCONFIG, ta, args); 3574d7de91fSDima Dorfman if (rv) 3584d7de91fSDima Dorfman errx(1, "mdconfig (attach) exited with error code %d", rv); 3594d7de91fSDima Dorfman 3604d7de91fSDima Dorfman /* Receive the unit number. */ 3614d7de91fSDima Dorfman if (norun) { /* Since we didn't run, we can't read. Fake it. */ 3624d7de91fSDima Dorfman unit = -1; 3634d7de91fSDima Dorfman return; 3644d7de91fSDima Dorfman } 3654d7de91fSDima Dorfman sfd = fdopen(fd, "r"); 3664d7de91fSDima Dorfman if (sfd == NULL) 3674d7de91fSDima Dorfman err(1, "fdopen"); 3684d7de91fSDima Dorfman linep = fgetln(sfd, &linelen); 3694d7de91fSDima Dorfman if (linep == NULL && linelen < mdnamelen + 1) 3704d7de91fSDima Dorfman errx(1, "unexpected output from mdconfig (attach)"); 3714d7de91fSDima Dorfman /* If the output format changes, we want to know about it. */ 3724d7de91fSDima Dorfman assert(strncmp(linep, mdname, mdnamelen) == 0); 3734d7de91fSDima Dorfman linebuf = malloc(linelen - mdnamelen + 1); 3744d7de91fSDima Dorfman assert(linebuf != NULL); 3754d7de91fSDima Dorfman /* Can't use strlcpy because linep is not NULL-terminated. */ 3764d7de91fSDima Dorfman strncpy(linebuf, linep + mdnamelen, linelen); 3774d7de91fSDima Dorfman linebuf[linelen] = '\0'; 3784d7de91fSDima Dorfman unit = strtoul(linebuf, &p, 10); 3794d7de91fSDima Dorfman if ((unsigned)unit == ULONG_MAX || *p != '\n') 3804d7de91fSDima Dorfman errx(1, "unexpected output from mdconfig (attach)"); 3814d7de91fSDima Dorfman 3824d7de91fSDima Dorfman fclose(sfd); 3834d7de91fSDima Dorfman close(fd); 3844d7de91fSDima Dorfman } 3854d7de91fSDima Dorfman 3864d7de91fSDima Dorfman /* 3874d7de91fSDima Dorfman * Detach a memory disk. 3884d7de91fSDima Dorfman */ 3894d7de91fSDima Dorfman static void 3904d7de91fSDima Dorfman do_mdconfig_detach(void) 3914d7de91fSDima Dorfman { 3924d7de91fSDima Dorfman int rv; 3934d7de91fSDima Dorfman 3944d7de91fSDima Dorfman rv = run(NULL, "%s -d -u %s%d", PATH_MDCONFIG, mdname, unit); 3954d7de91fSDima Dorfman if (rv && debug) /* This is allowed to fail. */ 3964d7de91fSDima Dorfman warnx("mdconfig (detach) exited with error code %d (ignored)", 3974d7de91fSDima Dorfman rv); 3984d7de91fSDima Dorfman } 3994d7de91fSDima Dorfman 4004d7de91fSDima Dorfman /* 4014d7de91fSDima Dorfman * Mount the configured memory disk. 4024d7de91fSDima Dorfman */ 4034d7de91fSDima Dorfman static void 4044d7de91fSDima Dorfman do_mount(const char *args, const char *mtpoint) 4054d7de91fSDima Dorfman { 4064d7de91fSDima Dorfman int rv; 4074d7de91fSDima Dorfman 4084d7de91fSDima Dorfman rv = run(NULL, "%s%s /dev/%s%dc %s", PATH_MOUNT, args, 4094d7de91fSDima Dorfman mdname, unit, mtpoint); 4104d7de91fSDima Dorfman if (rv) 4114d7de91fSDima Dorfman errx(1, "mount exited with error code %d", rv); 4124d7de91fSDima Dorfman } 4134d7de91fSDima Dorfman 4144d7de91fSDima Dorfman /* 4154d7de91fSDima Dorfman * Various configuration of the mountpoint. Mostly, enact 'mip'. 4164d7de91fSDima Dorfman */ 4174d7de91fSDima Dorfman static void 4184d7de91fSDima Dorfman do_mtptsetup(const char *mtpoint, struct mtpt_info *mip) 4194d7de91fSDima Dorfman { 4204d7de91fSDima Dorfman 4214d7de91fSDima Dorfman if (mip->mi_have_mode) { 4224d7de91fSDima Dorfman debugprintf("changing mode of %s to %o.", mtpoint, 4234d7de91fSDima Dorfman mip->mi_mode); 4244d7de91fSDima Dorfman if (!norun) 4254d7de91fSDima Dorfman if (chmod(mtpoint, mip->mi_mode) == -1) 4264d7de91fSDima Dorfman err(1, "chmod: %s", mtpoint); 4274d7de91fSDima Dorfman } 4284d7de91fSDima Dorfman /* 4294d7de91fSDima Dorfman * We have to do these separately because the user may have 4304d7de91fSDima Dorfman * only specified one of them. 4314d7de91fSDima Dorfman */ 4324d7de91fSDima Dorfman if (mip->mi_have_uid) { 4334d7de91fSDima Dorfman debugprintf("changing owner (user) or %s to %u.", mtpoint, 4344d7de91fSDima Dorfman mip->mi_uid); 4354d7de91fSDima Dorfman if (!norun) 4364d7de91fSDima Dorfman if (chown(mtpoint, mip->mi_uid, -1) == -1) 4374d7de91fSDima Dorfman err(1, "chown %s to %u (user)", mtpoint, 4384d7de91fSDima Dorfman mip->mi_uid); 4394d7de91fSDima Dorfman } 4404d7de91fSDima Dorfman if (mip->mi_have_gid) { 4414d7de91fSDima Dorfman debugprintf("changing owner (group) or %s to %u.", mtpoint, 4424d7de91fSDima Dorfman mip->mi_gid); 4434d7de91fSDima Dorfman if (!norun) 4444d7de91fSDima Dorfman if (chown(mtpoint, -1, mip->mi_gid) == -1) 4454d7de91fSDima Dorfman err(1, "chown %s to %u (group)", mtpoint, 4464d7de91fSDima Dorfman mip->mi_gid); 4474d7de91fSDima Dorfman } 4484d7de91fSDima Dorfman } 4494d7de91fSDima Dorfman 4504d7de91fSDima Dorfman /* 4514d7de91fSDima Dorfman * Put a filesystem on the memory disk. 4524d7de91fSDima Dorfman */ 4534d7de91fSDima Dorfman static void 4544d7de91fSDima Dorfman do_newfs(const char *args) 4554d7de91fSDima Dorfman { 4564d7de91fSDima Dorfman int rv; 4574d7de91fSDima Dorfman 4584d7de91fSDima Dorfman rv = run(NULL, "%s%s /dev/%s%dc", PATH_NEWFS, args, mdname, unit); 4594d7de91fSDima Dorfman if (rv) 4604d7de91fSDima Dorfman errx(1, "newfs exited with error code %d", rv); 4614d7de91fSDima Dorfman } 4624d7de91fSDima Dorfman 4634d7de91fSDima Dorfman /* 4644d7de91fSDima Dorfman * 'str' should be a user and group name similar to the last argument 4654d7de91fSDima Dorfman * to chown(1); i.e., a user, followed by a colon, followed by a 4664d7de91fSDima Dorfman * group. The user and group in 'str' may be either a [ug]id or a 4674d7de91fSDima Dorfman * name. Upon return, the uid and gid fields in 'mip' will contain 4684d7de91fSDima Dorfman * the uid and gid of the user and group name in 'str', respectively. 4694d7de91fSDima Dorfman * 4704d7de91fSDima Dorfman * In other words, this derives a user and group id from a string 4714d7de91fSDima Dorfman * formatted like the last argument to chown(1). 4724d7de91fSDima Dorfman */ 4734d7de91fSDima Dorfman static void 4744d7de91fSDima Dorfman extract_ugid(const char *str, struct mtpt_info *mip) 4754d7de91fSDima Dorfman { 4764d7de91fSDima Dorfman char *ug; /* Writable 'str'. */ 4774d7de91fSDima Dorfman char *user, *group; /* Result of extracton. */ 4784d7de91fSDima Dorfman struct passwd *pw; 4794d7de91fSDima Dorfman struct group *gr; 4804d7de91fSDima Dorfman char *p; 4814d7de91fSDima Dorfman uid_t *uid; 4824d7de91fSDima Dorfman gid_t *gid; 4834d7de91fSDima Dorfman 4844d7de91fSDima Dorfman uid = &mip->mi_uid; 4854d7de91fSDima Dorfman gid = &mip->mi_gid; 4864d7de91fSDima Dorfman mip->mi_have_uid = mip->mi_have_gid = false; 4874d7de91fSDima Dorfman 4884d7de91fSDima Dorfman /* Extract the user and group from 'str'. Format above. */ 4898d3c1246SDima Dorfman ug = strdup(str); 4904d7de91fSDima Dorfman assert(ug != NULL); 4914d7de91fSDima Dorfman group = ug; 4924d7de91fSDima Dorfman user = strsep(&group, ":"); 4934d7de91fSDima Dorfman if (user == NULL || group == NULL || *user == '\0' || *group == '\0') 4944d7de91fSDima Dorfman usage(); 4954d7de91fSDima Dorfman 4964d7de91fSDima Dorfman /* Derive uid. */ 4974d7de91fSDima Dorfman *uid = strtoul(user, &p, 10); 4984d7de91fSDima Dorfman if ((unsigned)*uid == ULONG_MAX) 4994d7de91fSDima Dorfman usage(); 5004d7de91fSDima Dorfman if (*p != '\0') { 5014d7de91fSDima Dorfman pw = getpwnam(user); 5024d7de91fSDima Dorfman if (pw == NULL) 5034d7de91fSDima Dorfman errx(1, "invalid user: %s", user); 5044d7de91fSDima Dorfman *uid = pw->pw_uid; 5054d7de91fSDima Dorfman mip->mi_have_uid = true; 5064d7de91fSDima Dorfman } 5074d7de91fSDima Dorfman 5084d7de91fSDima Dorfman /* Derive gid. */ 5094d7de91fSDima Dorfman *gid = strtoul(group, &p, 10); 5104d7de91fSDima Dorfman if ((unsigned)*gid == ULONG_MAX) 5114d7de91fSDima Dorfman usage(); 5124d7de91fSDima Dorfman if (*p != '\0') { 5134d7de91fSDima Dorfman gr = getgrnam(group); 5144d7de91fSDima Dorfman if (gr == NULL) 5154d7de91fSDima Dorfman errx(1, "invalid group: %s", group); 5164d7de91fSDima Dorfman *gid = gr->gr_gid; 5174d7de91fSDima Dorfman mip->mi_have_gid = true; 5184d7de91fSDima Dorfman } 5194d7de91fSDima Dorfman 5204d7de91fSDima Dorfman free(ug); 5214d7de91fSDima Dorfman /* 5224d7de91fSDima Dorfman * At this point we don't support only a username or only a 5234d7de91fSDima Dorfman * group name. do_mtptsetup already does, so when this 5244d7de91fSDima Dorfman * feature is desired, this is the only routine that needs to 5254d7de91fSDima Dorfman * be changed. 5264d7de91fSDima Dorfman */ 5274d7de91fSDima Dorfman assert(mip->mi_have_uid); 5284d7de91fSDima Dorfman assert(mip->mi_have_gid); 5294d7de91fSDima Dorfman } 5304d7de91fSDima Dorfman 5314d7de91fSDima Dorfman /* 5324d7de91fSDima Dorfman * Run a process with command name and arguments pointed to by the 5334d7de91fSDima Dorfman * formatted string 'cmdline'. Since system(3) is not used, the first 5344d7de91fSDima Dorfman * space-delimited token of 'cmdline' must be the full pathname of the 5354d7de91fSDima Dorfman * program to run. The return value is the return code of the process 5364d7de91fSDima Dorfman * spawned. If 'ofd' is non-NULL, it is set to the standard output of 5374d7de91fSDima Dorfman * the program spawned (i.e., you can read from ofd and get the output 5384d7de91fSDima Dorfman * of the program). 5394d7de91fSDima Dorfman */ 5404d7de91fSDima Dorfman static int 5414d7de91fSDima Dorfman run(int *ofd, const char *cmdline, ...) 5424d7de91fSDima Dorfman { 54394ddc5afSDavid E. O'Brien char **argv, **argvp; /* Result of splitting 'cmd'. */ 54494ddc5afSDavid E. O'Brien int argc; 5454d7de91fSDima Dorfman char *cmd; /* Expansion of 'cmdline'. */ 5464d7de91fSDima Dorfman int pid, status; /* Child info. */ 5474d7de91fSDima Dorfman int pfd[2]; /* Pipe to the child. */ 5484d7de91fSDima Dorfman int nfd; /* Null (/dev/null) file descriptor. */ 5494d7de91fSDima Dorfman bool dup2dn; /* Dup /dev/null to stdout? */ 5504d7de91fSDima Dorfman va_list ap; 5514d7de91fSDima Dorfman char *p; 5524d7de91fSDima Dorfman int rv, i; 5534d7de91fSDima Dorfman 5544d7de91fSDima Dorfman dup2dn = true; 5554d7de91fSDima Dorfman va_start(ap, cmdline); 5564d7de91fSDima Dorfman rv = vasprintf(&cmd, cmdline, ap); 5574d7de91fSDima Dorfman if (rv == -1) 5584d7de91fSDima Dorfman err(1, "vasprintf"); 5594d7de91fSDima Dorfman va_end(ap); 5604d7de91fSDima Dorfman 56194ddc5afSDavid E. O'Brien /* Split up 'cmd' into 'argv' for use with execve. */ 56294ddc5afSDavid E. O'Brien for (argc = 1, p = cmd; (p = strchr(p, ' ')) != NULL; p++) 56394ddc5afSDavid E. O'Brien argc++; /* 'argc' generation loop. */ 56494ddc5afSDavid E. O'Brien argv = (char **)malloc(sizeof(*argv) * (argc + 1)); 56594ddc5afSDavid E. O'Brien assert(argv != NULL); 56694ddc5afSDavid E. O'Brien for (p = cmd, argvp = argv; (*argvp = strsep(&p, " ")) != NULL;) 56794ddc5afSDavid E. O'Brien if (**argv != '\0') 56894ddc5afSDavid E. O'Brien if (++argvp >= &argv[argc]) { 56994ddc5afSDavid E. O'Brien *argvp = NULL; 5704d7de91fSDima Dorfman break; 5714d7de91fSDima Dorfman } 57294ddc5afSDavid E. O'Brien assert(*argv); 5734d7de91fSDima Dorfman 5744d7de91fSDima Dorfman /* Make sure the above loop works as expected. */ 5754d7de91fSDima Dorfman if (debug) { 5764d7de91fSDima Dorfman /* 5774d7de91fSDima Dorfman * We can't, but should, use debugprintf here. First, 5784d7de91fSDima Dorfman * it appends a trailing newline to the output, and 5794d7de91fSDima Dorfman * second it prepends "DEBUG: " to the output. The 5804d7de91fSDima Dorfman * former is a problem for this would-be first call, 5814d7de91fSDima Dorfman * and the latter for the would-be call inside the 5824d7de91fSDima Dorfman * loop. 5834d7de91fSDima Dorfman */ 5844d7de91fSDima Dorfman (void)fprintf(stderr, "DEBUG: running:"); 5854d7de91fSDima Dorfman /* Should be equivilent to 'cmd' (before strsep, of course). */ 58694ddc5afSDavid E. O'Brien for (i = 0; argv[i] != NULL; i++) 58794ddc5afSDavid E. O'Brien (void)fprintf(stderr, " %s", argv[i]); 5884d7de91fSDima Dorfman (void)fprintf(stderr, "\n"); 5894d7de91fSDima Dorfman } 5904d7de91fSDima Dorfman 5914d7de91fSDima Dorfman /* Create a pipe if necessary and fork the helper program. */ 5924d7de91fSDima Dorfman if (ofd != NULL) { 5934d7de91fSDima Dorfman if (pipe(&pfd[0]) == -1) 5944d7de91fSDima Dorfman err(1, "pipe"); 5954d7de91fSDima Dorfman *ofd = pfd[0]; 5964d7de91fSDima Dorfman dup2dn = false; 5974d7de91fSDima Dorfman } 5984d7de91fSDima Dorfman pid = fork(); 5994d7de91fSDima Dorfman switch (pid) { 6004d7de91fSDima Dorfman case 0: 6014d7de91fSDima Dorfman /* XXX can we call err() in here? */ 6024d7de91fSDima Dorfman if (norun) 6034d7de91fSDima Dorfman _exit(0); 6044d7de91fSDima Dorfman if (ofd != NULL) 6054d7de91fSDima Dorfman if (dup2(pfd[1], STDOUT_FILENO) < 0) 6064d7de91fSDima Dorfman err(1, "dup2"); 6074d7de91fSDima Dorfman if (!loudsubs) { 6084d7de91fSDima Dorfman nfd = open(_PATH_DEVNULL, O_RDWR); 6094d7de91fSDima Dorfman if (nfd == -1) 6104d7de91fSDima Dorfman err(1, "open: %s", _PATH_DEVNULL); 6114d7de91fSDima Dorfman if (dup2(nfd, STDIN_FILENO) < 0) 6124d7de91fSDima Dorfman err(1, "dup2"); 6134d7de91fSDima Dorfman if (dup2dn) 6144d7de91fSDima Dorfman if (dup2(nfd, STDOUT_FILENO) < 0) 6154d7de91fSDima Dorfman err(1, "dup2"); 6164d7de91fSDima Dorfman if (dup2(nfd, STDERR_FILENO) < 0) 6174d7de91fSDima Dorfman err(1, "dup2"); 6184d7de91fSDima Dorfman } 6194d7de91fSDima Dorfman 62094ddc5afSDavid E. O'Brien (void)execv(argv[0], argv); 62194ddc5afSDavid E. O'Brien warn("exec: %s", argv[0]); 6224d7de91fSDima Dorfman _exit(-1); 6234d7de91fSDima Dorfman case -1: 6244d7de91fSDima Dorfman err(1, "fork"); 6254d7de91fSDima Dorfman } 6264d7de91fSDima Dorfman 6274d7de91fSDima Dorfman free(cmd); 62894ddc5afSDavid E. O'Brien free(argv); 6294d7de91fSDima Dorfman while (waitpid(pid, &status, 0) != pid) 6304d7de91fSDima Dorfman ; 6314d7de91fSDima Dorfman return (WEXITSTATUS(status)); 6324d7de91fSDima Dorfman } 6334d7de91fSDima Dorfman 6344d7de91fSDima Dorfman static void 6354d7de91fSDima Dorfman usage(void) 6364d7de91fSDima Dorfman { 6374d7de91fSDima Dorfman 6384d7de91fSDima Dorfman fprintf(stderr, 6394d7de91fSDima Dorfman "usage: %s [-DLMNSX] [-a maxcontig] [-b block-size] [-c cylinders]\n" 6404d7de91fSDima Dorfman "\t[-d rotdelay] [-e maxbpg] [-F file] [-f frag-size] [-i bytes]\n" 6414d7de91fSDima Dorfman "\t[-m percent-free] [-n rotational-positions] [-O optimization]\n" 6424d7de91fSDima Dorfman "\t[-o mount-options] [-p permissions] [-s size] [-w user:group]\n" 6434d7de91fSDima Dorfman "\tmd-device mount-point\n", getprogname()); 6444d7de91fSDima Dorfman exit(1); 6454d7de91fSDima Dorfman } 646