#include <sys/param.h>
#include <sys/mount.h>
#include <sys/sysctl.h>
#include <err.h>
#include <errno.h>
#include <mntopts.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <vfs/ufs/ufsmount.h>
#include "extern.h"
static void ufs_usage(void);
static struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_ASYNC,
MOPT_FORCE,
MOPT_SYNC,
MOPT_UPDATE,
MOPT_IGNORE,
MOPT_TRIM,
MOPT_NULL
};
int mount_ufs(int, const char **);
int
mount_ufs(int argc, const char **argv)
{
struct ufs_args args;
int ch, mntflags;
const char *fs_name;
struct vfsconf vfc;
int error = 0;
mntflags = 0;
optind = optreset = 1;
while ((ch = getopt(argc, __DECONST(char **, argv), "o:")) != -1)
switch (ch) {
case 'o':
getmntopts(optarg, mopts, &mntflags, 0);
break;
case '?':
default:
ufs_usage();
}
argc -= optind;
argv += optind;
if (argc != 2)
ufs_usage();
args.fspec = __DECONST(char *, argv[0]);
fs_name = argv[1];
#define DEFAULT_ROOTUID -2
args.export.ex_root = DEFAULT_ROOTUID;
if (mntflags & MNT_RDONLY)
args.export.ex_flags = MNT_EXRDONLY;
else
args.export.ex_flags = 0;
if (mntflags & MNT_TRIM){
char sysctl_name[64];
int trim_enabled = 0;
size_t olen = sizeof(trim_enabled);
char *dev_name = strdup(args.fspec);
dev_name = strtok(dev_name + strlen("/dev/da"),"s");
sprintf(sysctl_name, "kern.cam.da.%s.trim_enabled", dev_name);
if (sysctlbyname(sysctl_name, &trim_enabled, &olen, NULL, 0) < 0) {
printf("Device:%s does not support the TRIM command\n",
args.fspec);
ufs_usage();
}
if(!trim_enabled) {
printf("Online TRIM selected, but sysctl (%s) "
"is not enabled\n",sysctl_name);
ufs_usage();
}
}
error = getvfsbyname("ufs", &vfc);
if (error && vfsisloadable("ufs")) {
if (vfsload("ufs")) {
warn("vfsload(ufs)");
return (1);
}
endvfsent();
error = getvfsbyname("ufs", &vfc);
}
if (error) {
warnx("ufs filesystem is not available");
return (1);
}
if (mount(vfc.vfc_name, fs_name, mntflags, &args) < 0) {
switch (errno) {
case EMFILE:
warnx("%s on %s: mount table full",
args.fspec, fs_name);
break;
case EINVAL:
if (mntflags & MNT_UPDATE)
warnx(
"%s on %s: specified device does not match mounted device",
args.fspec, fs_name);
else
warnx("%s on %s: incorrect super block",
args.fspec, fs_name);
break;
default:
warn("%s", args.fspec);
break;
}
return (1);
}
return (0);
}
static void
ufs_usage(void)
{
fprintf(stderr, "usage: mount_ufs [-o options] special node\n");
exit(1);
}