/*
- * $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.
#include <atalk/logger.h>
#include <atalk/afp.h>
#include <atalk/compat.h>
+#include <atalk/unix.h>
+#include <atalk/util.h>
#include "auth.h"
#include "volume.h"
#include "unix.h"
+#ifdef HAVE_LIBQUOTA
+#include <quota/quota.h>
+
+static int
+getfreespace(const AFPObj *obj, 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;
+ }
+
+ become_root();
+
+ if ((retq = getfsquota(obj, vol, ufsq, uid, classq)) < 0) {
+ LOG(log_info, logtype_afpd, "getfsquota(%s, %s): %s",
+ vol->v_path, classq, strerror(errno));
+ }
+
+ unbecome_root();
+
+ 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(const AFPObj *obj, struct vol *vol, VolSpace *bfree, VolSpace *btotal, const u_int32_t bsize)
+{
+ int uretq, gretq;
+ VolSpace ubfree, ubtotal;
+ VolSpace gbfree, gbtotal;
+
+ uretq = getfreespace(obj, vol, &ubfree, &ubtotal,
+ uuid, QUOTADICT_CLASS_USER);
+ LOG(log_info, logtype_afpd, "getfsquota(%s): %d %d",
+ vol->v_path, (int)ubfree, (int)ubtotal);
+ if (obj->ngroups >= 1) {
+ gretq = getfreespace(vol, &ubfree, &ubtotal,
+ obj->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
*/
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;
}
dev_t devno;
static struct mnttab mnt;
- if ( lstat( file, &sb ) < 0 ) {
+ if (stat(file, &sb) < 0) {
return( NULL );
}
devno = sb.st_dev;
while ( getmntent( mtab, &mnt ) == 0 ) {
/* local fs */
- if ( (lstat( mnt.mnt_special, &sb ) == 0) && (devno == sb.st_rdev)) {
+ if ( (stat( mnt.mnt_special, &sb ) == 0) && (devno == sb.st_rdev)) {
fclose( mtab );
return mnt.mnt_mountp;
}
/* check for nfs. we probably should use
* strcmp(mnt.mnt_fstype, MNTTYPE_NFS), but that's not as fast. */
- if ((lstat(mnt.mnt_mountp, &sb) == 0) && (devno == sb.st_dev) &&
+ if ((stat(mnt.mnt_mountp, &sb) == 0) && (devno == sb.st_dev) &&
strchr(mnt.mnt_special, ':')) {
*nfs = 1;
fclose( mtab );
struct mntent *mnt;
int found=0;
- if ( lstat( file, &sb ) < 0 ) {
+ if (stat(file, &sb) < 0 ) {
return( NULL );
}
devno = sb.st_dev;
while (( mnt = getmntent( mtab )) != NULL ) {
/* check for local fs */
- if ( (lstat( mnt->mnt_fsname, &sb ) == 0) && devno == sb.st_rdev) {
+ if ( (stat( mnt->mnt_fsname, &sb ) == 0) && devno == sb.st_rdev) {
found = 1;
break;
}
/* check for an nfs mount entry. the alternative is to use
* strcmp(mnt->mnt_type, MNTTYPE_NFS) instead of the strchr. */
- if ((lstat(mnt->mnt_dir, &sb) == 0) && (devno == sb.st_dev) &&
+ if ((stat(mnt->mnt_dir, &sb) == 0) && (devno == sb.st_dev) &&
strchr(mnt->mnt_fsname, ':')) {
*nfs = 1;
found = 1;
#endif /* __svr4__ */
-static int getfsquota(struct vol *vol, const int uid, struct dqblk *dq)
+static int getfsquota(const AFPObj *obj, struct vol *vol, const int uid, struct dqblk *dq)
{
struct dqblk dqg;
#endif /* TRU64 */
#ifdef BSD4_4
- if ( seteuid( getuid() ) == 0 ) {
+ become_root();
if ( quotactl( vol->v_path, QCMD(Q_GETQUOTA,USRQUOTA),
uid, (char *)dq ) != 0 ) {
/* try group quotas */
- if (ngroups >= 1) {
+ if (obj->ngroups >= 1) {
if ( quotactl(vol->v_path, QCMD(Q_GETQUOTA, GRPQUOTA),
- groups[0], (char *) &dqg) != 0 ) {
- seteuid( uid );
+ obj->groups[0], (char *) &dqg) != 0 ) {
+ unbecome_root();
return( AFPERR_PARAM );
}
}
}
- seteuid( uid );
- }
-
-#elif defined(TRU64)
- if ( seteuid( getuid() ) == 0 ) {
- if ( quotactl( vol->v_path, QCMD(Q_GETQUOTA, USRQUOTA),
- uid, (char *)dq ) != 0 ) {
- seteuid( uid );
- return ( AFPERR_PARAM );
- }
- seteuid( uid );
+ unbecome_root();
}
#else /* BSD4_4 */
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 */
{
}
-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;
return getnfsquota(vol, uuid, bsize, dq);
} else
/* local filesystem */
- return getfsquota(vol, uuid, dq);
+ return getfsquota(obj, vol, obj->uid, 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(obj, vol, obj->uid, dq);
#endif /* TRU64 */
}
#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 );
}
return( AFP_OK );
}
+#endif /* HAVE_LIBQUOTA */
#endif