]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mount/network.c
Make sure nfs_call_umount's callers are handling its return code correctly
[nfs-utils.git] / utils / mount / network.c
index c11fa3ea2dd72eb33b3e9c3c02d2fa507314dcc5..12fc7620877b11eb6d8e84e042302a445b42f465 100644 (file)
@@ -106,12 +106,13 @@ int nfs_gethostbyname(const char *hostname, struct sockaddr_in *saddr)
        saddr->sin_family = AF_INET;
        if (!inet_aton(hostname, &saddr->sin_addr)) {
                if ((hp = gethostbyname(hostname)) == NULL) {
-                       nfs_error(_("mount: can't get address for %s\n"),
-                               hostname);
+                       nfs_error(_("%s: can't get address for %s\n"),
+                                       progname, hostname);
                        return 0;
                } else {
                        if (hp->h_length > sizeof(*saddr)) {
-                               nfs_error(_("mount: got bad hp->h_length\n"));
+                               nfs_error(_("%s: got bad hp->h_length\n"),
+                                               progname);
                                hp->h_length = sizeof(*saddr);
                        }
                        memcpy(&saddr->sin_addr, hp->h_addr, hp->h_length);
@@ -244,7 +245,7 @@ out_ok:
        return 1;
 }
 
-int probe_nfsport(clnt_addr_t *nfs_server)
+static int probe_nfsport(clnt_addr_t *nfs_server)
 {
        struct pmap *pmap = &nfs_server->pmap;
 
@@ -257,7 +258,7 @@ int probe_nfsport(clnt_addr_t *nfs_server)
                return probe_port(nfs_server, probe_nfs2_only, probe_udp_only);
 }
 
-int probe_mntport(clnt_addr_t *mnt_server)
+static int probe_mntport(clnt_addr_t *mnt_server)
 {
        struct pmap *pmap = &mnt_server->pmap;
 
@@ -316,3 +317,92 @@ version_fixed:
                goto out_bad;
        return probe_mntport(mnt_server);
 }
+
+static int probe_statd(void)
+{
+       struct sockaddr_in addr;
+       unsigned short port;
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+       port = getport(&addr, 100024, 1, IPPROTO_UDP);
+
+       if (port == 0)
+               return 0;
+       addr.sin_port = htons(port);
+
+       if (clnt_ping(&addr, 100024, 1, IPPROTO_UDP, NULL) <= 0)
+               return 0;
+
+       return 1;
+}
+
+/*
+ * Attempt to start rpc.statd
+ */
+int start_statd(void)
+{
+#ifdef START_STATD
+       struct stat stb;
+#endif
+
+       if (probe_statd())
+               return 1;
+
+#ifdef START_STATD
+       if (stat(START_STATD, &stb) == 0) {
+               if (S_ISREG(stb.st_mode) && (stb.st_mode & S_IXUSR)) {
+                       system(START_STATD);
+                       if (probe_statd())
+                               return 1;
+               }
+       }
+#endif
+
+       return 0;
+}
+
+/*
+ * nfs_call_umount - ask the server to remove a share from it's rmtab
+ * @mnt_server: address of RPC MNT program server
+ * @argp: directory path of share to "unmount"
+ *
+ * Returns one if the unmount call succeeded; zero if the unmount
+ * failed for any reason.
+ *
+ * Note that a side effect of calling this function is that rpccreateerr
+ * is set.
+ */
+int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
+{
+       CLIENT *clnt;
+       enum clnt_stat res = 0;
+       int msock;
+
+       switch (mnt_server->pmap.pm_vers) {
+       case 3:
+       case 2:
+       case 1:
+               if (!probe_mntport(mnt_server))
+                       return 0;
+               clnt = mnt_openclnt(mnt_server, &msock);
+               if (!clnt)
+                       return 0;
+               res = clnt_call(clnt, MOUNTPROC_UMNT,
+                               (xdrproc_t)xdr_dirpath, (caddr_t)argp,
+                               (xdrproc_t)xdr_void, NULL,
+                               TIMEOUT);
+               mnt_closeclnt(clnt, msock);
+               if (res == RPC_SUCCESS)
+                       return 1;
+               break;
+       default:
+               res = RPC_SUCCESS;
+               break;
+       }
+
+       if (res == RPC_SUCCESS)
+               return 1;
+       return 0;
+}