//
//config:config MOUNT
-//config: bool "mount"
+//config: bool "mount (30 kb)"
//config: default y
//config: select PLATFORM_LINUX
//config: help
-//config: All files and filesystems in Unix are arranged into one big directory
-//config: tree. The 'mount' utility is used to graft a filesystem onto a
-//config: particular part of the tree. A filesystem can either live on a block
-//config: device, or it can be accessible over the network, as is the case with
-//config: NFS filesystems. Most people using BusyBox will also want to enable
-//config: the 'mount' utility.
+//config: All files and filesystems in Unix are arranged into one big directory
+//config: tree. The 'mount' utility is used to graft a filesystem onto a
+//config: particular part of the tree. A filesystem can either live on a block
+//config: device, or it can be accessible over the network, as is the case with
+//config: NFS filesystems.
//config:
//config:config FEATURE_MOUNT_FAKE
-//config: bool "Support option -f"
+//config: bool "Support -f (fake mount)"
//config: default y
//config: depends on MOUNT
//config: help
-//config: Enable support for faking a file system mount.
+//config: Enable support for faking a file system mount.
//config:
//config:config FEATURE_MOUNT_VERBOSE
-//config: bool "Support option -v"
+//config: bool "Support -v (verbose)"
//config: default y
//config: depends on MOUNT
//config: help
-//config: Enable multi-level -v[vv...] verbose messages. Useful if you
-//config: debug mount problems and want to see what is exactly passed
-//config: to the kernel.
+//config: Enable multi-level -v[vv...] verbose messages. Useful if you
+//config: debug mount problems and want to see what is exactly passed
+//config: to the kernel.
//config:
//config:config FEATURE_MOUNT_HELPERS
//config: bool "Support mount helpers"
//config: default n
//config: depends on MOUNT
//config: help
-//config: Enable mounting of virtual file systems via external helpers.
-//config: E.g. "mount obexfs#-b00.11.22.33.44.55 /mnt" will in effect call
-//config: "obexfs -b00.11.22.33.44.55 /mnt"
-//config: Also "mount -t sometype [-o opts] fs /mnt" will try
-//config: "sometype [-o opts] fs /mnt" if simple mount syscall fails.
-//config: The idea is to use such virtual filesystems in /etc/fstab.
+//config: Enable mounting of virtual file systems via external helpers.
+//config: E.g. "mount obexfs#-b00.11.22.33.44.55 /mnt" will in effect call
+//config: "obexfs -b00.11.22.33.44.55 /mnt"
+//config: Also "mount -t sometype [-o opts] fs /mnt" will try
+//config: "sometype [-o opts] fs /mnt" if simple mount syscall fails.
+//config: The idea is to use such virtual filesystems in /etc/fstab.
//config:
//config:config FEATURE_MOUNT_LABEL
//config: bool "Support specifying devices by label or UUID"
//config: depends on MOUNT
//config: select VOLUMEID
//config: help
-//config: This allows for specifying a device by label or uuid, rather than by
-//config: name. This feature utilizes the same functionality as blkid/findfs.
-//config: This also enables label or uuid support for swapon.
+//config: This allows for specifying a device by label or uuid, rather than by
+//config: name. This feature utilizes the same functionality as blkid/findfs.
//config:
//config:config FEATURE_MOUNT_NFS
//config: bool "Support mounting NFS file systems on Linux < 2.6.23"
//config: default n
//config: depends on MOUNT
-//config: select FEATURE_HAVE_RPC
//config: select FEATURE_SYSLOG
//config: help
-//config: Enable mounting of NFS file systems on Linux kernels prior
-//config: to version 2.6.23. Note that in this case mounting of NFS
-//config: over IPv6 will not be possible.
+//config: Enable mounting of NFS file systems on Linux kernels prior
+//config: to version 2.6.23. Note that in this case mounting of NFS
+//config: over IPv6 will not be possible.
//config:
-//config: Note that this option links in RPC support from libc,
-//config: which is rather large (~10 kbytes on uclibc).
+//config: Note that this option links in RPC support from libc,
+//config: which is rather large (~10 kbytes on uclibc).
//config:
//config:config FEATURE_MOUNT_CIFS
//config: bool "Support mounting CIFS/SMB file systems"
//config: default y
//config: depends on MOUNT
//config: help
-//config: Enable support for samba mounts.
+//config: Enable support for samba mounts.
//config:
//config:config FEATURE_MOUNT_FLAGS
//config: depends on MOUNT
-//config: bool "Support lots of -o flags in mount"
+//config: bool "Support lots of -o flags"
//config: default y
//config: help
-//config: Without this, mount only supports ro/rw/remount. With this, it
-//config: supports nosuid, suid, dev, nodev, exec, noexec, sync, async, atime,
-//config: noatime, diratime, nodiratime, loud, bind, move, shared, slave,
-//config: private, unbindable, rshared, rslave, rprivate, and runbindable.
+//config: Without this, mount only supports ro/rw/remount. With this, it
+//config: supports nosuid, suid, dev, nodev, exec, noexec, sync, async, atime,
+//config: noatime, diratime, nodiratime, loud, bind, move, shared, slave,
+//config: private, unbindable, rshared, rslave, rprivate, and runbindable.
//config:
//config:config FEATURE_MOUNT_FSTAB
//config: depends on MOUNT
-//config: bool "Support /etc/fstab and -a"
+//config: bool "Support /etc/fstab and -a (mount all)"
//config: default y
//config: help
-//config: Support mount all and looking for files in /etc/fstab.
+//config: Support mount all and looking for files in /etc/fstab.
//config:
//config:config FEATURE_MOUNT_OTHERTAB
//config: depends on FEATURE_MOUNT_FSTAB
//config: bool "Support -T <alt_fstab>"
//config: default y
//config: help
-//config: Support mount -T (specifying an alternate fstab)
+//config: Support mount -T (specifying an alternate fstab)
+
+/* On full-blown systems, requires suid for user mounts.
+ * But it's not unthinkable to have it available in non-suid flavor on some systems,
+ * for viewing mount table.
+ * Therefore we use BB_SUID_MAYBE instead of BB_SUID_REQUIRE: */
+//applet:IF_MOUNT(APPLET(mount, BB_DIR_BIN, IF_DESKTOP(BB_SUID_MAYBE) IF_NOT_DESKTOP(BB_SUID_DROP)))
+
+//kbuild:lib-$(CONFIG_MOUNT) += mount.o
//usage:#define mount_trivial_usage
//usage: "[OPTIONS] [-o OPT] DEVICE NODE"
#define BB_MS_INVERTED_VALUE (1u << 31)
#include "libbb.h"
+#include "common_bufsiz.h"
#if ENABLE_FEATURE_MOUNT_LABEL
# include "volume_id.h"
#else
/* This is just a warning of a common mistake. Possibly this should be a
* uclibc faq entry rather than in busybox... */
# if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__)
-# error "You need to build uClibc with UCLIBC_HAS_RPC for NFS support"
+# warning "You probably need to build uClibc with UCLIBC_HAS_RPC for NFS support"
+ /* not #error, since user may be using e.g. libtirpc instead.
+ * This might work:
+ * CONFIG_EXTRA_CFLAGS="-I/usr/include/tirpc"
+ * CONFIG_EXTRA_LDLIBS="tirpc"
+ */
# endif
# include <rpc/rpc.h>
# include <rpc/pmap_prot.h>
};
-#define OPTION_STR "o:t:rwanfvsiO:" IF_FEATURE_MOUNT_OTHERTAB("T:")
+#define OPTION_STR "o:*t:rwanfvsiO:" IF_FEATURE_MOUNT_OTHERTAB("T:")
enum {
OPT_o = (1 << 0),
OPT_t = (1 << 1),
/* "remount" */ MS_REMOUNT // action flag
};
-static const char mount_option_str[] =
+static const char mount_option_str[] ALIGN1 =
IF_FEATURE_MOUNT_LOOP(
"loop\0"
)
char getmntent_buf[1];
} FIX_ALIASING;
enum { GETMNTENT_BUFSIZE = COMMON_BUFSIZE - offsetof(struct globals, getmntent_buf) };
-#define G (*(struct globals*)&bb_common_bufsiz1)
+#define G (*(struct globals*)bb_common_bufsiz1)
#define nfs_mount_version (G.nfs_mount_version)
#if ENABLE_FEATURE_MOUNT_VERBOSE
#define verbose (G.verbose )
#endif
#define fslist (G.fslist )
#define getmntent_buf (G.getmntent_buf )
-#define INIT_G() do { } while (0)
+#define INIT_G() do { setup_common_bufsiz(); } while (0)
#if ENABLE_FEATURE_MTAB_SUPPORT
/*
# define EDQUOT ENOSPC
#endif
/* Convert each NFSERR_BLAH into EBLAH */
-static const uint8_t nfs_err_stat[] = {
+static const uint8_t nfs_err_stat[] ALIGN1 = {
1, 2, 5, 6, 13, 17,
19, 20, 21, 22, 27, 28,
30, 63, 66, 69, 70, 71
#else
typedef uint16_t nfs_err_type;
#endif
-static const nfs_err_type nfs_err_errnum[] = {
+static const nfs_err_type nfs_err_errnum[] ALIGN2 = {
EPERM , ENOENT , EIO , ENXIO , EACCES, EEXIST,
ENODEV, ENOTDIR , EISDIR , EINVAL, EFBIG , ENOSPC,
EROFS , ENAMETOOLONG, ENOTEMPTY, EDQUOT, ESTALE, EREMOTE
// NB: mp->xxx fields may be trashed on exit
static int singlemount(struct mntent *mp, int ignore_busy)
{
+ int loopfd = -1;
int rc = -1;
unsigned long vfsflags;
char *loopFile = NULL, *filteropts = NULL;
int len;
char c;
char *hostname, *share;
- char *dotted, *ip;
len_and_sockaddr *lsa;
// Parse mp->mnt_fsname of the form "//hostname/share[/dir1/dir2]"
if (!lsa)
goto report_error;
- // Insert "ip=..." option into options
- dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
- if (ENABLE_FEATURE_CLEAN_UP) free(lsa);
- ip = xasprintf("ip=%s", dotted);
- if (ENABLE_FEATURE_CLEAN_UP) free(dotted);
- parse_mount_options(ip, &filteropts);
- if (ENABLE_FEATURE_CLEAN_UP) free(ip);
+ // If there is no "ip=..." option yet
+ if (!is_prefixed_with(filteropts, ",ip="+1)
+ && !strstr(filteropts, ",ip=")
+ ) {
+ char *dotted, *ip;
+ // Insert "ip=..." option into options
+ dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
+ if (ENABLE_FEATURE_CLEAN_UP) free(lsa);
+ ip = xasprintf("ip=%s", dotted);
+ if (ENABLE_FEATURE_CLEAN_UP) free(dotted);
+// Note: IPv6 scoped addresses ("host%iface", see RFC 4007) should be
+// handled by libc in getnameinfo() (inside xmalloc_sockaddr2dotted_noport()).
+// Currently, glibc does not support that (has no NI_NUMERICSCOPE),
+// musl apparently does. This results in "ip=numericIPv6%iface_name"
+// (instead of _numeric_ iface_id) with glibc.
+// This probably should be fixed in glibc, not here.
+// The workaround is to manually specify correct "ip=ADDR%n" option.
+ parse_mount_options(ip, &filteropts);
+ if (ENABLE_FEATURE_CLEAN_UP) free(ip);
+ }
mp->mnt_type = (char*)"cifs";
rc = mount_it_now(mp, vfsflags, filteropts);
if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) {
loopFile = bb_simplify_path(mp->mnt_fsname);
mp->mnt_fsname = NULL; // will receive malloced loop dev name
- if (set_loop(&mp->mnt_fsname, loopFile, 0, /*ro:*/ (vfsflags & MS_RDONLY)) < 0) {
+
+ // mount always creates AUTOCLEARed loopdevs, so that umounting
+ // drops them without any code in the userspace.
+ // This happens since circa linux-2.6.25:
+ // commit 96c5865559cee0f9cbc5173f3c949f6ce3525581
+ // Date: Wed Feb 6 01:36:27 2008 -0800
+ // Subject: Allow auto-destruction of loop devices
+ loopfd = set_loop(&mp->mnt_fsname,
+ loopFile,
+ 0,
+ ((vfsflags & MS_RDONLY) ? BB_LO_FLAGS_READ_ONLY : 0)
+ | BB_LO_FLAGS_AUTOCLEAR
+ );
+ if (loopfd < 0) {
if (errno == EPERM || errno == EACCES)
bb_error_msg(bb_msg_perm_denied_are_you_root);
else
}
// If mount failed, clean up loop file (if any).
+ // (Newer kernels which support LO_FLAGS_AUTOCLEAR should not need this,
+ // merely "close(loopfd)" should do it?)
if (ENABLE_FEATURE_MOUNT_LOOP && rc && loopFile) {
del_loop(mp->mnt_fsname);
if (ENABLE_FEATURE_CLEAN_UP) {
free(loopFile);
- free(mp->mnt_fsname);
+ /* No, "rc != 0" needs it: free(mp->mnt_fsname); */
}
}
if (ENABLE_FEATURE_CLEAN_UP)
free(filteropts);
+ if (loopfd >= 0)
+ close(loopfd);
+
if (errno == EBUSY && ignore_busy)
return 0;
if (errno == ENOENT && (vfsflags & MOUNT_NOFAIL))
// Parse remaining options
// Max 2 params; -o is a list, -v is a counter
- opt_complementary = "?2o::" IF_FEATURE_MOUNT_VERBOSE("vv");
- opt = getopt32(argv, OPTION_STR, &lst_o, &fstype, &O_optmatch
- IF_FEATURE_MOUNT_OTHERTAB(, &fstabname)
- IF_FEATURE_MOUNT_VERBOSE(, &verbose));
+ opt = getopt32(argv, "^"
+ OPTION_STR
+ "\0" "?2"IF_FEATURE_MOUNT_VERBOSE("vv"),
+ &lst_o, &fstype, &O_optmatch
+ IF_FEATURE_MOUNT_OTHERTAB(, &fstabname)
+ IF_FEATURE_MOUNT_VERBOSE(, &verbose)
+ );
+
while (lst_o) append_mount_options(&cmdopts, llist_pop(&lst_o)); // -o
if (opt & OPT_r) append_mount_options(&cmdopts, "ro"); // -r
if (opt & OPT_w) append_mount_options(&cmdopts, "rw"); // -w
bb_error_msg_and_die(bb_msg_you_must_be_root);
// Does type match? (NULL matches always)
- if (!match_fstype(mtcur, fstype))
+ if (!fstype_matches(mtcur->mnt_type, fstype))
continue;
// Skip noauto and swap anyway