diff options
Diffstat (limited to 'util-linux/mount.c')
-rw-r--r-- | util-linux/mount.c | 102 |
1 files changed, 67 insertions, 35 deletions
diff --git a/util-linux/mount.c b/util-linux/mount.c index 525fdcce9..62fd41fd7 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c | |||
@@ -36,6 +36,10 @@ | |||
36 | //usage: IF_FEATURE_MTAB_SUPPORT( | 36 | //usage: IF_FEATURE_MTAB_SUPPORT( |
37 | //usage: "\n -n Don't update /etc/mtab" | 37 | //usage: "\n -n Don't update /etc/mtab" |
38 | //usage: ) | 38 | //usage: ) |
39 | //usage: IF_FEATURE_MOUNT_VERBOSE( | ||
40 | //usage: "\n -v Verbose" | ||
41 | //usage: ) | ||
42 | ////usage: "\n -s Sloppy (ignored)" | ||
39 | //usage: "\n -r Read-only mount" | 43 | //usage: "\n -r Read-only mount" |
40 | //usage: "\n -w Read-write mount (default)" | 44 | //usage: "\n -w Read-write mount (default)" |
41 | //usage: "\n -t FSTYPE[,...] Filesystem type(s)" | 45 | //usage: "\n -t FSTYPE[,...] Filesystem type(s)" |
@@ -224,7 +228,7 @@ static const int32_t mount_options[] = { | |||
224 | IF_DESKTOP(/* "user" */ MOUNT_USERS,) | 228 | IF_DESKTOP(/* "user" */ MOUNT_USERS,) |
225 | IF_DESKTOP(/* "users" */ MOUNT_USERS,) | 229 | IF_DESKTOP(/* "users" */ MOUNT_USERS,) |
226 | /* "_netdev" */ 0, | 230 | /* "_netdev" */ 0, |
227 | IF_DESKTOP(/* "comment" */ 0,) /* systemd uses this in fstab */ | 231 | IF_DESKTOP(/* "comment=" */ 0,) /* systemd uses this in fstab */ |
228 | ) | 232 | ) |
229 | 233 | ||
230 | IF_FEATURE_MOUNT_FLAGS( | 234 | IF_FEATURE_MOUNT_FLAGS( |
@@ -283,7 +287,7 @@ static const char mount_option_str[] = | |||
283 | IF_DESKTOP("user\0") | 287 | IF_DESKTOP("user\0") |
284 | IF_DESKTOP("users\0") | 288 | IF_DESKTOP("users\0") |
285 | "_netdev\0" | 289 | "_netdev\0" |
286 | IF_DESKTOP("comment\0") /* systemd uses this in fstab */ | 290 | IF_DESKTOP("comment=\0") /* systemd uses this in fstab */ |
287 | ) | 291 | ) |
288 | IF_FEATURE_MOUNT_FLAGS( | 292 | IF_FEATURE_MOUNT_FLAGS( |
289 | // vfs flags | 293 | // vfs flags |
@@ -475,10 +479,13 @@ static unsigned long parse_mount_options(char *options, char **unrecognized) | |||
475 | // FIXME: use hasmntopt() | 479 | // FIXME: use hasmntopt() |
476 | // Find this option in mount_options | 480 | // Find this option in mount_options |
477 | for (i = 0; i < ARRAY_SIZE(mount_options); i++) { | 481 | for (i = 0; i < ARRAY_SIZE(mount_options); i++) { |
478 | /* We support "option=" match for "comment=" thingy */ | ||
479 | unsigned opt_len = strlen(option_str); | 482 | unsigned opt_len = strlen(option_str); |
483 | |||
480 | if (strncasecmp(option_str, options, opt_len) == 0 | 484 | if (strncasecmp(option_str, options, opt_len) == 0 |
481 | && (options[opt_len] == '\0' || options[opt_len] == '=') | 485 | && (options[opt_len] == '\0' |
486 | /* or is it "comment=" thingy in fstab? */ | ||
487 | IF_FEATURE_MOUNT_FSTAB(IF_DESKTOP( || option_str[opt_len-1] == '=' )) | ||
488 | ) | ||
482 | ) { | 489 | ) { |
483 | unsigned long fl = mount_options[i]; | 490 | unsigned long fl = mount_options[i]; |
484 | if (fl & BB_MS_INVERTED_VALUE) | 491 | if (fl & BB_MS_INVERTED_VALUE) |
@@ -927,7 +934,7 @@ static bool_t xdr_fhandle(XDR *xdrs, fhandle objp) | |||
927 | static bool_t xdr_fhstatus(XDR *xdrs, fhstatus *objp) | 934 | static bool_t xdr_fhstatus(XDR *xdrs, fhstatus *objp) |
928 | { | 935 | { |
929 | if (!xdr_u_int(xdrs, &objp->fhs_status)) | 936 | if (!xdr_u_int(xdrs, &objp->fhs_status)) |
930 | return FALSE; | 937 | return FALSE; |
931 | if (objp->fhs_status == 0) | 938 | if (objp->fhs_status == 0) |
932 | return xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle); | 939 | return xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle); |
933 | return TRUE; | 940 | return TRUE; |
@@ -941,8 +948,8 @@ static bool_t xdr_dirpath(XDR *xdrs, dirpath *objp) | |||
941 | static bool_t xdr_fhandle3(XDR *xdrs, fhandle3 *objp) | 948 | static bool_t xdr_fhandle3(XDR *xdrs, fhandle3 *objp) |
942 | { | 949 | { |
943 | return xdr_bytes(xdrs, (char **)&objp->fhandle3_val, | 950 | return xdr_bytes(xdrs, (char **)&objp->fhandle3_val, |
944 | (unsigned int *) &objp->fhandle3_len, | 951 | (unsigned int *) &objp->fhandle3_len, |
945 | FHSIZE3); | 952 | FHSIZE3); |
946 | } | 953 | } |
947 | 954 | ||
948 | static bool_t xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp) | 955 | static bool_t xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp) |
@@ -950,10 +957,10 @@ static bool_t xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp) | |||
950 | if (!xdr_fhandle3(xdrs, &objp->fhandle)) | 957 | if (!xdr_fhandle3(xdrs, &objp->fhandle)) |
951 | return FALSE; | 958 | return FALSE; |
952 | return xdr_array(xdrs, &(objp->auth_flavours.auth_flavours_val), | 959 | return xdr_array(xdrs, &(objp->auth_flavours.auth_flavours_val), |
953 | &(objp->auth_flavours.auth_flavours_len), | 960 | &(objp->auth_flavours.auth_flavours_len), |
954 | ~0, | 961 | ~0, |
955 | sizeof(int), | 962 | sizeof(int), |
956 | (xdrproc_t) xdr_int); | 963 | (xdrproc_t) xdr_int); |
957 | } | 964 | } |
958 | 965 | ||
959 | static bool_t xdr_mountstat3(XDR *xdrs, mountstat3 *objp) | 966 | static bool_t xdr_mountstat3(XDR *xdrs, mountstat3 *objp) |
@@ -1522,19 +1529,19 @@ static NOINLINE int nfsmount(struct mntent *mp, unsigned long vfsflags, char *fi | |||
1522 | switch (pm_mnt.pm_prot) { | 1529 | switch (pm_mnt.pm_prot) { |
1523 | case IPPROTO_UDP: | 1530 | case IPPROTO_UDP: |
1524 | mclient = clntudp_create(&mount_server_addr, | 1531 | mclient = clntudp_create(&mount_server_addr, |
1525 | pm_mnt.pm_prog, | 1532 | pm_mnt.pm_prog, |
1526 | pm_mnt.pm_vers, | 1533 | pm_mnt.pm_vers, |
1527 | retry_timeout, | 1534 | retry_timeout, |
1528 | &msock); | 1535 | &msock); |
1529 | if (mclient) | 1536 | if (mclient) |
1530 | break; | 1537 | break; |
1531 | mount_server_addr.sin_port = htons(pm_mnt.pm_port); | 1538 | mount_server_addr.sin_port = htons(pm_mnt.pm_port); |
1532 | msock = RPC_ANYSOCK; | 1539 | msock = RPC_ANYSOCK; |
1533 | case IPPROTO_TCP: | 1540 | case IPPROTO_TCP: |
1534 | mclient = clnttcp_create(&mount_server_addr, | 1541 | mclient = clnttcp_create(&mount_server_addr, |
1535 | pm_mnt.pm_prog, | 1542 | pm_mnt.pm_prog, |
1536 | pm_mnt.pm_vers, | 1543 | pm_mnt.pm_vers, |
1537 | &msock, 0, 0); | 1544 | &msock, 0, 0); |
1538 | break; | 1545 | break; |
1539 | default: | 1546 | default: |
1540 | mclient = NULL; | 1547 | mclient = NULL; |
@@ -1555,18 +1562,18 @@ static NOINLINE int nfsmount(struct mntent *mp, unsigned long vfsflags, char *fi | |||
1555 | 1562 | ||
1556 | if (pm_mnt.pm_vers == 3) | 1563 | if (pm_mnt.pm_vers == 3) |
1557 | clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT, | 1564 | clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT, |
1558 | (xdrproc_t) xdr_dirpath, | 1565 | (xdrproc_t) xdr_dirpath, |
1559 | (caddr_t) &pathname, | 1566 | (caddr_t) &pathname, |
1560 | (xdrproc_t) xdr_mountres3, | 1567 | (xdrproc_t) xdr_mountres3, |
1561 | (caddr_t) &status, | 1568 | (caddr_t) &status, |
1562 | total_timeout); | 1569 | total_timeout); |
1563 | else | 1570 | else |
1564 | clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, | 1571 | clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, |
1565 | (xdrproc_t) xdr_dirpath, | 1572 | (xdrproc_t) xdr_dirpath, |
1566 | (caddr_t) &pathname, | 1573 | (caddr_t) &pathname, |
1567 | (xdrproc_t) xdr_fhstatus, | 1574 | (xdrproc_t) xdr_fhstatus, |
1568 | (caddr_t) &status, | 1575 | (caddr_t) &status, |
1569 | total_timeout); | 1576 | total_timeout); |
1570 | 1577 | ||
1571 | if (clnt_stat == RPC_SUCCESS) | 1578 | if (clnt_stat == RPC_SUCCESS) |
1572 | goto prepare_kernel_data; /* we're done */ | 1579 | goto prepare_kernel_data; /* we're done */ |
@@ -1817,17 +1824,44 @@ static int singlemount(struct mntent *mp, int ignore_busy) | |||
1817 | ) { | 1824 | ) { |
1818 | int len; | 1825 | int len; |
1819 | char c; | 1826 | char c; |
1827 | char *hostname, *share; | ||
1828 | char *dotted, *ip; | ||
1820 | len_and_sockaddr *lsa; | 1829 | len_and_sockaddr *lsa; |
1821 | char *hostname, *dotted, *ip; | 1830 | |
1831 | // Parse mp->mnt_fsname of the form "//hostname/share[/dir1/dir2]" | ||
1822 | 1832 | ||
1823 | hostname = mp->mnt_fsname + 2; | 1833 | hostname = mp->mnt_fsname + 2; |
1824 | len = strcspn(hostname, "/\\"); | 1834 | len = strcspn(hostname, "/\\"); |
1825 | if (len == 0 || hostname[len] == '\0') | 1835 | share = hostname + len + 1; |
1836 | if (len == 0 // 3rd char is a [back]slash (IOW: empty hostname) | ||
1837 | || share[-1] == '\0' // no [back]slash after hostname | ||
1838 | || share[0] == '\0' // empty share name | ||
1839 | ) { | ||
1826 | goto report_error; | 1840 | goto report_error; |
1827 | c = hostname[len]; | 1841 | } |
1828 | hostname[len] = '\0'; | 1842 | c = share[-1]; |
1843 | share[-1] = '\0'; | ||
1844 | len = strcspn(share, "/\\"); | ||
1845 | |||
1846 | // "unc=\\hostname\share" option is mandatory | ||
1847 | // after CIFS option parsing was rewritten in Linux 3.4. | ||
1848 | // Must use backslashes. | ||
1849 | // If /dir1/dir2 is present, also add "prefixpath=dir1/dir2" | ||
1850 | { | ||
1851 | char *unc = xasprintf( | ||
1852 | share[len] != '\0' /* "/dir1/dir2" exists? */ | ||
1853 | ? "unc=\\\\%s\\%.*s,prefixpath=%s" | ||
1854 | : "unc=\\\\%s\\%.*s", | ||
1855 | hostname, | ||
1856 | len, share, | ||
1857 | share + len + 1 /* "dir1/dir2" */ | ||
1858 | ); | ||
1859 | parse_mount_options(unc, &filteropts); | ||
1860 | if (ENABLE_FEATURE_CLEAN_UP) free(unc); | ||
1861 | } | ||
1862 | |||
1829 | lsa = host2sockaddr(hostname, 0); | 1863 | lsa = host2sockaddr(hostname, 0); |
1830 | hostname[len] = c; | 1864 | share[-1] = c; |
1831 | if (!lsa) | 1865 | if (!lsa) |
1832 | goto report_error; | 1866 | goto report_error; |
1833 | 1867 | ||
@@ -1839,8 +1873,6 @@ static int singlemount(struct mntent *mp, int ignore_busy) | |||
1839 | parse_mount_options(ip, &filteropts); | 1873 | parse_mount_options(ip, &filteropts); |
1840 | if (ENABLE_FEATURE_CLEAN_UP) free(ip); | 1874 | if (ENABLE_FEATURE_CLEAN_UP) free(ip); |
1841 | 1875 | ||
1842 | // "-o mand" is required [why?] | ||
1843 | vfsflags |= MS_MANDLOCK; | ||
1844 | mp->mnt_type = (char*)"cifs"; | 1876 | mp->mnt_type = (char*)"cifs"; |
1845 | rc = mount_it_now(mp, vfsflags, filteropts); | 1877 | rc = mount_it_now(mp, vfsflags, filteropts); |
1846 | 1878 | ||