X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=cmd%2Fmount_zfs%2Fmount_zfs.c;h=9a82a2b1703835c1c554758492858230e559aaa5;hb=462ee8e3f3f1e48c857d070fa5abaf4a72246344;hp=204f9fa14679a7818586b4139c1ad482fd30e517;hpb=3aff775555a40fe3e5193f1309ba6e80312be5ff;p=zfs.git diff --git a/cmd/mount_zfs/mount_zfs.c b/cmd/mount_zfs/mount_zfs.c index 204f9fa..9a82a2b 100644 --- a/cmd/mount_zfs/mount_zfs.c +++ b/cmd/mount_zfs/mount_zfs.c @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef HAVE_LIBSELINUX #include #endif /* HAVE_LIBSELINUX */ @@ -96,6 +97,7 @@ static const option_map_t option_map[] = { { MNTOPT_QUIET, MS_SILENT, ZS_COMMENT }, #endif /* Custom zfs options */ + { MNTOPT_XATTR, MS_COMMENT, ZS_COMMENT }, { MNTOPT_NOXATTR, MS_COMMENT, ZS_COMMENT }, { MNTOPT_ZFSUTIL, MS_COMMENT, ZS_ZFSUTIL }, { NULL, 0, 0 } }; @@ -120,6 +122,7 @@ parse_option(char *mntopt, unsigned long *mntflags, if (*ptr == '=') { *ptr = '\0'; value = ptr+1; + VERIFY3P(value, !=, NULL); break; } } @@ -228,7 +231,9 @@ parse_dataset(char *dataset) char cwd[PATH_MAX]; int len; - (void) getcwd(cwd, PATH_MAX); + if (getcwd(cwd, PATH_MAX) == NULL) + return (dataset); + len = strlen(cwd); /* Do not add one when cwd already ends in a trailing '/' */ @@ -249,7 +254,7 @@ mtab_is_writeable(void) struct stat st; int error, fd; - error = stat(MNTTAB, &st); + error = lstat(MNTTAB, &st); if (error || S_ISLNK(st.st_mode)) return (0); @@ -306,8 +311,9 @@ main(int argc, char **argv) char mntopts[MNT_LINE_MAX] = { '\0' }; char badopt[MNT_LINE_MAX] = { '\0' }; char mtabopt[MNT_LINE_MAX] = { '\0' }; - char *dataset, *mntpoint; - unsigned long mntflags = 0, zfsflags = 0, remount_ro = 0; + char mntpoint[PATH_MAX]; + char *dataset; + unsigned long mntflags = 0, zfsflags = 0, remount = 0; int sloppy = 0, fake = 0, verbose = 0, nomtab = 0, zfsutil = 0; int error, c; @@ -362,7 +368,13 @@ main(int argc, char **argv) } dataset = parse_dataset(argv[0]); - mntpoint = argv[1]; + + /* canonicalize the mount point */ + if (realpath(argv[1], mntpoint) == NULL) { + (void) fprintf(stderr, gettext("filesystem '%s' cannot be " + "mounted due to a canonicalization failure.\n"), dataset); + return (MOUNT_SYSERR); + } /* validate mount options and set mntflags */ error = parse_options(mntopts, &mntflags, &zfsflags, sloppy, @@ -412,11 +424,10 @@ main(int argc, char **argv) " mountopts: \"%s\"\n mtabopts: \"%s\"\n"), dataset, mntpoint, mntflags, zfsflags, mntopts, mtabopt); - if (mntflags & MS_REMOUNT) + if (mntflags & MS_REMOUNT) { nomtab = 1; - - if ((mntflags & MS_REMOUNT) && (mntflags & MS_RDONLY)) - remount_ro = 1; + remount = 1; + } if (zfsflags & ZS_ZFSUTIL) zfsutil = 1; @@ -425,15 +436,20 @@ main(int argc, char **argv) return (MOUNT_SYSERR); /* try to open the dataset to access the mount point */ - if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) { + if ((zhp = zfs_open(g_zfs, dataset, + ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT)) == NULL) { (void) fprintf(stderr, gettext("filesystem '%s' cannot be " "mounted, unable to open the dataset\n"), dataset); libzfs_fini(g_zfs); return (MOUNT_USAGE); } - (void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, legacy, - sizeof (legacy), NULL, NULL, 0, B_FALSE); + /* treat all snapshots as legacy mount points */ + if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) + (void) strlcpy(legacy, ZFS_MOUNTPOINT_LEGACY, ZFS_MAXPROPLEN); + else + (void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, legacy, + sizeof (legacy), NULL, NULL, 0, B_FALSE); zfs_close(zhp); libzfs_fini(g_zfs); @@ -444,9 +460,10 @@ main(int argc, char **argv) * we differentiate the two cases using the 'zfsutil' mount option. * This mount option should only be supplied by the 'zfs mount' util. * - * The only exception to the above rule is '-o remount,ro'. This is - * always allowed for non-legacy datasets for rc.sysinit/umountroot - * to safely remount the root filesystem and flush its cache. + * The only exception to the above rule is '-o remount' which is + * always allowed for non-legacy datasets. This is done because when + * using zfs as your root file system both rc.sysinit/umountroot and + * systemd depend on 'mount -o remount ' to work. */ if (zfsutil && !strcmp(legacy, ZFS_MOUNTPOINT_LEGACY)) { (void) fprintf(stderr, gettext( @@ -457,7 +474,8 @@ main(int argc, char **argv) return (MOUNT_USAGE); } - if (!zfsutil && strcmp(legacy, ZFS_MOUNTPOINT_LEGACY) && !remount_ro) { + if (!zfsutil && !(remount || fake) && + strcmp(legacy, ZFS_MOUNTPOINT_LEGACY)) { (void) fprintf(stderr, gettext( "filesystem '%s' cannot be mounted using 'mount'.\n" "Use 'zfs set mountpoint=%s' or 'zfs mount %s'.\n" @@ -471,6 +489,10 @@ main(int argc, char **argv) mntflags, mntopts); if (error) { switch (errno) { + case ENOENT: + (void) fprintf(stderr, gettext("mount point " + "'%s' does not exist\n"), mntpoint); + return (MOUNT_SYSERR); case EBUSY: (void) fprintf(stderr, gettext("filesystem " "'%s' is already mounted\n"), dataset);