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 /* 28b7e368f7SPoul-Henning Kamp * mdmfs (md/MFS) is a wrapper around mdconfig(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 33c69284caSDavid E. O'Brien #include <sys/cdefs.h> 34c69284caSDavid E. O'Brien __FBSDID("$FreeBSD$"); 354d7de91fSDima Dorfman 364d7de91fSDima Dorfman #include <sys/param.h> 374d7de91fSDima Dorfman #include <sys/mdioctl.h> 384d7de91fSDima Dorfman #include <sys/stat.h> 394d7de91fSDima Dorfman #include <sys/wait.h> 404d7de91fSDima Dorfman 414d7de91fSDima Dorfman #include <assert.h> 424d7de91fSDima Dorfman #include <err.h> 434d7de91fSDima Dorfman #include <fcntl.h> 444d7de91fSDima Dorfman #include <grp.h> 454d7de91fSDima Dorfman #include <paths.h> 464d7de91fSDima Dorfman #include <pwd.h> 474d7de91fSDima Dorfman #include <stdarg.h> 484d7de91fSDima Dorfman #include <stdio.h> 494d7de91fSDima Dorfman #include <stdlib.h> 504d7de91fSDima Dorfman #include <string.h> 514d7de91fSDima Dorfman #include <unistd.h> 524d7de91fSDima Dorfman 534d7de91fSDima Dorfman typedef enum { false, true } bool; 544d7de91fSDima Dorfman 554d7de91fSDima Dorfman struct mtpt_info { 564d7de91fSDima Dorfman uid_t mi_uid; 574d7de91fSDima Dorfman bool mi_have_uid; 584d7de91fSDima Dorfman gid_t mi_gid; 594d7de91fSDima Dorfman bool mi_have_gid; 604d7de91fSDima Dorfman mode_t mi_mode; 614d7de91fSDima Dorfman bool mi_have_mode; 624d7de91fSDima Dorfman }; 634d7de91fSDima Dorfman 64f7acb7e4SDima Dorfman static bool compat; /* Full compatibility with mount_mfs? */ 654d7de91fSDima Dorfman static bool debug; /* Emit debugging information? */ 664d7de91fSDima Dorfman static bool loudsubs; /* Suppress output from helper programs? */ 674d7de91fSDima Dorfman static bool norun; /* Actually run the helper programs? */ 684d7de91fSDima Dorfman static int unit; /* The unit we're working with. */ 694d7de91fSDima Dorfman static const char *mdname; /* Name of memory disk device (e.g., "md"). */ 704d7de91fSDima Dorfman static size_t mdnamelen; /* Length of mdname. */ 714d7de91fSDima Dorfman 72bc56b93aSKris Kennaway static void argappend(char **, const char *, ...) __printflike(2, 3); 73bc56b93aSKris Kennaway static void debugprintf(const char *, ...) __printflike(1, 2); 744d7de91fSDima Dorfman static void do_mdconfig_attach(const char *, const enum md_types); 754d7de91fSDima Dorfman static void do_mdconfig_attach_au(const char *, const enum md_types); 764d7de91fSDima Dorfman static void do_mdconfig_detach(void); 774d7de91fSDima Dorfman static void do_mount(const char *, const char *); 784d7de91fSDima Dorfman static void do_mtptsetup(const char *, struct mtpt_info *); 794d7de91fSDima Dorfman static void do_newfs(const char *); 804d7de91fSDima Dorfman static void extract_ugid(const char *, struct mtpt_info *); 81bc56b93aSKris Kennaway static int run(int *, const char *, ...) __printflike(2, 3); 824d7de91fSDima Dorfman static void usage(void); 834d7de91fSDima Dorfman 844d7de91fSDima Dorfman int 8594ddc5afSDavid E. O'Brien main(int argc, char **argv) 864d7de91fSDima Dorfman { 874d7de91fSDima Dorfman struct mtpt_info mi; /* Mountpoint info. */ 884d7de91fSDima Dorfman char *mdconfig_arg, *newfs_arg, /* Args to helper programs. */ 894d7de91fSDima Dorfman *mount_arg; 904d7de91fSDima Dorfman enum md_types mdtype; /* The type of our memory disk. */ 914d7de91fSDima Dorfman bool have_mdtype; 924d7de91fSDima Dorfman bool detach, softdep, autounit; 934d7de91fSDima Dorfman char *mtpoint, *unitstr; 945cfe0423SPeter Grehan char *p; 955cfe0423SPeter Grehan int ch; 96ce03e3a7SYaroslav Tykhiy void *set; 9747376189SSuleiman Souhlal unsigned long ul; 984d7de91fSDima Dorfman 994d7de91fSDima Dorfman /* Misc. initialization. */ 1004d7de91fSDima Dorfman (void)memset(&mi, '\0', sizeof(mi)); 1014d7de91fSDima Dorfman detach = true; 1024d7de91fSDima Dorfman softdep = true; 1034d7de91fSDima Dorfman autounit = false; 1044d7de91fSDima Dorfman have_mdtype = false; 1056449237fSSuleiman Souhlal mdtype = MD_SWAP; 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 1182dc4ac06SIan Dowse /* If we were started as mount_mfs or mfs, imply -C. */ 1192dc4ac06SIan Dowse if (strcmp(getprogname(), "mount_mfs") == 0 || 1202dc4ac06SIan Dowse strcmp(getprogname(), "mfs") == 0) 121f7acb7e4SDima Dorfman compat = true; 122f7acb7e4SDima Dorfman 12394ddc5afSDavid E. O'Brien while ((ch = getopt(argc, argv, 1241d3170aaSRobert Watson "a:b:Cc:Dd:e:F:f:hi:LlMm:Nn:O:o:p:Ss:t:Uv:w:X")) != -1) 1254d7de91fSDima Dorfman switch (ch) { 1264d7de91fSDima Dorfman case 'a': 1274d7de91fSDima Dorfman argappend(&newfs_arg, "-a %s", optarg); 1284d7de91fSDima Dorfman break; 1294d7de91fSDima Dorfman case 'b': 1304d7de91fSDima Dorfman argappend(&newfs_arg, "-b %s", optarg); 1314d7de91fSDima Dorfman break; 132f7acb7e4SDima Dorfman case 'C': 133f7acb7e4SDima Dorfman if (compat) 134f7acb7e4SDima Dorfman usage(); 135f7acb7e4SDima Dorfman compat = true; 136f7acb7e4SDima Dorfman break; 1374d7de91fSDima Dorfman case 'c': 1384d7de91fSDima Dorfman argappend(&newfs_arg, "-c %s", optarg); 1394d7de91fSDima Dorfman break; 1404d7de91fSDima Dorfman case 'D': 141f7acb7e4SDima Dorfman if (compat) 142f7acb7e4SDima Dorfman usage(); 1434d7de91fSDima Dorfman detach = false; 1444d7de91fSDima Dorfman break; 1454d7de91fSDima Dorfman case 'd': 1464d7de91fSDima Dorfman argappend(&newfs_arg, "-d %s", optarg); 1474d7de91fSDima Dorfman break; 1484d7de91fSDima Dorfman case 'e': 1494d7de91fSDima Dorfman argappend(&newfs_arg, "-e %s", optarg); 1504d7de91fSDima Dorfman break; 1514d7de91fSDima Dorfman case 'F': 1524d7de91fSDima Dorfman if (have_mdtype) 1534d7de91fSDima Dorfman usage(); 1544d7de91fSDima Dorfman mdtype = MD_VNODE; 1554d7de91fSDima Dorfman have_mdtype = true; 1564d7de91fSDima Dorfman argappend(&mdconfig_arg, "-f %s", optarg); 1574d7de91fSDima Dorfman break; 1584d7de91fSDima Dorfman case 'f': 1594d7de91fSDima Dorfman argappend(&newfs_arg, "-f %s", optarg); 1604d7de91fSDima Dorfman break; 1614d7de91fSDima Dorfman case 'h': 1624d7de91fSDima Dorfman usage(); 1634d7de91fSDima Dorfman break; 1644d7de91fSDima Dorfman case 'i': 1654d7de91fSDima Dorfman argappend(&newfs_arg, "-i %s", optarg); 1664d7de91fSDima Dorfman break; 1674d7de91fSDima Dorfman case 'L': 168f7acb7e4SDima Dorfman if (compat) 169f7acb7e4SDima Dorfman usage(); 1704d7de91fSDima Dorfman loudsubs = true; 1714d7de91fSDima Dorfman break; 1721d3170aaSRobert Watson case 'l': 1731d3170aaSRobert Watson argappend(&newfs_arg, "-l"); 1741d3170aaSRobert Watson break; 1754d7de91fSDima Dorfman case 'M': 1764d7de91fSDima Dorfman if (have_mdtype) 1774d7de91fSDima Dorfman usage(); 1784d7de91fSDima Dorfman mdtype = MD_MALLOC; 1794d7de91fSDima Dorfman have_mdtype = true; 1804d7de91fSDima Dorfman break; 1814d7de91fSDima Dorfman case 'm': 1824d7de91fSDima Dorfman argappend(&newfs_arg, "-m %s", optarg); 1834d7de91fSDima Dorfman break; 1844d7de91fSDima Dorfman case 'N': 185f7acb7e4SDima Dorfman if (compat) 186f7acb7e4SDima Dorfman usage(); 1874d7de91fSDima Dorfman norun = true; 1884d7de91fSDima Dorfman break; 1894d7de91fSDima Dorfman case 'n': 1904d7de91fSDima Dorfman argappend(&newfs_arg, "-n %s", optarg); 1914d7de91fSDima Dorfman break; 1924d7de91fSDima Dorfman case 'O': 1934d7de91fSDima Dorfman argappend(&newfs_arg, "-o %s", optarg); 1944d7de91fSDima Dorfman break; 1954d7de91fSDima Dorfman case 'o': 1964d7de91fSDima Dorfman argappend(&mount_arg, "-o %s", optarg); 1974d7de91fSDima Dorfman break; 1984d7de91fSDima Dorfman case 'p': 199f7acb7e4SDima Dorfman if (compat) 200f7acb7e4SDima Dorfman usage(); 201ce03e3a7SYaroslav Tykhiy if ((set = setmode(optarg)) == NULL) 2024d7de91fSDima Dorfman usage(); 203ce03e3a7SYaroslav Tykhiy mi.mi_mode = getmode(set, S_IRWXU | S_IRWXG | S_IRWXO); 2044d7de91fSDima Dorfman mi.mi_have_mode = true; 205ce03e3a7SYaroslav Tykhiy free(set); 2064d7de91fSDima Dorfman break; 2074d7de91fSDima Dorfman case 'S': 208f7acb7e4SDima Dorfman if (compat) 209f7acb7e4SDima Dorfman usage(); 2104d7de91fSDima Dorfman softdep = false; 2114d7de91fSDima Dorfman break; 2124d7de91fSDima Dorfman case 's': 2134d7de91fSDima Dorfman argappend(&mdconfig_arg, "-s %s", optarg); 2144d7de91fSDima Dorfman break; 215f7acb7e4SDima Dorfman case 'U': 216f7acb7e4SDima Dorfman softdep = true; 217f7acb7e4SDima Dorfman break; 218622448faSRobert Watson case 'v': 219622448faSRobert Watson argappend(&newfs_arg, "-O %s", optarg); 220622448faSRobert Watson break; 2214d7de91fSDima Dorfman case 'w': 222f7acb7e4SDima Dorfman if (compat) 223f7acb7e4SDima Dorfman usage(); 2244d7de91fSDima Dorfman extract_ugid(optarg, &mi); 2254d7de91fSDima Dorfman break; 2264d7de91fSDima Dorfman case 'X': 227f7acb7e4SDima Dorfman if (compat) 228f7acb7e4SDima Dorfman usage(); 2294d7de91fSDima Dorfman debug = true; 2304d7de91fSDima Dorfman break; 2314d7de91fSDima Dorfman default: 2324d7de91fSDima Dorfman usage(); 2334d7de91fSDima Dorfman } 23494ddc5afSDavid E. O'Brien argc -= optind; 23594ddc5afSDavid E. O'Brien argv += optind; 23694ddc5afSDavid E. O'Brien if (argc < 2) 2374d7de91fSDima Dorfman usage(); 2384d7de91fSDima Dorfman 239f7acb7e4SDima Dorfman /* Make compatibility assumptions. */ 240f7acb7e4SDima Dorfman if (compat) { 241f7acb7e4SDima Dorfman mi.mi_mode = 01777; 242f7acb7e4SDima Dorfman mi.mi_have_mode = true; 243f7acb7e4SDima Dorfman } 244f7acb7e4SDima Dorfman 2454d7de91fSDima Dorfman /* Derive 'unit' (global). */ 24694ddc5afSDavid E. O'Brien unitstr = argv[0]; 2474d7de91fSDima Dorfman if (strncmp(unitstr, "/dev/", 5) == 0) 2484d7de91fSDima Dorfman unitstr += 5; 2494d7de91fSDima Dorfman if (strncmp(unitstr, mdname, mdnamelen) == 0) 2504d7de91fSDima Dorfman unitstr += mdnamelen; 2514d7de91fSDima Dorfman if (*unitstr == '\0') { 2524d7de91fSDima Dorfman autounit = true; 2534d7de91fSDima Dorfman unit = -1; 2544d7de91fSDima Dorfman } else { 25547376189SSuleiman Souhlal ul = strtoul(unitstr, &p, 10); 25647376189SSuleiman Souhlal if (ul == ULONG_MAX || *p != '\0') 2574d7de91fSDima Dorfman errx(1, "bad device unit: %s", unitstr); 25847376189SSuleiman Souhlal unit = ul; 2594d7de91fSDima Dorfman } 2604d7de91fSDima Dorfman 26194ddc5afSDavid E. O'Brien mtpoint = argv[1]; 2624d7de91fSDima Dorfman if (!have_mdtype) 2634d7de91fSDima Dorfman mdtype = MD_SWAP; 2644d7de91fSDima Dorfman if (softdep) 2654d7de91fSDima Dorfman argappend(&newfs_arg, "-U"); 2664d7de91fSDima Dorfman 2674d7de91fSDima Dorfman /* Do the work. */ 2684d7de91fSDima Dorfman if (detach && !autounit) 2694d7de91fSDima Dorfman do_mdconfig_detach(); 2704d7de91fSDima Dorfman if (autounit) 2714d7de91fSDima Dorfman do_mdconfig_attach_au(mdconfig_arg, mdtype); 2724d7de91fSDima Dorfman else 2734d7de91fSDima Dorfman do_mdconfig_attach(mdconfig_arg, mdtype); 2744d7de91fSDima Dorfman do_newfs(newfs_arg); 2754d7de91fSDima Dorfman do_mount(mount_arg, mtpoint); 2764d7de91fSDima Dorfman do_mtptsetup(mtpoint, &mi); 2774d7de91fSDima Dorfman 2784d7de91fSDima Dorfman return (0); 2794d7de91fSDima Dorfman } 2804d7de91fSDima Dorfman 2814d7de91fSDima Dorfman /* 2824d7de91fSDima Dorfman * Append the expansion of 'fmt' to the buffer pointed to by '*dstp'; 2834d7de91fSDima Dorfman * reallocate as required. 2844d7de91fSDima Dorfman */ 2854d7de91fSDima Dorfman static void 2864d7de91fSDima Dorfman argappend(char **dstp, const char *fmt, ...) 2874d7de91fSDima Dorfman { 2884d7de91fSDima Dorfman char *old, *new; 2894d7de91fSDima Dorfman va_list ap; 2904d7de91fSDima Dorfman 2914d7de91fSDima Dorfman old = *dstp; 2924d7de91fSDima Dorfman assert(old != NULL); 2934d7de91fSDima Dorfman 2944d7de91fSDima Dorfman va_start(ap, fmt); 2954d7de91fSDima Dorfman if (vasprintf(&new, fmt,ap) == -1) 2964d7de91fSDima Dorfman errx(1, "vasprintf"); 2974d7de91fSDima Dorfman va_end(ap); 2984d7de91fSDima Dorfman 2994d7de91fSDima Dorfman *dstp = new; 3004d7de91fSDima Dorfman if (asprintf(&new, "%s %s", old, new) == -1) 3014d7de91fSDima Dorfman errx(1, "asprintf"); 3024d7de91fSDima Dorfman free(*dstp); 3034d7de91fSDima Dorfman free(old); 3044d7de91fSDima Dorfman 3054d7de91fSDima Dorfman *dstp = new; 3064d7de91fSDima Dorfman } 3074d7de91fSDima Dorfman 3084d7de91fSDima Dorfman /* 3094d7de91fSDima Dorfman * If run-time debugging is enabled, print the expansion of 'fmt'. 3104d7de91fSDima Dorfman * Otherwise, do nothing. 3114d7de91fSDima Dorfman */ 3124d7de91fSDima Dorfman static void 3134d7de91fSDima Dorfman debugprintf(const char *fmt, ...) 3144d7de91fSDima Dorfman { 3154d7de91fSDima Dorfman va_list ap; 3164d7de91fSDima Dorfman 3174d7de91fSDima Dorfman if (!debug) 3184d7de91fSDima Dorfman return; 3194d7de91fSDima Dorfman fprintf(stderr, "DEBUG: "); 3204d7de91fSDima Dorfman va_start(ap, fmt); 3214d7de91fSDima Dorfman vfprintf(stderr, fmt, ap); 3224d7de91fSDima Dorfman va_end(ap); 3234d7de91fSDima Dorfman fprintf(stderr, "\n"); 3244d7de91fSDima Dorfman fflush(stderr); 3254d7de91fSDima Dorfman } 3264d7de91fSDima Dorfman 3274d7de91fSDima Dorfman /* 3284d7de91fSDima Dorfman * Attach a memory disk with a known unit. 3294d7de91fSDima Dorfman */ 3304d7de91fSDima Dorfman static void 3314d7de91fSDima Dorfman do_mdconfig_attach(const char *args, const enum md_types mdtype) 3324d7de91fSDima Dorfman { 3334d7de91fSDima Dorfman int rv; 3344d7de91fSDima Dorfman const char *ta; /* Type arg. */ 3354d7de91fSDima Dorfman 3364d7de91fSDima Dorfman switch (mdtype) { 3374d7de91fSDima Dorfman case MD_SWAP: 3384d7de91fSDima Dorfman ta = "-t swap"; 3394d7de91fSDima Dorfman break; 3404d7de91fSDima Dorfman case MD_VNODE: 3414d7de91fSDima Dorfman ta = "-t vnode"; 3424d7de91fSDima Dorfman break; 3434d7de91fSDima Dorfman case MD_MALLOC: 3444d7de91fSDima Dorfman ta = "-t malloc"; 3454d7de91fSDima Dorfman break; 3464d7de91fSDima Dorfman default: 3474d7de91fSDima Dorfman abort(); 3484d7de91fSDima Dorfman } 3491386defaSGordon Tetlow rv = run(NULL, "%s -a %s%s -u %s%d", _PATH_MDCONFIG, ta, args, 3504d7de91fSDima Dorfman mdname, unit); 3514d7de91fSDima Dorfman if (rv) 3524d7de91fSDima Dorfman errx(1, "mdconfig (attach) exited with error code %d", rv); 3534d7de91fSDima Dorfman } 3544d7de91fSDima Dorfman 3554d7de91fSDima Dorfman /* 3564d7de91fSDima Dorfman * Attach a memory disk with an unknown unit; use autounit. 3574d7de91fSDima Dorfman */ 3584d7de91fSDima Dorfman static void 3594d7de91fSDima Dorfman do_mdconfig_attach_au(const char *args, const enum md_types mdtype) 3604d7de91fSDima Dorfman { 3614d7de91fSDima Dorfman const char *ta; /* Type arg. */ 3624d7de91fSDima Dorfman char *linep, *linebuf; /* Line pointer, line buffer. */ 3634d7de91fSDima Dorfman int fd; /* Standard output of mdconfig invocation. */ 3644d7de91fSDima Dorfman FILE *sfd; 3654d7de91fSDima Dorfman int rv; 3664d7de91fSDima Dorfman char *p; 3674d7de91fSDima Dorfman size_t linelen; 36847376189SSuleiman Souhlal unsigned long ul; 3694d7de91fSDima Dorfman 3704d7de91fSDima Dorfman switch (mdtype) { 3714d7de91fSDima Dorfman case MD_SWAP: 3724d7de91fSDima Dorfman ta = "-t swap"; 3734d7de91fSDima Dorfman break; 3744d7de91fSDima Dorfman case MD_VNODE: 3754d7de91fSDima Dorfman ta = "-t vnode"; 3764d7de91fSDima Dorfman break; 3774d7de91fSDima Dorfman case MD_MALLOC: 3784d7de91fSDima Dorfman ta = "-t malloc"; 3794d7de91fSDima Dorfman break; 3804d7de91fSDima Dorfman default: 3814d7de91fSDima Dorfman abort(); 3824d7de91fSDima Dorfman } 3831386defaSGordon Tetlow rv = run(&fd, "%s -a %s%s", _PATH_MDCONFIG, ta, args); 3844d7de91fSDima Dorfman if (rv) 3854d7de91fSDima Dorfman errx(1, "mdconfig (attach) exited with error code %d", rv); 3864d7de91fSDima Dorfman 3874d7de91fSDima Dorfman /* Receive the unit number. */ 3884d7de91fSDima Dorfman if (norun) { /* Since we didn't run, we can't read. Fake it. */ 389541ce3c1SDima Dorfman unit = 0; 3904d7de91fSDima Dorfman return; 3914d7de91fSDima Dorfman } 3924d7de91fSDima Dorfman sfd = fdopen(fd, "r"); 3934d7de91fSDima Dorfman if (sfd == NULL) 3944d7de91fSDima Dorfman err(1, "fdopen"); 3954d7de91fSDima Dorfman linep = fgetln(sfd, &linelen); 3964d7de91fSDima Dorfman if (linep == NULL && linelen < mdnamelen + 1) 3974d7de91fSDima Dorfman errx(1, "unexpected output from mdconfig (attach)"); 3984d7de91fSDima Dorfman /* If the output format changes, we want to know about it. */ 3994d7de91fSDima Dorfman assert(strncmp(linep, mdname, mdnamelen) == 0); 4004d7de91fSDima Dorfman linebuf = malloc(linelen - mdnamelen + 1); 4014d7de91fSDima Dorfman assert(linebuf != NULL); 4024d7de91fSDima Dorfman /* Can't use strlcpy because linep is not NULL-terminated. */ 4034d7de91fSDima Dorfman strncpy(linebuf, linep + mdnamelen, linelen); 4044d7de91fSDima Dorfman linebuf[linelen] = '\0'; 40547376189SSuleiman Souhlal ul = strtoul(linebuf, &p, 10); 40647376189SSuleiman Souhlal if (ul == ULONG_MAX || *p != '\n') 4074d7de91fSDima Dorfman errx(1, "unexpected output from mdconfig (attach)"); 40847376189SSuleiman Souhlal unit = ul; 4094d7de91fSDima Dorfman 4104d7de91fSDima Dorfman fclose(sfd); 4114d7de91fSDima Dorfman close(fd); 4124d7de91fSDima Dorfman } 4134d7de91fSDima Dorfman 4144d7de91fSDima Dorfman /* 4154d7de91fSDima Dorfman * Detach a memory disk. 4164d7de91fSDima Dorfman */ 4174d7de91fSDima Dorfman static void 4184d7de91fSDima Dorfman do_mdconfig_detach(void) 4194d7de91fSDima Dorfman { 4204d7de91fSDima Dorfman int rv; 4214d7de91fSDima Dorfman 4221386defaSGordon Tetlow rv = run(NULL, "%s -d -u %s%d", _PATH_MDCONFIG, mdname, unit); 4234d7de91fSDima Dorfman if (rv && debug) /* This is allowed to fail. */ 4244d7de91fSDima Dorfman warnx("mdconfig (detach) exited with error code %d (ignored)", 4254d7de91fSDima Dorfman rv); 4264d7de91fSDima Dorfman } 4274d7de91fSDima Dorfman 4284d7de91fSDima Dorfman /* 4294d7de91fSDima Dorfman * Mount the configured memory disk. 4304d7de91fSDima Dorfman */ 4314d7de91fSDima Dorfman static void 4324d7de91fSDima Dorfman do_mount(const char *args, const char *mtpoint) 4334d7de91fSDima Dorfman { 4344d7de91fSDima Dorfman int rv; 4354d7de91fSDima Dorfman 4361386defaSGordon Tetlow rv = run(NULL, "%s%s /dev/%s%d %s", _PATH_MOUNT, args, 4374d7de91fSDima Dorfman mdname, unit, mtpoint); 4384d7de91fSDima Dorfman if (rv) 4394d7de91fSDima Dorfman errx(1, "mount exited with error code %d", rv); 4404d7de91fSDima Dorfman } 4414d7de91fSDima Dorfman 4424d7de91fSDima Dorfman /* 4434d7de91fSDima Dorfman * Various configuration of the mountpoint. Mostly, enact 'mip'. 4444d7de91fSDima Dorfman */ 4454d7de91fSDima Dorfman static void 4464d7de91fSDima Dorfman do_mtptsetup(const char *mtpoint, struct mtpt_info *mip) 4474d7de91fSDima Dorfman { 4484d7de91fSDima Dorfman 4494d7de91fSDima Dorfman if (mip->mi_have_mode) { 4504d7de91fSDima Dorfman debugprintf("changing mode of %s to %o.", mtpoint, 4514d7de91fSDima Dorfman mip->mi_mode); 4524d7de91fSDima Dorfman if (!norun) 4534d7de91fSDima Dorfman if (chmod(mtpoint, mip->mi_mode) == -1) 4544d7de91fSDima Dorfman err(1, "chmod: %s", mtpoint); 4554d7de91fSDima Dorfman } 4564d7de91fSDima Dorfman /* 4574d7de91fSDima Dorfman * We have to do these separately because the user may have 4584d7de91fSDima Dorfman * only specified one of them. 4594d7de91fSDima Dorfman */ 4604d7de91fSDima Dorfman if (mip->mi_have_uid) { 4614d7de91fSDima Dorfman debugprintf("changing owner (user) or %s to %u.", mtpoint, 4624d7de91fSDima Dorfman mip->mi_uid); 4634d7de91fSDima Dorfman if (!norun) 4644d7de91fSDima Dorfman if (chown(mtpoint, mip->mi_uid, -1) == -1) 4654d7de91fSDima Dorfman err(1, "chown %s to %u (user)", mtpoint, 4664d7de91fSDima Dorfman mip->mi_uid); 4674d7de91fSDima Dorfman } 4684d7de91fSDima Dorfman if (mip->mi_have_gid) { 4694d7de91fSDima Dorfman debugprintf("changing owner (group) or %s to %u.", mtpoint, 4704d7de91fSDima Dorfman mip->mi_gid); 4714d7de91fSDima Dorfman if (!norun) 4724d7de91fSDima Dorfman if (chown(mtpoint, -1, mip->mi_gid) == -1) 4734d7de91fSDima Dorfman err(1, "chown %s to %u (group)", mtpoint, 4744d7de91fSDima Dorfman mip->mi_gid); 4754d7de91fSDima Dorfman } 4764d7de91fSDima Dorfman } 4774d7de91fSDima Dorfman 4784d7de91fSDima Dorfman /* 4794d7de91fSDima Dorfman * Put a file system on the memory disk. 4804d7de91fSDima Dorfman */ 4814d7de91fSDima Dorfman static void 4824d7de91fSDima Dorfman do_newfs(const char *args) 4834d7de91fSDima Dorfman { 4844d7de91fSDima Dorfman int rv; 4854d7de91fSDima Dorfman 4861386defaSGordon Tetlow rv = run(NULL, "%s%s /dev/%s%d", _PATH_NEWFS, args, mdname, unit); 4874d7de91fSDima Dorfman if (rv) 4884d7de91fSDima Dorfman errx(1, "newfs exited with error code %d", rv); 4894d7de91fSDima Dorfman } 4904d7de91fSDima Dorfman 4914d7de91fSDima Dorfman /* 4924d7de91fSDima Dorfman * 'str' should be a user and group name similar to the last argument 4934d7de91fSDima Dorfman * to chown(1); i.e., a user, followed by a colon, followed by a 4944d7de91fSDima Dorfman * group. The user and group in 'str' may be either a [ug]id or a 4954d7de91fSDima Dorfman * name. Upon return, the uid and gid fields in 'mip' will contain 4964d7de91fSDima Dorfman * the uid and gid of the user and group name in 'str', respectively. 4974d7de91fSDima Dorfman * 4984d7de91fSDima Dorfman * In other words, this derives a user and group id from a string 4994d7de91fSDima Dorfman * formatted like the last argument to chown(1). 500de90a634SRalf S. Engelschall * 501de90a634SRalf S. Engelschall * Notice: At this point we don't support only a username or only a 502de90a634SRalf S. Engelschall * group name. do_mtptsetup already does, so when this feature is 503de90a634SRalf S. Engelschall * desired, this is the only routine that needs to be changed. 5044d7de91fSDima Dorfman */ 5054d7de91fSDima Dorfman static void 5064d7de91fSDima Dorfman extract_ugid(const char *str, struct mtpt_info *mip) 5074d7de91fSDima Dorfman { 5084d7de91fSDima Dorfman char *ug; /* Writable 'str'. */ 5094d7de91fSDima Dorfman char *user, *group; /* Result of extracton. */ 5104d7de91fSDima Dorfman struct passwd *pw; 5114d7de91fSDima Dorfman struct group *gr; 5124d7de91fSDima Dorfman char *p; 5134d7de91fSDima Dorfman uid_t *uid; 5144d7de91fSDima Dorfman gid_t *gid; 5154d7de91fSDima Dorfman 5164d7de91fSDima Dorfman uid = &mip->mi_uid; 5174d7de91fSDima Dorfman gid = &mip->mi_gid; 5184d7de91fSDima Dorfman mip->mi_have_uid = mip->mi_have_gid = false; 5194d7de91fSDima Dorfman 5204d7de91fSDima Dorfman /* Extract the user and group from 'str'. Format above. */ 5218d3c1246SDima Dorfman ug = strdup(str); 5224d7de91fSDima Dorfman assert(ug != NULL); 5234d7de91fSDima Dorfman group = ug; 5244d7de91fSDima Dorfman user = strsep(&group, ":"); 5254d7de91fSDima Dorfman if (user == NULL || group == NULL || *user == '\0' || *group == '\0') 5264d7de91fSDima Dorfman usage(); 5274d7de91fSDima Dorfman 5284d7de91fSDima Dorfman /* Derive uid. */ 5294d7de91fSDima Dorfman *uid = strtoul(user, &p, 10); 5308a50130bSAlexander Kabaev if (*uid == (uid_t)ULONG_MAX) 5314d7de91fSDima Dorfman usage(); 5324d7de91fSDima Dorfman if (*p != '\0') { 5334d7de91fSDima Dorfman pw = getpwnam(user); 5344d7de91fSDima Dorfman if (pw == NULL) 5354d7de91fSDima Dorfman errx(1, "invalid user: %s", user); 5364d7de91fSDima Dorfman *uid = pw->pw_uid; 5374d7de91fSDima Dorfman } 538de90a634SRalf S. Engelschall mip->mi_have_uid = true; 5394d7de91fSDima Dorfman 5404d7de91fSDima Dorfman /* Derive gid. */ 5414d7de91fSDima Dorfman *gid = strtoul(group, &p, 10); 5428a50130bSAlexander Kabaev if (*gid == (gid_t)ULONG_MAX) 5434d7de91fSDima Dorfman usage(); 5444d7de91fSDima Dorfman if (*p != '\0') { 5454d7de91fSDima Dorfman gr = getgrnam(group); 5464d7de91fSDima Dorfman if (gr == NULL) 5474d7de91fSDima Dorfman errx(1, "invalid group: %s", group); 5484d7de91fSDima Dorfman *gid = gr->gr_gid; 5494d7de91fSDima Dorfman } 550de90a634SRalf S. Engelschall mip->mi_have_gid = true; 5514d7de91fSDima Dorfman 5524d7de91fSDima Dorfman free(ug); 5534d7de91fSDima Dorfman } 5544d7de91fSDima Dorfman 5554d7de91fSDima Dorfman /* 5564d7de91fSDima Dorfman * Run a process with command name and arguments pointed to by the 5574d7de91fSDima Dorfman * formatted string 'cmdline'. Since system(3) is not used, the first 5584d7de91fSDima Dorfman * space-delimited token of 'cmdline' must be the full pathname of the 5594d7de91fSDima Dorfman * program to run. The return value is the return code of the process 5604d7de91fSDima Dorfman * spawned. If 'ofd' is non-NULL, it is set to the standard output of 5614d7de91fSDima Dorfman * the program spawned (i.e., you can read from ofd and get the output 5624d7de91fSDima Dorfman * of the program). 5634d7de91fSDima Dorfman */ 5644d7de91fSDima Dorfman static int 5654d7de91fSDima Dorfman run(int *ofd, const char *cmdline, ...) 5664d7de91fSDima Dorfman { 56794ddc5afSDavid E. O'Brien char **argv, **argvp; /* Result of splitting 'cmd'. */ 56894ddc5afSDavid E. O'Brien int argc; 5694d7de91fSDima Dorfman char *cmd; /* Expansion of 'cmdline'. */ 5704d7de91fSDima Dorfman int pid, status; /* Child info. */ 5714d7de91fSDima Dorfman int pfd[2]; /* Pipe to the child. */ 5724d7de91fSDima Dorfman int nfd; /* Null (/dev/null) file descriptor. */ 5734d7de91fSDima Dorfman bool dup2dn; /* Dup /dev/null to stdout? */ 5744d7de91fSDima Dorfman va_list ap; 5754d7de91fSDima Dorfman char *p; 5764d7de91fSDima Dorfman int rv, i; 5774d7de91fSDima Dorfman 5784d7de91fSDima Dorfman dup2dn = true; 5794d7de91fSDima Dorfman va_start(ap, cmdline); 5804d7de91fSDima Dorfman rv = vasprintf(&cmd, cmdline, ap); 5814d7de91fSDima Dorfman if (rv == -1) 5824d7de91fSDima Dorfman err(1, "vasprintf"); 5834d7de91fSDima Dorfman va_end(ap); 5844d7de91fSDima Dorfman 58594ddc5afSDavid E. O'Brien /* Split up 'cmd' into 'argv' for use with execve. */ 58694ddc5afSDavid E. O'Brien for (argc = 1, p = cmd; (p = strchr(p, ' ')) != NULL; p++) 58794ddc5afSDavid E. O'Brien argc++; /* 'argc' generation loop. */ 58894ddc5afSDavid E. O'Brien argv = (char **)malloc(sizeof(*argv) * (argc + 1)); 58994ddc5afSDavid E. O'Brien assert(argv != NULL); 59094ddc5afSDavid E. O'Brien for (p = cmd, argvp = argv; (*argvp = strsep(&p, " ")) != NULL;) 59194ddc5afSDavid E. O'Brien if (**argv != '\0') 59294ddc5afSDavid E. O'Brien if (++argvp >= &argv[argc]) { 59394ddc5afSDavid E. O'Brien *argvp = NULL; 5944d7de91fSDima Dorfman break; 5954d7de91fSDima Dorfman } 59694ddc5afSDavid E. O'Brien assert(*argv); 5974d7de91fSDima Dorfman 5984d7de91fSDima Dorfman /* Make sure the above loop works as expected. */ 5994d7de91fSDima Dorfman if (debug) { 6004d7de91fSDima Dorfman /* 6014d7de91fSDima Dorfman * We can't, but should, use debugprintf here. First, 6024d7de91fSDima Dorfman * it appends a trailing newline to the output, and 6034d7de91fSDima Dorfman * second it prepends "DEBUG: " to the output. The 6044d7de91fSDima Dorfman * former is a problem for this would-be first call, 6054d7de91fSDima Dorfman * and the latter for the would-be call inside the 6064d7de91fSDima Dorfman * loop. 6074d7de91fSDima Dorfman */ 6084d7de91fSDima Dorfman (void)fprintf(stderr, "DEBUG: running:"); 6094d7de91fSDima Dorfman /* Should be equivilent to 'cmd' (before strsep, of course). */ 61094ddc5afSDavid E. O'Brien for (i = 0; argv[i] != NULL; i++) 61194ddc5afSDavid E. O'Brien (void)fprintf(stderr, " %s", argv[i]); 6124d7de91fSDima Dorfman (void)fprintf(stderr, "\n"); 6134d7de91fSDima Dorfman } 6144d7de91fSDima Dorfman 6154d7de91fSDima Dorfman /* Create a pipe if necessary and fork the helper program. */ 6164d7de91fSDima Dorfman if (ofd != NULL) { 6174d7de91fSDima Dorfman if (pipe(&pfd[0]) == -1) 6184d7de91fSDima Dorfman err(1, "pipe"); 6194d7de91fSDima Dorfman *ofd = pfd[0]; 6204d7de91fSDima Dorfman dup2dn = false; 6214d7de91fSDima Dorfman } 6224d7de91fSDima Dorfman pid = fork(); 6234d7de91fSDima Dorfman switch (pid) { 6244d7de91fSDima Dorfman case 0: 6254d7de91fSDima Dorfman /* XXX can we call err() in here? */ 6264d7de91fSDima Dorfman if (norun) 6274d7de91fSDima Dorfman _exit(0); 6284d7de91fSDima Dorfman if (ofd != NULL) 6294d7de91fSDima Dorfman if (dup2(pfd[1], STDOUT_FILENO) < 0) 6304d7de91fSDima Dorfman err(1, "dup2"); 6314d7de91fSDima Dorfman if (!loudsubs) { 6324d7de91fSDima Dorfman nfd = open(_PATH_DEVNULL, O_RDWR); 6334d7de91fSDima Dorfman if (nfd == -1) 6344d7de91fSDima Dorfman err(1, "open: %s", _PATH_DEVNULL); 6354d7de91fSDima Dorfman if (dup2(nfd, STDIN_FILENO) < 0) 6364d7de91fSDima Dorfman err(1, "dup2"); 6374d7de91fSDima Dorfman if (dup2dn) 6384d7de91fSDima Dorfman if (dup2(nfd, STDOUT_FILENO) < 0) 6394d7de91fSDima Dorfman err(1, "dup2"); 6404d7de91fSDima Dorfman if (dup2(nfd, STDERR_FILENO) < 0) 6414d7de91fSDima Dorfman err(1, "dup2"); 6424d7de91fSDima Dorfman } 6434d7de91fSDima Dorfman 64494ddc5afSDavid E. O'Brien (void)execv(argv[0], argv); 64594ddc5afSDavid E. O'Brien warn("exec: %s", argv[0]); 6464d7de91fSDima Dorfman _exit(-1); 6474d7de91fSDima Dorfman case -1: 6484d7de91fSDima Dorfman err(1, "fork"); 6494d7de91fSDima Dorfman } 6504d7de91fSDima Dorfman 6514d7de91fSDima Dorfman free(cmd); 65294ddc5afSDavid E. O'Brien free(argv); 6534d7de91fSDima Dorfman while (waitpid(pid, &status, 0) != pid) 6544d7de91fSDima Dorfman ; 6554d7de91fSDima Dorfman return (WEXITSTATUS(status)); 6564d7de91fSDima Dorfman } 6574d7de91fSDima Dorfman 6584d7de91fSDima Dorfman static void 6594d7de91fSDima Dorfman usage(void) 6604d7de91fSDima Dorfman { 661f7acb7e4SDima Dorfman const char *name; 6624d7de91fSDima Dorfman 663f7acb7e4SDima Dorfman if (compat) 664f7acb7e4SDima Dorfman name = getprogname(); 665f7acb7e4SDima Dorfman else 666f7acb7e4SDima Dorfman name = "mdmfs"; 667f7acb7e4SDima Dorfman if (!compat) 6684d7de91fSDima Dorfman fprintf(stderr, 6698d646af5SRuslan Ermilov "usage: %s [-DLlMNSUX] [-a maxcontig] [-b block-size] [-c cylinders]\n" 6704d7de91fSDima Dorfman "\t[-d rotdelay] [-e maxbpg] [-F file] [-f frag-size] [-i bytes]\n" 6714d7de91fSDima Dorfman "\t[-m percent-free] [-n rotational-positions] [-O optimization]\n" 6728d646af5SRuslan Ermilov "\t[-o mount-options] [-p permissions] [-s size] [-v version]\n" 6738d646af5SRuslan Ermilov "\t[-w user:group] md-device mount-point\n", name); 674f7acb7e4SDima Dorfman fprintf(stderr, 6752921afedSRuslan Ermilov "usage: %s -C [-lNU] [-a maxcontig] [-b block-size] [-c cylinders]\n" 676f7acb7e4SDima Dorfman "\t[-d rotdelay] [-e maxbpg] [-F file] [-f frag-size] [-i bytes]\n" 677f7acb7e4SDima Dorfman "\t[-m percent-free] [-n rotational-positions] [-O optimization]\n" 6788d646af5SRuslan Ermilov "\t[-o mount-options] [-s size] [-v version] md-device mount-point\n", name); 6794d7de91fSDima Dorfman exit(1); 6804d7de91fSDima Dorfman } 681