//usage: IF_FEATURE_MTAB_SUPPORT(
//usage: "\n -n Don't update /etc/mtab"
//usage: )
+//usage: IF_FEATURE_MOUNT_VERBOSE(
+//usage: "\n -v Verbose"
+//usage: )
+////usage: "\n -s Sloppy (ignored)"
//usage: "\n -r Read-only mount"
//usage: "\n -w Read-write mount (default)"
//usage: "\n -t FSTYPE[,...] Filesystem type(s)"
#ifndef MS_RELATIME
# define MS_RELATIME (1 << 21)
#endif
+#ifndef MS_STRICTATIME
+# define MS_STRICTATIME (1 << 24)
+#endif
+
+/* Any ~MS_FOO value has this bit set: */
+#define BB_MS_INVERTED_VALUE (1u << 31)
#include "libbb.h"
#if ENABLE_FEATURE_MOUNT_LABEL
IF_DESKTOP(/* "user" */ MOUNT_USERS,)
IF_DESKTOP(/* "users" */ MOUNT_USERS,)
/* "_netdev" */ 0,
- IF_DESKTOP(/* "comment" */ 0,) /* systemd uses this in fstab */
+ IF_DESKTOP(/* "comment=" */ 0,) /* systemd uses this in fstab */
)
IF_FEATURE_MOUNT_FLAGS(
/* "nomand" */ ~MS_MANDLOCK,
/* "relatime" */ MS_RELATIME,
/* "norelatime" */ ~MS_RELATIME,
+ /* "strictatime" */ MS_STRICTATIME,
/* "loud" */ ~MS_SILENT,
/* "rbind" */ MS_BIND|MS_RECURSIVE,
IF_DESKTOP("user\0")
IF_DESKTOP("users\0")
"_netdev\0"
- IF_DESKTOP("comment\0") /* systemd uses this in fstab */
+ IF_DESKTOP("comment=\0") /* systemd uses this in fstab */
)
IF_FEATURE_MOUNT_FLAGS(
// vfs flags
"nomand\0"
"relatime\0"
"norelatime\0"
+ "strictatime\0"
"loud\0"
"rbind\0"
// FIXME: use hasmntopt()
// Find this option in mount_options
for (i = 0; i < ARRAY_SIZE(mount_options); i++) {
- /* We support "option=" match for "comment=" thingy */
unsigned opt_len = strlen(option_str);
+
if (strncasecmp(option_str, options, opt_len) == 0
- && (options[opt_len] == '\0' || options[opt_len] == '=')
+ && (options[opt_len] == '\0'
+ /* or is it "comment=" thingy in fstab? */
+ IF_FEATURE_MOUNT_FSTAB(IF_DESKTOP( || option_str[opt_len-1] == '=' ))
+ )
) {
unsigned long fl = mount_options[i];
- if ((long)fl < 0)
+ if (fl & BB_MS_INVERTED_VALUE)
flags &= fl;
else
flags |= fl;
static bool_t xdr_fhstatus(XDR *xdrs, fhstatus *objp)
{
if (!xdr_u_int(xdrs, &objp->fhs_status))
- return FALSE;
+ return FALSE;
if (objp->fhs_status == 0)
return xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle);
return TRUE;
static bool_t xdr_fhandle3(XDR *xdrs, fhandle3 *objp)
{
return xdr_bytes(xdrs, (char **)&objp->fhandle3_val,
- (unsigned int *) &objp->fhandle3_len,
- FHSIZE3);
+ (unsigned int *) &objp->fhandle3_len,
+ FHSIZE3);
}
static bool_t xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp)
if (!xdr_fhandle3(xdrs, &objp->fhandle))
return FALSE;
return xdr_array(xdrs, &(objp->auth_flavours.auth_flavours_val),
- &(objp->auth_flavours.auth_flavours_len),
- ~0,
- sizeof(int),
- (xdrproc_t) xdr_int);
+ &(objp->auth_flavours.auth_flavours_len),
+ ~0,
+ sizeof(int),
+ (xdrproc_t) xdr_int);
}
static bool_t xdr_mountstat3(XDR *xdrs, mountstat3 *objp)
switch (pm_mnt.pm_prot) {
case IPPROTO_UDP:
mclient = clntudp_create(&mount_server_addr,
- pm_mnt.pm_prog,
- pm_mnt.pm_vers,
- retry_timeout,
- &msock);
+ pm_mnt.pm_prog,
+ pm_mnt.pm_vers,
+ retry_timeout,
+ &msock);
if (mclient)
break;
mount_server_addr.sin_port = htons(pm_mnt.pm_port);
msock = RPC_ANYSOCK;
case IPPROTO_TCP:
mclient = clnttcp_create(&mount_server_addr,
- pm_mnt.pm_prog,
- pm_mnt.pm_vers,
- &msock, 0, 0);
+ pm_mnt.pm_prog,
+ pm_mnt.pm_vers,
+ &msock, 0, 0);
break;
default:
mclient = NULL;
if (pm_mnt.pm_vers == 3)
clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT,
- (xdrproc_t) xdr_dirpath,
- (caddr_t) &pathname,
- (xdrproc_t) xdr_mountres3,
- (caddr_t) &status,
- total_timeout);
+ (xdrproc_t) xdr_dirpath,
+ (caddr_t) &pathname,
+ (xdrproc_t) xdr_mountres3,
+ (caddr_t) &status,
+ total_timeout);
else
clnt_stat = clnt_call(mclient, MOUNTPROC_MNT,
- (xdrproc_t) xdr_dirpath,
- (caddr_t) &pathname,
- (xdrproc_t) xdr_fhstatus,
- (caddr_t) &status,
- total_timeout);
+ (xdrproc_t) xdr_dirpath,
+ (caddr_t) &pathname,
+ (xdrproc_t) xdr_fhstatus,
+ (caddr_t) &status,
+ total_timeout);
if (clnt_stat == RPC_SUCCESS)
goto prepare_kernel_data; /* we're done */
) {
int len;
char c;
+ char *hostname, *share;
+ char *dotted, *ip;
len_and_sockaddr *lsa;
- char *hostname, *dotted, *ip;
+
+ // Parse mp->mnt_fsname of the form "//hostname/share[/dir1/dir2]"
hostname = mp->mnt_fsname + 2;
len = strcspn(hostname, "/\\");
- if (len == 0 || hostname[len] == '\0')
+ share = hostname + len + 1;
+ if (len == 0 // 3rd char is a [back]slash (IOW: empty hostname)
+ || share[-1] == '\0' // no [back]slash after hostname
+ || share[0] == '\0' // empty share name
+ ) {
goto report_error;
- c = hostname[len];
- hostname[len] = '\0';
+ }
+ c = share[-1];
+ share[-1] = '\0';
+ len = strcspn(share, "/\\");
+
+ // "unc=\\hostname\share" option is mandatory
+ // after CIFS option parsing was rewritten in Linux 3.4.
+ // Must use backslashes.
+ // If /dir1/dir2 is present, also add "prefixpath=dir1/dir2"
+ {
+ char *unc = xasprintf(
+ share[len] != '\0' /* "/dir1/dir2" exists? */
+ ? "unc=\\\\%s\\%.*s,prefixpath=%s"
+ : "unc=\\\\%s\\%.*s",
+ hostname,
+ len, share,
+ share + len + 1 /* "dir1/dir2" */
+ );
+ parse_mount_options(unc, &filteropts);
+ if (ENABLE_FEATURE_CLEAN_UP) free(unc);
+ }
+
lsa = host2sockaddr(hostname, 0);
- hostname[len] = c;
+ share[-1] = c;
if (!lsa)
goto report_error;
parse_mount_options(ip, &filteropts);
if (ENABLE_FEATURE_CLEAN_UP) free(ip);
- // "-o mand" is required [why?]
- vfsflags |= MS_MANDLOCK;
mp->mnt_type = (char*)"cifs";
rc = mount_it_now(mp, vfsflags, filteropts);