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, "astat)) { 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 + -
显示快捷键?