* Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
* Copyright (C) 2005-2006 by Rob Landley <rob@landley.net>
*
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
*/
// Design notes: There is no spec for mount. Remind me to write one.
//
#include <sys/utsname.h>
#undef TRUE
#undef FALSE
-#include <rpc/rpc.h>
-#include <rpc/pmap_prot.h>
-#include <rpc/pmap_clnt.h>
+#if ENABLE_FEATURE_MOUNT_NFS
+/* 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"
+# endif
+# include <rpc/rpc.h>
+# include <rpc/pmap_prot.h>
+# include <rpc/pmap_clnt.h>
+#endif
#if defined(__dietlibc__)
#endif
llist_t *fslist;
char getmntent_buf[1];
-
-};
+} FIX_ALIASING;
enum { GETMNTENT_BUFSIZE = COMMON_BUFSIZE - offsetof(struct globals, getmntent_buf) };
#define G (*(struct globals*)&bb_common_bufsiz1)
#define nfs_mount_version (G.nfs_mount_version)
args[rc++] = filteropts;
}
args[rc] = NULL;
- rc = wait4pid(spawn(args));
+ rc = spawn_and_wait(args);
free(args[0]);
if (!rc)
break;
* Linux NFS mount
* Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
*
- * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ * Licensed under GPLv2, see file LICENSE in this source tree.
*
* Wed Feb 8 12:51:48 1995, biro@yggdrasil.com (Ross Biro): allow all port
* numbers to be specified on the command line.
* plus NFSv3 stuff.
*/
-/* 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."
-#endif
-
#define MOUNTPORT 635
#define MNTPATHLEN 1024
#define MNTNAMLEN 255
* "after #include <errno.h> the symbol errno is reserved for any use,
* it cannot even be used as a struct tag or field name".
*/
-
#ifndef EDQUOT
-#define EDQUOT ENOSPC
+# define EDQUOT ENOSPC
#endif
-
/* Convert each NFSERR_BLAH into EBLAH */
-static const struct {
- short stat;
- short errnum;
-} nfs_errtbl[] = {
- {0,0}, {1,EPERM}, {2,ENOENT}, {5,EIO}, {6,ENXIO}, {13,EACCES}, {17,EEXIST},
- {19,ENODEV}, {20,ENOTDIR}, {21,EISDIR}, {22,EINVAL}, {27,EFBIG},
- {28,ENOSPC}, {30,EROFS}, {63,ENAMETOOLONG}, {66,ENOTEMPTY}, {69,EDQUOT},
- {70,ESTALE}, {71,EREMOTE}, {-1,EIO}
+static const uint8_t nfs_err_stat[] = {
+ 1, 2, 5, 6, 13, 17,
+ 19, 20, 21, 22, 27, 28,
+ 30, 63, 66, 69, 70, 71
+};
+#if ( \
+ EPERM | ENOENT | EIO | ENXIO | EACCES| EEXIST | \
+ ENODEV| ENOTDIR | EISDIR | EINVAL| EFBIG | ENOSPC | \
+ EROFS | ENAMETOOLONG| ENOTEMPTY| EDQUOT| ESTALE| EREMOTE) < 256
+typedef uint8_t nfs_err_type;
+#else
+typedef uint16_t nfs_err_type;
+#endif
+static const nfs_err_type nfs_err_errnum[] = {
+ EPERM , ENOENT , EIO , ENXIO , EACCES, EEXIST,
+ ENODEV, ENOTDIR , EISDIR , EINVAL, EFBIG , ENOSPC,
+ EROFS , ENAMETOOLONG, ENOTEMPTY, EDQUOT, ESTALE, EREMOTE
};
static char *nfs_strerror(int status)
{
int i;
- for (i = 0; nfs_errtbl[i].stat != -1; i++) {
- if (nfs_errtbl[i].stat == status)
- return strerror(nfs_errtbl[i].errnum);
+ for (i = 0; i < ARRAY_SIZE(nfs_err_stat); i++) {
+ if (nfs_err_stat[i] == status)
+ return strerror(nfs_err_errnum[i]);
}
return xasprintf("unknown nfs status return value: %d", status);
}
static bool_t xdr_fhandle3(XDR *xdrs, fhandle3 *objp)
{
- if (!xdr_bytes(xdrs, (char **)&objp->fhandle3_val, (unsigned int *) &objp->fhandle3_len, FHSIZE3))
+ if (!xdr_bytes(xdrs, (char **)&objp->fhandle3_val,
+ (unsigned int *) &objp->fhandle3_len,
+ FHSIZE3)
+ ) {
return FALSE;
+ }
return TRUE;
}
{
if (!xdr_fhandle3(xdrs, &objp->fhandle))
return FALSE;
- if (!xdr_array(xdrs, &(objp->auth_flavours.auth_flavours_val), &(objp->auth_flavours.auth_flavours_len), ~0,
- sizeof(int), (xdrproc_t) xdr_int))
+ if (!xdr_array(xdrs, &(objp->auth_flavours.auth_flavours_val),
+ &(objp->auth_flavours.auth_flavours_len),
+ ~0,
+ sizeof(int),
+ (xdrproc_t) xdr_int)
+ ) {
return FALSE;
+ }
return TRUE;
}
kernel_version = get_linux_version_code();
if (kernel_version) {
- if (kernel_version < KERNEL_VERSION(2,1,32))
- nfs_mount_version = 1;
- else if (kernel_version < KERNEL_VERSION(2,2,18) ||
- (kernel_version >= KERNEL_VERSION(2,3,0) &&
- kernel_version < KERNEL_VERSION(2,3,99)))
+ if (kernel_version < KERNEL_VERSION(2,2,18))
nfs_mount_version = 3;
/* else v4 since 2.3.99pre4 */
}
goto next;
if (version && version <= 2 && pmap->pml_map.pm_vers > 2)
goto next;
- if (pmap->pml_map.pm_vers > MAX_NFSPROT ||
- (proto && pm_mnt->pm_prot && pmap->pml_map.pm_prot != proto) ||
- (port && pmap->pml_map.pm_port != port))
+ if (pmap->pml_map.pm_vers > MAX_NFSPROT
+ || (proto && pm_mnt->pm_prot && pmap->pml_map.pm_prot != proto)
+ || (port && pmap->pml_map.pm_port != port)
+ ) {
goto next;
+ }
memcpy(pm_mnt, &pmap->pml_map, sizeof(*pm_mnt));
next:
pmap = pmap->pml_next;
bb_herror_msg("%s", hostname);
goto fail;
}
- if ((size_t)hp->h_length > sizeof(struct in_addr)) {
- bb_error_msg("got bad hp->h_length");
- hp->h_length = sizeof(struct in_addr);
+ if (hp->h_length != (int)sizeof(struct in_addr)) {
+ bb_error_msg_and_die("only IPv4 is supported");
}
- memcpy(&server_addr.sin_addr,
- hp->h_addr, hp->h_length);
+ memcpy(&server_addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
}
memcpy(&mount_server_addr, &server_addr, sizeof(mount_server_addr));
continue;
}
- val = xatoi_u(opteq);
+ val = xatoi_positive(opteq);
switch (idx) {
case 0: // "rsize"
data.rsize = val;
bb_herror_msg("%s", mounthost);
goto fail;
}
- if ((size_t)hp->h_length > sizeof(struct in_addr)) {
- bb_error_msg("got bad hp->h_length");
- hp->h_length = sizeof(struct in_addr);
+ if (hp->h_length != (int)sizeof(struct in_addr)) {
+ bb_error_msg_and_die("only IPv4 is supported");
}
mount_server_addr.sin_family = AF_INET;
- memcpy(&mount_server_addr.sin_addr,
- hp->h_addr, hp->h_length);
+ memcpy(&mount_server_addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
}
}
llist_t *fl = NULL;
struct stat st;
+ errno = 0;
+
vfsflags = parse_mount_options(mp->mnt_opts, &filteropts);
// Treat fstype "auto" as unspecified
}
args[n++] = mp->mnt_dir;
args[n] = NULL;
- rc = wait4pid(xspawn(args));
+ rc = spawn_and_wait(args);
goto report_error;
}
&& (mp->mnt_fsname[0] == '/' || mp->mnt_fsname[0] == '\\')
&& mp->mnt_fsname[0] == mp->mnt_fsname[1]
) {
-#if 0 /* reported to break things */
+ int len;
+ char c;
len_and_sockaddr *lsa;
- char *ip, *dotted;
- char *s;
+ char *hostname, *dotted, *ip;
- // Replace '/' with '\' and verify that unc points to "//server/share".
- for (s = mp->mnt_fsname; *s; ++s)
- if (*s == '/') *s = '\\';
-
- // Get server IP
- s = strrchr(mp->mnt_fsname, '\\');
- if (s <= mp->mnt_fsname+1)
+ hostname = mp->mnt_fsname + 2;
+ len = strcspn(hostname, "/\\");
+ if (len == 0 || hostname[len] == '\0')
goto report_error;
- *s = '\0';
- lsa = host2sockaddr(mp->mnt_fsname+2, 0);
- *s = '\\';
+ c = hostname[len];
+ hostname[len] = '\0';
+ lsa = host2sockaddr(hostname, 0);
+ hostname[len] = c;
if (!lsa)
goto report_error;
- // Insert ip=... option into string flags.
+ // 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);
- // Compose new unc '\\server-ip\share'
- // (s => slash after hostname)
- mp->mnt_fsname = xasprintf("\\\\%s%s", dotted, s);
-#endif
- // Lock is required [why?]
+ // "-o mand" is required [why?]
vfsflags |= MS_MANDLOCK;
mp->mnt_type = (char*)"cifs";
rc = mount_it_now(mp, vfsflags, filteropts);
-#if 0
- if (ENABLE_FEATURE_CLEAN_UP) {
- free(mp->mnt_fsname);
- free(ip);
- free(dotted);
- free(lsa);
- }
-#endif
+
goto report_error;
}
// Might this be an NFS filesystem?
if (ENABLE_FEATURE_MOUNT_NFS
- && (!mp->mnt_type || !strcmp(mp->mnt_type, "nfs"))
+ && (!mp->mnt_type || strcmp(mp->mnt_type, "nfs") == 0)
&& strchr(mp->mnt_fsname, ':') != NULL
) {
rc = nfsmount(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) < 0) {
+ if (set_loop(&mp->mnt_fsname, loopFile, 0) < 0) {
if (errno == EPERM || errno == EACCES)
bb_error_msg(bb_msg_perm_denied_are_you_root);
else
// If we know the fstype (or don't need to), jump straight
// to the actual mount.
- if (mp->mnt_type || (vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE)))
+ if (mp->mnt_type || (vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE))) {
rc = mount_it_now(mp, vfsflags, filteropts);
- else {
+ } else {
// Loop through filesystem types until mount succeeds
// or we run out
- // Initialize list of block backed filesystems. This has to be
- // done here so that during "mount -a", mounts after /proc shows up
- // can autodetect.
+ // Initialize list of block backed filesystems.
+ // This has to be done here so that during "mount -a",
+ // mounts after /proc shows up can autodetect.
if (!fslist) {
fslist = get_block_backed_filesystems();
if (ENABLE_FEATURE_CLEAN_UP && fslist)
if (errno == EBUSY && ignore_busy)
return 0;
- if (rc < 0)
+ if (rc != 0)
bb_perror_msg("mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir);
return rc;
}
{
// Don't show rootfs. FIXME: why??
// util-linux 2.12a happily shows rootfs...
- //if (!strcmp(mtpair->mnt_fsname, "rootfs")) continue;
+ //if (strcmp(mtpair->mnt_fsname, "rootfs") == 0) continue;
- if (!fstype || !strcmp(mtpair->mnt_type, fstype))
+ if (!fstype || strcmp(mtpair->mnt_type, fstype) == 0)
printf("%s on %s type %s (%s)\n", mtpair->mnt_fsname,
mtpair->mnt_dir, mtpair->mnt_type,
mtpair->mnt_opts);
}
fstab = setmntent(fstabname, "r");
if (!fstab)
- bb_perror_msg_and_die("can't read %s", fstabname);
+ bb_perror_msg_and_die("can't read '%s'", fstabname);
// Loop through entries until we find what we're looking for
memset(mtpair, 0, sizeof(mtpair));