smbd/quotas.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    support for quotas
00004    Copyright (C) Andrew Tridgell 1992-1998
00005    
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 
00022 /* 
00023  * This is one of the most system dependent parts of Samba, and its
00024  * done a litle differently. Each system has its own way of doing 
00025  * things :-(
00026  */
00027 
00028 #include "includes.h"
00029 
00030 #undef DBGC_CLASS
00031 #define DBGC_CLASS DBGC_QUOTA
00032 
00033 #ifndef HAVE_SYS_QUOTAS
00034 
00035 /* just a quick hack because sysquotas.h is included before linux/quota.h */
00036 #ifdef QUOTABLOCK_SIZE
00037 #undef QUOTABLOCK_SIZE
00038 #endif
00039 
00040 #ifdef WITH_QUOTAS
00041 
00042 #if defined(VXFS_QUOTA)
00043 
00044 /*
00045  * In addition to their native filesystems, some systems have Veritas VxFS.
00046  * Declare here, define at end: reduces likely "include" interaction problems.
00047  *      David Lee <T.D.Lee@durham.ac.uk>
00048  */
00049 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
00050 
00051 #endif /* VXFS_QUOTA */
00052 
00053 #ifdef LINUX
00054 
00055 #include <sys/types.h>
00056 #include <mntent.h>
00057 
00058 /*
00059  * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
00060  * So we include all the files has *should* be in the system into a large,
00061  * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA.
00062  */
00063 
00064 #include "samba_linux_quota.h"
00065 #include "samba_xfs_quota.h"
00066 
00067 typedef struct _LINUX_SMB_DISK_QUOTA {
00068         SMB_BIG_UINT bsize;
00069         SMB_BIG_UINT hardlimit; /* In bsize units. */
00070         SMB_BIG_UINT softlimit; /* In bsize units. */
00071         SMB_BIG_UINT curblocks; /* In bsize units. */
00072         SMB_BIG_UINT ihardlimit; /* inode hard limit. */
00073         SMB_BIG_UINT isoftlimit; /* inode soft limit. */
00074         SMB_BIG_UINT curinodes; /* Current used inodes. */
00075 } LINUX_SMB_DISK_QUOTA;
00076 
00077 /****************************************************************************
00078  Abstract out the XFS Quota Manager quota get call.
00079 ****************************************************************************/
00080 
00081 static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
00082 {
00083         struct fs_disk_quota D;
00084         int ret;
00085 
00086         ZERO_STRUCT(D);
00087 
00088         ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
00089 
00090         if (ret)
00091                 ret = quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
00092 
00093         if (ret)
00094                 return ret;
00095 
00096         dp->bsize = (SMB_BIG_UINT)512;
00097         dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
00098         dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
00099         dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
00100         dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
00101         dp->curinodes = (SMB_BIG_UINT)D.d_icount;
00102         dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
00103 
00104         return ret;
00105 }
00106 
00107 /****************************************************************************
00108  Abstract out the old and new Linux quota get calls.
00109 ****************************************************************************/
00110 
00111 static int get_smb_linux_v1_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
00112 {
00113         struct v1_kern_dqblk D;
00114         int ret;
00115 
00116         ZERO_STRUCT(D);
00117 
00118         ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
00119 
00120         if (ret && errno != EDQUOT)
00121                 ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
00122 
00123         if (ret && errno != EDQUOT)
00124                 return ret;
00125 
00126         dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
00127         dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
00128         dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
00129         dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
00130         dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
00131         dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
00132         dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
00133 
00134         return ret;
00135 }
00136 
00137 static int get_smb_linux_v2_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
00138 {
00139         struct v2_kern_dqblk D;
00140         int ret;
00141 
00142         ZERO_STRUCT(D);
00143 
00144         ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
00145 
00146         if (ret && errno != EDQUOT)
00147                 ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
00148 
00149         if (ret && errno != EDQUOT)
00150                 return ret;
00151 
00152         dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
00153         dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
00154         dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
00155         dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
00156         dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
00157         dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
00158         dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
00159 
00160         return ret;
00161 }
00162 
00163 /****************************************************************************
00164  Brand-new generic quota interface.
00165 ****************************************************************************/
00166 
00167 static int get_smb_linux_gen_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
00168 {
00169         struct if_dqblk D;
00170         int ret;
00171 
00172         ZERO_STRUCT(D);
00173 
00174         ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
00175 
00176         if (ret && errno != EDQUOT)
00177                 ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
00178 
00179         if (ret && errno != EDQUOT)
00180                 return ret;
00181 
00182         dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
00183         dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
00184         dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
00185         dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
00186         dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
00187         dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
00188         dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
00189 
00190         return ret;
00191 }
00192 
00193 /****************************************************************************
00194  Try to get the disk space from disk quotas (LINUX version).
00195 ****************************************************************************/
00196 
00197 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
00198 {
00199         int r;
00200         SMB_STRUCT_STAT S;
00201         FILE *fp;
00202         LINUX_SMB_DISK_QUOTA D;
00203         struct mntent *mnt;
00204         SMB_DEV_T devno;
00205         int found;
00206         uid_t euser_id;
00207         gid_t egrp_id;
00208 
00209         ZERO_STRUCT(D);
00210 
00211         euser_id = geteuid();
00212         egrp_id = getegid();
00213 
00214         /* find the block device file */
00215   
00216         if ( sys_stat(path, &S) == -1 )
00217                 return(False) ;
00218 
00219         devno = S.st_dev ;
00220   
00221         if ((fp = setmntent(MOUNTED,"r")) == NULL)
00222                 return(False) ;
00223 
00224         found = False ;
00225   
00226         while ((mnt = getmntent(fp))) {
00227                 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
00228                         continue ;
00229 
00230                 if (S.st_dev == devno) {
00231                         found = True ;
00232                         break;
00233                 }
00234         }
00235 
00236         endmntent(fp) ;
00237   
00238         if (!found)
00239                 return(False);
00240 
00241         become_root();
00242 
00243         if (strcmp(mnt->mnt_type, "xfs")==0) {
00244                 r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
00245         } else {
00246                 r=get_smb_linux_gen_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
00247                 if (r == -1 && errno != EDQUOT) {
00248                         r=get_smb_linux_v2_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
00249                         if (r == -1 && errno != EDQUOT)
00250                                 r=get_smb_linux_v1_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
00251                 }
00252         }
00253 
00254         unbecome_root();
00255 
00256         /* Use softlimit to determine disk space, except when it has been exceeded */
00257         *bsize = D.bsize;
00258         if (r == -1) {
00259                 if (errno == EDQUOT) {
00260                         *dfree =0;
00261                         *dsize =D.curblocks;
00262                         return (True);
00263                 } else {
00264                         return(False);
00265                 }
00266         }
00267 
00268         /* Use softlimit to determine disk space, except when it has been exceeded */
00269         if (
00270                 (D.softlimit && D.curblocks >= D.softlimit) ||
00271                 (D.hardlimit && D.curblocks >= D.hardlimit) ||
00272                 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
00273                 (D.ihardlimit && D.curinodes>=D.ihardlimit)
00274         ) {
00275                 *dfree = 0;
00276                 *dsize = D.curblocks;
00277         } else if (D.softlimit==0 && D.hardlimit==0) {
00278                 return(False);
00279         } else {
00280                 if (D.softlimit == 0)
00281                         D.softlimit = D.hardlimit;
00282                 *dfree = D.softlimit - D.curblocks;
00283                 *dsize = D.softlimit;
00284         }
00285 
00286         return (True);
00287 }
00288 
00289 #elif defined(CRAY)
00290 
00291 #include <sys/quota.h>
00292 #include <mntent.h>
00293 
00294 /****************************************************************************
00295 try to get the disk space from disk quotas (CRAY VERSION)
00296 ****************************************************************************/
00297 
00298 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
00299 {
00300   struct mntent *mnt;
00301   FILE *fd;
00302   SMB_STRUCT_STAT sbuf;
00303   SMB_DEV_T devno ;
00304   static SMB_DEV_T devno_cached = 0 ;
00305   static pstring name;
00306   struct q_request request ;
00307   struct qf_header header ;
00308   static int quota_default = 0 ;
00309   int found ;
00310   
00311   if ( sys_stat(path,&sbuf) == -1 )
00312     return(False) ;
00313   
00314   devno = sbuf.st_dev ;
00315   
00316   if ( devno != devno_cached ) {
00317     
00318     devno_cached = devno ;
00319     
00320     if ((fd = setmntent(KMTAB)) == NULL)
00321       return(False) ;
00322     
00323     found = False ;
00324     
00325     while ((mnt = getmntent(fd)) != NULL) {
00326       
00327       if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
00328         continue ;
00329       
00330       if (sbuf.st_dev == devno) {
00331         
00332         found = True ;
00333         break ;
00334         
00335       }
00336       
00337     }
00338     
00339     pstrcpy(name,mnt->mnt_dir) ;
00340     endmntent(fd) ;
00341     
00342     if ( ! found )
00343       return(False) ;
00344   }
00345   
00346   request.qf_magic = QF_MAGIC ;
00347   request.qf_entry.id = geteuid() ;
00348   
00349   if (quotactl(name, Q_GETQUOTA, &request) == -1)
00350     return(False) ;
00351   
00352   if ( ! request.user )
00353     return(False) ;
00354   
00355   if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
00356     
00357     if ( ! quota_default ) {
00358       
00359       if ( quotactl(name, Q_GETHEADER, &header) == -1 )
00360         return(False) ;
00361       else
00362         quota_default = header.user_h.def_fq ;
00363     }
00364     
00365     *dfree = quota_default ;
00366     
00367   }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
00368     
00369     *dfree = 0 ;
00370     
00371   }else{
00372     
00373     *dfree = request.qf_entry.user_q.f_quota ;
00374     
00375   }
00376   
00377   *dsize = request.qf_entry.user_q.f_use ;
00378   
00379   if ( *dfree < *dsize )
00380     *dfree = 0 ;
00381   else
00382     *dfree -= *dsize ;
00383   
00384   *bsize = 4096 ;  /* Cray blocksize */
00385   
00386   return(True) ;
00387   
00388 }
00389 
00390 
00391 #elif defined(SUNOS5) || defined(SUNOS4)
00392 
00393 #include <fcntl.h>
00394 #include <sys/param.h>
00395 #if defined(SUNOS5)
00396 #include <sys/fs/ufs_quota.h>
00397 #include <sys/mnttab.h>
00398 #include <sys/mntent.h>
00399 #else /* defined(SUNOS4) */
00400 #include <ufs/quota.h>
00401 #include <mntent.h>
00402 #endif
00403 
00404 #if defined(SUNOS5)
00405 
00406 /****************************************************************************
00407  Allows querying of remote hosts for quotas on NFS mounted shares.
00408  Supports normal NFS and AMD mounts.
00409  Alan Romeril <a.romeril@ic.ac.uk> July 2K.
00410 ****************************************************************************/
00411 
00412 #include <rpc/rpc.h>
00413 #include <rpc/types.h>
00414 #include <rpcsvc/rquota.h>
00415 #include <rpc/nettype.h>
00416 #include <rpc/xdr.h>
00417 
00418 static int quotastat;
00419 
00420 static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
00421 {
00422         if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
00423                 return(0);
00424         if (!xdr_int(xdrsp, &args->gqa_uid))
00425                 return(0);
00426         return (1);
00427 }
00428 
00429 static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
00430 {
00431         if (!xdr_int(xdrsp, &quotastat)) {
00432                 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
00433                 return 0;
00434         }
00435         if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
00436                 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
00437                 return 0;
00438         }
00439         if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
00440                 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
00441                 return 0;
00442         }
00443         if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
00444                 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
00445                 return 0;
00446         }
00447         if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
00448                 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
00449                 return 0;
00450         }
00451         if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
00452                 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
00453                 return 0;
00454         }
00455         return (1);
00456 }
00457 
00458 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */ 
00459 static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
00460 {
00461         uid_t uid = euser_id;
00462         struct dqblk D;
00463         char *mnttype = nfspath;
00464         CLIENT *clnt;
00465         struct getquota_rslt gqr;
00466         struct getquota_args args;
00467         char *cutstr, *pathname, *host, *testpath;
00468         int len;
00469         static struct timeval timeout = {2,0};
00470         enum clnt_stat clnt_stat;
00471         BOOL ret = True;
00472 
00473         *bsize = *dfree = *dsize = (SMB_BIG_UINT)0;
00474 
00475         len=strcspn(mnttype, ":");
00476         pathname=strstr(mnttype, ":");
00477         cutstr = (char *) SMB_MALLOC(len+1);
00478         if (!cutstr)
00479                 return False;
00480 
00481         memset(cutstr, '\0', len+1);
00482         host = strncat(cutstr,mnttype, sizeof(char) * len );
00483         DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
00484         DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
00485         testpath=strchr_m(mnttype, ':');
00486         args.gqa_pathp = testpath+1;
00487         args.gqa_uid = uid;
00488 
00489         DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
00490 
00491         if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
00492                 ret = False;
00493                 goto out;
00494         }
00495 
00496         clnt->cl_auth = authunix_create_default();
00497         DEBUG(9,("nfs_quotas: auth_success\n"));
00498 
00499         clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, my_xdr_getquota_args, (caddr_t)&args, my_xdr_getquota_rslt, (caddr_t)&gqr, timeout);
00500 
00501         if (clnt_stat != RPC_SUCCESS) {
00502                 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
00503                 ret = False;
00504                 goto out;
00505         }
00506 
00507         /* 
00508          * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
00509          * no quota set, and 3 if no permission to get the quota.  If 0 or 3 return
00510          * something sensible.
00511          */   
00512 
00513         switch ( quotastat ) {
00514         case 0:
00515                 DEBUG(9,("nfs_quotas: Remote Quotas Failed!  Error \"%i\" \n", quotastat ));
00516                 ret = False;
00517                 goto out;
00518 
00519         case 1:
00520                 DEBUG(9,("nfs_quotas: Good quota data\n"));
00521                 D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
00522                 D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
00523                 D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
00524                 break;
00525 
00526         case 2:
00527         case 3:
00528                 D.dqb_bsoftlimit = 1;
00529                 D.dqb_curblocks = 1;
00530                 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat ));
00531                 break;
00532 
00533         default:
00534                 DEBUG(9,("nfs_quotas: Remote Quotas Questionable!  Error \"%i\" \n", quotastat ));
00535                 break;
00536         }
00537 
00538         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",
00539                         quotastat,
00540                         gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
00541                         gqr.getquota_rslt_u.gqr_rquota.rq_active,
00542                         gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
00543                         gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
00544                         gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
00545 
00546         *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
00547         *dsize = D.dqb_bsoftlimit;
00548 
00549         if (D.dqb_curblocks == D.dqb_curblocks == 1)
00550                 *bsize = 512;
00551 
00552         if (D.dqb_curblocks > D.dqb_bsoftlimit) {
00553                 *dfree = 0;
00554                 *dsize = D.dqb_curblocks;
00555         } else
00556                 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
00557 
00558   out:
00559 
00560         if (clnt) {
00561                 if (clnt->cl_auth)
00562                         auth_destroy(clnt->cl_auth);
00563                 clnt_destroy(clnt);
00564         }
00565 
00566         DEBUG(5,("nfs_quotas: For path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
00567 
00568         SAFE_FREE(cutstr);
00569         DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
00570         return ret;
00571 }
00572 #endif
00573 
00574 /****************************************************************************
00575 try to get the disk space from disk quotas (SunOS & Solaris2 version)
00576 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
00577 ****************************************************************************/
00578 
00579 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
00580 {
00581         uid_t euser_id;
00582         int ret;
00583         struct dqblk D;
00584 #if defined(SUNOS5)
00585         struct quotctl command;
00586         int file;
00587         static struct mnttab mnt;
00588         static pstring name;
00589 #else /* SunOS4 */
00590         struct mntent *mnt;
00591         static pstring name;
00592 #endif
00593         FILE *fd;
00594         SMB_STRUCT_STAT sbuf;
00595         SMB_DEV_T devno ;
00596         static SMB_DEV_T devno_cached = 0 ;
00597         static int found ;
00598 
00599         euser_id = geteuid();
00600   
00601         if ( sys_stat(path,&sbuf) == -1 )
00602                 return(False) ;
00603   
00604         devno = sbuf.st_dev ;
00605         DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
00606                 path, (unsigned int)devno));
00607         if ( devno != devno_cached ) {
00608                 devno_cached = devno ;
00609 #if defined(SUNOS5)
00610                 if ((fd = sys_fopen(MNTTAB, "r")) == NULL)
00611                         return(False) ;
00612     
00613                 found = False ;
00614 
00615                 while (getmntent(fd, &mnt) == 0) {
00616                         if (sys_stat(mnt.mnt_mountp, &sbuf) == -1)
00617                                 continue;
00618 
00619                         DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
00620                                 mnt.mnt_mountp, (unsigned int)devno));
00621 
00622                         /* quotas are only on vxfs, UFS or NFS */
00623                         if ( (sbuf.st_dev == devno) && (
00624                                 strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
00625                                 strcmp( mnt.mnt_fstype, "nfs" ) == 0    ||
00626                                 strcmp( mnt.mnt_fstype, "vxfs" ) == 0 )) { 
00627                                         found = True ;
00628                                         break;
00629                         }
00630                 }
00631     
00632                 pstrcpy(name,mnt.mnt_mountp) ;
00633                 pstrcat(name,"/quotas") ;
00634                 fclose(fd) ;
00635 #else /* SunOS4 */
00636                 if ((fd = setmntent(MOUNTED, "r")) == NULL)
00637                         return(False) ;
00638     
00639                 found = False ;
00640                 while ((mnt = getmntent(fd)) != NULL) {
00641                         if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
00642                                 continue ;
00643                         DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt->mnt_dir,(unsigned int)sbuf.st_dev));
00644                         if (sbuf.st_dev == devno) {
00645                                 found = True ;
00646                                 break;
00647                         }
00648                 }
00649     
00650                 pstrcpy(name,mnt->mnt_fsname) ;
00651                 endmntent(fd) ;
00652 #endif
00653         }
00654 
00655         if ( ! found )
00656                 return(False) ;
00657 
00658         become_root();
00659 
00660 #if defined(SUNOS5)
00661         if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) {
00662                 BOOL retval;
00663                 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special));
00664                 retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize);
00665                 unbecome_root();
00666                 return retval;
00667         }
00668 
00669         DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
00670         if((file=sys_open(name, O_RDONLY,0))<0) {
00671                 unbecome_root();
00672                 return(False);
00673         }
00674         command.op = Q_GETQUOTA;
00675         command.uid = euser_id;
00676         command.addr = (caddr_t) &D;
00677         ret = ioctl(file, Q_QUOTACTL, &command);
00678         close(file);
00679 #else
00680         DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
00681         ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
00682 #endif
00683 
00684         unbecome_root();
00685 
00686         if (ret < 0) {
00687                 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) ));
00688 
00689 #if defined(SUNOS5) && defined(VXFS_QUOTA)
00690                 /* If normal quotactl() fails, try vxfs private calls */
00691                 set_effective_uid(euser_id);
00692                 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
00693                 if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
00694                         BOOL retval;
00695                         retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize);
00696                         return(retval);
00697                 }
00698 #else
00699                 return(False);
00700 #endif
00701         }
00702 
00703         /* If softlimit is zero, set it equal to hardlimit.
00704          */
00705   
00706         if (D.dqb_bsoftlimit==0)
00707                 D.dqb_bsoftlimit = D.dqb_bhardlimit;
00708 
00709         /* Use softlimit to determine disk space. A user exceeding the quota is told
00710          * that there's no space left. Writes might actually work for a bit if the
00711          * hardlimit is set higher than softlimit. Effectively the disk becomes
00712          * made of rubber latex and begins to expand to accommodate the user :-)
00713          */
00714 
00715         if (D.dqb_bsoftlimit==0)
00716                 return(False);
00717         *bsize = DEV_BSIZE;
00718         *dsize = D.dqb_bsoftlimit;
00719 
00720         if (D.dqb_curblocks > D.dqb_bsoftlimit) {
00721                 *dfree = 0;
00722                 *dsize = D.dqb_curblocks;
00723         } else
00724                 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
00725       
00726         DEBUG(5,("disk_quotas for path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",
00727                 path,(double)*bsize,(double)*dfree,(double)*dsize));
00728 
00729         return(True);
00730 }
00731 
00732 
00733 #elif defined(OSF1)
00734 #include <ufs/quota.h>
00735 
00736 /****************************************************************************
00737 try to get the disk space from disk quotas - OSF1 version
00738 ****************************************************************************/
00739 
00740 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
00741 {
00742   int r, save_errno;
00743   struct dqblk D;
00744   SMB_STRUCT_STAT S;
00745   uid_t euser_id;
00746 
00747   /*
00748    * This code presumes that OSF1 will only
00749    * give out quota info when the real uid 
00750    * matches the effective uid. JRA.
00751    */
00752   euser_id = geteuid();
00753   save_re_uid();
00754   if (set_re_uid() != 0) return False;
00755 
00756   r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D);
00757   if (r) {
00758      save_errno = errno;
00759   }
00760 
00761   restore_re_uid();
00762 
00763   *bsize = DEV_BSIZE;
00764 
00765   if (r)
00766   {
00767       if (save_errno == EDQUOT)   /* disk quota exceeded */
00768       {
00769          *dfree = 0;
00770          *dsize = D.dqb_curblocks;
00771          return (True);
00772       }
00773       else
00774          return (False);  
00775   }
00776 
00777   /* If softlimit is zero, set it equal to hardlimit.
00778    */
00779 
00780   if (D.dqb_bsoftlimit==0)
00781     D.dqb_bsoftlimit = D.dqb_bhardlimit;
00782 
00783   /* Use softlimit to determine disk space, except when it has been exceeded */
00784 
00785   if (D.dqb_bsoftlimit==0)
00786     return(False);
00787 
00788   if ((D.dqb_curblocks>D.dqb_bsoftlimit)) {
00789     *dfree = 0;
00790     *dsize = D.dqb_curblocks;
00791   } else {
00792     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
00793     *dsize = D.dqb_bsoftlimit;
00794   }
00795   return (True);
00796 }
00797 
00798 #elif defined (IRIX6)
00799 /****************************************************************************
00800 try to get the disk space from disk quotas (IRIX 6.2 version)
00801 ****************************************************************************/
00802 
00803 #include <sys/quota.h>
00804 #include <mntent.h>
00805 
00806 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
00807 {
00808   uid_t euser_id;
00809   int r;
00810   struct dqblk D;
00811   struct fs_disk_quota        F;
00812   SMB_STRUCT_STAT S;
00813   FILE *fp;
00814   struct mntent *mnt;
00815   SMB_DEV_T devno;
00816   int found;
00817   
00818   /* find the block device file */
00819   
00820   if ( sys_stat(path, &S) == -1 ) {
00821     return(False) ;
00822   }
00823 
00824   devno = S.st_dev ;
00825   
00826   fp = setmntent(MOUNTED,"r");
00827   found = False ;
00828   
00829   while ((mnt = getmntent(fp))) {
00830     if ( sys_stat(mnt->mnt_dir,&S) == -1 )
00831       continue ;
00832     if (S.st_dev == devno) {
00833       found = True ;
00834       break ;
00835     }
00836   }
00837   endmntent(fp) ;
00838   
00839   if (!found) {
00840     return(False);
00841   }
00842 
00843   euser_id=geteuid();
00844   become_root();
00845 
00846   /* Use softlimit to determine disk space, except when it has been exceeded */
00847 
00848   *bsize = 512;
00849 
00850   if ( 0 == strcmp ( mnt->mnt_type, "efs" ))
00851   {
00852     r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);
00853 
00854     unbecome_root();
00855 
00856     if (r==-1)
00857       return(False);
00858         
00859     /* Use softlimit to determine disk space, except when it has been exceeded */
00860     if (
00861         (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
00862         (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
00863         (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) ||
00864         (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit)
00865        )
00866     {
00867       *dfree = 0;
00868       *dsize = D.dqb_curblocks;
00869     }
00870     else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
00871     {
00872       return(False);
00873     }
00874     else 
00875     {
00876       *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
00877       *dsize = D.dqb_bsoftlimit;
00878     }
00879 
00880   }
00881   else if ( 0 == strcmp ( mnt->mnt_type, "xfs" ))
00882   {
00883     r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);
00884 
00885     unbecome_root();
00886 
00887     if (r==-1)
00888     {
00889       DEBUG(5, ("quotactl for uid=%u: %s", euser_id, strerror(errno)));
00890       return(False);
00891     }
00892         
00893     /* No quota for this user. */
00894     if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0)
00895     {
00896       return(False);
00897     }
00898 
00899     /* Use softlimit to determine disk space, except when it has been exceeded */
00900     if (
00901         (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) ||
00902         (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) ||
00903         (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) ||
00904         (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit)
00905        )
00906     {
00907       *dfree = 0;
00908       *dsize = F.d_bcount;
00909     }
00910     else 
00911     {
00912       *dfree = (F.d_blk_softlimit - F.d_bcount);
00913       *dsize = F.d_blk_softlimit ? F.d_blk_softlimit : F.d_blk_hardlimit;
00914     }
00915 
00916   }
00917   else
00918   {
00919           unbecome_root();
00920           return(False);
00921   }
00922 
00923   return (True);
00924 
00925 }
00926 
00927 #else
00928 
00929 #if    defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
00930 #include <ufs/ufs/quota.h>
00931 #include <machine/param.h>
00932 #elif         AIX
00933 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
00934 #include <jfs/quota.h>
00935 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
00936 #define dqb_curfiles dqb_curinodes
00937 #define dqb_fhardlimit dqb_ihardlimit
00938 #define dqb_fsoftlimit dqb_isoftlimit
00939 #ifdef _AIXVERSION_530 
00940 #include <sys/statfs.h>
00941 #include <sys/vmount.h>
00942 #endif /* AIX 5.3 */
00943 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
00944 #include <sys/quota.h>
00945 #include <devnm.h>
00946 #endif
00947 
00948 #if defined(__FreeBSD__) || defined(__DragonFly__)
00949 
00950 #include <rpc/rpc.h>
00951 #include <rpc/types.h>
00952 #include <rpcsvc/rquota.h>
00953 #ifdef HAVE_RPC_NETTYPE_H
00954 #include <rpc/nettype.h>
00955 #endif
00956 #include <rpc/xdr.h>
00957 
00958 static int quotastat;
00959 
00960 static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
00961 {
00962         if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
00963                 return(0);
00964         if (!xdr_int(xdrsp, &args->gqa_uid))
00965                 return(0);
00966         return (1);
00967 }
00968 
00969 static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
00970 {
00971         if (!xdr_int(xdrsp, &quotastat)) {
00972                 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
00973                 return 0;
00974         }
00975         if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
00976                 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
00977                 return 0;
00978         }
00979         if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
00980                 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
00981                 return 0;
00982         }
00983         if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
00984                 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
00985                 return 0;
00986         }
00987         if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
00988                 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
00989                 return 0;
00990         }
00991         if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
00992                 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
00993                 return 0;
00994         }
00995         return (1);
00996 }
00997 
00998 /* Works on FreeBSD, too. :-) */
00999 static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
01000 {
01001         uid_t uid = euser_id;
01002         struct dqblk D;
01003         char *mnttype = nfspath;
01004         CLIENT *clnt;
01005         struct getquota_rslt gqr;
01006         struct getquota_args args;
01007         char *cutstr, *pathname, *host, *testpath;
01008         int len;
01009         static struct timeval timeout = {2,0};
01010         enum clnt_stat clnt_stat;
01011         BOOL ret = True;
01012 
01013         *bsize = *dfree = *dsize = (SMB_BIG_UINT)0;
01014 
01015         len=strcspn(mnttype, ":");
01016         pathname=strstr(mnttype, ":");
01017         cutstr = (char *) SMB_MALLOC(len+1);
01018         if (!cutstr)
01019                 return False;
01020 
01021         memset(cutstr, '\0', len+1);
01022         host = strncat(cutstr,mnttype, sizeof(char) * len );
01023         DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
01024         DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
01025         testpath=strchr_m(mnttype, ':');
01026         args.gqa_pathp = testpath+1;
01027         args.gqa_uid = uid;
01028 
01029         DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
01030 
01031         if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
01032                 ret = False;
01033                 goto out;
01034         }
01035 
01036         clnt->cl_auth = authunix_create_default();
01037         DEBUG(9,("nfs_quotas: auth_success\n"));
01038 
01039         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);
01040 
01041         if (clnt_stat != RPC_SUCCESS) {
01042                 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
01043                 ret = False;
01044                 goto out;
01045         }
01046 
01047         /* 
01048          * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
01049          * no quota set, and 3 if no permission to get the quota.  If 0 or 3 return
01050          * something sensible.
01051          */   
01052 
01053         switch ( quotastat ) {
01054         case 0:
01055                 DEBUG(9,("nfs_quotas: Remote Quotas Failed!  Error \"%i\" \n", quotastat ));
01056                 ret = False;
01057                 goto out;
01058 
01059         case 1:
01060                 DEBUG(9,("nfs_quotas: Good quota data\n"));
01061                 D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
01062                 D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
01063                 D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
01064                 break;
01065 
01066         case 2:
01067         case 3:
01068                 D.dqb_bsoftlimit = 1;
01069                 D.dqb_curblocks = 1;
01070                 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat ));
01071                 break;
01072 
01073         default:
01074                 DEBUG(9,("nfs_quotas: Remote Quotas Questionable!  Error \"%i\" \n", quotastat ));
01075                 break;
01076         }
01077 
01078         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",
01079                         quotastat,
01080                         gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
01081                         gqr.getquota_rslt_u.gqr_rquota.rq_active,
01082                         gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
01083                         gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
01084                         gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
01085 
01086         if (D.dqb_bsoftlimit == 0)
01087                 D.dqb_bsoftlimit = D.dqb_bhardlimit;
01088         if (D.dqb_bsoftlimit == 0)
01089                 return False;
01090 
01091         *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
01092         *dsize = D.dqb_bsoftlimit;
01093 
01094         if (D.dqb_curblocks == D.dqb_curblocks == 1)
01095                 *bsize = DEV_BSIZE;
01096 
01097         if (D.dqb_curblocks > D.dqb_bsoftlimit) {
01098                 *dfree = 0;
01099                 *dsize = D.dqb_curblocks;
01100         } else
01101                 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
01102 
01103   out:
01104 
01105         if (clnt) {
01106                 if (clnt->cl_auth)
01107                         auth_destroy(clnt->cl_auth);
01108                 clnt_destroy(clnt);
01109         }
01110 
01111         DEBUG(5,("nfs_quotas: For path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
01112 
01113         SAFE_FREE(cutstr);
01114         DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
01115         return ret;
01116 }
01117 
01118 #endif
01119 
01120 /****************************************************************************
01121 try to get the disk space from disk quotas - default version
01122 ****************************************************************************/
01123 
01124 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
01125 {
01126   int r;
01127   struct dqblk D;
01128   uid_t euser_id;
01129 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__)
01130   char dev_disk[256];
01131   SMB_STRUCT_STAT S;
01132 
01133   /* find the block device file */
01134 
01135 #ifdef HPUX
01136   /* Need to set the cache flag to 1 for HPUX. Seems
01137    * to have a significant performance boost when
01138    * lstat calls on /dev access this function.
01139    */
01140   if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0))
01141 #else
01142   if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) 
01143         return (False);
01144 #endif /* ifdef HPUX */
01145 
01146 #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__) */
01147 
01148   euser_id = geteuid();
01149 
01150 #ifdef HPUX
01151   /* for HPUX, real uid must be same as euid to execute quotactl for euid */
01152   save_re_uid();
01153   if (set_re_uid() != 0) return False;
01154   
01155   r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
01156 
01157   restore_re_uid();
01158 #else 
01159 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
01160   {
01161     /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
01162     gid_t egrp_id;
01163 #if defined(__FreeBSD__) || defined(__DragonFly__)
01164     SMB_DEV_T devno;
01165     struct statfs *mnts;
01166     SMB_STRUCT_STAT st;
01167     int mntsize, i;
01168     
01169     if (sys_stat(path,&st) < 0)
01170         return False;
01171     devno = st.st_dev;
01172 
01173     mntsize = getmntinfo(&mnts,MNT_NOWAIT);
01174     if (mntsize <= 0)
01175         return False;
01176 
01177     for (i = 0; i < mntsize; i++) {
01178         if (sys_stat(mnts[i].f_mntonname,&st) < 0)
01179             return False;
01180         if (st.st_dev == devno)
01181             break;
01182     }
01183     if (i == mntsize)
01184         return False;
01185 #endif
01186     
01187     become_root();
01188 
01189 #if defined(__FreeBSD__) || defined(__DragonFly__)
01190     if (strcmp(mnts[i].f_fstypename,"nfs") == 0) {
01191         BOOL retval;
01192         retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize);
01193         unbecome_root();
01194         return retval;
01195     }
01196 #endif
01197 
01198     egrp_id = getegid();
01199     r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
01200 
01201     /* As FreeBSD has group quotas, if getting the user
01202        quota fails, try getting the group instead. */
01203     if (r) {
01204             r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
01205     }
01206 
01207     unbecome_root();
01208   }
01209 #elif defined(AIX)
01210   /* AIX has both USER and GROUP quotas: 
01211      Get the USER quota (ohnielse@fysik.dtu.dk) */
01212 #ifdef _AIXVERSION_530
01213   {
01214     struct statfs statbuf;
01215     quota64_t user_quota;
01216     if (statfs(path,&statbuf) != 0)
01217       return False;
01218     if(statbuf.f_vfstype == MNT_J2)
01219     {
01220     /* For some reason we need to be root for jfs2 */
01221       become_root();
01222       r = quotactl(path,QCMD(Q_J2GETQUOTA,USRQUOTA),euser_id,(char *) &user_quota);
01223       unbecome_root();
01224     /* Copy results to old struct to let the following code work as before */
01225       D.dqb_curblocks  = user_quota.bused;
01226       D.dqb_bsoftlimit = user_quota.bsoft;
01227       D.dqb_bhardlimit = user_quota.bhard;
01228       D.dqb_curfiles   = user_quota.iused;
01229       D.dqb_fsoftlimit = user_quota.isoft;
01230       D.dqb_fhardlimit = user_quota.ihard;
01231     }
01232     else if(statbuf.f_vfstype == MNT_JFS)
01233     {
01234 #endif /* AIX 5.3 */
01235   save_re_uid();
01236   if (set_re_uid() != 0) 
01237     return False;
01238   r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
01239   restore_re_uid();
01240 #ifdef _AIXVERSION_530
01241     }
01242     else
01243       r = 1; /* Fail for other FS-types */
01244   }
01245 #endif /* AIX 5.3 */
01246 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
01247   r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
01248 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
01249 #endif /* HPUX */
01250 
01251   /* Use softlimit to determine disk space, except when it has been exceeded */
01252 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
01253   *bsize = DEV_BSIZE;
01254 #else /* !__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
01255   *bsize = 1024;
01256 #endif /*!__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
01257 
01258   if (r)
01259     {
01260       if (errno == EDQUOT) 
01261         {
01262           *dfree =0;
01263           *dsize =D.dqb_curblocks;
01264           return (True);
01265         }
01266       else return(False);
01267     }
01268 
01269   /* If softlimit is zero, set it equal to hardlimit.
01270    */
01271 
01272   if (D.dqb_bsoftlimit==0)
01273     D.dqb_bsoftlimit = D.dqb_bhardlimit;
01274 
01275   if (D.dqb_bsoftlimit==0)
01276     return(False);
01277   /* Use softlimit to determine disk space, except when it has been exceeded */
01278   if ((D.dqb_curblocks>D.dqb_bsoftlimit)
01279 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__)
01280 ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
01281 #endif
01282     ) {
01283       *dfree = 0;
01284       *dsize = D.dqb_curblocks;
01285     }
01286   else {
01287     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
01288     *dsize = D.dqb_bsoftlimit;
01289   }
01290   return (True);
01291 }
01292 
01293 #endif
01294 
01295 #if defined(VXFS_QUOTA)
01296 
01297 /****************************************************************************
01298 Try to get the disk space from Veritas disk quotas.
01299     David Lee <T.D.Lee@durham.ac.uk> August 1999.
01300 
01301 Background assumptions:
01302     Potentially under many Operating Systems.  Initially Solaris 2.
01303 
01304     My guess is that Veritas is largely, though not entirely,
01305     independent of OS.  So I have separated it out.
01306 
01307     There may be some details.  For example, OS-specific "include" files.
01308 
01309     It is understood that HPUX 10 somehow gets Veritas quotas without
01310     any special effort; if so, this routine need not be compiled in.
01311         Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
01312 
01313 Warning:
01314     It is understood that Veritas do not publicly support this ioctl interface.
01315     Rather their preference would be for the user (us) to call the native
01316     OS and then for the OS itself to call through to the VxFS filesystem.
01317     Presumably HPUX 10, see above, does this.
01318 
01319 Hints for porting:
01320     Add your OS to "IFLIST" below.
01321     Get it to compile successfully:
01322         Almost certainly "include"s require attention: see SUNOS5.
01323     In the main code above, arrange for it to be called: see SUNOS5.
01324     Test!
01325     
01326 ****************************************************************************/
01327 
01328 /* "IFLIST"
01329  * This "if" is a list of ports:
01330  *      if defined(OS1) || defined(OS2) || ...
01331  */
01332 #if defined(SUNOS5)
01333 
01334 #if defined(SUNOS5)
01335 #include <sys/fs/vx_solaris.h>
01336 #endif
01337 #include <sys/fs/vx_machdep.h>
01338 #include <sys/fs/vx_layout.h>
01339 #include <sys/fs/vx_quota.h>
01340 #include <sys/fs/vx_aioctl.h>
01341 #include <sys/fs/vx_ioctl.h>
01342 
01343 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
01344 {
01345   uid_t user_id, euser_id;
01346   int ret;
01347   struct vx_dqblk D;
01348   struct vx_quotctl quotabuf;
01349   struct vx_genioctl genbuf;
01350   pstring qfname;
01351   int file;
01352 
01353   /*
01354    * "name" may or may not include a trailing "/quotas".
01355    * Arranging consistency of calling here in "quotas.c" may not be easy and
01356    * it might be easier to examine and adjust it here.
01357    * Fortunately, VxFS seems not to mind at present.
01358    */
01359   pstrcpy(qfname, name) ;
01360   /* pstrcat(qfname, "/quotas") ; */    /* possibly examine and adjust "name" */
01361 
01362   euser_id = geteuid();
01363   set_effective_uid(0);
01364 
01365   DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
01366   if((file=sys_open(qfname, O_RDONLY,0))<0) {
01367     set_effective_uid(euser_id);
01368     return(False);
01369   }
01370   genbuf.ioc_cmd = VX_QUOTACTL;
01371   genbuf.ioc_up = (void *) &quotabuf;
01372 
01373   quotabuf.cmd = VX_GETQUOTA;
01374   quotabuf.uid = euser_id;
01375   quotabuf.addr = (caddr_t) &D;
01376   ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
01377   close(file);
01378 
01379   set_effective_uid(euser_id);
01380 
01381   if (ret < 0) {
01382     DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
01383     return(False);
01384   }
01385 
01386   /* If softlimit is zero, set it equal to hardlimit.
01387    */
01388 
01389   if (D.dqb_bsoftlimit==0)
01390     D.dqb_bsoftlimit = D.dqb_bhardlimit;
01391 
01392   /* Use softlimit to determine disk space. A user exceeding the quota is told
01393    * that there's no space left. Writes might actually work for a bit if the
01394    * hardlimit is set higher than softlimit. Effectively the disk becomes
01395    * made of rubber latex and begins to expand to accommodate the user :-)
01396    */
01397   DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
01398          path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
01399          D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));
01400 
01401   if (D.dqb_bsoftlimit==0)
01402     return(False);
01403   *bsize = DEV_BSIZE;
01404   *dsize = D.dqb_bsoftlimit;
01405 
01406   if (D.dqb_curblocks > D.dqb_bsoftlimit) {
01407      *dfree = 0;
01408      *dsize = D.dqb_curblocks;
01409   } else
01410     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
01411       
01412   DEBUG(5,("disk_quotas for path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",
01413          path,(double)*bsize,(double)*dfree,(double)*dsize));
01414 
01415   return(True);
01416 }
01417 
01418 #endif /* SUNOS5 || ... */
01419 
01420 #endif /* VXFS_QUOTA */
01421 
01422 #else /* WITH_QUOTAS */
01423 
01424 BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
01425 {
01426   (*bsize) = 512; /* This value should be ignored */
01427 
01428   /* And just to be sure we set some values that hopefully */
01429   /* will be larger that any possible real-world value     */
01430   (*dfree) = (SMB_BIG_UINT)-1;
01431   (*dsize) = (SMB_BIG_UINT)-1;
01432 
01433   /* As we have select not to use quotas, allways fail */
01434   return False;
01435 }
01436 #endif /* WITH_QUOTAS */
01437 
01438 #else /* HAVE_SYS_QUOTAS */
01439 /* wrapper to the new sys_quota interface 
01440    this file should be removed later
01441    */
01442 BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
01443 {
01444         int r;
01445         SMB_DISK_QUOTA D;
01446         unid_t id;
01447 
01448         id.uid = geteuid();
01449 
01450         ZERO_STRUCT(D);
01451         r=sys_get_quota(path, SMB_USER_QUOTA_TYPE, id, &D);
01452 
01453         /* Use softlimit to determine disk space, except when it has been exceeded */
01454         *bsize = D.bsize;
01455         if (r == -1) {
01456                 if (errno == EDQUOT) {
01457                         *dfree =0;
01458                         *dsize =D.curblocks;
01459                         return (True);
01460                 } else {
01461                         goto try_group_quota;
01462                 }
01463         }
01464 
01465         /* Use softlimit to determine disk space, except when it has been exceeded */
01466         if (
01467                 (D.softlimit && D.curblocks >= D.softlimit) ||
01468                 (D.hardlimit && D.curblocks >= D.hardlimit) ||
01469                 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
01470                 (D.ihardlimit && D.curinodes>=D.ihardlimit)
01471         ) {
01472                 *dfree = 0;
01473                 *dsize = D.curblocks;
01474         } else if (D.softlimit==0 && D.hardlimit==0) {
01475                 goto try_group_quota;
01476         } else {
01477                 if (D.softlimit == 0)
01478                         D.softlimit = D.hardlimit;
01479                 *dfree = D.softlimit - D.curblocks;
01480                 *dsize = D.softlimit;
01481         }
01482 
01483         return True;
01484         
01485 try_group_quota:
01486         id.gid = getegid();
01487 
01488         ZERO_STRUCT(D);
01489         r=sys_get_quota(path, SMB_GROUP_QUOTA_TYPE, id, &D);
01490 
01491         /* Use softlimit to determine disk space, except when it has been exceeded */
01492         *bsize = D.bsize;
01493         if (r == -1) {
01494                 if (errno == EDQUOT) {
01495                         *dfree =0;
01496                         *dsize =D.curblocks;
01497                         return (True);
01498                 } else {
01499                         return False;
01500                 }
01501         }
01502 
01503         /* Use softlimit to determine disk space, except when it has been exceeded */
01504         if (
01505                 (D.softlimit && D.curblocks >= D.softlimit) ||
01506                 (D.hardlimit && D.curblocks >= D.hardlimit) ||
01507                 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
01508                 (D.ihardlimit && D.curinodes>=D.ihardlimit)
01509         ) {
01510                 *dfree = 0;
01511                 *dsize = D.curblocks;
01512         } else if (D.softlimit==0 && D.hardlimit==0) {
01513                 return False;
01514         } else {
01515                 if (D.softlimit == 0)
01516                         D.softlimit = D.hardlimit;
01517                 *dfree = D.softlimit - D.curblocks;
01518                 *dsize = D.softlimit;
01519         }
01520 
01521         return (True);
01522 }
01523 #endif /* HAVE_SYS_QUOTAS */

Sambaに対してSat Aug 29 21:23:25 2009に生成されました。  doxygen 1.4.7