]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/rquotad/rquota_server.c
update manpages for showmount and mountd
[nfs-utils.git] / utils / rquotad / rquota_server.c
index e9167ca19692a3bbaf7f374614c74c53d894f654..f8bd8f18ab956f1fe47ff3b568f75ecc0c5aeda7 100644 (file)
  *          as published by the Free Software Foundation; either version
  *          2 of the License, or (at your option) any later version.
  */
-#include "config.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
 
 #include <rpc/rpc.h>
 #include "rquota.h"
 #include <sys/file.h>
 #include <sys/stat.h>
 #include <sys/param.h>
+/* Unfortunately we cannot trust sys/quota.h to have
+ * what we need, either the old interface could be missing
+ * (SLES9) or the new (SLES8 and others).
+ * So we will just put it explicitly below
+ */
+#if 0
 #include <sys/quota.h>
+#endif
+#include <sys/mount.h>
 #include <dirent.h>
 #include <paths.h>
 #include <stdio.h>
 #define MNTTYPE_AUTOFS "autofs"
 #endif
 
+#ifndef BLOCK_SIZE
+#define BLOCK_SIZE 1024
+#endif
+
+#define MAXQUOTAS 2
+#define USRQUOTA  0            /* element used for user quotas */
+#define GRPQUOTA  1            /* element used for group quotas */
+
+struct dqblk {
+       u_int32_t dqb_bhardlimit;   /* absolute limit on disk blks alloc */
+       u_int32_t dqb_bsoftlimit;   /* preferred limit on disk blks */
+       u_int32_t dqb_curblocks;    /* current block count */
+       u_int32_t dqb_ihardlimit;   /* maximum # allocated inodes */
+       u_int32_t dqb_isoftlimit;   /* preferred inode limit */
+       u_int32_t dqb_curinodes;    /* current # allocated inodes */
+       time_t dqb_btime;           /* time limit for excessive disk use */
+       time_t dqb_itime;           /* time limit for excessive files */
+};
+
+struct if_dqblk {
+        u_int64_t dqb_bhardlimit;
+        u_int64_t dqb_bsoftlimit;
+        u_int64_t dqb_curspace;
+        u_int64_t dqb_ihardlimit;
+        u_int64_t dqb_isoftlimit;
+        u_int64_t dqb_curinodes;
+        u_int64_t dqb_btime;
+        u_int64_t dqb_itime;
+        u_int32_t dqb_valid;
+};
+
+#define SUBCMDMASK  0x00ff
+#define SUBCMDSHIFT 8
+#define QCMD(cmd, type)  (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK))
+
+#define Q_GETQUOTA 0x0300      /* get limits and usage */
+#define Q_SETQUOTA 0x0400      /* set limits and usage */
+
+#define Q_GETFMT   0x800004     /* get quota format used on given filesystem */
+#define Q_GETQUOTA_NEW 0x800007 /* get user quota structure */
+#define Q_SETQUOTA_NEW 0x800008 /* set user quota structure */
+#define dqoff(UID)      ((loff_t)((UID) * sizeof (struct dqblk)))
+
+extern int quotactl (int __cmd, const char *__special, int __id,
+                    caddr_t __addr) __THROW;
 /*
  * Global unix authentication credentials.
  */
@@ -66,11 +122,12 @@ getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp)
       ext_getquota_args *ext_args;
    } arguments;
    FILE *fp;
-   struct dqblk dq_dqb;
    struct mntent *mnt;
    char *pathname, *qfpathname;
    int fd, err, id, type;
