]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/quota.c
Merge remote branch 'netafp/master' into branch-allea
[netatalk.git] / etc / afpd / quota.c
index 06008c20f6140a627ad1aab9ff308d7aceaea0ca..5887c6d60da1f853bb1eb0c2cda1e5f01d267992 100644 (file)
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/param.h>
-#ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#ifdef HAVE_FCNTL_H
 #include <fcntl.h>
-#endif /* HAVE_FCNTL_H */
 
 #include <atalk/logger.h>
 #include <atalk/afp.h>
 #include "volume.h"
 #include "unix.h"
 
+#ifdef HAVE_LIBQUOTA
+#include <quota/quota.h>
+
+static int
+getfreespace(struct vol *vol, VolSpace *bfree, VolSpace *btotal,
+    uid_t uid, const char *classq)
+{
+       int retq;
+       struct ufs_quota_entry ufsq[QUOTA_NLIMITS];
+       time_t now;
+
+       if (time(&now) == -1) {
+               LOG(log_info, logtype_afpd, "time(): %s",
+                   strerror(errno));
+               return -1;
+       }
+
+       if ( seteuid( getuid() ) != 0 )  {
+               LOG(log_info, logtype_afpd, "seteuid(): %s",
+                   strerror(errno));
+               return -1;
+       }
+       if ((retq = getfsquota(vol->v_path, ufsq, uid, classq)) < 0) {
+               LOG(log_info, logtype_afpd, "getfsquota(%s, %s): %s",
+                   vol->v_path, classq, strerror(errno));
+       }
+        seteuid( uid );
+       if (retq < 1)
+               return retq;
+
+       switch(QL_STATUS(quota_check_limit(ufsq[QUOTA_LIMIT_BLOCK].ufsqe_cur, 1,
+           ufsq[QUOTA_LIMIT_BLOCK].ufsqe_softlimit,
+           ufsq[QUOTA_LIMIT_BLOCK].ufsqe_hardlimit,
+           ufsq[QUOTA_LIMIT_BLOCK].ufsqe_time, now))) {
+       case QL_S_DENY_HARD:
+       case QL_S_DENY_GRACE:
+               *bfree = 0;
+               *btotal = dbtob(ufsq[QUOTA_LIMIT_BLOCK].ufsqe_cur);
+               break;
+       default:
+               *bfree = dbtob(ufsq[QUOTA_LIMIT_BLOCK].ufsqe_hardlimit -
+                   ufsq[QUOTA_LIMIT_BLOCK].ufsqe_cur);
+               *btotal = dbtob(ufsq[QUOTA_LIMIT_BLOCK].ufsqe_hardlimit);
+               break;
+       }
+       return 1;
+}
+
+int uquota_getvolspace( struct vol *vol, VolSpace *bfree, VolSpace *btotal, const u_int32_t bsize)
+{
+       int uretq, gretq;
+       VolSpace ubfree, ubtotal;
+       VolSpace gbfree, gbtotal;
+
+       uretq = getfreespace(vol, &ubfree, &ubtotal,
+           uuid, QUOTADICT_CLASS_USER);
+       LOG(log_info, logtype_afpd, "getfsquota(%s): %d %d",
+           vol->v_path, (int)ubfree, (int)ubtotal);
+       if (ngroups >= 1) {
+               gretq = getfreespace(vol, &ubfree, &ubtotal,
+                   groups[0], QUOTADICT_CLASS_GROUP);
+       } else
+               gretq = -1;
+       if (uretq < 1 && gretq < 1) { /* no quota for this fs */
+               return AFPERR_PARAM;
+       }
+       if (uretq < 1) {
+               /* use group quotas */
+               *bfree = gbfree;
+               *btotal = gbtotal;
+       } else if (gretq < 1) {
+               /* use user quotas */
+               *bfree = ubfree;
+               *btotal = ubtotal;
+       } else {
+               /* return smallest remaining space of user and group */
+               if (ubfree < gbfree) {
+                       *bfree = ubfree;
+                       *btotal = ubtotal;
+               } else {
+                       *bfree = gbfree;
+                       *btotal = gbtotal;
+               }
+       }
+       return AFP_OK;
+
+}
+
+#else /* HAVE_LIBQUOTA */
+
 /*
 #define DEBUG_QUOTA 0
 */
