#include <sys/mount.h>
#include <sys/stat.h>
#include <libzfs.h>
+#include <locale.h>
#ifdef HAVE_LIBSELINUX
#include <selinux/selinux.h>
#endif /* HAVE_LIBSELINUX */
{ 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 } };
if (*ptr == '=') {
*ptr = '\0';
value = ptr+1;
+ VERIFY3P(value, !=, NULL);
break;
}
}
struct stat st;
int error, fd;
- error = stat(MNTTAB, &st);
+ error = lstat(MNTTAB, &st);
if (error || S_ISLNK(st.st_mode))
return (0);
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;
}
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,
" 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;
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);
* 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 <mountpoint>' to work.
*/
if (zfsutil && !strcmp(legacy, ZFS_MOUNTPOINT_LEGACY)) {
(void) fprintf(stderr, gettext(
return (MOUNT_USAGE);
}
- if (!zfsutil && strcmp(legacy, ZFS_MOUNTPOINT_LEGACY) && !remount_ro) {
+ if (!zfsutil && strcmp(legacy, ZFS_MOUNTPOINT_LEGACY) && !remount) {
(void) fprintf(stderr, gettext(
"filesystem '%s' cannot be mounted using 'mount'.\n"
"Use 'zfs set mountpoint=%s' or 'zfs mount %s'.\n"
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);