X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fmount%2Fstropts.c;h=57d8dad0d66d32b09490063510bfe111fceb8978;hp=95392a1f6eb67de47fe2a76c3825fb14d32d3412;hb=b4c9ca0c8b132f36743e324766b8532eb623e98e;hpb=798d0f1244ad4b77f1862c670ada16780c26a7af diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c index 95392a1..57d8dad 100644 --- a/utils/mount/stropts.c +++ b/utils/mount/stropts.c @@ -37,6 +37,7 @@ #include "nls.h" #include "nfs_mount.h" #include "mount_constants.h" +#include "stropts.h" #include "error.h" #include "network.h" @@ -51,6 +52,14 @@ #define NFS_PORT 2049 #endif +#ifndef NFS_MAXHOSTNAME +#define NFS_MAXHOSTNAME (255) +#endif + +#ifndef NFS_MAXPATHNAME +#define NFS_MAXPATHNAME (1024) +#endif + extern int nfs_mount_data_version; extern char *progname; extern int verbose; @@ -60,26 +69,55 @@ static int bg_opt = 0; static int addr_opt = 0; static int ca_opt = 0; -static int parse_devname(char *hostdir, char **hostname, char **dirname) +static int parse_devname(const char *spec, char **hostname) { - char *s; + int ret = 0; + char *dev, *pathname, *s; + + dev = xstrdup(spec); - if (!(s = strchr(hostdir, ':'))) { - nfs_error(_("%s: directory to mount not in host:dir format"), + if (!(pathname = strchr(dev, ':'))) { + nfs_error(_("%s: remote share not in 'host:dir' format"), progname); - return -1; + goto out; } - *hostname = hostdir; - *dirname = s + 1; - *s = '\0'; - /* Ignore all but first hostname in replicated mounts - until they can be fully supported. (mack@sgi.com) */ - if ((s = strchr(hostdir, ','))) { + *pathname = '\0'; + pathname++; + + /* + * We don't need a copy of the pathname, but let's + * sanity check it anyway. + */ + if (strlen(pathname) > NFS_MAXPATHNAME) { + nfs_error(_("%s: export pathname is too long"), + progname); + goto out; + } + + /* + * Ignore all but first hostname in replicated mounts + * until they can be fully supported. (mack@sgi.com) + */ + if ((s = strchr(dev, ','))) { *s = '\0'; nfs_error(_("%s: warning: multiple hostnames not supported"), progname); + nfs_error(_("%s: ignoring hostnames that follow the first one"), + progname); } - return 0; + *hostname = xstrdup(dev); + if (strlen(*hostname) > NFS_MAXHOSTNAME) { + nfs_error(_("%s: server hostname is too long"), + progname); + free(*hostname); + goto out; + } + + ret = 1; + +out: + free(dev); + return ret; } static int fill_ipv4_sockaddr(const char *hostname, struct sockaddr_in *addr) @@ -129,7 +167,7 @@ static int get_my_ipv4addr(char *ip_addr, int len) /* * Walk through our mount options string, and indicate the presence - * of 'bg', 'retry=', and 'clientaddr='. + * of 'bg', 'retry=', 'addr=', and 'clientaddr='. */ static void extract_interesting_options(char *opts) { @@ -160,40 +198,23 @@ static void extract_interesting_options(char *opts) } /* - * Append the "addr=" option to the options string. + * Append the 'addr=' option to the options string. The server + * address is added to /etc/mtab for use when unmounting. * - * We always add our own addr= to the end of the options string. + * Returns 1 if 'addr=' option created successfully; + * otherwise zero. */ -static int append_addr_opt(const char *spec, char **extra_opts) +static int append_addr_opt(struct sockaddr_in *saddr, char **extra_opts) { - static char hostdir[1024], new_opts[1024], ip_addr[255]; - char *hostname, *dirname, *s, *old_opts; - struct sockaddr_in addr; + static char new_opts[1024]; + char *s, *old_opts; - if (strlen(spec) >= sizeof(hostdir)) { - nfs_error(_("%s: excessively long host:dir argument\n"), - progname); - return 0; - } - strcpy(hostdir, spec); - if (parse_devname(hostdir, &hostname, &dirname)) { - nfs_error(_("%s: parsing host:dir argument failed\n"), - progname); - return 0; - } - - if (!fill_ipv4_sockaddr(hostname, &addr)) - return 0; - if (!get_my_ipv4addr(ip_addr, sizeof(ip_addr))) - return 0; - - /* add IP address to mtab options for use when unmounting */ - s = inet_ntoa(addr.sin_addr); + s = inet_ntoa(saddr->sin_addr); old_opts = *extra_opts; if (!old_opts) old_opts = ""; if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) { - nfs_error(_("%s: excessively long option argument\n"), + nfs_error(_("%s: too many mount options\n"), progname); return 0; } @@ -205,9 +226,9 @@ static int append_addr_opt(const char *spec, char **extra_opts) } /* - * Append the "clientaddr=" option to the options string. + * Append the 'clientaddr=' option to the options string. * - * Returns 1 if clientaddr option created successfully; + * Returns 1 if 'clientaddr=' option created successfully; * otherwise zero. */ static int append_clientaddr_opt(const char *spec, char **extra_opts) @@ -252,12 +273,26 @@ static int append_clientaddr_opt(const char *spec, char **extra_opts) int nfsmount_s(const char *spec, const char *node, int flags, char **extra_opts, int fake, int bg) { - int retval = EX_FAIL; + struct sockaddr_in saddr; + char *hostname; + int err; + + if (!parse_devname(spec, &hostname)) + return EX_FAIL; + err = fill_ipv4_sockaddr(hostname, &saddr); + free(hostname); + if (!err) + return EX_FAIL; extract_interesting_options(*extra_opts); - if (!addr_opt && !append_addr_opt(spec, extra_opts)) - goto fail; + if (!bg && addr_opt) { + nfs_error(_("%s: Illegal option: 'addr='"), progname); + return EX_FAIL; + } + + if (!append_addr_opt(&saddr, extra_opts)) + return EX_FAIL; if (verbose) printf(_("%s: text-based options: '%s'\n"), @@ -267,14 +302,11 @@ int nfsmount_s(const char *spec, const char *node, int flags, if (mount(spec, node, "nfs", flags & ~(MS_USER|MS_USERS), *extra_opts)) { mount_error(spec, node, errno); - goto fail; + return EX_FAIL; } } return 0; - -fail: - return retval; } /* @@ -286,23 +318,42 @@ fail: * @extra_opts: pointer to C string containing fs-specific mount options * (possibly also a return argument) * @fake: flag indicating whether to carry out the whole operation - * @bg: one if this is a backgrounded mount attempt + * @child: one if this is a backgrounded mount * * XXX: need to handle bg, fg, and retry options. * */ int nfs4mount_s(const char *spec, const char *node, int flags, - char **extra_opts, int fake) + char **extra_opts, int fake, int child) { - int retval = EX_FAIL; + struct sockaddr_in saddr; + char *hostname; + int err; + + if (!parse_devname(spec, &hostname)) + return EX_FAIL; + err = fill_ipv4_sockaddr(hostname, &saddr); + free(hostname); + if (!err) + return EX_FAIL; extract_interesting_options(*extra_opts); - if (!addr_opt && !append_addr_opt(spec, extra_opts)) - goto fail; + if (addr_opt) { + nfs_error(_("%s: Illegal option: 'addr='"), progname); + return EX_FAIL; + } - if (!ca_opt && !append_clientaddr_opt(spec, extra_opts)) - goto fail; + if (ca_opt) { + nfs_error(_("%s: Illegal option: 'clientaddr='"), progname); + return EX_FAIL; + } + + if (!append_addr_opt(&saddr, extra_opts)) + return EX_FAIL; + + if (!append_clientaddr_opt(spec, extra_opts)) + return EX_FAIL; if (verbose) printf(_("%s: text-based options: '%s'\n"), @@ -312,12 +363,9 @@ int nfs4mount_s(const char *spec, const char *node, int flags, if (mount(spec, node, "nfs4", flags & ~(MS_USER|MS_USERS), *extra_opts)) { mount_error(spec, node, errno); - goto fail; + return EX_FAIL; } } return 0; - -fail: - return retval; }