@@ -189,13 +275,13 @@ static int get_linux_xfs_quota(int what, char *path, uid_t euser_id, struct dqbl
        if ((ret = quotactl(QCMD(Q_XGETQUOTA,(what ? GRPQUOTA : USRQUOTA)), path, euser_id, (caddr_t)&D)))
                return ret;
 
-       dqb->bsize = (u_int64_t)512;
-        dqb->dqb_bsoftlimit  = (u_int64_t)D.d_blk_softlimit;
-        dqb->dqb_bhardlimit  = (u_int64_t)D.d_blk_hardlimit;
-        dqb->dqb_ihardlimit  = (u_int64_t)D.d_ino_hardlimit;
-        dqb->dqb_isoftlimit  = (u_int64_t)D.d_ino_softlimit;
-        dqb->dqb_curinodes   = (u_int64_t)D.d_icount;
-        dqb->dqb_curblocks   = (u_int64_t)D.d_bcount; 
+       dqb->bsize = (uint64_t)512;
+        dqb->dqb_bsoftlimit  = (uint64_t)D.d_blk_softlimit;
+        dqb->dqb_bhardlimit  = (uint64_t)D.d_blk_hardlimit;
+        dqb->dqb_ihardlimit  = (uint64_t)D.d_ino_hardlimit;
+        dqb->dqb_isoftlimit  = (uint64_t)D.d_ino_softlimit;
+        dqb->dqb_curinodes   = (uint64_t)D.d_icount;
+        dqb->dqb_curblocks   = (uint64_t)D.d_bcount; 
 #endif
        return ret;
 }
@@ -504,12 +590,12 @@ static int getfsquota(struct vol *vol, const int uid, struct dqblk *dq)
     if( 
         /* if overquota, free space is 0 otherwise hard-current */
         ( overquota( dq ) ? 0 : ( dq->dqb_bhardlimit ? dq->dqb_bhardlimit - 
-                                  dq->dqb_curblocks : ~((u_int64_t) 0) ) )
+                                  dq->dqb_curblocks : ~((uint64_t) 0) ) )
 
       >
         
         ( overquota( &dqg ) ? 0 : ( dqg.dqb_bhardlimit ? dqg.dqb_bhardlimit - 
-                                    dqg.dqb_curblocks : ~((u_int64_t) 0) ) )
+                                    dqg.dqb_curblocks : ~((uint64_t) 0) ) )
 
       ) /* if */
     {
@@ -529,7 +615,7 @@ static int getfsquota(struct vol *vol, const int uid, struct dqblk *dq)
 }
 
 
-static int getquota( struct vol *vol, struct dqblk *dq, const u_int32_t bsize)
+static int getquota(const AFPObj *obj, struct vol *vol, struct dqblk *dq, const uint32_t bsize)
 {
     char *p;
 
@@ -607,8 +693,8 @@ static int getquota( struct vol *vol, struct dqblk *dq, const u_int32_t bsize)
        return getfsquota(vol, uuid, dq);
           
 #else /* TRU64 */
-    return vol->v_nfs ? getnfsquota(vol, uuid, bsize, dq) :
-           getfsquota(vol, uuid, dq);
+    return vol->v_nfs ? getnfsquota(vol, obj->uid, bsize, dq) :
+           getfsquota(vol, obj->uid, dq);
 #endif /* TRU64 */
 }
 
@@ -667,14 +753,14 @@ static int overquota( struct dqblk *dqblk)
 #define tobytes(a, b)  dbtob((VolSpace) (a))
 #endif
 
-int uquota_getvolspace( struct vol *vol, VolSpace *bfree, VolSpace *btotal, const u_int32_t bsize)
+int uquota_getvolspace(const AFPObj *obj, struct vol *vol, VolSpace *bfree, VolSpace *btotal, const uint32_t bsize)
 {
-       u_int64_t this_bsize;
+       uint64_t this_bsize;
        struct dqblk dqblk;
 
        this_bsize = bsize;
                        
-       if (getquota( vol, &dqblk, bsize) != 0 ) {
+       if (getquota(obj, vol, &dqblk, bsize) != 0 ) {
                return( AFPERR_PARAM );
        }
 
@@ -726,4 +812,5 @@ int uquota_getvolspace( struct vol *vol, VolSpace *bfree, VolSpace *btotal, cons
 
        return( AFP_OK );
 }
+#endif /* HAVE_LIBQUOTA */
 #endif