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=1bfc05b6bca4fc6397c524509eeab4137d30199e;hb=450114e8c52574c5444d856e8a0208f2bbaab80c;hpb=cd88519f69dbd46eab346a83774e07c343820e75 diff --git a/etc/afpd/quota.c b/etc/afpd/quota.c index 1bfc05b6..bab14e13 100644 --- a/etc/afpd/quota.c +++ b/etc/afpd/quota.c @@ -1,5 +1,4 @@ /* - * $Id: quota.c,v 1.27 2006-09-15 00:07:43 didg Exp $ * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. @@ -15,38 +14,116 @@ #include #include #include -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ #include #include #include -#ifdef HAVE_UNISTD_H #include -#endif /* HAVE_UNISTD_H */ -#ifdef HAVE_FCNTL_H #include -#endif /* HAVE_FCNTL_H */ #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 +*/ + #define WANT_USER_QUOTA 0 #define WANT_GROUP_QUOTA 1 @@ -187,11 +264,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 @@ -202,13 +275,13 @@ struct dqblk *dqb; 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; } @@ -218,11 +291,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; @@ -294,16 +363,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; @@ -341,9 +408,7 @@ int *nfs; */ static char * -special( file, nfs ) -char *file; -int *nfs; +special( char *file, int *nfs) { static struct fs_data fsd; @@ -362,9 +427,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; @@ -387,9 +450,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; @@ -397,7 +458,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; @@ -440,10 +501,7 @@ int *nfs; #endif /* __svr4__ */ -static int getfsquota(vol, uid, dq) -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; @@ -452,6 +510,7 @@ struct dqblk *dq; struct quotctl qc; #endif + memset(dq, 0, sizeof(struct dqblk)); memset(&dqg, 0, sizeof(dqg)); #ifdef __svr4__ @@ -483,34 +542,26 @@ 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) { @@ -532,20 +583,25 @@ 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 */ @@ -557,10 +613,7 @@ struct dqblk *dq; } -static int getquota( vol, dq, bsize) -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; @@ -635,16 +688,15 @@ 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 */ } -static int overquota( dqblk ) -struct dqblk *dqblk; +static int overquota( struct dqblk *dqblk) { struct timeval tv; @@ -662,7 +714,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 ); } @@ -699,17 +751,14 @@ 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(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 ); } @@ -718,19 +767,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. */ @@ -753,12 +802,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