diff options
-rw-r--r-- | util-linux/mount.c | 186 |
1 files changed, 87 insertions, 99 deletions
diff --git a/util-linux/mount.c b/util-linux/mount.c index de0558024..61ad23528 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c | |||
@@ -407,7 +407,7 @@ static int mount_it_now(struct mntent *mp, long vfsflags, char *filteropts) | |||
407 | vfsflags, filteropts); | 407 | vfsflags, filteropts); |
408 | 408 | ||
409 | // If mount failed, try | 409 | // If mount failed, try |
410 | // helper program <mnt_type> | 410 | // helper program mount.<mnt_type> |
411 | if (ENABLE_FEATURE_MOUNT_HELPERS && rc) { | 411 | if (ENABLE_FEATURE_MOUNT_HELPERS && rc) { |
412 | char *args[6]; | 412 | char *args[6]; |
413 | int errno_save = errno; | 413 | int errno_save = errno; |
@@ -1727,11 +1727,11 @@ static int singlemount(struct mntent *mp, int ignore_busy) | |||
1727 | static const char must_be_root[] ALIGN1 = "you must be root"; | 1727 | static const char must_be_root[] ALIGN1 = "you must be root"; |
1728 | 1728 | ||
1729 | int mount_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 1729 | int mount_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1730 | int mount_main(int argc, char **argv) | 1730 | int mount_main(int argc ATTRIBUTE_UNUSED, char **argv) |
1731 | { | 1731 | { |
1732 | char *cmdopts = xstrdup(""); | 1732 | char *cmdopts = xstrdup(""); |
1733 | char *fstype = NULL; | 1733 | char *fstype = NULL; |
1734 | char *storage_path = NULL; | 1734 | char *storage_path; |
1735 | char *opt_o; | 1735 | char *opt_o; |
1736 | const char *fstabname; | 1736 | const char *fstabname; |
1737 | FILE *fstab; | 1737 | FILE *fstab; |
@@ -1740,43 +1740,35 @@ int mount_main(int argc, char **argv) | |||
1740 | struct mntent mtpair[2], *mtcur = mtpair; | 1740 | struct mntent mtpair[2], *mtcur = mtpair; |
1741 | SKIP_DESKTOP(const int nonroot = 0;) | 1741 | SKIP_DESKTOP(const int nonroot = 0;) |
1742 | 1742 | ||
1743 | USE_DESKTOP( int nonroot = ) sanitize_env_if_suid(); | 1743 | USE_DESKTOP(int nonroot = ) sanitize_env_if_suid(); |
1744 | 1744 | ||
1745 | // Parse long options, like --bind and --move. Note that -o option | 1745 | // Parse long options, like --bind and --move. Note that -o option |
1746 | // and --option are synonymous. Yes, this means --remount,rw works. | 1746 | // and --option are synonymous. Yes, this means --remount,rw works. |
1747 | 1747 | for (i = j = 1; argv[i]; i++) { | |
1748 | for (i = j = 0; i < argc; i++) { | 1748 | if (argv[i][0] == '-' && argv[i][1] == '-') |
1749 | if (argv[i][0] == '-' && argv[i][1] == '-') { | 1749 | append_mount_options(&cmdopts, argv[i] + 2); |
1750 | append_mount_options(&cmdopts, argv[i]+2); | 1750 | else |
1751 | } else argv[j++] = argv[i]; | 1751 | argv[j++] = argv[i]; |
1752 | } | 1752 | } |
1753 | argv[j] = NULL; | 1753 | argv[j] = NULL; |
1754 | argc = j; | ||
1755 | 1754 | ||
1756 | // Parse remaining options | 1755 | // Parse remaining options |
1757 | 1756 | // Max 2 params; -v is a counter | |
1758 | #if ENABLE_FEATURE_MOUNT_VERBOSE | 1757 | opt_complementary = "?2" USE_FEATURE_MOUNT_VERBOSE(":vv"); |
1759 | opt_complementary = "vv"; // -v is a counter | ||
1760 | #endif | ||
1761 | opt = getopt32(argv, OPTION_STR, &opt_o, &fstype | 1758 | opt = getopt32(argv, OPTION_STR, &opt_o, &fstype |
1762 | USE_FEATURE_MOUNT_VERBOSE(, &verbose)); | 1759 | USE_FEATURE_MOUNT_VERBOSE(, &verbose)); |
1763 | if (opt & OPT_o) append_mount_options(&cmdopts, opt_o); // -o | 1760 | if (opt & OPT_o) append_mount_options(&cmdopts, opt_o); // -o |
1764 | if (opt & OPT_r) append_mount_options(&cmdopts, "ro"); // -r | 1761 | if (opt & OPT_r) append_mount_options(&cmdopts, "ro"); // -r |
1765 | if (opt & OPT_w) append_mount_options(&cmdopts, "rw"); // -w | 1762 | if (opt & OPT_w) append_mount_options(&cmdopts, "rw"); // -w |
1766 | argv += optind; | 1763 | argv += optind; |
1767 | argc -= optind; | ||
1768 | |||
1769 | // Three or more non-option arguments? Die with a usage message. | ||
1770 | |||
1771 | if (argc > 2) bb_show_usage(); | ||
1772 | 1764 | ||
1773 | // If we have no arguments, show currently mounted filesystems | 1765 | // If we have no arguments, show currently mounted filesystems |
1774 | 1766 | if (!argv[0]) { | |
1775 | if (!argc) { | ||
1776 | if (!(opt & OPT_a)) { | 1767 | if (!(opt & OPT_a)) { |
1777 | FILE *mountTable = setmntent(bb_path_mtab_file, "r"); | 1768 | FILE *mountTable = setmntent(bb_path_mtab_file, "r"); |
1778 | 1769 | ||
1779 | if (!mountTable) bb_error_msg_and_die("no %s", bb_path_mtab_file); | 1770 | if (!mountTable) |
1771 | bb_error_msg_and_die("no %s", bb_path_mtab_file); | ||
1780 | 1772 | ||
1781 | while (getmntent_r(mountTable, &mtpair[0], getmntent_buf, | 1773 | while (getmntent_r(mountTable, &mtpair[0], getmntent_buf, |
1782 | GETMNTENT_BUFSIZE)) | 1774 | GETMNTENT_BUFSIZE)) |
@@ -1790,152 +1782,148 @@ int mount_main(int argc, char **argv) | |||
1790 | mtpair->mnt_dir, mtpair->mnt_type, | 1782 | mtpair->mnt_dir, mtpair->mnt_type, |
1791 | mtpair->mnt_opts); | 1783 | mtpair->mnt_opts); |
1792 | } | 1784 | } |
1793 | if (ENABLE_FEATURE_CLEAN_UP) endmntent(mountTable); | 1785 | if (ENABLE_FEATURE_CLEAN_UP) |
1786 | endmntent(mountTable); | ||
1794 | return EXIT_SUCCESS; | 1787 | return EXIT_SUCCESS; |
1795 | } | 1788 | } |
1796 | } else storage_path = bb_simplify_path(argv[0]); | 1789 | storage_path = NULL; |
1797 | 1790 | } else { | |
1798 | // When we have two arguments, the second is the directory and we can | 1791 | // When we have two arguments, the second is the directory and we can |
1799 | // skip looking at fstab entirely. We can always abspath() the directory | 1792 | // skip looking at fstab entirely. We can always abspath() the directory |
1800 | // argument when we get it. | 1793 | // argument when we get it. |
1801 | 1794 | if (argv[1]) { | |
1802 | if (argc == 2) { | 1795 | if (nonroot) |
1803 | if (nonroot) | 1796 | bb_error_msg_and_die(must_be_root); |
1804 | bb_error_msg_and_die(must_be_root); | 1797 | mtpair->mnt_fsname = argv[0]; |
1805 | mtpair->mnt_fsname = argv[0]; | 1798 | mtpair->mnt_dir = argv[1]; |
1806 | mtpair->mnt_dir = argv[1]; | 1799 | mtpair->mnt_type = fstype; |
1807 | mtpair->mnt_type = fstype; | 1800 | mtpair->mnt_opts = cmdopts; |
1808 | mtpair->mnt_opts = cmdopts; | 1801 | if (ENABLE_FEATURE_MOUNT_LABEL) { |
1809 | if (ENABLE_FEATURE_MOUNT_LABEL) { | 1802 | resolve_mount_spec(&mtpair->mnt_fsname); |
1810 | resolve_mount_spec(&mtpair->mnt_fsname); | 1803 | } |
1804 | rc = singlemount(mtpair, 0); | ||
1805 | return rc; | ||
1811 | } | 1806 | } |
1812 | rc = singlemount(mtpair, 0); | 1807 | storage_path = bb_simplify_path(argv[0]); // malloced |
1813 | goto clean_up; | ||
1814 | } | 1808 | } |
1815 | 1809 | ||
1810 | // Past this point, we are handling either "mount -a [opts]" | ||
1811 | // or "mount [opts] single_param" | ||
1812 | |||
1816 | i = parse_mount_options(cmdopts, 0); // FIXME: should be "long", not "int" | 1813 | i = parse_mount_options(cmdopts, 0); // FIXME: should be "long", not "int" |
1817 | if (nonroot && (i & ~MS_SILENT)) // Non-root users cannot specify flags | 1814 | if (nonroot && (i & ~MS_SILENT)) // Non-root users cannot specify flags |
1818 | bb_error_msg_and_die(must_be_root); | 1815 | bb_error_msg_and_die(must_be_root); |
1819 | 1816 | ||
1820 | // If we have a shared subtree flag, don't worry about fstab or mtab. | 1817 | // If we have a shared subtree flag, don't worry about fstab or mtab. |
1821 | |||
1822 | if (ENABLE_FEATURE_MOUNT_FLAGS | 1818 | if (ENABLE_FEATURE_MOUNT_FLAGS |
1823 | && (i & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) | 1819 | && (i & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) |
1824 | ) { | 1820 | ) { |
1825 | rc = verbose_mount("", argv[0], "", i, ""); | 1821 | rc = verbose_mount(/*source:*/ "", /*target:*/ argv[0], |
1826 | if (rc) bb_simple_perror_msg_and_die(argv[0]); | 1822 | /*type:*/ "", /*flags:*/ i, /*data:*/ ""); |
1827 | goto clean_up; | 1823 | if (rc) |
1824 | bb_simple_perror_msg_and_die(argv[0]); | ||
1825 | return rc; | ||
1828 | } | 1826 | } |
1829 | 1827 | ||
1830 | // Open either fstab or mtab | 1828 | // Open either fstab or mtab |
1831 | |||
1832 | fstabname = "/etc/fstab"; | 1829 | fstabname = "/etc/fstab"; |
1833 | if (i & MS_REMOUNT) { | 1830 | if (i & MS_REMOUNT) { |
1831 | // WARNING. I am not sure this matches util-linux's | ||
1832 | // behavior. It's possible util-linux does not | ||
1833 | // take -o opts from mtab (takes only mount source). | ||
1834 | fstabname = bb_path_mtab_file; | 1834 | fstabname = bb_path_mtab_file; |
1835 | } | 1835 | } |
1836 | fstab = setmntent(fstabname, "r"); | 1836 | fstab = setmntent(fstabname, "r"); |
1837 | if (!fstab) | 1837 | if (!fstab) |
1838 | bb_perror_msg_and_die("cannot read %s", fstabname); | 1838 | bb_perror_msg_and_die("cannot read %s", fstabname); |
1839 | 1839 | ||
1840 | // Loop through entries until we find what we're looking for. | 1840 | // Loop through entries until we find what we're looking for |
1841 | |||
1842 | memset(mtpair, 0, sizeof(mtpair)); | 1841 | memset(mtpair, 0, sizeof(mtpair)); |
1843 | for (;;) { | 1842 | for (;;) { |
1844 | struct mntent *mtnext = (mtcur==mtpair ? mtpair+1 : mtpair); | 1843 | struct mntent *mtother = (mtcur==mtpair ? mtpair+1 : mtpair); |
1845 | 1844 | ||
1846 | // Get next fstab entry | 1845 | // Get next fstab entry |
1847 | |||
1848 | if (!getmntent_r(fstab, mtcur, getmntent_buf | 1846 | if (!getmntent_r(fstab, mtcur, getmntent_buf |
1849 | + (mtcur==mtpair ? GETMNTENT_BUFSIZE/2 : 0), | 1847 | + (mtcur==mtpair ? GETMNTENT_BUFSIZE/2 : 0), |
1850 | GETMNTENT_BUFSIZE/2)) | 1848 | GETMNTENT_BUFSIZE/2) |
1851 | { | 1849 | ) { // End of fstab/mtab is reached |
1852 | // Were we looking for something specific? | 1850 | mtcur = mtother; // the thing we found last time |
1853 | 1851 | break; | |
1854 | if (argc) { | ||
1855 | |||
1856 | // If we didn't find anything, complain. | ||
1857 | |||
1858 | if (!mtnext->mnt_fsname) | ||
1859 | bb_error_msg_and_die("can't find %s in %s", | ||
1860 | argv[0], fstabname); | ||
1861 | |||
1862 | mtcur = mtnext; | ||
1863 | if (nonroot) { | ||
1864 | // fstab must have "users" or "user" | ||
1865 | if (!(parse_mount_options(mtcur->mnt_opts, 0) & MOUNT_USERS)) | ||
1866 | bb_error_msg_and_die(must_be_root); | ||
1867 | } | ||
1868 | |||
1869 | // Mount the last thing we found. | ||
1870 | |||
1871 | mtcur->mnt_opts = xstrdup(mtcur->mnt_opts); | ||
1872 | append_mount_options(&(mtcur->mnt_opts), cmdopts); | ||
1873 | if (ENABLE_FEATURE_MOUNT_LABEL) { | ||
1874 | resolve_mount_spec(&mtpair->mnt_fsname); | ||
1875 | } | ||
1876 | rc = singlemount(mtcur, 0); | ||
1877 | free(mtcur->mnt_opts); | ||
1878 | } | ||
1879 | goto clean_up; | ||
1880 | } | 1852 | } |
1881 | 1853 | ||
1882 | /* If we're trying to mount something specific and this isn't it, | 1854 | // If we're trying to mount something specific and this isn't it, |
1883 | * skip it. Note we must match both the exact text in fstab (ala | 1855 | // skip it. Note we must match the exact text in fstab (ala |
1884 | * "proc") or a full path from root */ | 1856 | // "proc") or a full path from root |
1885 | 1857 | if (argv[0]) { | |
1886 | if (argc) { | ||
1887 | 1858 | ||
1888 | // Is this what we're looking for? | 1859 | // Is this what we're looking for? |
1889 | |||
1890 | if (strcmp(argv[0], mtcur->mnt_fsname) && | 1860 | if (strcmp(argv[0], mtcur->mnt_fsname) && |
1891 | strcmp(storage_path, mtcur->mnt_fsname) && | 1861 | strcmp(storage_path, mtcur->mnt_fsname) && |
1892 | strcmp(argv[0], mtcur->mnt_dir) && | 1862 | strcmp(argv[0], mtcur->mnt_dir) && |
1893 | strcmp(storage_path, mtcur->mnt_dir)) continue; | 1863 | strcmp(storage_path, mtcur->mnt_dir)) continue; |
1894 | 1864 | ||
1895 | // Remember this entry. Something later may have overmounted | 1865 | // Remember this entry. Something later may have |
1896 | // it, and we want the _last_ match. | 1866 | // overmounted it, and we want the _last_ match. |
1897 | 1867 | mtcur = mtother; | |
1898 | mtcur = mtnext; | ||
1899 | |||
1900 | // If we're mounting all. | ||
1901 | 1868 | ||
1869 | // If we're mounting all | ||
1902 | } else { | 1870 | } else { |
1903 | // Do we need to match a filesystem type? | 1871 | // Do we need to match a filesystem type? |
1904 | if (fstype && match_fstype(mtcur, fstype)) | 1872 | if (fstype && match_fstype(mtcur, fstype)) |
1905 | continue; | 1873 | continue; |
1906 | 1874 | ||
1907 | // Skip noauto and swap anyway. | 1875 | // Skip noauto and swap anyway. |
1908 | |||
1909 | if (parse_mount_options(mtcur->mnt_opts, 0) & (MOUNT_NOAUTO | MOUNT_SWAP)) | 1876 | if (parse_mount_options(mtcur->mnt_opts, 0) & (MOUNT_NOAUTO | MOUNT_SWAP)) |
1910 | continue; | 1877 | continue; |
1911 | 1878 | ||
1912 | // No, mount -a won't mount anything, | 1879 | // No, mount -a won't mount anything, |
1913 | // even user mounts, for mere humans. | 1880 | // even user mounts, for mere humans |
1914 | |||
1915 | if (nonroot) | 1881 | if (nonroot) |
1916 | bb_error_msg_and_die(must_be_root); | 1882 | bb_error_msg_and_die(must_be_root); |
1917 | 1883 | ||
1918 | // Mount this thing. | 1884 | // Mount this thing |
1919 | if (ENABLE_FEATURE_MOUNT_LABEL) | 1885 | if (ENABLE_FEATURE_MOUNT_LABEL) |
1920 | resolve_mount_spec(&mtpair->mnt_fsname); | 1886 | resolve_mount_spec(&mtpair->mnt_fsname); |
1921 | 1887 | ||
1922 | // NFS mounts want this to be xrealloc-able | 1888 | // NFS mounts want this to be xrealloc-able |
1923 | mtcur->mnt_opts = xstrdup(mtcur->mnt_opts); | 1889 | mtcur->mnt_opts = xstrdup(mtcur->mnt_opts); |
1924 | if (singlemount(mtcur, 1)) { | 1890 | if (singlemount(mtcur, 1)) { |
1925 | /* Count number of failed mounts */ | 1891 | // Count number of failed mounts |
1926 | rc++; | 1892 | rc++; |
1927 | } | 1893 | } |
1928 | free(mtcur->mnt_opts); | 1894 | free(mtcur->mnt_opts); |
1929 | } | 1895 | } |
1930 | } | 1896 | } |
1931 | if (ENABLE_FEATURE_CLEAN_UP) endmntent(fstab); | ||
1932 | 1897 | ||
1933 | clean_up: | 1898 | // End of fstab/mtab is reached. |
1899 | // Were we looking for something specific? | ||
1900 | if (argv[0]) { | ||
1901 | // If we didn't find anything, complain | ||
1902 | if (!mtcur->mnt_fsname) | ||
1903 | bb_error_msg_and_die("can't find %s in %s", | ||
1904 | argv[0], fstabname); | ||
1905 | if (nonroot) { | ||
1906 | // fstab must have "users" or "user" | ||
1907 | if (!(parse_mount_options(mtcur->mnt_opts, 0) & MOUNT_USERS)) | ||
1908 | bb_error_msg_and_die(must_be_root); | ||
1909 | } | ||
1934 | 1910 | ||
1911 | // Mount the last thing we found | ||
1912 | mtcur->mnt_opts = xstrdup(mtcur->mnt_opts); | ||
1913 | append_mount_options(&(mtcur->mnt_opts), cmdopts); | ||
1914 | if (ENABLE_FEATURE_MOUNT_LABEL) { | ||
1915 | resolve_mount_spec(&mtpair->mnt_fsname); | ||
1916 | } | ||
1917 | rc = singlemount(mtcur, 0); | ||
1918 | if (ENABLE_FEATURE_CLEAN_UP) | ||
1919 | free(mtcur->mnt_opts); | ||
1920 | } | ||
1921 | |||
1922 | if (ENABLE_FEATURE_CLEAN_UP) | ||
1923 | endmntent(fstab); | ||
1935 | if (ENABLE_FEATURE_CLEAN_UP) { | 1924 | if (ENABLE_FEATURE_CLEAN_UP) { |
1936 | free(storage_path); | 1925 | free(storage_path); |
1937 | free(cmdopts); | 1926 | free(cmdopts); |
1938 | } | 1927 | } |
1939 | |||
1940 | return rc; | 1928 | return rc; |
1941 | } | 1929 | } |