X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Fquota.c;h=bab14e1345baf9a9f8b9447518ab1233b7f7650b;hp=1a04ada07511050f9ad1bfe847ba0f7ab4ec0f17;hb=450114e8c52574c5444d856e8a0208f2bbaab80c;hpb=f357762920325c7d84ec891e468655fea5b4473e diff --git a/etc/afpd/quota.c b/etc/afpd/quota.c index 1a04ada0..bab14e13 100644 --- a/etc/afpd/quota.c +++ b/etc/afpd/quota.c @@ -1,5 +1,4 @@ /* - * $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. @@ -25,11 +24,102 @@ #include #include #include +#include +#include #include "auth.h" #include "volume.h" #include "unix.h" +#ifdef HAVE_LIBQUOTA +#include + +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 */ @@ -185,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; } @@ -280,7 +370,7 @@ mountp( char *file, int *nfs) dev_t devno; static struct mnttab mnt; - if ( lstat( file, &sb ) < 0 ) { + if (stat(file, &sb) < 0) { return( NULL ); } devno = sb.st_dev; @@ -291,14 +381,14 @@ mountp( char *file, int *nfs) 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 ); @@ -368,7 +458,7 @@ special(char *file, int *nfs) struct mntent *mnt; int found=0; - if ( lstat( file, &sb ) < 0 ) { + if (stat(file, &sb) < 0 ) { return( NULL ); } devno = sb.st_dev; @@ -379,14 +469,14 @@ special(char *file, int *nfs) 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; @@ -411,7 +501,7 @@ special(char *file, int *nfs) #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; @@ -420,6 +510,7 @@ static int getfsquota(struct vol *vol, const int uid, struct dqblk *dq) struct quotctl qc; #endif + memset(dq, 0, sizeof(struct dqblk)); memset(&dqg, 0, sizeof(dqg)); #ifdef __svr4__ @@ -451,34 +542,26 @@ static int getfsquota(struct vol *vol, const int uid, struct dqblk *dq) #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 (get_linux_quota (WANT_USER_QUOTA, vol->v_gvs, uid, dq) !=0) { - return( AFPERR_PARAM ); +#ifdef DEBUG_QUOTA + LOG(log_debug, logtype_afpd, "user quota did not work!" ); +#endif /* DEBUG_QUOTA */ } if (get_linux_quota(WANT_GROUP_QUOTA, vol->v_gvs, getegid(), &dqg) != 0) { @@ -500,20 +583,25 @@ 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 */ { /* use group quota limits rather than user limits */ - dq->dqb_curblocks = dqg.dqb_curblocks; dq->dqb_bhardlimit = dqg.dqb_bhardlimit; dq->dqb_bsoftlimit = dqg.dqb_bsoftlimit; - dq->dqb_btimelimit = dqg.dqb_btimelimit; + dq->dqb_curblocks = dqg.dqb_curblocks; + dq->dqb_ihardlimit = dqg.dqb_ihardlimit; + dq->dqb_isoftlimit = dqg.dqb_isoftlimit; + dq->dqb_curinodes = dqg.dqb_curinodes; + dq->dqb_btime = dqg.dqb_btime; + dq->dqb_itime = dqg.dqb_itime; + dq->bsize = dqg.bsize; } /* if */ #endif /* TRU64 */ @@ -525,7 +613,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; @@ -600,11 +688,11 @@ static int getquota( struct vol *vol, struct dqblk *dq, const u_int32_t bsize) 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 */ } @@ -663,14 +751,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 ); } @@ -722,4 +810,5 @@ int uquota_getvolspace( struct vol *vol, VolSpace *bfree, VolSpace *btotal, cons return( AFP_OK ); } +#endif /* HAVE_LIBQUOTA */ #endif