Copy dq_dqb into rquota structure more carefully
[nfs-utils.git] / utils / rquotad / rquota_server.c
index 08c4f8c..27a206c 100644 (file)
@@ -26,6 +26,7 @@
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <sys/quota.h>
+#include <sys/mount.h>
 #include <dirent.h>
 #include <paths.h>
 #include <stdio.h>
 #define TYPE_EXTENDED  0x01
 #define ACTIVE         0x02
 
-#ifdef ELM
-#define _PATH_DEV_DSK   "/dev/dsk/"
-#else
-#define _PATH_DEV_DSK   "/dev/"
+#ifndef MNTTYPE_AUTOFS
+#define MNTTYPE_AUTOFS "autofs"
+#endif
+
+#ifndef BLOCK_SIZE
+#define BLOCK_SIZE 1024
 #endif
 
 /*
  */
 extern struct authunix_parms *unix_cred;
 
-char *nfsmount_to_devname(char *pathname, int *blksize)
-{
-   DIR *dp;
-   dev_t device;
-   struct stat st;
-   struct dirent *de;
-   static char *devicename = NULL;
-   static int devicelen = 0;
-
-   if (stat(pathname, &st) == -1)
-      return (char *)0;
-
-   device = st.st_dev;
-   *blksize = st.st_blksize;
-
-   /*
-    * search for devicename in _PATH_DEV_DSK dir.
-    */
-   if ((dp = opendir(_PATH_DEV_DSK)) == (DIR *)0)
-      return (char *)0;
-
-   while ((de = readdir(dp)) != (struct dirent *)0) {
-      if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
-         continue;
-
-      if (devicelen == 0) {
-        devicelen = sizeof (_PATH_DEV_DSK) + strlen (de->d_name) + 1;
-        devicename = (char *) xmalloc (devicelen);
-      }
-      else {
-         int newlen = sizeof (_PATH_DEV_DSK) + strlen (de->d_name) + 1;
-         if (newlen > devicelen) {
-             devicelen = newlen;
-             devicename = (char *) xrealloc (devicename, devicelen);
-         }
-      }
-
-      strcpy(devicename, _PATH_DEV_DSK);
-      strcat(devicename, de->d_name);
-      if (stat(devicename, &st) == -1)
-         continue;
-
-      if (!S_ISBLK(st.st_mode))
-         continue;
-
-      if ((device == st.st_rdev) && S_ISBLK(st.st_mode))
-         break;
-   }
-   closedir(dp);
-
-   if (de != (struct dirent *)0) {
-      return devicename;
-   } else
-      return (char *)0;
-}
-
 int in_group (gid_t *gids, u_int len, gid_t gid)
 {
    int cnt = 0;
@@ -126,8 +73,10 @@ getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp)
    FILE *fp;
    struct dqblk dq_dqb;
    struct mntent *mnt;
-   char *pathname, *devicename, *qfpathname;
+   char *pathname, *qfpathname;
    int fd, err, id, type;
+   struct stat stm, stn;
+   struct rquota *rquota;
 
    /*
     * First check authentication.
@@ -160,23 +109,30 @@ getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp)
       }
    }
 
-   /*
-    * Convert a nfs_mountpoint to a local devicename.
-    */
-   if ((devicename = nfsmount_to_devname(pathname,
-        &result.getquota_rslt_u.gqr_rquota.rq_bsize)) == (char *)0) {
-      result.status = Q_NOQUOTA;   
-      return(&result);
-   }
-
    fp = setmntent(MNTTAB, "r");
    while ((mnt = getmntent(fp)) != (struct mntent *)0) {
-      if (strcmp(devicename, mnt->mnt_fsname))
-         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)
+         break;
+
+      /* 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), devicename, id,
-            (caddr_t)&dq_dqb)) == -1 && !(flags & ACTIVE)) {
+         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);
@@ -211,10 +167,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 = dq_dqb.dqb_bhardlimit;
+         rquota->rq_bsoftlimit = dq_dqb.dqb_bsoftlimit;;
+         rquota->rq_curblocks = dq_dqb.dqb_curblocks;
+         rquota->rq_fhardlimit = dq_dqb.dqb_ihardlimit;
+         rquota->rq_fsoftlimit = dq_dqb.dqb_isoftlimit;
+         rquota->rq_curfiles = dq_dqb.dqb_curinodes;
+         rquota->rq_btimeleft = dq_dqb.dqb_btime;
+         rquota->rq_ftimeleft = dq_dqb.dqb_itime;
 
          return(&result);
       }