quotas.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 1,493 行 · 第 1/3 页
C
1,493 行
{ 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")); 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; } /* * quotastat 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 ( quotastat ) { case 0: DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat )); ret = False; goto out; case 1: DEBUG(9,("nfs_quotas: Good quota data\n")); D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit; D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit; D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks; break; case 2: case 3: D.dqb_bsoftlimit = 1; D.dqb_curblocks = 1; DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat )); break; default: DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", quotastat )); 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", quotastat, 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.dqb_bsoftlimit == 0) D.dqb_bsoftlimit = D.dqb_bhardlimit; if (D.dqb_bsoftlimit == 0) return False; *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize; *dsize = D.dqb_bsoftlimit; if (D.dqb_curblocks == D.dqb_curblocks == 1) *bsize = DEV_BSIZE; if (D.dqb_curblocks > D.dqb_bsoftlimit) { *dfree = 0; *dsize = D.dqb_curblocks; } else *dfree = D.dqb_bsoftlimit - D.dqb_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;}#endif/****************************************************************************try to get the disk space from disk quotas - default version****************************************************************************/BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize){ int r; struct dqblk D; uid_t euser_id;#if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__) char dev_disk[256]; SMB_STRUCT_STAT S; /* find the block device file */#ifdef HPUX /* Need to set the cache flag to 1 for HPUX. Seems * to have a significant performance boost when * lstat calls on /dev access this function. */ if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0))#else if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False);#endif /* ifdef HPUX */#endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__) */ euser_id = geteuid();#ifdef HPUX /* for HPUX, real uid must be same as euid to execute quotactl for euid */ save_re_uid(); if (set_re_uid() != 0) return False; r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D); restore_re_uid();#else #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) { /* FreeBSD patches from Marty Moll <martym@arbor.edu> */ gid_t egrp_id;#if defined(__FreeBSD__) || defined(__DragonFly__) SMB_DEV_T devno; struct statfs *mnts; SMB_STRUCT_STAT st; int mntsize, i; if (sys_stat(path,&st) < 0) return False; devno = st.st_dev; mntsize = getmntinfo(&mnts,MNT_NOWAIT); if (mntsize <= 0) return False; for (i = 0; i < mntsize; i++) { if (sys_stat(mnts[i].f_mntonname,&st) < 0) return False; if (st.st_dev == devno) break; } if (i == mntsize) return False;#endif save_re_uid(); set_effective_uid(0);#if defined(__FreeBSD__) || defined(__DragonFly__) if (strcmp(mnts[i].f_fstypename,"nfs") == 0) { BOOL retval; retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize); restore_re_uid(); return retval; }#endif egrp_id = getegid(); r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); /* As FreeBSD has group quotas, if getting the user quota fails, try getting the group instead. */ if (r) { r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D); } restore_re_uid(); }#elif defined(AIX) /* AIX has both USER and GROUP quotas: Get the USER quota (ohnielse@fysik.dtu.dk) */ save_re_uid(); if (set_re_uid() != 0) return False; r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D); restore_re_uid();#else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */ r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);#endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */#endif /* HPUX */ /* Use softlimit to determine disk space, except when it has been exceeded */#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) *bsize = DEV_BSIZE;#else /* !__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */ *bsize = 1024;#endif /*!__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */ if (r) { if (errno == EDQUOT) { *dfree =0; *dsize =D.dqb_curblocks; return (True); } else return(False); } /* If softlimit is zero, set it equal to hardlimit. */ if (D.dqb_bsoftlimit==0) D.dqb_bsoftlimit = D.dqb_bhardlimit; if (D.dqb_bsoftlimit==0) return(False); /* Use softlimit to determine disk space, except when it has been exceeded */ if ((D.dqb_curblocks>D.dqb_bsoftlimit)#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__)||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))#endif ) { *dfree = 0; *dsize = D.dqb_curblocks; } else { *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; *dsize = D.dqb_bsoftlimit; } return (True);}#endif#if defined(VXFS_QUOTA)/****************************************************************************Try to get the disk space from Veritas disk quotas. David Lee <T.D.Lee@durham.ac.uk> August 1999.Background assumptions: Potentially under many Operating Systems. Initially Solaris 2. My guess is that Veritas is largely, though not entirely, independent of OS. So I have separated it out. There may be some details. For example, OS-specific "include" files. It is understood that HPUX 10 somehow gets Veritas quotas without any special effort; if so, this routine need not be compiled in. Dirk De Wachter <Dirk.DeWachter@rug.ac.be>Warning: It is understood that Veritas do not publicly support this ioctl interface. Rather their preference would be for the user (us) to call the native OS and then for the OS itself to call through to the VxFS filesystem. Presumably HPUX 10, see above, does this.Hints for porting: Add your OS to "IFLIST" below. Get it to compile successfully: Almost certainly "include"s require attention: see SUNOS5. In the main code above, arrange for it to be called: see SUNOS5. Test! ****************************************************************************//* "IFLIST" * This "if" is a list of ports: * if defined(OS1) || defined(OS2) || ... */#if defined(SUNOS5)#if defined(SUNOS5)#include <sys/fs/vx_solaris.h>#endif#include <sys/fs/vx_machdep.h>#include <sys/fs/vx_layout.h>#include <sys/fs/vx_quota.h>#include <sys/fs/vx_aioctl.h>#include <sys/fs/vx_ioctl.h>BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize){ uid_t user_id, euser_id; int ret; struct vx_dqblk D; struct vx_quotctl quotabuf; struct vx_genioctl genbuf; pstring qfname; int file; /* * "name" may or may not include a trailing "/quotas". * Arranging consistency of calling here in "quotas.c" may not be easy and * it might be easier to examine and adjust it here. * Fortunately, VxFS seems not to mind at present. */ pstrcpy(qfname, name) ; /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */ euser_id = geteuid(); set_effective_uid(0); DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname)); if((file=sys_open(qfname, O_RDONLY,0))<0) { set_effective_uid(euser_id); return(False); } genbuf.ioc_cmd = VX_QUOTACTL; genbuf.ioc_up = (void *) "abuf; quotabuf.cmd = VX_GETQUOTA; quotabuf.uid = euser_id; quotabuf.addr = (caddr_t) &D; ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf); close(file); set_effective_uid(euser_id); if (ret < 0) { DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) )); return(False); } /* If softlimit is zero, set it equal to hardlimit. */ if (D.dqb_bsoftlimit==0) D.dqb_bsoftlimit = D.dqb_bhardlimit; /* Use softlimit to determine disk space. A user exceeding the quota is told * that there's no space left. Writes might actually work for a bit if the * hardlimit is set higher than softlimit. Effectively the disk becomes * made of rubber latex and begins to expand to accommodate the user :-) */ DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n", path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit, D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit)); if (D.dqb_bsoftlimit==0) return(False); *bsize = DEV_BSIZE; *dsize = D.dqb_bsoftlimit; if (D.dqb_curblocks > D.dqb_bsoftlimit) { *dfree = 0; *dsize = D.dqb_curblocks; } else *dfree = D.dqb_bsoftlimit - D.dqb_curblocks; DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n", path,(double)*bsize,(double)*dfree,(double)*dsize)); return(True);}#endif /* SUNOS5 || ... */#endif /* VXFS_QUOTA */#else /* WITH_QUOTAS */BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize){ (*bsize) = 512; /* This value should be ignored */ /* And just to be sure we set some values that hopefully */ /* will be larger that any possible real-world value */ (*dfree) = (SMB_BIG_UINT)-1; (*dsize) = (SMB_BIG_UINT)-1; /* As we have select not to use quotas, allways fail */ return False;}#endif /* WITH_QUOTAS */#else /* HAVE_SYS_QUOTAS *//* wrapper to the new sys_quota interface this file should be removed later */BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize){ int r; SMB_DISK_QUOTA D; unid_t id; id.uid = geteuid(); ZERO_STRUCT(D); r=sys_get_quota(path, SMB_USER_QUOTA_TYPE, id, &D); /* 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 { goto try_group_quota; } } /* 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) { goto try_group_quota; } else { if (D.softlimit == 0) D.softlimit = D.hardlimit; *dfree = D.softlimit - D.curblocks; *dsize = D.softlimit; } return True; try_group_quota: id.gid = getegid(); ZERO_STRUCT(D); r=sys_get_quota(path, SMB_GROUP_QUOTA_TYPE, id, &D); /* 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);}#endif /* HAVE_SYS_QUOTAS */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?