2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 * This is one of the most system dependent parts of Samba, and its
25 * done a litle differently. Each system has its own way of doing
31 extern int DEBUGLEVEL;
33 #if defined(VXFS_QUOTA)
36 * In addition to their native filesystems, some systems have Veritas VxFS.
37 * Declare here, define at end: reduces likely "include" interaction problems.
38 * David Lee <T.D.Lee@durham.ac.uk>
40 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
42 #endif /* VXFS_QUOTA */
46 #include <sys/types.h>
47 #include <asm/types.h>
50 * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
51 * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk
52 * rather than the struct dqblk defined in /usr/include/sys/quota.h.
53 * This means we must include linux/quota.h to have a hope of working on
54 * RH7.1 systems. And it also means this breaks if the kernel is upgraded
55 * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until
56 * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA.
59 #include <linux/quota.h>
62 #include <linux/unistd.h>
65 #define LINUX_QUOTAS_2
67 typedef struct _LINUX_SMB_DISK_QUOTA {
69 SMB_BIG_UINT hardlimit; /* In bsize units. */
70 SMB_BIG_UINT softlimit; /* In bsize units. */
71 SMB_BIG_UINT curblocks; /* In bsize units. */
72 SMB_BIG_UINT ihardlimit; /* inode hard limit. */
73 SMB_BIG_UINT isoftlimit; /* inode soft limit. */
74 SMB_BIG_UINT curinodes; /* Current used inodes. */
75 } LINUX_SMB_DISK_QUOTA;
77 /****************************************************************************
78 Abstract out the old and new Linux quota get calls.
79 ****************************************************************************/
81 static int get_smb_linux_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
87 dp->bsize = (SMB_BIG_UINT)1024;
88 #else /* LINUX_QUOTAS_2 */
91 #ifndef QUOTABLOCK_SIZE
92 #define QUOTABLOCK_SIZE 1024
94 dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
97 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D)))
100 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
101 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
102 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
103 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
104 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
106 #ifdef LINUX_QUOTAS_1
107 dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
108 #else /* LINUX_QUOTAS_2 */
109 dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace)/ dp->bsize;
115 /****************************************************************************
116 try to get the disk space from disk quotas (LINUX version)
117 ****************************************************************************/
119 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
124 LINUX_SMB_DISK_QUOTA D;
130 euser_id = geteuid();
132 /* find the block device file */
134 if ( sys_stat(path, &S) == -1 )
139 fp = setmntent(MOUNTED,"r");
142 while ((mnt = getmntent(fp))) {
143 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
146 if (S.st_dev == devno) {
158 set_effective_uid(0);
159 r=get_smb_linux_quota(mnt->mnt_fsname, euser_id, &D);
162 /* Use softlimit to determine disk space, except when it has been exceeded */
165 if (errno == EDQUOT) {
174 /* Use softlimit to determine disk space, except when it has been exceeded */
176 (D.softlimit && D.curblocks >= D.softlimit) ||
177 (D.hardlimit && D.curblocks >= D.hardlimit) ||
178 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
179 (D.ihardlimit && D.curinodes>=D.ihardlimit)
182 *dsize = D.curblocks;
183 } else if (D.softlimit==0 && D.hardlimit==0) {
186 if (D.softlimit == 0)
187 D.softlimit = D.hardlimit;
188 *dfree = D.softlimit - D.curblocks;
189 *dsize = D.softlimit;
197 #include <sys/quota.h>
200 /****************************************************************************
201 try to get the disk space from disk quotas (CRAY VERSION)
202 ****************************************************************************/
204 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
208 SMB_STRUCT_STAT sbuf;
210 static SMB_DEV_T devno_cached = 0 ;
212 struct q_request request ;
213 struct qf_header header ;
214 static int quota_default = 0 ;
217 if ( sys_stat(path,&sbuf) == -1 )
220 devno = sbuf.st_dev ;
222 if ( devno != devno_cached ) {
224 devno_cached = devno ;
226 if ((fd = setmntent(KMTAB)) == NULL)
231 while ((mnt = getmntent(fd)) != NULL) {
233 if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
236 if (sbuf.st_dev == devno) {
245 pstrcpy(name,mnt->mnt_dir) ;
252 request.qf_magic = QF_MAGIC ;
253 request.qf_entry.id = geteuid() ;
255 if (quotactl(name, Q_GETQUOTA, &request) == -1)
258 if ( ! request.user )
261 if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
263 if ( ! quota_default ) {
265 if ( quotactl(name, Q_GETHEADER, &header) == -1 )
268 quota_default = header.user_h.def_fq ;
271 *dfree = quota_default ;
273 }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
279 *dfree = request.qf_entry.user_q.f_quota ;
283 *dsize = request.qf_entry.user_q.f_use ;
285 if ( *dfree < *dsize )
290 *bsize = 4096 ; /* Cray blocksize */
297 #elif defined(SUNOS5) || defined(SUNOS4)
300 #include <sys/param.h>
302 #include <sys/fs/ufs_quota.h>
303 #include <sys/mnttab.h>
304 #include <sys/mntent.h>
305 #else /* defined(SUNOS4) */
306 #include <ufs/quota.h>
312 /****************************************************************************
313 Allows querying of remote hosts for quotas on NFS mounted shares.
314 Supports normal NFS and AMD mounts.
315 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
316 ****************************************************************************/
319 #include <rpc/types.h>
320 #include <rpcsvc/rquota.h>
321 #include <rpc/nettype.h>
324 static int quotastat;
326 static int xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
328 if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
330 if (!xdr_int(xdrsp, &args->gqa_uid))
335 static int xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
337 if (!xdr_int(xdrsp, "astat)) {
338 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
341 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
342 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
345 if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
346 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
349 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
350 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
353 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
354 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
357 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
358 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
364 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
365 static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
367 uid_t uid = euser_id;
369 char *mnttype = nfspath;
371 struct getquota_rslt gqr;
372 struct getquota_args args;
373 char *cutstr, *pathname, *host, *testpath;
375 static struct timeval timeout = {2,0};
376 enum clnt_stat clnt_stat;
379 *bsize = *dfree = *dsize = (SMB_BIG_UINT)0;
381 len=strcspn(mnttype, ":");
382 pathname=strstr(mnttype, ":");
383 cutstr = (char *) malloc(sizeof(char) * len );
387 host = strncat(cutstr,mnttype, sizeof(char) * len );
388 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
389 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
390 testpath=strchr_m(mnttype, ':');
391 args.gqa_pathp = testpath+1;
394 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
396 if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
401 clnt->cl_auth = authunix_create_default();
402 DEBUG(9,("nfs_quotas: auth_success\n"));
404 clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, xdr_getquota_args, (caddr_t)&args, xdr_getquota_rslt, (caddr_t)&gqr, timeout);
406 if (clnt_stat != RPC_SUCCESS) {
407 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
413 * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
414 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
415 * something sensible.
418 switch ( quotastat ) {
420 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat ));
425 DEBUG(9,("nfs_quotas: Good quota data\n"));
426 D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
427 D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
428 D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
433 D.dqb_bsoftlimit = 1;
435 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat ));
439 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", quotastat ));
443 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",
445 gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
446 gqr.getquota_rslt_u.gqr_rquota.rq_active,
447 gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
448 gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
449 gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
451 *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
452 *dsize = D.dqb_bsoftlimit;
454 if (D.dqb_curblocks == D.dqb_curblocks == 1)
457 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
459 *dsize = D.dqb_curblocks;
461 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
467 auth_destroy(clnt->cl_auth);
471 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
474 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
479 /****************************************************************************
480 try to get the disk space from disk quotas (SunOS & Solaris2 version)
481 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
482 ****************************************************************************/
484 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
490 struct quotctl command;
492 static struct mnttab mnt;
500 SMB_STRUCT_STAT sbuf;
502 static SMB_DEV_T devno_cached = 0 ;
505 euser_id = geteuid();
507 if ( sys_stat(path,&sbuf) == -1 )
510 devno = sbuf.st_dev ;
511 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,(unsigned int)devno));
512 if ( devno != devno_cached ) {
513 devno_cached = devno ;
515 if ((fd = sys_fopen(MNTTAB, "r")) == NULL)
519 slprintf(devopt, sizeof(devopt) - 1, "dev=%x", (unsigned int)devno);
520 while (getmntent(fd, &mnt) == 0) {
521 if( !hasmntopt(&mnt, devopt) )
524 DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt));
526 /* quotas are only on vxfs, UFS or NFS */
527 if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
528 strcmp( mnt.mnt_fstype, "nfs" ) == 0 ||
529 strcmp( mnt.mnt_fstype, "vxfs" ) == 0 ) {
535 pstrcpy(name,mnt.mnt_mountp) ;
536 pstrcat(name,"/quotas") ;
539 if ((fd = setmntent(MOUNTED, "r")) == NULL)
543 while ((mnt = getmntent(fd)) != NULL) {
544 if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
546 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt->mnt_dir,(unsigned int)sbuf.st_dev));
547 if (sbuf.st_dev == devno) {
553 pstrcpy(name,mnt->mnt_fsname) ;
562 set_effective_uid(0);
565 if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) {
567 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special));
568 retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize);
573 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
574 if((file=sys_open(name, O_RDONLY,0))<0) {
578 command.op = Q_GETQUOTA;
579 command.uid = euser_id;
580 command.addr = (caddr_t) &D;
581 ret = ioctl(file, Q_QUOTACTL, &command);
584 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
585 ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
591 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) ));
593 #if defined(SUNOS5) && defined(VXFS_QUOTA)
594 /* If normal quotactl() fails, try vxfs private calls */
595 set_effective_uid(euser_id);
596 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
597 if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
599 retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize);
607 /* If softlimit is zero, set it equal to hardlimit.
610 if (D.dqb_bsoftlimit==0)
611 D.dqb_bsoftlimit = D.dqb_bhardlimit;
613 /* Use softlimit to determine disk space. A user exceeding the quota is told
614 * that there's no space left. Writes might actually work for a bit if the
615 * hardlimit is set higher than softlimit. Effectively the disk becomes
616 * made of rubber latex and begins to expand to accommodate the user :-)
619 if (D.dqb_bsoftlimit==0)
622 *dsize = D.dqb_bsoftlimit;
624 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
626 *dsize = D.dqb_curblocks;
628 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
630 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
631 path,(double)*bsize,(double)*dfree,(double)*dsize));
638 #include <ufs/quota.h>
640 /****************************************************************************
641 try to get the disk space from disk quotas - OSF1 version
642 ****************************************************************************/
644 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
652 * This code presumes that OSF1 will only
653 * give out quota info when the real uid
654 * matches the effective uid. JRA.
656 euser_id = geteuid();
658 if (set_re_uid() != 0) return False;
660 r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D);
671 if (save_errno == EDQUOT) /* disk quota exceeded */
674 *dsize = D.dqb_curblocks;
681 /* If softlimit is zero, set it equal to hardlimit.
684 if (D.dqb_bsoftlimit==0)
685 D.dqb_bsoftlimit = D.dqb_bhardlimit;
687 /* Use softlimit to determine disk space, except when it has been exceeded */
689 if (D.dqb_bsoftlimit==0)
692 if ((D.dqb_curblocks>D.dqb_bsoftlimit)) {
694 *dsize = D.dqb_curblocks;
696 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
697 *dsize = D.dqb_bsoftlimit;
702 #elif defined (IRIX6)
703 /****************************************************************************
704 try to get the disk space from disk quotas (IRIX 6.2 version)
705 ****************************************************************************/
707 #include <sys/quota.h>
710 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
715 struct fs_disk_quota F;
722 /* find the block device file */
724 if ( sys_stat(path, &S) == -1 ) {
730 fp = setmntent(MOUNTED,"r");
733 while ((mnt = getmntent(fp))) {
734 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
736 if (S.st_dev == devno) {
749 set_effective_uid(0);
751 /* Use softlimit to determine disk space, except when it has been exceeded */
755 if ( 0 == strcmp ( mnt->mnt_type, "efs" ))
757 r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);
764 /* Use softlimit to determine disk space, except when it has been exceeded */
766 (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
767 (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
768 (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) ||
769 (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit)
773 *dsize = D.dqb_curblocks;
775 else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
781 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
782 *dsize = D.dqb_bsoftlimit;
786 else if ( 0 == strcmp ( mnt->mnt_type, "xfs" ))
788 r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);
795 /* Use softlimit to determine disk space, except when it has been exceeded */
797 (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) ||
798 (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) ||
799 (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) ||
800 (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit)
806 else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0)
812 *dfree = (F.d_blk_softlimit - F.d_bcount);
813 *dsize = F.d_blk_softlimit;
829 #if defined(__FreeBSD__) || defined(__OpenBSD__)
830 #include <ufs/ufs/quota.h>
831 #include <machine/param.h>
833 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
834 #include <jfs/quota.h>
835 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
836 #define dqb_curfiles dqb_curinodes
837 #define dqb_fhardlimit dqb_ihardlimit
838 #define dqb_fsoftlimit dqb_isoftlimit
839 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
840 #include <sys/quota.h>
844 /****************************************************************************
845 try to get the disk space from disk quotas - default version
846 ****************************************************************************/
848 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
853 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__)
856 /* find the block device file */
857 if ((sys_stat(path, &S)<0) ||
858 (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False);
861 euser_id = geteuid();
864 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
866 if (set_re_uid() != 0) return False;
868 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
872 #if defined(__FreeBSD__) || defined(__OpenBSD__)
874 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
878 set_effective_uid(0);
881 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
883 /* As FreeBSD has group quotas, if getting the user
884 quota fails, try getting the group instead. */
886 r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
892 /* AIX has both USER and GROUP quotas:
893 Get the USER quota (ohnielse@fysik.dtu.dk) */
894 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
895 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
896 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
897 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
900 /* Use softlimit to determine disk space, except when it has been exceeded */
901 #if defined(__FreeBSD__) || defined(__OpenBSD__)
903 #else /* !__FreeBSD__ && !__OpenBSD__ */
905 #endif /*!__FreeBSD__ && !__OpenBSD__ */
912 *dsize =D.dqb_curblocks;
918 /* If softlimit is zero, set it equal to hardlimit.
921 if (D.dqb_bsoftlimit==0)
922 D.dqb_bsoftlimit = D.dqb_bhardlimit;
924 if (D.dqb_bsoftlimit==0)
926 /* Use softlimit to determine disk space, except when it has been exceeded */
927 if ((D.dqb_curblocks>D.dqb_bsoftlimit)
928 #if !defined(__FreeBSD__) && !defined(__OpenBSD__)
929 ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
933 *dsize = D.dqb_curblocks;
936 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
937 *dsize = D.dqb_bsoftlimit;
944 #if defined(VXFS_QUOTA)
946 /****************************************************************************
947 Try to get the disk space from Veritas disk quotas.
948 David Lee <T.D.Lee@durham.ac.uk> August 1999.
950 Background assumptions:
951 Potentially under many Operating Systems. Initially Solaris 2.
953 My guess is that Veritas is largely, though not entirely,
954 independent of OS. So I have separated it out.
956 There may be some details. For example, OS-specific "include" files.
958 It is understood that HPUX 10 somehow gets Veritas quotas without
959 any special effort; if so, this routine need not be compiled in.
960 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
963 It is understood that Veritas do not publicly support this ioctl interface.
964 Rather their preference would be for the user (us) to call the native
965 OS and then for the OS itself to call through to the VxFS filesystem.
966 Presumably HPUX 10, see above, does this.
969 Add your OS to "IFLIST" below.
970 Get it to compile successfully:
971 Almost certainly "include"s require attention: see SUNOS5.
972 In the main code above, arrange for it to be called: see SUNOS5.
975 ****************************************************************************/
978 * This "if" is a list of ports:
979 * if defined(OS1) || defined(OS2) || ...
984 #include <sys/fs/vx_solaris.h>
986 #include <sys/fs/vx_machdep.h>
987 #include <sys/fs/vx_layout.h>
988 #include <sys/fs/vx_quota.h>
989 #include <sys/fs/vx_aioctl.h>
990 #include <sys/fs/vx_ioctl.h>
992 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
994 uid_t user_id, euser_id;
997 struct vx_quotctl quotabuf;
998 struct vx_genioctl genbuf;
1003 * "name" may or may not include a trailing "/quotas".
1004 * Arranging consistency of calling here in "quotas.c" may not be easy and
1005 * it might be easier to examine and adjust it here.
1006 * Fortunately, VxFS seems not to mind at present.
1008 pstrcpy(qfname, name) ;
1009 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
1011 euser_id = geteuid();
1012 set_effective_uid(0);
1014 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
1015 if((file=sys_open(qfname, O_RDONLY,0))<0) {
1016 set_effective_uid(euser_id);
1019 genbuf.ioc_cmd = VX_QUOTACTL;
1020 genbuf.ioc_up = (void *) "abuf;
1022 quotabuf.cmd = VX_GETQUOTA;
1023 quotabuf.uid = euser_id;
1024 quotabuf.addr = (caddr_t) &D;
1025 ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
1028 set_effective_uid(euser_id);
1031 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
1035 /* If softlimit is zero, set it equal to hardlimit.
1038 if (D.dqb_bsoftlimit==0)
1039 D.dqb_bsoftlimit = D.dqb_bhardlimit;
1041 /* Use softlimit to determine disk space. A user exceeding the quota is told
1042 * that there's no space left. Writes might actually work for a bit if the
1043 * hardlimit is set higher than softlimit. Effectively the disk becomes
1044 * made of rubber latex and begins to expand to accommodate the user :-)
1046 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
1047 path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
1048 D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));
1050 if (D.dqb_bsoftlimit==0)
1053 *dsize = D.dqb_bsoftlimit;
1055 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
1057 *dsize = D.dqb_curblocks;
1059 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
1061 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
1062 path,(double)*bsize,(double)*dfree,(double)*dsize));
1067 #endif /* SUNOS5 || ... */
1069 #endif /* VXFS_QUOTA */