Fix mount helper
[zfs.git] / cmd / zfs / zfs_main.c
index f21c36b..32f85b1 100644 (file)
@@ -3827,371 +3827,6 @@ zfs_do_python(int argc, char **argv)
        return (-1);
 }
 
-typedef struct option_map {
-       const char *name;
-       int mask;
-} option_map_t;
-
-static const option_map_t option_map[] = {
-       /* Canonicalized filesystem independent options from mount(8) */
-       { MNTOPT_NOAUTO,        MS_COMMENT      },
-       { MNTOPT_DEFAULTS,      MS_COMMENT      },
-       { MNTOPT_NODEVICES,     MS_NODEV        },
-       { MNTOPT_DIRSYNC,       MS_DIRSYNC      },
-       { MNTOPT_NOEXEC,        MS_NOEXEC       },
-       { MNTOPT_GROUP,         MS_GROUP        },
-       { MNTOPT_NETDEV,        MS_COMMENT      },
-       { MNTOPT_NOFAIL,        MS_COMMENT      },
-       { MNTOPT_NOSUID,        MS_NOSUID       },
-       { MNTOPT_OWNER,         MS_OWNER        },
-       { MNTOPT_REMOUNT,       MS_REMOUNT      },
-       { MNTOPT_RO,            MS_RDONLY       },
-       { MNTOPT_SYNC,          MS_SYNCHRONOUS  },
-       { MNTOPT_USER,          MS_USERS        },
-       { MNTOPT_USERS,         MS_USERS        },
-#ifdef MS_NOATIME
-       { MNTOPT_NOATIME,       MS_NOATIME      },
-#endif
-#ifdef MS_NODIRATIME
-       { MNTOPT_NODIRATIME,    MS_NODIRATIME   },
-#endif
-#ifdef MS_RELATIME
-       { MNTOPT_RELATIME,      MS_RELATIME     },
-#endif
-#ifdef MS_STRICTATIME
-       { MNTOPT_DFRATIME,      MS_STRICTATIME  },
-#endif
-#ifdef HAVE_SELINUX
-       { MNTOPT_CONTEXT,       MS_COMMENT      },
-       { MNTOPT_FSCONTEXT,     MS_COMMENT      },
-       { MNTOPT_DEFCONTEXT,    MS_COMMENT      },
-       { MNTOPT_ROOTCONTEXT,   MS_COMMENT      },
-#endif
-#ifdef MS_I_VERSION
-       { MNTOPT_IVERSION,      MS_I_VERSION    },
-#endif
-#ifdef MS_MANDLOCK
-       { MNTOPT_NBMAND,        MS_MANDLOCK     },
-#endif
-       /* Valid options not found in mount(8) */
-       { MNTOPT_BIND,          MS_BIND         },
-#ifdef MS_REC
-       { MNTOPT_RBIND,         MS_BIND|MS_REC  },
-#endif
-       { MNTOPT_COMMENT,       MS_COMMENT      },
-       { MNTOPT_BOOTWAIT,      MS_COMMENT      },
-       { MNTOPT_NOBOOTWAIT,    MS_COMMENT      },
-       { MNTOPT_OPTIONAL,      MS_COMMENT      },
-       { MNTOPT_SHOWTHROUGH,   MS_COMMENT      },
-#ifdef MS_NOSUB
-       { MNTOPT_NOSUB,         MS_NOSUB        },
-#endif
-#ifdef MS_SILENT
-       { MNTOPT_QUIET,         MS_SILENT       },
-#endif
-       /* Custom zfs options */
-       { MNTOPT_NOXATTR,       MS_COMMENT      },
-       { NULL,                 0               } };
-
-/*
- * Break the mount option in to a name/value pair.  The name is
- * validated against the option map and mount flags set accordingly.
- */
-static int
-parse_option(char *mntopt, unsigned long *mntflags, int sloppy)
-{
-       const option_map_t *opt;
-       char *ptr, *name, *value = NULL;
-       int rc = 0;
-
-       name = strdup(mntopt);
-       if (name == NULL)
-               return (ENOMEM);
-
-       for (ptr = name; ptr && *ptr; ptr++) {
-               if (*ptr == '=') {
-                       *ptr = '\0';
-                       value = ptr+1;
-                       break;
-               }
-       }
-
-       for (opt = option_map; opt->name != NULL; opt++) {
-               if (strncmp(name, opt->name, strlen(name)) == 0) {
-                       *mntflags |= opt->mask;
-
-                       /* MS_USERS implies default user options */
-                       if (opt->mask & (MS_USERS))
-                               *mntflags |= (MS_NOEXEC|MS_NOSUID|MS_NODEV);
-
-                       /* MS_OWNER|MS_GROUP imply default owner options */
-                       if (opt->mask & (MS_OWNER | MS_GROUP))
-                               *mntflags |= (MS_NOSUID|MS_NODEV);
-
-                       rc = 0;
-                       goto out;
-               }
-       }
-
-       if (!sloppy)
-               rc = ENOENT;
-out:
-       /* If required further process on the value may be done here */
-       free(name);
-       return (rc);
-}
-
-/*
- * Translate the mount option string in to MS_* mount flags for the
- * kernel vfs.  When sloppy is non-zero unknown options will be ignored
- * otherwise they are considered fatal are copied in to badopt.
- */
-static int
-parse_options(char *mntopts, unsigned long *mntflags, int sloppy, char *badopt)
-{
-       int rc = 0, quote = 0;
-       char *ptr, *opt, *opts;
-
-       opts = strdup(mntopts);
-       if (opts == NULL)
-               return (ENOMEM);
-
-       *mntflags = 0;
-       opt = NULL;
-
-       /*
-        * Scan through all mount options which must be comma delimited.
-        * We must be careful to notice regions which are double quoted
-        * and skip commas in these regions.  Each option is then checked
-        * to determine if it is a known option.
-        */
-       for (ptr = opts; ptr && *ptr; ptr++) {
-               if (opt == NULL)
-                       opt = ptr;
-
-               if (*ptr == '"')
-                       quote = !quote;
-
-               if (quote)
-                       continue;
-
-               if ((*ptr == ',') || (*ptr == '\0')) {
-                       *ptr = '\0';
-                       rc = parse_option(opt, mntflags, sloppy);
-                       if (rc) {
-                               strcpy(badopt, opt);
-                               goto out;
-                       }
-
-                       opt = NULL;
-               }
-       }
-out:
-       free(opts);
-       return (rc);
-}
-
-/*
- * Called when invoked as /sbin/mount.zfs, mount helper for mount(8).
- */
-static int
-manual_mount(int argc, char **argv)
-{
-       zfs_handle_t *zhp;
-       char legacy[ZFS_MAXPROPLEN];
-       char mntopts[MNT_LINE_MAX] = { '\0' };
-       char badopt[MNT_LINE_MAX] = { '\0' };
-       char *dataset, *mntpoint;
-       unsigned long mntflags;
-       int sloppy = 0, fake = 0, verbose = 0;
-       int rc, c;
-
-       /* check options */
-       while ((c = getopt(argc, argv, "sfnvo:h?")) != -1) {
-               switch (c) {
-               case 's':
-                       sloppy = 1;
-                       break;
-               case 'f':
-                       fake = 1;
-                       break;
-               case 'n':
-                       /* Ignored, handled by mount(8) */
-                       break;
-               case 'v':
-                       verbose++;
-                       break;
-               case 'o':
-                       (void) strlcpy(mntopts, optarg, sizeof (mntopts));
-                       break;
-               case 'h':
-               case '?':
-                       (void) fprintf(stderr, gettext("Invalid option '%c'\n"),
-                           optopt);
-                       (void) fprintf(stderr, gettext("Usage: mount.zfs "
-                           "[-sfnv] [-o options] <dataset> <mountpoint>\n"));
-                       return (MOUNT_USAGE);
-               }
-       }
-
-       argc -= optind;
-       argv += optind;
-
-       /* check that we only have two arguments */
-       if (argc != 2) {
-               if (argc == 0)
-                       (void) fprintf(stderr, gettext("missing dataset "
-                           "argument\n"));
-               else if (argc == 1)
-                       (void) fprintf(stderr,
-                           gettext("missing mountpoint argument\n"));
-               else
-                       (void) fprintf(stderr, gettext("too many arguments\n"));
-               (void) fprintf(stderr, "usage: mount <dataset> <mountpoint>\n");
-               return (MOUNT_USAGE);
-       }
-
-       dataset = argv[0];
-       mntpoint = argv[1];
-
-       /* try to open the dataset to access the mount point */
-       if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) {
-               (void) fprintf(stderr, gettext("filesystem '%s' cannot be "
-                   "mounted, unable to open the dataset\n"), dataset);
-               return (MOUNT_USAGE);
-       }
-
-       (void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, legacy,
-           sizeof (legacy), NULL, NULL, 0, B_FALSE);
-
-       zfs_close(zhp);
-
-       /* check for legacy mountpoint or util mount option */
-       if ((!strcmp(legacy, ZFS_MOUNTPOINT_LEGACY) == 0) &&
-           (strstr(mntopts, MNTOPT_ZFSUTIL) == NULL)) {
-               (void) fprintf(stderr, gettext("filesystem '%s' cannot be "
-                   "mounted using 'mount -a -t zfs'\n"), dataset);
-               (void) fprintf(stderr, gettext("Use 'zfs set mountpoint=%s' "
-                   "instead.\n"), mntpoint);
-               (void) fprintf(stderr, gettext("If you must use 'mount -a -t "
-                   "zfs' or /etc/fstab, use 'zfs set mountpoint=legacy'.\n"));
-               (void) fprintf(stderr, gettext("See zfs(8) for more "
-                   "information.\n"));
-               return (MOUNT_USAGE);
-       }
-
-       /* validate mount options and set mntflags */
-       rc = parse_options(mntopts, &mntflags, sloppy, badopt);
-       if (rc) {
-               switch (rc) {
-               case ENOMEM:
-                       (void) fprintf(stderr, gettext("filesystem '%s' "
-                           "cannot be mounted due to a memory allocation "
-                           "failure\n"), dataset);
-                       return (MOUNT_SYSERR);
-               case EINVAL:
-                       (void) fprintf(stderr, gettext("filesystem '%s' "
-                           "cannot be mounted of due to the invalid option "
-                           "'%s'\n"), dataset, badopt);
-                       (void) fprintf(stderr, gettext("Use the '-s' option "
-                           "to ignore the bad mount option.\n"));
-                       return (MOUNT_USAGE);
-               default:
-                       (void) fprintf(stderr, gettext("filesystem '%s' "
-                           "cannot be mounted due to internal error %d\n"),
-                           dataset, rc);
-                       return (MOUNT_SOFTWARE);
-               }
-       }
-
-       if (verbose > 2)
-               printf("mount.zfs: dataset: \"%s\", mountpoint: \"%s\" "
-                   "mountflags: 0x%lx, mountopts: \"%s\"\n", dataset,
-                   mntpoint, mntflags, mntopts);
-
-       /* load the zfs posix layer module (zpl) */
-       if (libzfs_load_module("zpl")) {
-               (void) fprintf(stderr, gettext("filesystem '%s' cannot be "
-                   "mounted without the zpl kernel module\n"), dataset);
-               (void) fprintf(stderr, gettext("Use 'dmesg' to determine why "
-                   "the module could not be loaded.\n"));
-               return (MOUNT_SYSERR);
-       }
-
-       if (!fake) {
-               rc = mount(dataset, mntpoint, MNTTYPE_ZFS, mntflags, mntopts);
-               if (rc) {
-                       (void) fprintf(stderr, gettext("filesystem '%s' can"
-                           "not be mounted due to error %d\n"), dataset, rc);
-                       return (MOUNT_USAGE);
-               }
-       }
-
-       return (MOUNT_SUCCESS);
-}
-
-#ifdef HAVE_UNMOUNT_HELPER
-/*
- * Called when invoked as /sbin/umount.zfs, mount helper for mount(8).
- * Unlike a manual mount, we allow unmounts of non-legacy filesystems,
- * as this is the dominant administrative interface.
- */
-static int
-manual_unmount(int argc, char **argv)
-{
-       int verbose = 0, flags = 0;
-       int c;
-
-       /* check options */
-       while ((c = getopt(argc, argv, "nlfvrh?")) != -1) {
-               switch (c) {
-               case 'n':
-                       /* Ignored, handled by mount(8) */
-                       break;
-               case 'l':
-                       flags = MS_DETACH;
-                       break;
-               case 'f':
-                       flags = MS_FORCE;
-                       break;
-               case 'v':
-                       verbose++;
-                       break;
-               case 'r':
-                       /* Remount read-only on umount failure, unsupported */
-                       (void) fprintf(stderr, gettext("Unsupported option "
-                           "'%c'\n"), optopt);
-                       return (MOUNT_USAGE);
-               case 'h':
-               case '?':
-                       (void) fprintf(stderr, gettext("Invalid option '%c'\n"),
-                           optopt);
-                       (void) fprintf(stderr, gettext("Usage: umount.zfs "
-                           "[-nlfvr] <mountpoint>\n"));
-                       return (MOUNT_USAGE);
-               }
-       }
-
-       argc -= optind;
-       argv += optind;
-
-       /* check that we only have one argument */
-       if (argc != 1) {
-               if (argc == 0)
-                       (void) fprintf(stderr, gettext("missing mountpoint "
-                           "argument\n"));
-               else
-                       (void) fprintf(stderr, gettext("too many arguments\n"));
-
-               (void) fprintf(stderr, gettext("Usage: umount.zfs [-nlfvr] "
-                   "<mountpoint>\n"));
-               return (MOUNT_USAGE);
-       }
-
-       return (unshare_unmount_path(OP_MOUNT, argv[0], flags, B_TRUE));
-}
-#endif /* HAVE_UNMOUNT_HELPER */
-
 static int
 find_command_idx(char *command, int *idx)
 {
@@ -4289,7 +3924,6 @@ main(int argc, char **argv)
 {
        int ret;
        int i = 0;
-       char *progname;
        char *cmdname;
 
        (void) setlocale(LC_ALL, "");
@@ -4304,78 +3938,64 @@ main(int argc, char **argv)
        }
 
        /*
-        * This command also doubles as the /etc/fs mount and unmount program.
-        * Determine if we should take this behavior based on argv[0].
+        * Make sure the user has specified some command.
         */
-       progname = basename(argv[0]);
-       if (strcmp(progname, "mount.zfs") == 0) {
-               ret = manual_mount(argc, argv);
-#ifdef HAVE_UNMOUNT_HELPER
-       } else if (strcmp(progname, "umount.zfs") == 0) {
-               ret = manual_unmount(argc, argv);
-#endif /* HAVE_UNMOUNT_HELPER */
-       } else {
-               /*
-                * Make sure the user has specified some command.
-                */
-               if (argc < 2) {
-                       (void) fprintf(stderr, gettext("missing command\n"));
-                       usage(B_FALSE);
-               }
+       if (argc < 2) {
+               (void) fprintf(stderr, gettext("missing command\n"));
+               usage(B_FALSE);
+       }
 
-               cmdname = argv[1];
+       cmdname = argv[1];
 
-               /*
-                * The 'umount' command is an alias for 'unmount'
-                */
-               if (strcmp(cmdname, "umount") == 0)
-                       cmdname = "unmount";
+       /*
+        * The 'umount' command is an alias for 'unmount'
+        */
+       if (strcmp(cmdname, "umount") == 0)
+               cmdname = "unmount";
 
-               /*
-                * The 'recv' command is an alias for 'receive'
-                */
-               if (strcmp(cmdname, "recv") == 0)
-                       cmdname = "receive";
+       /*
+        * The 'recv' command is an alias for 'receive'
+        */
+       if (strcmp(cmdname, "recv") == 0)
+               cmdname = "receive";
 
-               /*
-                * Special case '-?'
-                */
-               if ((strcmp(cmdname, "-?") == 0) ||
-                   (strcmp(cmdname, "--help") == 0))
-                       usage(B_TRUE);
+       /*
+        * Special case '-?'
+        */
+       if ((strcmp(cmdname, "-?") == 0) ||
+           (strcmp(cmdname, "--help") == 0))
+               usage(B_TRUE);
 
-               if ((g_zfs = libzfs_init()) == NULL)
-                       return (1);
+       if ((g_zfs = libzfs_init()) == NULL)
+               return (1);
 
-               zpool_set_history_str("zfs", argc, argv, history_str);
-               verify(zpool_stage_history(g_zfs, history_str) == 0);
+       zpool_set_history_str("zfs", argc, argv, history_str);
+       verify(zpool_stage_history(g_zfs, history_str) == 0);
 
-               libzfs_print_on_error(g_zfs, B_TRUE);
+       libzfs_print_on_error(g_zfs, B_TRUE);
 
-               /*
-                * Run the appropriate command.
-                */
-               libzfs_mnttab_cache(g_zfs, B_TRUE);
-               if (find_command_idx(cmdname, &i) == 0) {
-                       current_command = &command_table[i];
-                       ret = command_table[i].func(argc - 1, argv + 1);
-               } else if (strchr(cmdname, '=') != NULL) {
-                       verify(find_command_idx("set", &i) == 0);
-                       current_command = &command_table[i];
-                       ret = command_table[i].func(argc, argv);
-               } else {
-                       (void) fprintf(stderr, gettext("unrecognized "
-                           "command '%s'\n"), cmdname);
-                       usage(B_FALSE);
-                       ret = 1;
-               }
-               libzfs_mnttab_cache(g_zfs, B_FALSE);
+       /*
+        * Run the appropriate command.
+        */
+       libzfs_mnttab_cache(g_zfs, B_TRUE);
+       if (find_command_idx(cmdname, &i) == 0) {
+               current_command = &command_table[i];
+               ret = command_table[i].func(argc - 1, argv + 1);
+       } else if (strchr(cmdname, '=') != NULL) {
+               verify(find_command_idx("set", &i) == 0);
+               current_command = &command_table[i];
+               ret = command_table[i].func(argc, argv);
+       } else {
+               (void) fprintf(stderr, gettext("unrecognized "
+                   "command '%s'\n"), cmdname);
+               usage(B_FALSE);
+               ret = 1;
        }
+       libzfs_mnttab_cache(g_zfs, B_FALSE);
+       libzfs_fini(g_zfs);
 
        (void) fclose(mnttab_file);
 
-       libzfs_fini(g_zfs);
-
        /*
         * The 'ZFS_ABORT' environment variable causes us to dump core on exit
         * for the purposes of running ::findleaks.