[RFC] mount(8) can figure out fstype



Hi,

This is a different version of the patch I posted here:
http://lists.freebsd.org/pipermail/freebsd-arch/2006-July/005439.html

One of the pet peeves I have with FreeBSD is that
if I have a device with a local filesystem that I want to mount,
I need to explicitly know what type of filesystem is on the
device in order to mount it from the command-line.

For example,

mount -t cd9660
mount -t udf
mount -t ext2fs
mount -t msdosfs

Where this is particularly annoying is if I have multiple
USB thumb drives with different filesystems on them.

What I usually end up doing is something like:
file - < /dev/ad0s4

to figure out the filesystem type, and then mount -t [whatever] to mount it.

What I would like to do is:

mount /dev/ad0s4 /mnt

and if I do not specify a filesystem type with -t, the mount
program should "magically" figure out how to mount the disk.
This is closer to how the mount program behaves on Linux for example.

In this patch, I only modified the userland mount program.
If the user does not specify "-t vfstype" to mount,
the mount program gets a list of local filesystems from the vfs.conflist
sysctl. It then tries to mount the filesystem, always
starting with "ufs", and then iterating through the list if
the nmount() fails with EINVAL.

Using this patch, I have been able to do:
mount /dev/blah /mnt

and mount a UFS, cd9660, or FAT filesystem, depending on what filesystem
is on the /dev/blah device.

Comments?
--
Craig Rodrigues
rodrigc@xxxxxxxxxxxxxx
Index: mount.c
===================================================================
RCS file: /home/ncvs/src/sbin/mount/mount.c,v
retrieving revision 1.92
diff -u -u -r1.92 mount.c
--- mount.c 14 Nov 2006 01:07:42 -0000 1.92
+++ mount.c 18 Jan 2007 13:41:53 -0000
@@ -139,6 +139,9 @@
NULL
};

