diff options
-rw-r--r-- | include/usage.h | 53 | ||||
-rw-r--r-- | libbb/match_fstype.c | 36 | ||||
-rw-r--r-- | util-linux/mount.c | 103 | ||||
-rw-r--r-- | util-linux/umount.c | 4 |
4 files changed, 136 insertions, 60 deletions
diff --git a/include/usage.h b/include/usage.h index e945840b8..25a716278 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -2796,45 +2796,50 @@ | |||
2796 | "$ dmesg | more\n" | 2796 | "$ dmesg | more\n" |
2797 | 2797 | ||
2798 | #define mount_trivial_usage \ | 2798 | #define mount_trivial_usage \ |
2799 | "[flags] DEVICE NODE [-o options,more-options]" | 2799 | "[flags] DEVICE NODE [-o OPT,OPT]" |
2800 | #define mount_full_usage "\n\n" \ | 2800 | #define mount_full_usage "\n\n" \ |
2801 | "Mount a filesystem. Filesystem autodetection requires /proc be mounted.\n" \ | 2801 | "Mount a filesystem. Filesystem autodetection requires /proc be mounted.\n" \ |
2802 | "\nOptions:" \ | 2802 | "\nOptions:" \ |
2803 | "\n -a Mount all filesystems in fstab" \ | 2803 | "\n -a Mount all filesystems in fstab" \ |
2804 | USE_FEATURE_MOUNT_FAKE( \ | 2804 | USE_FEATURE_MOUNT_FAKE( \ |
2805 | "\n -f "USE_FEATURE_MTAB_SUPPORT("Update /etc/mtab, but ")"don't mount" \ | 2805 | USE_FEATURE_MTAB_SUPPORT( \ |
2806 | "\n -f Update /etc/mtab, but don't mount" \ | ||
2807 | ) \ | ||
2808 | SKIP_FEATURE_MTAB_SUPPORT( \ | ||
2809 | "\n -f Dry run" \ | ||
2810 | ) \ | ||
2806 | ) \ | 2811 | ) \ |
2807 | USE_FEATURE_MTAB_SUPPORT( \ | 2812 | USE_FEATURE_MTAB_SUPPORT( \ |
2808 | "\n -n Don't update /etc/mtab" \ | 2813 | "\n -n Don't update /etc/mtab" \ |
2809 | ) \ | 2814 | ) \ |
2810 | "\n -r Read-only mount" \ | 2815 | "\n -r Read-only mount" \ |
2811 | "\n -t fs-type Filesystem type" \ | ||
2812 | "\n -w Read-write mount (default)" \ | 2816 | "\n -w Read-write mount (default)" \ |
2813 | "\n" \ | 2817 | "\n -t FSTYPE Filesystem type" \ |
2814 | "-o option:\n" \ | 2818 | "\n -O OPT Mount only filesystems with option OPT (-a only)" \ |
2819 | "\n-o OPT:" \ | ||
2815 | USE_FEATURE_MOUNT_LOOP( \ | 2820 | USE_FEATURE_MOUNT_LOOP( \ |
2816 | " loop Ignored (loop devices are autodetected)\n" \ | 2821 | "\n loop Ignored (loop devices are autodetected)" \ |
2817 | ) \ | 2822 | ) \ |
2818 | USE_FEATURE_MOUNT_FLAGS( \ | 2823 | USE_FEATURE_MOUNT_FLAGS( \ |
2819 | " [a]sync Writes are asynchronous / synchronous\n" \ | 2824 | "\n [a]sync Writes are [a]synchronous" \ |
2820 | " [no]atime Disable / enable updates to inode access times\n" \ | 2825 | "\n [no]atime Disable/enable updates to inode access times" \ |
2821 | " [no]diratime Disable / enable atime updates to directories\n" \ | 2826 | "\n [no]diratime Disable/enable atime updates to directories" \ |
2822 | " [no]relatime Disable / enable atime updates relative to modification time\n" \ | 2827 | "\n [no]relatime Disable/enable atime updates relative to modification time" \ |
2823 | " [no]dev Allow use of special device files / disallow them\n" \ | 2828 | "\n [no]dev (Dis)allow use of special device files" \ |
2824 | " [no]exec Allow use of executable files / disallow them\n" \ | 2829 | "\n [no]exec (Dis)allow use of executable files" \ |
2825 | " [no]suid Allow set-user-id-root programs / disallow them\n" \ | 2830 | "\n [no]suid (Dis)allow set-user-id-root programs" \ |
2826 | " [r]shared Convert [recursively] to a shared subtree\n" \ | 2831 | "\n [r]shared Convert [recursively] to a shared subtree" \ |
2827 | " [r]slave Convert [recursively] to a slave subtree\n" \ | 2832 | "\n [r]slave Convert [recursively] to a slave subtree" \ |
2828 | " [r]private Convert [recursively] to a private subtree\n" \ | 2833 | "\n [r]private Convert [recursively] to a private subtree" \ |
2829 | " [un]bindable Make mount point [un]able to be bind mounted\n" \ | 2834 | "\n [un]bindable Make mount point [un]able to be bind mounted" \ |
2830 | " bind Bind a directory to an additional location\n" \ | 2835 | "\n bind Bind a directory to an additional location" \ |
2831 | " move Relocate an existing mount point\n" \ | 2836 | "\n move Relocate an existing mount point" \ |
2832 | ) \ | 2837 | ) \ |
2833 | " remount Remount a mounted filesystem, changing its flags\n" \ | 2838 | "\n remount Remount a mounted filesystem, changing its flags" \ |
2834 | " ro/rw Mount for read-only / read-write\n" \ | 2839 | "\n ro/rw Read-only/read-write mount" \ |
2835 | "\n" \ | 2840 | "\n" \ |
2836 | "There are EVEN MORE flags that are specific to each filesystem\n" \ | 2841 | "\nThere are EVEN MORE flags that are specific to each filesystem" \ |
2837 | "You'll have to see the written documentation for those filesystems" \ | 2842 | "\nYou'll have to see the written documentation for those filesystems" \ |
2838 | 2843 | ||
2839 | #define mount_example_usage \ | 2844 | #define mount_example_usage \ |
2840 | "$ mount\n" \ | 2845 | "$ mount\n" \ |
diff --git a/libbb/match_fstype.c b/libbb/match_fstype.c index 99e276784..9360e757a 100644 --- a/libbb/match_fstype.c +++ b/libbb/match_fstype.c | |||
@@ -5,40 +5,38 @@ | |||
5 | * This allows us to match fstypes that start with no like so | 5 | * This allows us to match fstypes that start with no like so |
6 | * mount -at ,noddy | 6 | * mount -at ,noddy |
7 | * | 7 | * |
8 | * Returns 0 for a match, otherwise -1 | 8 | * Returns 1 for a match, otherwise 0 |
9 | * | 9 | * |
10 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 10 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include "libbb.h" | 13 | #include "libbb.h" |
14 | 14 | ||
15 | int FAST_FUNC match_fstype(const struct mntent *mt, const char *fstype) | 15 | int FAST_FUNC match_fstype(const struct mntent *mt, const char *t_fstype) |
16 | { | 16 | { |
17 | int no = 0; | 17 | int match = 1; |
18 | int len; | 18 | int len; |
19 | 19 | ||
20 | if (!mt) | 20 | if (!t_fstype) |
21 | return -1; | 21 | return match; |
22 | 22 | ||
23 | if (!fstype) | 23 | if (t_fstype[0] == 'n' && t_fstype[1] == 'o') { |
24 | return 0; | 24 | match--; |
25 | 25 | t_fstype += 2; | |
26 | if (fstype[0] == 'n' && fstype[1] == 'o') { | ||
27 | no = -1; | ||
28 | fstype += 2; | ||
29 | } | 26 | } |
30 | 27 | ||
31 | len = strlen(mt->mnt_type); | 28 | len = strlen(mt->mnt_type); |
32 | while (fstype) { | 29 | while (1) { |
33 | if (!strncmp(mt->mnt_type, fstype, len) | 30 | if (strncmp(mt->mnt_type, t_fstype, len) == 0 |
34 | && (!fstype[len] || fstype[len] == ',') | 31 | && (t_fstype[len] == '\0' || t_fstype[len] == ',') |
35 | ) { | 32 | ) { |
36 | return no; | 33 | return match; |
37 | } | 34 | } |
38 | fstype = strchr(fstype, ','); | 35 | t_fstype = strchr(t_fstype, ','); |
39 | if (fstype) | 36 | if (!t_fstype) |
40 | fstype++; | 37 | break; |
38 | t_fstype++; | ||
41 | } | 39 | } |
42 | 40 | ||
43 | return -(no + 1); | 41 | return !match; |
44 | } | 42 | } |
diff --git a/util-linux/mount.c b/util-linux/mount.c index 3b8311318..d647c71b1 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c | |||
@@ -63,7 +63,7 @@ enum { | |||
63 | }; | 63 | }; |
64 | 64 | ||
65 | 65 | ||
66 | #define OPTION_STR "o:t:rwanfvsi" | 66 | #define OPTION_STR "o:t:rwanfvsiO:" |
67 | enum { | 67 | enum { |
68 | OPT_o = (1 << 0), | 68 | OPT_o = (1 << 0), |
69 | OPT_t = (1 << 1), | 69 | OPT_t = (1 << 1), |
@@ -75,6 +75,7 @@ enum { | |||
75 | OPT_v = (1 << 7), | 75 | OPT_v = (1 << 7), |
76 | OPT_s = (1 << 8), | 76 | OPT_s = (1 << 8), |
77 | OPT_i = (1 << 9), | 77 | OPT_i = (1 << 9), |
78 | OPT_O = (1 << 10), | ||
78 | }; | 79 | }; |
79 | 80 | ||
80 | #if ENABLE_FEATURE_MTAB_SUPPORT | 81 | #if ENABLE_FEATURE_MTAB_SUPPORT |
@@ -1721,6 +1722,45 @@ static int singlemount(struct mntent *mp, int ignore_busy) | |||
1721 | return rc; | 1722 | return rc; |
1722 | } | 1723 | } |
1723 | 1724 | ||
1725 | /* -O support | ||
1726 | * Unlike -t, -O should interpret "no" prefix differently: | ||
1727 | * -t noa,b,c = -t no(a,b,c) = mount all except fs'es with types a,b, and c | ||
1728 | * -O noa,b,c = -O noa,b,c = mount all with without option a, | ||
1729 | * or with option b or c. | ||
1730 | * But for now we do not support -O a,b,c at all (only -O a). | ||
1731 | * | ||
1732 | * Another difference from -t support (match_fstype) is that | ||
1733 | * we need to examine the _list_ of options in fsopt, not just a string. | ||
1734 | */ | ||
1735 | static int match_opt(const char *fs_opt, const char *O_opt) | ||
1736 | { | ||
1737 | int match = 1; | ||
1738 | int len; | ||
1739 | |||
1740 | if (!O_opt) | ||
1741 | return match; | ||
1742 | |||
1743 | if (O_opt[0] == 'n' && O_opt[1] == 'o') { | ||
1744 | match--; | ||
1745 | O_opt += 2; | ||
1746 | } | ||
1747 | |||
1748 | len = strlen(O_opt); | ||
1749 | while (1) { | ||
1750 | if (strncmp(fs_opt, O_opt, len) == 0 | ||
1751 | && (fs_opt[len] == '\0' || fs_opt[len] == ',') | ||
1752 | ) { | ||
1753 | return match; | ||
1754 | } | ||
1755 | fs_opt = strchr(fs_opt, ','); | ||
1756 | if (!fs_opt) | ||
1757 | break; | ||
1758 | fs_opt++; | ||
1759 | } | ||
1760 | |||
1761 | return !match; | ||
1762 | } | ||
1763 | |||
1724 | // Parse options, if necessary parse fstab/mtab, and call singlemount for | 1764 | // Parse options, if necessary parse fstab/mtab, and call singlemount for |
1725 | // each directory to be mounted. | 1765 | // each directory to be mounted. |
1726 | static const char must_be_root[] ALIGN1 = "you must be root"; | 1766 | static const char must_be_root[] ALIGN1 = "you must be root"; |
@@ -1728,8 +1768,9 @@ static const char must_be_root[] ALIGN1 = "you must be root"; | |||
1728 | int mount_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1768 | int mount_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1729 | int mount_main(int argc UNUSED_PARAM, char **argv) | 1769 | int mount_main(int argc UNUSED_PARAM, char **argv) |
1730 | { | 1770 | { |
1731 | char *cmdopts = xstrdup(""); | 1771 | char *cmdopts = xzalloc(1); |
1732 | char *fstype = NULL; | 1772 | char *fstype = NULL; |
1773 | char *O_optmatch = NULL; | ||
1733 | char *storage_path; | 1774 | char *storage_path; |
1734 | llist_t *lst_o = NULL; | 1775 | llist_t *lst_o = NULL; |
1735 | const char *fstabname; | 1776 | const char *fstabname; |
@@ -1752,9 +1793,9 @@ int mount_main(int argc UNUSED_PARAM, char **argv) | |||
1752 | argv[j] = NULL; | 1793 | argv[j] = NULL; |
1753 | 1794 | ||
1754 | // Parse remaining options | 1795 | // Parse remaining options |
1755 | // Max 2 params; -v is a counter | 1796 | // Max 2 params; -o is a list, -v is a counter |
1756 | opt_complementary = "?2o::" USE_FEATURE_MOUNT_VERBOSE(":vv"); | 1797 | opt_complementary = "?2o::" USE_FEATURE_MOUNT_VERBOSE("vv"); |
1757 | opt = getopt32(argv, OPTION_STR, &lst_o, &fstype | 1798 | opt = getopt32(argv, OPTION_STR, &lst_o, &fstype, &O_optmatch |
1758 | USE_FEATURE_MOUNT_VERBOSE(, &verbose)); | 1799 | USE_FEATURE_MOUNT_VERBOSE(, &verbose)); |
1759 | while (lst_o) append_mount_options(&cmdopts, llist_pop(&lst_o)); // -o | 1800 | while (lst_o) append_mount_options(&cmdopts, llist_pop(&lst_o)); // -o |
1760 | if (opt & OPT_r) append_mount_options(&cmdopts, "ro"); // -r | 1801 | if (opt & OPT_r) append_mount_options(&cmdopts, "ro"); // -r |
@@ -1807,7 +1848,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv) | |||
1807 | // Past this point, we are handling either "mount -a [opts]" | 1848 | // Past this point, we are handling either "mount -a [opts]" |
1808 | // or "mount [opts] single_param" | 1849 | // or "mount [opts] single_param" |
1809 | 1850 | ||
1810 | i = parse_mount_options(cmdopts, 0); // FIXME: should be "long", not "int" | 1851 | i = parse_mount_options(cmdopts, NULL); // FIXME: should be "long", not "int" |
1811 | if (nonroot && (i & ~MS_SILENT)) // Non-root users cannot specify flags | 1852 | if (nonroot && (i & ~MS_SILENT)) // Non-root users cannot specify flags |
1812 | bb_error_msg_and_die(must_be_root); | 1853 | bb_error_msg_and_die(must_be_root); |
1813 | 1854 | ||
@@ -1865,20 +1906,29 @@ int mount_main(int argc UNUSED_PARAM, char **argv) | |||
1865 | 1906 | ||
1866 | // If we're mounting all | 1907 | // If we're mounting all |
1867 | } else { | 1908 | } else { |
1868 | // Do we need to match a filesystem type? | 1909 | // No, mount -a won't mount anything, |
1869 | if (fstype && match_fstype(mtcur, fstype)) | 1910 | // even user mounts, for mere humans |
1911 | if (nonroot) | ||
1912 | bb_error_msg_and_die(must_be_root); | ||
1913 | |||
1914 | // Does type match? (NULL matches always) | ||
1915 | if (!match_fstype(mtcur, fstype)) | ||
1870 | continue; | 1916 | continue; |
1871 | 1917 | ||
1872 | // Skip noauto and swap anyway. | 1918 | // Skip noauto and swap anyway. |
1873 | if (parse_mount_options(mtcur->mnt_opts, 0) & (MOUNT_NOAUTO | MOUNT_SWAP)) | 1919 | if ((parse_mount_options(mtcur->mnt_opts, NULL) & (MOUNT_NOAUTO | MOUNT_SWAP)) |
1920 | // swap is bogus "fstype", parse_mount_options can't check fstypes | ||
1921 | || strcasecmp(mtcur->mnt_type, "swap") == 0 | ||
1922 | ) { | ||
1874 | continue; | 1923 | continue; |
1924 | } | ||
1875 | 1925 | ||
1876 | // No, mount -a won't mount anything, | 1926 | // Does (at least one) option match? |
1877 | // even user mounts, for mere humans | 1927 | // (NULL matches always) |
1878 | if (nonroot) | 1928 | if (!match_opt(mtcur->mnt_opts, O_optmatch)) |
1879 | bb_error_msg_and_die(must_be_root); | 1929 | continue; |
1880 | 1930 | ||
1881 | resolve_mount_spec(&mtpair->mnt_fsname); | 1931 | resolve_mount_spec(&mtcur->mnt_fsname); |
1882 | 1932 | ||
1883 | // NFS mounts want this to be xrealloc-able | 1933 | // NFS mounts want this to be xrealloc-able |
1884 | mtcur->mnt_opts = xstrdup(mtcur->mnt_opts); | 1934 | mtcur->mnt_opts = xstrdup(mtcur->mnt_opts); |
@@ -1895,13 +1945,35 @@ int mount_main(int argc UNUSED_PARAM, char **argv) | |||
1895 | // End of fstab/mtab is reached. | 1945 | // End of fstab/mtab is reached. |
1896 | // Were we looking for something specific? | 1946 | // Were we looking for something specific? |
1897 | if (argv[0]) { | 1947 | if (argv[0]) { |
1948 | long l; | ||
1949 | |||
1898 | // If we didn't find anything, complain | 1950 | // If we didn't find anything, complain |
1899 | if (!mtcur->mnt_fsname) | 1951 | if (!mtcur->mnt_fsname) |
1900 | bb_error_msg_and_die("can't find %s in %s", | 1952 | bb_error_msg_and_die("can't find %s in %s", |
1901 | argv[0], fstabname); | 1953 | argv[0], fstabname); |
1954 | |||
1955 | // What happens when we try to "mount swap_partition"? | ||
1956 | // (fstab containts "swap_partition swap swap defaults 0 0") | ||
1957 | // util-linux-ng 2.13.1 does this: | ||
1958 | // stat("/sbin/mount.swap", 0x7fff62a3a350) = -1 ENOENT (No such file or directory) | ||
1959 | // mount("swap_partition", "swap", "swap", MS_MGC_VAL, NULL) = -1 ENOENT (No such file or directory) | ||
1960 | // lstat("swap", 0x7fff62a3a640) = -1 ENOENT (No such file or directory) | ||
1961 | // write(2, "mount: mount point swap does not exist\n", 39) = 39 | ||
1962 | // exit_group(32) = ? | ||
1963 | #if 0 | ||
1964 | // In case we want to simply skip swap partitions: | ||
1965 | l = parse_mount_options(mtcur->mnt_opts, NULL); | ||
1966 | if ((l & MOUNT_SWAP) | ||
1967 | // swap is bogus "fstype", parse_mount_options can't check fstypes | ||
1968 | || strcasecmp(mtcur->mnt_type, "swap") == 0 | ||
1969 | ) { | ||
1970 | goto ret; | ||
1971 | } | ||
1972 | #endif | ||
1902 | if (nonroot) { | 1973 | if (nonroot) { |
1903 | // fstab must have "users" or "user" | 1974 | // fstab must have "users" or "user" |
1904 | if (!(parse_mount_options(mtcur->mnt_opts, 0) & MOUNT_USERS)) | 1975 | l = parse_mount_options(mtcur->mnt_opts, NULL); |
1976 | if (!(l & MOUNT_USERS)) | ||
1905 | bb_error_msg_and_die(must_be_root); | 1977 | bb_error_msg_and_die(must_be_root); |
1906 | } | 1978 | } |
1907 | 1979 | ||
@@ -1914,6 +1986,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv) | |||
1914 | free(mtcur->mnt_opts); | 1986 | free(mtcur->mnt_opts); |
1915 | } | 1987 | } |
1916 | 1988 | ||
1989 | //ret: | ||
1917 | if (ENABLE_FEATURE_CLEAN_UP) | 1990 | if (ENABLE_FEATURE_CLEAN_UP) |
1918 | endmntent(fstab); | 1991 | endmntent(fstab); |
1919 | if (ENABLE_FEATURE_CLEAN_UP) { | 1992 | if (ENABLE_FEATURE_CLEAN_UP) { |
diff --git a/util-linux/umount.c b/util-linux/umount.c index 901c9094f..5b22bfacc 100644 --- a/util-linux/umount.c +++ b/util-linux/umount.c | |||
@@ -73,9 +73,9 @@ int umount_main(int argc UNUSED_PARAM, char **argv) | |||
73 | } else { | 73 | } else { |
74 | while (getmntent_r(fp, &me, path, PATH_MAX)) { | 74 | while (getmntent_r(fp, &me, path, PATH_MAX)) { |
75 | /* Match fstype if passed */ | 75 | /* Match fstype if passed */ |
76 | if (fstype && match_fstype(&me, fstype)) | 76 | if (!match_fstype(&me, fstype)) |
77 | continue; | 77 | continue; |
78 | m = xmalloc(sizeof(struct mtab_list)); | 78 | m = xzalloc(sizeof(*m)); |
79 | m->next = mtl; | 79 | m->next = mtl; |
80 | m->device = xstrdup(me.mnt_fsname); | 80 | m->device = xstrdup(me.mnt_fsname); |
81 | m->dir = xstrdup(me.mnt_dir); | 81 | m->dir = xstrdup(me.mnt_dir); |