-   struct stat st;
+   struct stat stm, stn;
+   struct rquota *rquota;
+   struct if_dqblk dqb;
 
    /*
     * First check authentication.
@@ -105,51 +162,73 @@ getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp)
 
    fp = setmntent(MNTTAB, "r");
    while ((mnt = getmntent(fp)) != (struct mntent *)0) {
-      if (strcasecmp (mnt->mnt_dir, pathname))
-         continue;
+      if (stat(mnt->mnt_dir, &stm) == -1)
+         continue;
+
+      if (stat(pathname, &stn) == -1)
+         break;
+      else if (stm.st_dev != stn.st_dev)
+         continue;
 
       if (mnt->mnt_fsname [0] != '/'
          || strcasecmp (mnt->mnt_type, MNTTYPE_NFS) == 0
          || strcasecmp (mnt->mnt_type, MNTTYPE_AUTOFS) == 0
          || strcasecmp (mnt->mnt_type, MNTTYPE_SWAP) == 0
-         || strcasecmp (mnt->mnt_type, MNTTYPE_IGNORE) == 0
-         || stat(pathname, &st) == -1)
+         || strcasecmp (mnt->mnt_type, MNTTYPE_IGNORE) == 0)
          break;
 
-#if 0
-      result.getquota_rslt_u.gqr_rquota.rq_bsize = st.st_blksize;
-#else
-      /* All blocks reported are 512 Bytes blocks. */
-      result.getquota_rslt_u.gqr_rquota.rq_bsize = 512;
-#endif
+      /* All blocks reported are in BLOCK_SIZE. */
+      result.getquota_rslt_u.gqr_rquota.rq_bsize = BLOCK_SIZE;
 
       if (hasquota(mnt, type, &qfpathname)) {
-         if ((err = quotactl(QCMD(Q_GETQUOTA, type), mnt->mnt_fsname,
-                            id, (caddr_t)&dq_dqb)) == -1
-            && !(flags & ACTIVE)) {
-            if ((fd = open(qfpathname, O_RDONLY)) < 0)
-           {
-              free(qfpathname);
-               continue;
-           }
-            free(qfpathname);
-            lseek(fd, (long) dqoff(id), L_SET);
-            switch (read(fd, &dq_dqb, sizeof(struct dqblk))) {
-               case 0:/* EOF */
-                  /*
-                   * Convert implicit 0 quota (EOF) into an
-                   * explicit one (zero'ed dqblk)
-                   */
-                  memset((caddr_t)&dq_dqb, 0, sizeof(struct dqblk));
-                  break;
-               case sizeof(struct dqblk):   /* OK */
-                  break;
-               default:   /* ERROR */
-                  close(fd);
-                  continue;
-            }
-            close(fd);
-         }
+             int fmt;
+             if (quotactl(QCMD(Q_GETFMT, type), mnt->mnt_fsname, 0, (caddr_t)&fmt)==0) {
+                     /* new style interface
+                      * Don't bother trying to read from the file
+                      */
+                     err = quotactl(QCMD(Q_GETQUOTA_NEW, type),
+                                    mnt->mnt_fsname, id, (caddr_t)&dqb);
+                     if (err) memset(&dqb, 0, sizeof(dqb));
+             } else {
+                     /* old style */
+                     struct dqblk dq_dqb;
+
+                     if ((err = quotactl(QCMD(Q_GETQUOTA, type), mnt->mnt_fsname,
+                                         id, (caddr_t)&dq_dqb)) == -1
+                         && !(flags & ACTIVE)) {
+                             if ((fd = open(qfpathname, O_RDONLY)) < 0)
+                             {
+                                     free(qfpathname);
+                                     continue;
+                             }
+                             lseek(fd, (long) dqoff(id), L_SET);
+                             switch (read(fd, &dq_dqb, sizeof(struct dqblk))) {
+                             case 0:/* EOF */
+                                     /*
+                                      * Convert implicit 0 quota (EOF) into an
+                                      * explicit one (zero'ed dqblk)
+                                      */
+                                     memset((caddr_t)&dq_dqb, 0, sizeof(struct dqblk));
+                                     break;
+                             case sizeof(struct dqblk):   /* OK */
+                                     break;
+                             default:   /* ERROR */
+                                     close(fd);
+                                     free(qfpathname);
+                                     continue;
+                             }
+                             close(fd);
+                     }
+                     dqb.dqb_bhardlimit = dq_dqb.dqb_bhardlimit;
+                     dqb.dqb_bsoftlimit = dq_dqb.dqb_bsoftlimit;
+                     dqb.dqb_curspace = dq_dqb.dqb_curblocks * 1024;
+                     dqb.dqb_ihardlimit = dq_dqb.dqb_ihardlimit;
+                     dqb.dqb_isoftlimit = dq_dqb.dqb_isoftlimit;
+                     dqb.dqb_curinodes = dq_dqb.dqb_curinodes;
+                     dqb.dqb_btime = dq_dqb.dqb_btime;
+                     dqb.dqb_itime = dq_dqb.dqb_itime;
+             }
+             free(qfpathname);
          endmntent(fp);
 
          if (err && (flags & ACTIVE)) {
@@ -161,10 +240,18 @@ getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp)
          result.getquota_rslt_u.gqr_rquota.rq_active = (err == 0) ? TRUE : FALSE;
          /*
           * Make a copy of the info into the last part of the remote quota
-          * struct which is exactly the same.
+          * struct might not be exactly the same on all architectures...
           */
-         memcpy((caddr_t *)&result.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
-                (caddr_t *)&dq_dqb, sizeof(struct dqblk));
+
+         rquota = &result.getquota_rslt_u.gqr_rquota;
+         rquota->rq_bhardlimit = dqb.dqb_bhardlimit;
+         rquota->rq_bsoftlimit = dqb.dqb_bsoftlimit;;
+         rquota->rq_curblocks = dqb.dqb_curspace/1024;
+         rquota->rq_fhardlimit = dqb.dqb_ihardlimit;
+         rquota->rq_fsoftlimit = dqb.dqb_isoftlimit;
+         rquota->rq_curfiles = dqb.dqb_curinodes;
+         rquota->rq_btimeleft = dqb.dqb_btime;
+         rquota->rq_ftimeleft = dqb.dqb_itime;
 
          return(&result);
       }
@@ -175,22 +262,22 @@ getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp)
    return(&result);
 }
 
-getquota_rslt *rquotaproc_getquota_1(getquota_args *argp, struct svc_req *rqstp)
+getquota_rslt *rquotaproc_getquota_1_svc(getquota_args *argp, struct svc_req *rqstp)
 {
    return(getquotainfo(0, (caddr_t *)argp, rqstp));
 }
 
-getquota_rslt *rquotaproc_getactivequota_1(getquota_args *argp, struct svc_req *rqstp)
+getquota_rslt *rquotaproc_getactivequota_1_svc(getquota_args *argp, struct svc_req *rqstp)
 {
    return(getquotainfo(ACTIVE, (caddr_t *)argp, rqstp));
 }
 
-getquota_rslt *rquotaproc_getquota_2(ext_getquota_args *argp, struct svc_req *rqstp)
+getquota_rslt *rquotaproc_getquota_2_svc(ext_getquota_args *argp, struct svc_req *rqstp)
 {
    return(getquotainfo(TYPE_EXTENDED, (caddr_t *)argp, rqstp));
 }
 
-getquota_rslt *rquotaproc_getactivequota_2(ext_getquota_args *argp, struct svc_req *rqstp)
+getquota_rslt *rquotaproc_getactivequota_2_svc(ext_getquota_args *argp, struct svc_req *rqstp)
 {
    return(getquotainfo(TYPE_EXTENDED | ACTIVE, (caddr_t *)argp, rqstp));
 }