]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mountd/mountd.c
Open channel files O_WRONLY, and improve mountlist support.
[nfs-utils.git] / utils / mountd / mountd.c
index 145a4daa555691ec4748287205eb2bb1a98b6175..6dbd224fc27af0e0422e0972d8ecf3599c415e0c 100644 (file)
@@ -25,7 +25,7 @@
 #include "rpcmisc.h"
 
 extern void    cache_open(void);
-extern struct nfs_fh_len *cache_get_filehandle(nfs_export *exp, int len);
+extern struct nfs_fh_len *cache_get_filehandle(nfs_export *exp, int len, char *p);
 extern void cache_export(nfs_export *exp);
 
 extern void my_svc_run(void);
@@ -117,8 +117,14 @@ mount_umnt_1_svc(struct svc_req *rqstp, dirpath *argp, void *resp)
        if (!(exp = auth_authenticate("unmount", sin, p))) {
                return 1;
        }
-       mountlist_del(exp, p);
-       export_reset (exp);
+       if (new_cache) {
+               if (strcmp(inet_ntoa(exp->m_client->m_addrlist[0]), exp->m_client->m_hostname))
+                       mountlist_del(inet_ntoa(exp->m_client->m_addrlist[0]), exp->m_client->m_hostname);
+               mountlist_del(exp->m_client->m_hostname, p);
+       } else {
+               mountlist_del(exp->m_client->m_hostname, p);
+               export_reset (exp);
+       }
        return 1;
 }
 
@@ -242,7 +248,7 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, int *error, int v3)
 {
        struct sockaddr_in *sin =
                (struct sockaddr_in *) svc_getcaller(rqstp->rq_xprt);
-       struct stat     stb;
+       struct stat     stb, estb;
        nfs_export      *exp;
        char            rpath[MAXPATHLEN+1];
        char            *p = *path;
@@ -272,6 +278,23 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, int *error, int v3)
        } else if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) {
                xlog(L_WARNING, "%s is not a directory or regular file", p);
                *error = NFSERR_NOTDIR;
+       } else if (stat(exp->m_export.e_path, &estb) < 0) {
+               xlog(L_WARNING, "can't stat export point %s: %s",
+                    p, strerror(errno));
+               *error = NFSERR_NOENT;
+       } else if (estb.st_dev != stb.st_dev
+                  /* && (!new_cache || !(exp->m_export.e_flags & NFSEXP_CROSSMNT)) */
+               ) {
+               xlog(L_WARNING, "request to export directory %s below nearest filesystem %s",
+                    p, exp->m_export.e_path);
+               *error = NFSERR_ACCES;
+       } else if (exp->m_export.e_mountpoint &&
+                  !is_mountpoint(exp->m_export.e_mountpoint[0]?
+                                 exp->m_export.e_mountpoint:
+                                 exp->m_export.e_path)) {
+               xlog(L_WARNING, "request to export an unmounted filesystem: %s",
+                    p);
+               *error = NFSERR_NOENT;
        } else if (new_cache) {
                /* This will be a static private nfs_export with just one
                 * address.  We feed it to kernel then extract the filehandle,
@@ -280,7 +303,7 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, int *error, int v3)
                struct nfs_fh_len  *fh;
 
                cache_export(exp);
-               fh = cache_get_filehandle(exp, v3?64:32);
+               fh = cache_get_filehandle(exp, v3?64:32, p);
                if (fh == NULL) 
                        *error = NFSERR_ACCES;
                else
@@ -305,7 +328,7 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, int *error, int v3)
                                                stb.st_dev, stb.st_ino);
                }
                if (fh != NULL) {
-                       mountlist_add(exp, p);
+                       mountlist_add(exp->m_client->m_hostname, p);
                        *error = NFS_OK;
                        export_reset (exp);
                        return fh;
@@ -414,14 +437,14 @@ main(int argc, char **argv)
        char    *export_file = _PATH_EXPORTS;
        int     foreground = 0;
        int     port = 0;
-       int     descriptors = 256;
+       int     descriptors = 0;
        int     c;
        struct sigaction sa;
        struct rlimit rlim;
 
        /* Parse the command line options and arguments. */
        opterr = 0;
-       while ((c = getopt_long(argc, argv, "on:Fd:f:p:P:hN:V:v", longopts, NULL)) != EOF)
+       while ((c = getopt_long(argc, argv, "o:n:Fd:f:p:P:hN:V:v", longopts, NULL)) != EOF)
                switch (c) {
                case 'o':
                        descriptors = atoi(optarg);
@@ -481,19 +504,20 @@ main(int argc, char **argv)
                exit(1);
        }
 
-       if (getrlimit (RLIMIT_NOFILE, &rlim) != 0) {
-               fprintf(stderr, "%s: getrlimit (RLIMIT_NOFILE) failed: %s\n",
-                       argv [0], strerror(errno));
-               exit(1);
-       }
+       if (descriptors) {
+               if (getrlimit (RLIMIT_NOFILE, &rlim) != 0) {
+                       fprintf(stderr, "%s: getrlimit (RLIMIT_NOFILE) failed: %s\n",
+                               argv [0], strerror(errno));
+                       exit(1);
+               }
 
-       rlim.rlim_cur = descriptors;
-       if (setrlimit (RLIMIT_NOFILE, &rlim) != 0) {
-               fprintf(stderr, "%s: setrlimit (RLIMIT_NOFILE) failed: %s\n",
-                       argv [0], strerror(errno));
-               exit(1);
+               rlim.rlim_cur = descriptors;
+               if (setrlimit (RLIMIT_NOFILE, &rlim) != 0) {
+                       fprintf(stderr, "%s: setrlimit (RLIMIT_NOFILE) failed: %s\n",
+                               argv [0], strerror(errno));
+                       exit(1);
+               }
        }
-
        /* Initialize logging. */
 /*     xlog_open("mountd"); */
 
@@ -503,6 +527,7 @@ main(int argc, char **argv)
        sigaction(SIGHUP, &sa, NULL);
        sigaction(SIGINT, &sa, NULL);
        sigaction(SIGTERM, &sa, NULL);
+       sigaction(SIGPIPE, &sa, NULL);
        /* WARNING: the following works on Linux and SysV, but not BSD! */
        sigaction(SIGCHLD, &sa, NULL);