summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/smbd/quotas.c439
1 files changed, 1 insertions, 438 deletions
diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c
index 10b05562af..0179e928d7 100644
--- a/source3/smbd/quotas.c
+++ b/source3/smbd/quotas.c
@@ -52,444 +52,7 @@ bool disk_quotas_vxfs(const char *name, char *path, uint64_t *bsize, uint64_t *d
#endif /* VXFS_QUOTA */
-#ifdef LINUX
-
-#include <sys/types.h>
-#include <mntent.h>
-
-/*
- * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
- * So we include all the files has *should* be in the system into a large,
- * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA.
- */
-
-#include "samba_linux_quota.h"
-
-typedef struct _LINUX_SMB_DISK_QUOTA {
- uint64_t bsize;
- uint64_t hardlimit; /* In bsize units. */
- uint64_t softlimit; /* In bsize units. */
- uint64_t curblocks; /* In bsize units. */
- uint64_t ihardlimit; /* inode hard limit. */
- uint64_t isoftlimit; /* inode soft limit. */
- uint64_t curinodes; /* Current used inodes. */
-} LINUX_SMB_DISK_QUOTA;
-
-
-/*
- * nfs quota support
- * (essentially taken from FreeBSD / SUNOS5 section)
- */
-#include <rpc/rpc.h>
-#include <rpc/types.h>
-#include <rpcsvc/rquota.h>
-#ifdef HAVE_RPC_NETTYPE_H
-#include <rpc/nettype.h>
-#endif
-#include <rpc/xdr.h>
-
-static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
-{
- int quotastat;
-
- if (!xdr_int(xdrsp, &quotastat)) {
- DEBUG(6,("nfs_quotas: Status bad or zero\n"));
- return 0;
- }
- gqr->status = quotastat;
-
- if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
- DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
- return 0;
- }
- if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
- DEBUG(6,("nfs_quotas: Active bad or zero\n"));
- return 0;
- }
- if (!xdr_int(xdrsp, (int *)&gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
- DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
- return 0;
- }
- if (!xdr_int(xdrsp, (int *)&gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
- DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
- return 0;
- }
- if (!xdr_int(xdrsp, (int *)&gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
- DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
- return 0;
- }
- return 1;
-}
-
-static bool nfs_quotas(char *nfspath, uid_t euser_id, uint64_t *bsize,
- uint64_t *dfree, uint64_t *dsize)
-{
- uid_t uid = euser_id;
- LINUX_SMB_DISK_QUOTA D;
- char *mnttype = nfspath;
- CLIENT *clnt;
- struct getquota_rslt gqr;
- struct getquota_args args;
- char *cutstr, *pathname, *host, *testpath;
- int len;
- static struct timeval timeout = {2,0};
- enum clnt_stat clnt_stat;
- bool ret = True;
-
- *bsize = *dfree = *dsize = (uint64_t)0;
-
- len=strcspn(mnttype, ":");
- pathname=strstr(mnttype, ":");
- cutstr = (char *) SMB_MALLOC(len+1);
- if (!cutstr)
- return False;
-
- memset(cutstr, '\0', len+1);
- host = strncat(cutstr,mnttype, sizeof(char) * len );
- DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
- DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
- testpath=strchr_m(mnttype, ':');
- args.gqa_pathp = testpath+1;
- args.gqa_uid = uid;
-
- DEBUG(5, ("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers "
- "\"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS,
- "udp"));
-
- if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
- ret = False;
- goto out;
- }
-
- clnt->cl_auth = authunix_create_default();
- DEBUG(9,("nfs_quotas: auth_success\n"));
-
- clnt_stat=clnt_call(clnt,
- RQUOTAPROC_GETQUOTA,
- (const xdrproc_t)my_xdr_getquota_args,
- (caddr_t)&args,
- (const xdrproc_t)my_xdr_getquota_rslt,
- (caddr_t)&gqr, timeout);
-
- if (clnt_stat != RPC_SUCCESS) {
- DEBUG(9,("nfs_quotas: clnt_call fail\n"));
- ret = False;
- goto out;
- }
-
- /*
- * gqr.status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
- * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
- * something sensible.
- */
-
- switch (gqr.status) {
- case 0:
- DEBUG(9, ("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n",
- gqr.status));
- ret = False;
- goto out;
-
- case 1:
- DEBUG(9,("nfs_quotas: Good quota data\n"));
- D.softlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
- D.hardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
- D.curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
- break;
-
- case 2:
- case 3:
- D.softlimit = 1;
- D.curblocks = 1;
- DEBUG(9, ("nfs_quotas: Remote Quotas returned \"%i\" \n",
- gqr.status));
- break;
-
- default:
- DEBUG(9, ("nfs_quotas: Remote Quotas Questionable! "
- "Error \"%i\" \n", gqr.status));
- break;
- }
-
- DEBUG(10, ("nfs_quotas: Let`s look at D a bit closer... "
- "status \"%i\" bsize \"%i\" active? \"%i\" bhard "
- "\"%i\" bsoft \"%i\" curb \"%i\" \n",
- gqr.status,
- gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
- gqr.getquota_rslt_u.gqr_rquota.rq_active,
- gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
- gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
- gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
-
- if (D.softlimit == 0)
- D.softlimit = D.hardlimit;
- if (D.softlimit == 0)
- return False;
-
- *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
- *dsize = D.softlimit;
-
- if (D.curblocks == 1)
- *bsize = DEV_BSIZE;
-
- if (D.curblocks > D.softlimit) {
- *dfree = 0;
- *dsize = D.curblocks;
- } else
- *dfree = D.softlimit - D.curblocks;
-
- out:
-
- if (clnt) {
- if (clnt->cl_auth)
- auth_destroy(clnt->cl_auth);
- clnt_destroy(clnt);
- }
-
- DEBUG(5, ("nfs_quotas: For path \"%s\" returning "
- "bsize %.0f, dfree %.0f, dsize %.0f\n",
- args.gqa_pathp, (double)*bsize, (double)*dfree,
- (double)*dsize));
-
- SAFE_FREE(cutstr);
- DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
- return ret;
-}
-
-/* end of nfs quota section */
-
-#ifdef HAVE_LINUX_DQBLK_XFS_H
-#include <linux/dqblk_xfs.h>
-
-/****************************************************************************
- Abstract out the XFS Quota Manager quota get call.
-****************************************************************************/
-
-static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
-{
- struct fs_disk_quota D;
- int ret;
-
- ZERO_STRUCT(D);
-
- ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
-
- if (ret)
- ret = quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
-
- if (ret)
- return ret;
-
- dp->bsize = (uint64_t)512;
- dp->softlimit = (uint64_t)D.d_blk_softlimit;
- dp->hardlimit = (uint64_t)D.d_blk_hardlimit;
- dp->ihardlimit = (uint64_t)D.d_ino_hardlimit;
- dp->isoftlimit = (uint64_t)D.d_ino_softlimit;
- dp->curinodes = (uint64_t)D.d_icount;
- dp->curblocks = (uint64_t)D.d_bcount;
-
- return ret;
-}
-#else
-static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
-{
- DEBUG(0,("XFS quota support not available\n"));
- errno = ENOSYS;
- return -1;
-}
-#endif
-
-
-/****************************************************************************
- Abstract out the old and new Linux quota get calls.
-****************************************************************************/
-
-static int get_smb_linux_v1_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
-{
- struct v1_kern_dqblk D;
- int ret;
-
- ZERO_STRUCT(D);
-
- ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
-
- if (ret && errno != EDQUOT)
- ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
-
- if (ret && errno != EDQUOT)
- return ret;
-
- dp->bsize = (uint64_t)QUOTABLOCK_SIZE;
- dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
- dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
- dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
- dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
- dp->curinodes = (uint64_t)D.dqb_curinodes;
- dp->curblocks = (uint64_t)D.dqb_curblocks;
-
- return ret;
-}
-
-static int get_smb_linux_v2_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
-{
- struct v2_kern_dqblk D;
- int ret;
-
- ZERO_STRUCT(D);
-
- ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
-
- if (ret && errno != EDQUOT)
- ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
-
- if (ret && errno != EDQUOT)
- return ret;
-
- dp->bsize = (uint64_t)QUOTABLOCK_SIZE;
- dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
- dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
- dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
- dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
- dp->curinodes = (uint64_t)D.dqb_curinodes;
- dp->curblocks = ((uint64_t)D.dqb_curspace) / dp->bsize;
-
- return ret;
-}
-
-/****************************************************************************
- Brand-new generic quota interface.
-****************************************************************************/
-
-static int get_smb_linux_gen_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
-{
- struct if_dqblk D;
- int ret;
-
- ZERO_STRUCT(D);
-
- ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
-
- if (ret && errno != EDQUOT)
- ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
-
- if (ret && errno != EDQUOT)
- return ret;
-
- dp->bsize = (uint64_t)QUOTABLOCK_SIZE;
- dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
- dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
- dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
- dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
- dp->curinodes = (uint64_t)D.dqb_curinodes;
- dp->curblocks = ((uint64_t)D.dqb_curspace) / dp->bsize;
-
- return ret;
-}
-
-/****************************************************************************
- Try to get the disk space from disk quotas (LINUX version).
-****************************************************************************/
-
-bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
-{
- int r;
- SMB_STRUCT_STAT S;
- FILE *fp;
- LINUX_SMB_DISK_QUOTA D;
- struct mntent *mnt;
- SMB_DEV_T devno;
- int found;
- uid_t euser_id;
- gid_t egrp_id;
-
- ZERO_STRUCT(D);
-
- euser_id = geteuid();
- egrp_id = getegid();
-
- /* find the block device file */
-
- if (sys_stat(path, &S, false) == -1 )
- return(False) ;
-
- devno = S.st_ex_dev ;
-
- if ((fp = setmntent(MOUNTED,"r")) == NULL)
- return(False) ;
-
- found = False ;
-
- while ((mnt = getmntent(fp))) {
- if (sys_stat(mnt->mnt_dir, &S, false) == -1)
- continue ;
-
- if (S.st_ex_dev == devno) {
- found = True ;
- break;
- }
- }
-
- endmntent(fp) ;
-
- if (!found)
- return(False);
-
- become_root();
-
- if (strcmp(mnt->mnt_type, "nfs") == 0) {
- bool retval;
- retval = nfs_quotas(mnt->mnt_fsname , euser_id, bsize, dfree, dsize);
- unbecome_root();
- return retval;
- }
-
- if (strcmp(mnt->mnt_type, "xfs")==0) {
- r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
- } else {
- r=get_smb_linux_gen_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
- if (r == -1 && errno != EDQUOT) {
- r=get_smb_linux_v2_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
- if (r == -1 && errno != EDQUOT)
- r=get_smb_linux_v1_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
- }
- }
-
- unbecome_root();
-
- /* Use softlimit to determine disk space, except when it has been exceeded */
- *bsize = D.bsize;
- if (r == -1) {
- if (errno == EDQUOT) {
- *dfree =0;
- *dsize =D.curblocks;
- return (True);
- } else {
- return(False);
- }
- }
-
- /* Use softlimit to determine disk space, except when it has been exceeded */
- if (
- (D.softlimit && D.curblocks >= D.softlimit) ||
- (D.hardlimit && D.curblocks >= D.hardlimit) ||
- (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
- (D.ihardlimit && D.curinodes>=D.ihardlimit)
- ) {
- *dfree = 0;
- *dsize = D.curblocks;
- } else if (D.softlimit==0 && D.hardlimit==0) {
- return(False);
- } else {
- if (D.softlimit == 0)
- D.softlimit = D.hardlimit;
- *dfree = D.softlimit - D.curblocks;
- *dsize = D.softlimit;
- }
-
- return (True);
-}
-
-#elif defined(SUNOS5) || defined(SUNOS4)
+#if defined(SUNOS5) || defined(SUNOS4)
#include <fcntl.h>
#include <sys/param.h>