From owner-freebsd-arch@FreeBSD.ORG Thu Jan 18 14:01:21 2007 Return-Path: X-Original-To: freebsd-arch@freebsd.org Delivered-To: freebsd-arch@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 7D31C16A40F for ; Thu, 18 Jan 2007 14:01:21 +0000 (UTC) (envelope-from rodrigc@crodrigues.org) Received: from rwcrmhc12.comcast.net (rwcrmhc12.comcast.net [216.148.227.152]) by mx1.freebsd.org (Postfix) with ESMTP id 645D813C467 for ; Thu, 18 Jan 2007 14:01:21 +0000 (UTC) (envelope-from rodrigc@crodrigues.org) Received: from c-66-31-35-94.hsd1.ma.comcast.net ([66.31.35.94]) by comcast.net (rwcrmhc12) with ESMTP id <20070118134936m12002gpk9e>; Thu, 18 Jan 2007 13:49:37 +0000 Received: from c-66-31-35-94.hsd1.ma.comcast.net (localhost.crodrigues.org [127.0.0.1]) by c-66-31-35-94.hsd1.ma.comcast.net (8.13.8/8.13.8) with ESMTP id l0IDnald007431; Thu, 18 Jan 2007 08:49:36 -0500 (EST) (envelope-from rodrigc@c-66-31-35-94.hsd1.ma.comcast.net) Received: (from rodrigc@localhost) by c-66-31-35-94.hsd1.ma.comcast.net (8.13.8/8.13.8/Submit) id l0IDna8w007430; Thu, 18 Jan 2007 08:49:36 -0500 (EST) (envelope-from rodrigc) Date: Thu, 18 Jan 2007 08:49:36 -0500 From: Craig Rodrigues To: freebsd-current@freebsd.org Message-ID: <20070118134936.GA7391@crodrigues.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="W/nzBZO5zC0uMSeA" Content-Disposition: inline User-Agent: Mutt/1.4.2.1i Cc: freebsd-arch@freebsd.org Subject: [RFC] mount(8) can figure out fstype X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 18 Jan 2007 14:01:21 -0000 --W/nzBZO5zC0uMSeA Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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@crodrigues.org --W/nzBZO5zC0uMSeA Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mount_patch.txt" 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 #include +#include #include +#include #include #include #include @@ -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); } --W/nzBZO5zC0uMSeA--