]> arthur.barton.de Git - netatalk.git/blobdiff - etc/afpd/quota.c
Merge branch 'product-2-2' of git://github.com/franklahm/Netatalk into alex-master
[netatalk.git] / etc / afpd / quota.c
index 39ad23cfecad00f17da6647f6bd6fd0bdafc0db1..53938442b09242a1576010dfb891be5bc0b95680 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: quota.c,v 1.30 2008-05-16 04:19:41 didg Exp $
+ * $Id: quota.c,v 1.35 2010-04-03 07:11:35 franklahm Exp $
  *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * All Rights Reserved.  See COPYRIGHT.
@@ -41,11 +41,103 @@ char *strchr (), *strrchr ();
 
 #include <atalk/logger.h>
 #include <atalk/afp.h>
+#include <atalk/compat.h>
+#include <atalk/util.h>
 
 #include "auth.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
 */
@@ -190,11 +282,7 @@ static int get_linux_quota(int what, char *path, uid_t euser_id, struct dqblk *d
  Abstract out the XFS Quota Manager quota get call.
 ****************************************************************************/
 
-static int get_linux_xfs_quota(what, path, euser_id, dqb)
-int what;
-char *path;
-uid_t euser_id;
-struct dqblk *dqb;
+static int get_linux_xfs_quota(int what, char *path, uid_t euser_id, struct dqblk *dqb)
 {
        int ret = -1;
 #ifdef HAVE_LINUX_XQM_H
@@ -221,11 +309,7 @@ struct dqblk *dqb;
 ** For API v2 the results are copied back into a v1 structure.
 ** Taken from quota-1.4.8 perl module
 */
-static int get_linux_fs_quota( what, path, euser_id, dqb)
-int what;
-char *path;
-uid_t euser_id;
-struct dqblk *dqb;
+static int get_linux_fs_quota(int what, char *path, uid_t euser_id, struct dqblk *dqb)
 {
        int ret;
 
@@ -297,16 +381,14 @@ struct dqblk *dqb;
  * on which "file" resides.  Returns NULL on failure.
  */
 static char *
-mountp( file, nfs)
-char   *file;
-int         *nfs;
+mountp( char *file, int *nfs)
 {
     struct stat                        sb;
     FILE                       *mtab;
     dev_t                      devno;
     static struct mnttab       mnt;
 
-    if ( stat( file, &sb ) < 0 ) {
+    if (stat(file, &sb) < 0) {
         return( NULL );
     }
     devno = sb.st_dev;
@@ -344,9 +426,7 @@ int         *nfs;
 */
 
 static char *
-special( file, nfs )
-char *file;
-int  *nfs;
+special( char *file, int *nfs)
 {
     static struct fs_data      fsd;
 
@@ -365,9 +445,7 @@ int  *nfs;
 #if (defined(HAVE_SYS_MOUNT_H) && !defined(__linux__)) || defined(BSD4_4) || defined(_IBMR2)
 
 static char *
-special( file, nfs )
-char   *file;
-int         *nfs;
+special(char *file, int *nfs)
 {
     static struct statfs       sfs;
 
@@ -390,9 +468,7 @@ int         *nfs;
 #else /* BSD4_4 */
 
 static char *
-special( file, nfs )
-char *file;
-int *nfs;
+special(char *file, int *nfs)
 {
     struct stat                sb;
     FILE               *mtab;
@@ -400,7 +476,7 @@ int *nfs;
     struct mntent      *mnt;
     int                found=0;
 
-    if ( stat( file, &sb ) < 0 ) {
+    if (stat(file, &sb) < 0 ) {
         return( NULL );
     }
     devno = sb.st_dev;
@@ -443,10 +519,7 @@ int *nfs;
 #endif /* __svr4__ */
 
 
-static int getfsquota(vol, uid, dq)
-struct vol             *vol;
-const int              uid;
-struct dqblk           *dq;
+static int getfsquota(struct vol *vol, const int uid, struct dqblk *dq)
 
 {
        struct dqblk dqg;
@@ -560,10 +633,7 @@ struct dqblk               *dq;
 }
 
 
-static int getquota( vol, dq, bsize)
-struct vol             *vol;
-struct dqblk           *dq;
-const u_int32_t                bsize;
+static int getquota( struct vol *vol, struct dqblk *dq, const u_int32_t bsize)
 {
     char *p;
 
@@ -646,8 +716,7 @@ const u_int32_t             bsize;
 #endif /* TRU64 */
 }
 
-static int overquota( dqblk )
-struct dqblk     *dqblk;
+static int overquota( struct dqblk *dqblk)
 {
     struct timeval     tv;
 
@@ -665,7 +734,7 @@ struct dqblk          *dqblk;
         return( 0 );
     }
 #else /* ultrix */
-    if ( gettimeofday( &tv, 0 ) < 0 ) {
+    if ( gettimeofday( &tv, NULL ) < 0 ) {
         LOG(log_error, logtype_afpd, "overquota: gettimeofday: %s", strerror(errno) );
         return( AFPERR_PARAM );
     }
@@ -702,10 +771,7 @@ struct dqblk         *dqblk;
 #define tobytes(a, b)  dbtob((VolSpace) (a))
 #endif
 
-int uquota_getvolspace( vol, bfree, btotal, bsize)
-struct vol     *vol;
-VolSpace       *bfree, *btotal;
-const u_int32_t bsize;
+int uquota_getvolspace( struct vol *vol, VolSpace *bfree, VolSpace *btotal, const u_int32_t bsize)
 {
        u_int64_t this_bsize;
        struct dqblk dqblk;
@@ -721,19 +787,19 @@ const u_int32_t bsize;
 #endif
 
 #ifdef DEBUG_QUOTA
-        LOG(log_info, logtype_afpd, "after calling getquota in uquota_getvolspace!" );
-        LOG(log_info, logtype_afpd, "dqb_ihardlimit: %u", dqblk.dqb_ihardlimit );
-        LOG(log_info, logtype_afpd, "dqb_isoftlimit: %u", dqblk.dqb_isoftlimit );
-        LOG(log_info, logtype_afpd, "dqb_curinodes : %u", dqblk.dqb_curinodes );
-        LOG(log_info, logtype_afpd, "dqb_bhardlimit: %u", dqblk.dqb_bhardlimit );
-        LOG(log_info, logtype_afpd, "dqb_bsoftlimit: %u", dqblk.dqb_bsoftlimit );
-        LOG(log_info, logtype_afpd, "dqb_curblocks : %u", dqblk.dqb_curblocks );
-        LOG(log_info, logtype_afpd, "dqb_btime     : %u", dqblk.dqb_btime );
-        LOG(log_info, logtype_afpd, "dqb_itime     : %u", dqblk.dqb_itime );
-        LOG(log_info, logtype_afpd, "bsize/this_bsize : %u/%u", bsize, this_bsize );
-       LOG(log_info, logtype_afpd, "dqblk.dqb_bhardlimit size: %u", tobytes( dqblk.dqb_bhardlimit, this_bsize ));
-       LOG(log_info, logtype_afpd, "dqblk.dqb_bsoftlimit size: %u", tobytes( dqblk.dqb_bsoftlimit, this_bsize ));
-       LOG(log_info, logtype_afpd, "dqblk.dqb_curblocks  size: %u", tobytes( dqblk.dqb_curblocks, this_bsize ));
+        LOG(log_debug, logtype_afpd, "after calling getquota in uquota_getvolspace!" );
+        LOG(log_debug, logtype_afpd, "dqb_ihardlimit: %u", dqblk.dqb_ihardlimit );
+        LOG(log_debug, logtype_afpd, "dqb_isoftlimit: %u", dqblk.dqb_isoftlimit );
+        LOG(log_debug, logtype_afpd, "dqb_curinodes : %u", dqblk.dqb_curinodes );
+        LOG(log_debug, logtype_afpd, "dqb_bhardlimit: %u", dqblk.dqb_bhardlimit );
+        LOG(log_debug, logtype_afpd, "dqb_bsoftlimit: %u", dqblk.dqb_bsoftlimit );
+        LOG(log_debug, logtype_afpd, "dqb_curblocks : %u", dqblk.dqb_curblocks );
+        LOG(log_debug, logtype_afpd, "dqb_btime     : %u", dqblk.dqb_btime );
+        LOG(log_debug, logtype_afpd, "dqb_itime     : %u", dqblk.dqb_itime );
+        LOG(log_debug, logtype_afpd, "bsize/this_bsize : %u/%u", bsize, this_bsize );
+       LOG(log_debug, logtype_afpd, "dqblk.dqb_bhardlimit size: %u", tobytes( dqblk.dqb_bhardlimit, this_bsize ));
+       LOG(log_debug, logtype_afpd, "dqblk.dqb_bsoftlimit size: %u", tobytes( dqblk.dqb_bsoftlimit, this_bsize ));
+       LOG(log_debug, logtype_afpd, "dqblk.dqb_curblocks  size: %u", tobytes( dqblk.dqb_curblocks, this_bsize ));
 #endif /* DEBUG_QUOTA */ 
 
        /* no limit set for this user. it might be set in the future. */
@@ -756,12 +822,13 @@ const u_int32_t bsize;
        }
 
 #ifdef DEBUG_QUOTA
-        LOG(log_info, logtype_afpd, "bfree          : %u", *bfree );
-        LOG(log_info, logtype_afpd, "btotal         : %u", *btotal );
-        LOG(log_info, logtype_afpd, "bfree          : %uKB", *bfree/1024 );
-        LOG(log_info, logtype_afpd, "btotal         : %uKB", *btotal/1024 );
+        LOG(log_debug, logtype_afpd, "bfree          : %u", *bfree );
+        LOG(log_debug, logtype_afpd, "btotal         : %u", *btotal );
+        LOG(log_debug, logtype_afpd, "bfree          : %uKB", *bfree/1024 );
+        LOG(log_debug, logtype_afpd, "btotal         : %uKB", *btotal/1024 );
 #endif
 
        return( AFP_OK );
 }
+#endif /* HAVE_LIBQUOTA */
 #endif