quotas.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 1,493 行 · 第 1/3 页

C
1,493
字号
/*    Unix SMB/CIFS implementation.   support for quotas   Copyright (C) Andrew Tridgell 1992-1998      This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*//*  * This is one of the most system dependent parts of Samba, and its * done a litle differently. Each system has its own way of doing  * things :-( */#include "includes.h"#undef DBGC_CLASS#define DBGC_CLASS DBGC_QUOTA#ifndef HAVE_SYS_QUOTAS/* just a quick hack because sysquotas.h is included before linux/quota.h */#ifdef QUOTABLOCK_SIZE#undef QUOTABLOCK_SIZE#endif#ifdef WITH_QUOTAS#if defined(VXFS_QUOTA)/* * In addition to their native filesystems, some systems have Veritas VxFS. * Declare here, define at end: reduces likely "include" interaction problems. *	David Lee <T.D.Lee@durham.ac.uk> */BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);#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"#include "samba_xfs_quota.h"typedef struct _LINUX_SMB_DISK_QUOTA {	SMB_BIG_UINT bsize;	SMB_BIG_UINT hardlimit; /* In bsize units. */	SMB_BIG_UINT softlimit; /* In bsize units. */	SMB_BIG_UINT curblocks; /* In bsize units. */	SMB_BIG_UINT ihardlimit; /* inode hard limit. */	SMB_BIG_UINT isoftlimit; /* inode soft limit. */	SMB_BIG_UINT curinodes; /* Current used inodes. */} LINUX_SMB_DISK_QUOTA;/**************************************************************************** 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 = (SMB_BIG_UINT)512;	dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;	dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;	dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;	dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;	dp->curinodes = (SMB_BIG_UINT)D.d_icount;	dp->curblocks = (SMB_BIG_UINT)D.d_bcount;	return ret;}/**************************************************************************** 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 = (SMB_BIG_UINT)QUOTABLOCK_SIZE;	dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;	dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;	dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;	dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;	dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;	dp->curblocks = (SMB_BIG_UINT)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 = (SMB_BIG_UINT)QUOTABLOCK_SIZE;	dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;	dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;	dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;	dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;	dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;	dp->curblocks = ((SMB_BIG_UINT)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 = (SMB_BIG_UINT)QUOTABLOCK_SIZE;	dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;	dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;	dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;	dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;	dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;	dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;	return ret;}/**************************************************************************** Try to get the disk space from disk quotas (LINUX version).****************************************************************************/BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *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) == -1 )		return(False) ;	devno = S.st_dev ;  	if ((fp = setmntent(MOUNTED,"r")) == NULL)		return(False) ;	found = False ;  	while ((mnt = getmntent(fp))) {		if ( sys_stat(mnt->mnt_dir,&S) == -1 )			continue ;		if (S.st_dev == devno) {			found = True ;			break;		}	}	endmntent(fp) ;  	if (!found)		return(False);	save_re_uid();	set_effective_uid(0);  	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);		}	}	restore_re_uid();	/* 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(CRAY)#include <sys/quota.h>#include <mntent.h>/****************************************************************************try to get the disk space from disk quotas (CRAY VERSION)****************************************************************************/BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize){  struct mntent *mnt;  FILE *fd;  SMB_STRUCT_STAT sbuf;  SMB_DEV_T devno ;  static SMB_DEV_T devno_cached = 0 ;  static pstring name;  struct q_request request ;  struct qf_header header ;  static int quota_default = 0 ;  int found ;    if ( sys_stat(path,&sbuf) == -1 )    return(False) ;    devno = sbuf.st_dev ;    if ( devno != devno_cached ) {        devno_cached = devno ;        if ((fd = setmntent(KMTAB)) == NULL)      return(False) ;        found = False ;        while ((mnt = getmntent(fd)) != NULL) {            if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )	continue ;            if (sbuf.st_dev == devno) {		found = True ;	break ;	      }          }        pstrcpy(name,mnt->mnt_dir) ;    endmntent(fd) ;        if ( ! found )      return(False) ;  }    request.qf_magic = QF_MAGIC ;  request.qf_entry.id = geteuid() ;    if (quotactl(name, Q_GETQUOTA, &request) == -1)    return(False) ;    if ( ! request.user )    return(False) ;    if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {        if ( ! quota_default ) {            if ( quotactl(name, Q_GETHEADER, &header) == -1 )	return(False) ;      else	quota_default = header.user_h.def_fq ;    }        *dfree = quota_default ;      }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {        *dfree = 0 ;      }else{        *dfree = request.qf_entry.user_q.f_quota ;      }    *dsize = request.qf_entry.user_q.f_use ;    if ( *dfree < *dsize )    *dfree = 0 ;  else    *dfree -= *dsize ;    *bsize = 4096 ;  /* Cray blocksize */    return(True) ;  }#elif defined(SUNOS5) || defined(SUNOS4)#include <fcntl.h>#include <sys/param.h>#if defined(SUNOS5)#include <sys/fs/ufs_quota.h>#include <sys/mnttab.h>#include <sys/mntent.h>#else /* defined(SUNOS4) */#include <ufs/quota.h>#include <mntent.h>#endif#if defined(SUNOS5)/**************************************************************************** Allows querying of remote hosts for quotas on NFS mounted shares. Supports normal NFS and AMD mounts. Alan Romeril <a.romeril@ic.ac.uk> July 2K.****************************************************************************/#include <rpc/rpc.h>#include <rpc/types.h>#include <rpcsvc/rquota.h>#include <rpc/nettype.h>#include <rpc/xdr.h>static int quotastat;static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args){	if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))		return(0);	if (!xdr_int(xdrsp, &args->gqa_uid))		return(0);	return (1);}static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr){	if (!xdr_int(xdrsp, &quotastat)) {		DEBUG(6,("nfs_quotas: Status bad or zero\n"));		return 0;	}	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, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {		DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));		return 0;	}	if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {		DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));		return 0;	}	if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {		DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));		return 0;	}	return (1);}/* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */ static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize){	uid_t uid = euser_id;	struct dqblk 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 = (SMB_BIG_UINT)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"));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?