+ if (vfstype == NULL)
+ return (0);
+
for (i = 0; fs[i] != NULL; ++i) {
if (strcmp(vfstype, fs[i]) == 0)
return (1);
@@ -219,7 +222,7 @@
ro = 0;
options = NULL;
vfslist = NULL;
- vfstype = "ufs";
+ vfstype = NULL;
while ((ch = getopt(argc, argv, "adF:flo:prt:uvw")) != -1)
switch (ch) {
case 'a':
@@ -516,7 +519,7 @@
optbuf = catopt(optbuf, "update");

/* Compatibility glue. */
- if (strcmp(vfstype, "msdos") == 0)
+ if (vfstype != NULL && strcmp(vfstype, "msdos") == 0)
vfstype = "msdosfs";

/* Construct the name of the appropriate mount command */
@@ -532,8 +535,11 @@
if (debug) {
if (use_mountprog(vfstype))
printf("exec: mount_%s", vfstype);
- else
- printf("mount -t %s", vfstype);
+ else {
+ printf("mount ");
+ if (vfstype != NULL)
+ printf("-t %s", vfstype);
+ };
for (i = 1; i < argc; i++)
(void)printf(" %s", argv[i]);
(void)printf("\n");
Index: mount_fs.c
===================================================================
RCS file: /home/ncvs/src/sbin/mount/mount_fs.c,v
retrieving revision 1.3
diff -u -u -r1.3 mount_fs.c
--- mount_fs.c 7 Dec 2006 03:24:43 -0000 1.3
+++ mount_fs.c 18 Jan 2007 13:41:53 -0000
@@ -50,8 +50,10 @@

#include <sys/param.h>
#include <sys/mount.h>
+#include <sys/sysctl.h>

#include <err.h>
+#include <errno.h>
#include <getopt.h>
#include <libgen.h>
#include <stdio.h>
@@ -62,6 +64,8 @@
#include "extern.h"
#include "mntopts.h"

+extern int debug, verbose;
+
struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_END
@@ -75,8 +79,9 @@
exit(1);
}

-int
-mount_fs(const char *vfstype, int argc, char *argv[])
+static int
+do_mount_fs(const char *vfstype, int argc, char *argv[], int *nmount_errno,
+ char *msg, size_t msg_len)
{
struct iovec *iov;
int iovlen;
@@ -131,8 +136,83 @@
build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));

ret = nmount(iov, iovlen, mntflags);
+ if (nmount_errno != NULL)
+ *nmount_errno = errno;
if (ret < 0)
- err(1, "%s %s", dev, errmsg);
+ snprintf(msg, msg_len, "%s : %s : %s", dev, errmsg,
+ strerror(errno));
+
+ return (ret);
+}
+
+static int
+mount_fs_try(int argc, char *argv[])
+{
+ struct xvfsconf *vfsp;
+ char msg[512];
+ unsigned int cnt, i;
+ int ret, j, nmount_errno;
+ size_t buflen;
+
+ /* First, see if mounting mounting with vfstype "ufs" works. */
+ ret = do_mount_fs("ufs", argc, argv, &nmount_errno, msg, sizeof(msg));
+ if (ret == 0)
+ return (0);
+
+ /* Get a list of registered vfs types */
+ if (sysctlbyname("vfs.conflist", NULL, &buflen, NULL, 0) < 0)
+ err(1, "sysctl(vfs.conflist)");
+ vfsp = malloc(buflen);
+ if (vfsp == NULL)
+ errx(1, "malloc failed");
+ if (sysctlbyname("vfs.conflist", vfsp, &buflen, NULL, 0) < 0)
+ err(1, "sysctl(vfs.conflist)");
+ cnt = buflen / sizeof(struct xvfsconf);
+
+ for (i = 0; i < cnt; i++) {
+ /* We already tried "ufs" above, so skip it. */
+ if (strcmp("ufs", vfsp[i].vfc_name) == 0)
+ continue;
+ /*
+ * Only try local filesystems. Skip network, synthetic,
+ * and loopback filesystems.
+ */
+ if (vfsp[i].vfc_flags &
+ (VFCF_NETWORK | VFCF_SYNTHETIC | VFCF_LOOPBACK))
+ continue;
+
+ if (debug || verbose) {
+ printf("mount -t %s ", vfsp[i].vfc_name);
+ for (j = 1; j < argc; j++)
+ (void)printf(" %s", argv[j]);
+ (void)printf("\n");
+ }
+ ret = do_mount_fs(vfsp[i].vfc_name, argc, argv, &nmount_errno,
+ msg, sizeof(msg));
+ if (ret == 0 || nmount_errno != EINVAL)
+ break;
+ }
+ free(vfsp);
+
+ if (ret < 0)
+ printf("%s", msg);
+ return (ret);
+}
+
+int
+mount_fs(const char *vfstype, int argc, char *argv[])
+{
+ char msg[512];
+ int ret, nmount_errno;
+
+ if (vfstype != NULL) {
+ ret = do_mount_fs(vfstype, argc, argv, &nmount_errno, msg,
+ sizeof(msg));
+ if (ret < 0)
+ printf("%s", msg);
+ }
+ else
+ ret = mount_fs_try(argc, argv);

return (ret);
}
_______________________________________________
freebsd-arch@xxxxxxxxxxx mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-arch
To unsubscribe, send any mail to "freebsd-arch-unsubscribe@xxxxxxxxxxx"

Relevant Pages

  • Re: mount() function problem !
    ... mount() attaches the filesystem specified by source (which is often a device name, ... point within a file system. ... details of the options available for each filesystem type. ... Specifies the journalling mode for file data. ...
    (comp.lang.c)
  • Bind Mount Extensions 0.02
    ... This is an update to the BME patch, ... for a RO --bind mount ... ... int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) ...
    (Linux-Kernel)
  • [PATCH] fmount system call
    ... as mount(), except the second parameter (mount target) is a file ... The patch applies against 2.6.6-rc2 and 2.6.6-rc2-mm1. ... +static int dentry_mount(char *dev_name, struct nameidata *nd, ...
    (Linux-Kernel)
  • Re: [autofs] [RFC] Towards a Modern Autofs
    ... >entangling autofs with that work. ... >filesystem it's willing to export. ... >>map is mounted. ... The result is that some users will see mount points ...
    (Linux-Kernel)
  • [RFC] [PATCH] allowing user mounts
    ... This patch allows the use of the mount syscall by ... - allows unmount of a filesystem which was mounted by the same user ... extern int __init init_rootfs; ... static inline unsigned long hash(struct vfsmount *mnt, ...
    (Linux-Kernel)