Changeset View
Changeset View
Standalone View
Standalone View
sbin/mdmfs/mdmfs.c
Show All 28 Lines | |||||
* newfs(8), and mount(8) that mimics the command line option set of | * newfs(8), and mount(8) that mimics the command line option set of | ||||
* the deprecated mount_mfs(8). | * the deprecated mount_mfs(8). | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/linker.h> | |||||
#include <sys/mdioctl.h> | #include <sys/mdioctl.h> | ||||
#include <sys/module.h> | |||||
#include <sys/mount.h> | #include <sys/mount.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <sys/wait.h> | #include <sys/wait.h> | ||||
#include <assert.h> | #include <assert.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | |||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <grp.h> | #include <grp.h> | ||||
#include <inttypes.h> | |||||
#include <paths.h> | #include <paths.h> | ||||
#include <pwd.h> | #include <pwd.h> | ||||
#include <stdarg.h> | #include <stdarg.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <ctype.h> | #include <ctype.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
Show All 19 Lines | |||||
static size_t mdnamelen; /* Length of mdname. */ | static size_t mdnamelen; /* Length of mdname. */ | ||||
static const char *path_mdconfig =_PATH_MDCONFIG; | static const char *path_mdconfig =_PATH_MDCONFIG; | ||||
static void argappend(char **, const char *, ...) __printflike(2, 3); | static void argappend(char **, const char *, ...) __printflike(2, 3); | ||||
static void debugprintf(const char *, ...) __printflike(1, 2); | static void debugprintf(const char *, ...) __printflike(1, 2); | ||||
static void do_mdconfig_attach(const char *, const enum md_types); | static void do_mdconfig_attach(const char *, const enum md_types); | ||||
static void do_mdconfig_attach_au(const char *, const enum md_types); | static void do_mdconfig_attach_au(const char *, const enum md_types); | ||||
static void do_mdconfig_detach(void); | static void do_mdconfig_detach(void); | ||||
static void do_mount(const char *, const char *); | static void do_mount_md(const char *, const char *); | ||||
static void do_mount_tmpfs(const char *, const char *); | |||||
static void do_mtptsetup(const char *, struct mtpt_info *); | static void do_mtptsetup(const char *, struct mtpt_info *); | ||||
static void do_newfs(const char *); | static void do_newfs(const char *); | ||||
static void extract_ugid(const char *, struct mtpt_info *); | static void extract_ugid(const char *, struct mtpt_info *); | ||||
static int run(int *, const char *, ...) __printflike(2, 3); | static int run(int *, const char *, ...) __printflike(2, 3); | ||||
static void usage(void); | static void usage(void); | ||||
int | int | ||||
main(int argc, char **argv) | main(int argc, char **argv) | ||||
{ | { | ||||
struct mtpt_info mi; /* Mountpoint info. */ | struct mtpt_info mi; /* Mountpoint info. */ | ||||
intmax_t mdsize; | |||||
char *mdconfig_arg, *newfs_arg, /* Args to helper programs. */ | char *mdconfig_arg, *newfs_arg, /* Args to helper programs. */ | ||||
*mount_arg; | *mount_arg; | ||||
enum md_types mdtype; /* The type of our memory disk. */ | enum md_types mdtype; /* The type of our memory disk. */ | ||||
bool have_mdtype; | bool have_mdtype, mlmac; | ||||
bool detach, softdep, autounit, newfs; | bool detach, softdep, autounit, newfs; | ||||
char *mtpoint, *unitstr; | const char *mtpoint, *size_arg, *unitstr; | ||||
char *p; | char *p; | ||||
int ch; | int ch, idx; | ||||
void *set; | void *set; | ||||
unsigned long ul; | unsigned long ul; | ||||
/* Misc. initialization. */ | /* Misc. initialization. */ | ||||
(void)memset(&mi, '\0', sizeof(mi)); | (void)memset(&mi, '\0', sizeof(mi)); | ||||
detach = true; | detach = true; | ||||
softdep = true; | softdep = true; | ||||
autounit = false; | autounit = false; | ||||
mlmac = false; | |||||
newfs = true; | newfs = true; | ||||
have_mdtype = false; | have_mdtype = false; | ||||
mdtype = MD_SWAP; | mdtype = MD_SWAP; | ||||
mdname = MD_NAME; | mdname = MD_NAME; | ||||
mdnamelen = strlen(mdname); | mdnamelen = strlen(mdname); | ||||
/* | /* | ||||
* Can't set these to NULL. They may be passed to the | * Can't set these to NULL. They may be passed to the | ||||
* respective programs without modification. I.e., we may not | * respective programs without modification. I.e., we may not | ||||
* receive any command-line options which will caused them to | * receive any command-line options which will caused them to | ||||
* be modified. | * be modified. | ||||
*/ | */ | ||||
mdconfig_arg = strdup(""); | mdconfig_arg = strdup(""); | ||||
newfs_arg = strdup(""); | newfs_arg = strdup(""); | ||||
mount_arg = strdup(""); | mount_arg = strdup(""); | ||||
size_arg = NULL; | |||||
/* If we were started as mount_mfs or mfs, imply -C. */ | /* If we were started as mount_mfs or mfs, imply -C. */ | ||||
if (strcmp(getprogname(), "mount_mfs") == 0 || | if (strcmp(getprogname(), "mount_mfs") == 0 || | ||||
strcmp(getprogname(), "mfs") == 0) { | strcmp(getprogname(), "mfs") == 0) { | ||||
/* Make compatibility assumptions. */ | /* Make compatibility assumptions. */ | ||||
mi.mi_mode = 01777; | mi.mi_mode = 01777; | ||||
mi.mi_have_mode = true; | mi.mi_have_mode = true; | ||||
} | } | ||||
Show All 40 Lines | case 'h': | ||||
break; | break; | ||||
case 'i': | case 'i': | ||||
argappend(&newfs_arg, "-i %s", optarg); | argappend(&newfs_arg, "-i %s", optarg); | ||||
break; | break; | ||||
case 'L': | case 'L': | ||||
loudsubs = true; | loudsubs = true; | ||||
break; | break; | ||||
case 'l': | case 'l': | ||||
mlmac = true; | |||||
argappend(&newfs_arg, "-l"); | argappend(&newfs_arg, "-l"); | ||||
break; | break; | ||||
case 'M': | case 'M': | ||||
if (have_mdtype) | if (have_mdtype) | ||||
usage(); | usage(); | ||||
mdtype = MD_MALLOC; | mdtype = MD_MALLOC; | ||||
have_mdtype = true; | have_mdtype = true; | ||||
break; | break; | ||||
Show All 22 Lines | case 'p': | ||||
mi.mi_have_mode = true; | mi.mi_have_mode = true; | ||||
mi.mi_forced_pw = true; | mi.mi_forced_pw = true; | ||||
free(set); | free(set); | ||||
break; | break; | ||||
case 'S': | case 'S': | ||||
softdep = false; | softdep = false; | ||||
break; | break; | ||||
case 's': | case 's': | ||||
argappend(&mdconfig_arg, "-s %s", optarg); | size_arg = optarg; | ||||
break; | break; | ||||
case 't': | case 't': | ||||
argappend(&newfs_arg, "-t"); | argappend(&newfs_arg, "-t"); | ||||
break; | break; | ||||
case 'T': | case 'T': | ||||
argappend(&mount_arg, "-t %s", optarg); | argappend(&mount_arg, "-t %s", optarg); | ||||
break; | break; | ||||
case 'U': | case 'U': | ||||
Show All 12 Lines | while ((ch = getopt(argc, argv, | ||||
default: | default: | ||||
usage(); | usage(); | ||||
} | } | ||||
argc -= optind; | argc -= optind; | ||||
argv += optind; | argv += optind; | ||||
if (argc < 2) | if (argc < 2) | ||||
usage(); | usage(); | ||||
/* Derive 'unit' (global). */ | /* | ||||
* Historically our size arg was passed directly to mdconfig, which | |||||
* treats a number without a suffix as a count of 512-byte sectors; | |||||
* tmpfs would treat it as a count of bytes. To get predictable | |||||
* behavior for 'auto' we document that the size always uses mdconfig | |||||
* rules. To make that work, decode the size here so it can be passed | |||||
* to either tmpfs or mdconfig as a count of bytes. | |||||
*/ | |||||
if (size_arg != NULL) { | |||||
mdsize = (intmax_t)strtoumax(size_arg, &p, 0); | |||||
if (p == size_arg || (p[0] != 0 && p[1] != 0) || mdsize < 0) | |||||
errx(1, "invalid size '%s'", size_arg); | |||||
switch (*p) { | |||||
case 'p': | |||||
case 'P': | |||||
mdsize *= 1024; | |||||
case 't': | |||||
case 'T': | |||||
mdsize *= 1024; | |||||
case 'g': | |||||
case 'G': | |||||
mdsize *= 1024; | |||||
case 'm': | |||||
case 'M': | |||||
mdsize *= 1024; | |||||
case 'k': | |||||
case 'K': | |||||
mdsize *= 1024; | |||||
case 'b': | |||||
case 'B': | |||||
break; | |||||
case '\0': | |||||
mdsize *= 512; | |||||
break; | |||||
default: | |||||
errx(1, "invalid size suffix on '%s'", size_arg); | |||||
} | |||||
} | |||||
/* | |||||
* Based on the command line 'md-device' either mount a tmpfs filesystem | |||||
* or configure the md device then format and mount a filesystem on it. | |||||
* If the device is 'auto' use tmpfs if it is available and there is no | |||||
* request for multilabel MAC (which tmpfs does not support). | |||||
*/ | |||||
unitstr = argv[0]; | unitstr = argv[0]; | ||||
mtpoint = argv[1]; | |||||
if (strcmp(unitstr, "auto") == 0) { | |||||
if (mlmac) | |||||
idx = -1; /* Must use md for mlmac. */ | |||||
else if ((idx = modfind("tmpfs")) == -1) | |||||
idx = kldload("tmpfs"); | |||||
if (idx == -1) | |||||
unitstr = "md"; | |||||
else | |||||
unitstr = "tmpfs"; | |||||
} | |||||
if (strcmp(unitstr, "tmpfs") == 0) { | |||||
if (size_arg != NULL && mdsize != 0) | |||||
argappend(&mount_arg, "-o size=%jd", mdsize); | |||||
do_mount_tmpfs(mount_arg, mtpoint); | |||||
} else { | |||||
if (size_arg != NULL) | |||||
argappend(&mdconfig_arg, "-s %jdB", mdsize); | |||||
if (strncmp(unitstr, "/dev/", 5) == 0) | if (strncmp(unitstr, "/dev/", 5) == 0) | ||||
unitstr += 5; | unitstr += 5; | ||||
if (strncmp(unitstr, mdname, mdnamelen) == 0) | if (strncmp(unitstr, mdname, mdnamelen) == 0) | ||||
unitstr += mdnamelen; | unitstr += mdnamelen; | ||||
if (!isdigit(*unitstr)) { | if (!isdigit(*unitstr)) { | ||||
autounit = true; | autounit = true; | ||||
unit = -1; | unit = -1; | ||||
mdsuffix = unitstr; | mdsuffix = unitstr; | ||||
} else { | } else { | ||||
ul = strtoul(unitstr, &p, 10); | ul = strtoul(unitstr, &p, 10); | ||||
if (ul == ULONG_MAX) | if (ul == ULONG_MAX) | ||||
errx(1, "bad device unit: %s", unitstr); | errx(1, "bad device unit: %s", unitstr); | ||||
unit = ul; | unit = ul; | ||||
mdsuffix = p; /* can be empty */ | mdsuffix = p; /* can be empty */ | ||||
} | } | ||||
mtpoint = argv[1]; | |||||
if (!have_mdtype) | if (!have_mdtype) | ||||
mdtype = MD_SWAP; | mdtype = MD_SWAP; | ||||
if (softdep) | if (softdep) | ||||
argappend(&newfs_arg, "-U"); | argappend(&newfs_arg, "-U"); | ||||
if (mdtype != MD_VNODE && !newfs) | if (mdtype != MD_VNODE && !newfs) | ||||
errx(1, "-P requires a vnode-backed disk"); | errx(1, "-P requires a vnode-backed disk"); | ||||
/* Do the work. */ | /* Do the work. */ | ||||
if (detach && !autounit) | if (detach && !autounit) | ||||
do_mdconfig_detach(); | do_mdconfig_detach(); | ||||
if (autounit) | if (autounit) | ||||
do_mdconfig_attach_au(mdconfig_arg, mdtype); | do_mdconfig_attach_au(mdconfig_arg, mdtype); | ||||
else | else | ||||
do_mdconfig_attach(mdconfig_arg, mdtype); | do_mdconfig_attach(mdconfig_arg, mdtype); | ||||
if (newfs) | if (newfs) | ||||
do_newfs(newfs_arg); | do_newfs(newfs_arg); | ||||
do_mount(mount_arg, mtpoint); | do_mount_md(mount_arg, mtpoint); | ||||
} | |||||
do_mtptsetup(mtpoint, &mi); | do_mtptsetup(mtpoint, &mi); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Append the expansion of 'fmt' to the buffer pointed to by '*dstp'; | * Append the expansion of 'fmt' to the buffer pointed to by '*dstp'; | ||||
* reallocate as required. | * reallocate as required. | ||||
▲ Show 20 Lines • Show All 140 Lines • ▼ Show 20 Lines | if (rv && debug) /* This is allowed to fail. */ | ||||
warnx("mdconfig (detach) exited with error code %d (ignored)", | warnx("mdconfig (detach) exited with error code %d (ignored)", | ||||
rv); | rv); | ||||
} | } | ||||
/* | /* | ||||
* Mount the configured memory disk. | * Mount the configured memory disk. | ||||
*/ | */ | ||||
static void | static void | ||||
do_mount(const char *args, const char *mtpoint) | do_mount_md(const char *args, const char *mtpoint) | ||||
{ | { | ||||
int rv; | int rv; | ||||
rv = run(NULL, "%s%s /dev/%s%d%s %s", _PATH_MOUNT, args, | rv = run(NULL, "%s%s /dev/%s%d%s %s", _PATH_MOUNT, args, | ||||
mdname, unit, mdsuffix, mtpoint); | mdname, unit, mdsuffix, mtpoint); | ||||
if (rv) | if (rv) | ||||
errx(1, "mount exited with error code %d", rv); | errx(1, "mount exited with error code %d", rv); | ||||
} | |||||
/* | |||||
* Mount the configured tmpfs. | |||||
*/ | |||||
static void | |||||
do_mount_tmpfs(const char *args, const char *mtpoint) | |||||
{ | |||||
int rv; | |||||
rv = run(NULL, "%s -t tmpfs %s tmp %s", _PATH_MOUNT, args, mtpoint); | |||||
if (rv) | |||||
errx(1, "tmpfs mount exited with error code %d", rv); | |||||
} | } | ||||
/* | /* | ||||
* Various configuration of the mountpoint. Mostly, enact 'mip'. | * Various configuration of the mountpoint. Mostly, enact 'mip'. | ||||
*/ | */ | ||||
static void | static void | ||||
do_mtptsetup(const char *mtpoint, struct mtpt_info *mip) | do_mtptsetup(const char *mtpoint, struct mtpt_info *mip) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 247 Lines • Show Last 20 Lines |