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 #if defined(VXFS_QUOTA)
34 * In addition to their native filesystems, some systems have Veritas VxFS.
35 * Declare here, define at end: reduces likely "include" interaction problems.
36 * David Lee <T.D.Lee@durham.ac.uk>
38 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
40 #endif /* VXFS_QUOTA */
44 #include <sys/types.h>
45 #include <asm/types.h>
48 * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
49 * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk
50 * rather than the struct dqblk defined in /usr/include/sys/quota.h.
51 * This means we must include linux/quota.h to have a hope of working on
52 * RH7.1 systems. And it also means this breaks if the kernel is upgraded
53 * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until
54 * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA.
57 #include <linux/quota.h>
60 #include <linux/unistd.h>
63 #define LINUX_QUOTAS_2
65 typedef struct _LINUX_SMB_DISK_QUOTA {
67 SMB_BIG_UINT hardlimit; /* In bsize units. */
68 SMB_BIG_UINT softlimit; /* In bsize units. */
69 SMB_BIG_UINT curblocks; /* In bsize units. */
70 SMB_BIG_UINT ihardlimit; /* inode hard limit. */
71 SMB_BIG_UINT isoftlimit; /* inode soft limit. */
72 SMB_BIG_UINT curinodes; /* Current used inodes. */
73 } LINUX_SMB_DISK_QUOTA;
75 /****************************************************************************
76 Abstract out the old and new Linux quota get calls.
77 ****************************************************************************/
79 static int get_smb_linux_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
85 dp->bsize = (SMB_BIG_UINT)1024;
86 #else /* LINUX_QUOTAS_2 */
89 #ifndef QUOTABLOCK_SIZE
90 #define QUOTABLOCK_SIZE 1024
92 dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
95 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D)))
98 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
99 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
100 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
101 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
102 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
104 #ifdef LINUX_QUOTAS_1
105 dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
106 #else /* LINUX_QUOTAS_2 */
107 dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace)/ dp->bsize;
113 /****************************************************************************
114 try to get the disk space from disk quotas (LINUX version)
115 ****************************************************************************/
117 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
122 LINUX_SMB_DISK_QUOTA D;
128 euser_id = geteuid();
130 /* find the block device file */
132 if ( sys_stat(path, &S) == -1 )
137 fp = setmntent(MOUNTED,"r");
140 while ((mnt = getmntent(fp))) {
141 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
144 if (S.st_dev == devno) {
156 set_effective_uid(0);
157 r=get_smb_linux_quota(mnt->mnt_fsname, euser_id, &D);
160 /* Use softlimit to determine disk space, except when it has been exceeded */
163 if (errno == EDQUOT) {
172 /* Use softlimit to determine disk space, except when it has been exceeded */
174 (D.softlimit && D.curblocks >= D.softlimit) ||
175 (D.hardlimit && D.curblocks >= D.hardlimit) ||
176 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
177 (D.ihardlimit && D.curinodes>=D.ihardlimit)
180 *dsize = D.curblocks;
181 } else if (D.softlimit==0 && D.hardlimit==0) {
184 if (D.softlimit == 0)
185 D.softlimit = D.hardlimit;
186 *dfree = D.softlimit - D.curblocks;
187 *dsize = D.softlimit;
195 #include <sys/quota.h>
198 /****************************************************************************
199 try to get the disk space from disk quotas (CRAY VERSION)
200 ****************************************************************************/
202 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
206 SMB_STRUCT_STAT sbuf;
208 static SMB_DEV_T devno_cached = 0 ;
210 struct q_request request ;
211 struct qf_header header ;
212 static int quota_default = 0 ;
215 if ( sys_stat(path,&sbuf) == -1 )
218 devno = sbuf.st_dev ;
220 if ( devno != devno_cached ) {
222 devno_cached = devno ;
224 if ((fd = setmntent(KMTAB)) == NULL)
229 while ((mnt = getmntent(fd)) != NULL) {
231 if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
234 if (sbuf.st_dev == devno) {
243 pstrcpy(name,mnt->mnt_dir) ;
250 request.qf_magic = QF_MAGIC ;
251 request.qf_entry.id = geteuid() ;
253 if (quotactl(name, Q_GETQUOTA, &request) == -1)
256 if ( ! request.user )
259 if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
261 if ( ! quota_default ) {
263 if ( quotactl(name, Q_GETHEADER, &header) == -1 )
266 quota_default = header.user_h.def_fq ;
269 *dfree = quota_default ;
271 }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
277 *dfree = request.qf_entry.user_q.f_quota ;
281 *dsize = request.qf_entry.user_q.f_use ;
283 if ( *dfree < *dsize )
288 *bsize = 4096 ; /* Cray blocksize */
295 #elif defined(SUNOS5) || defined(SUNOS4)
298 #include <sys/param.h>
300 #include <sys/fs/ufs_quota.h>
301 #include <sys/mnttab.h>
302 #include <sys/mntent.h>
303 #else /* defined(SUNOS4) */
304 #include <ufs/quota.h>
310 /****************************************************************************
311 Allows querying of remote hosts for quotas on NFS mounted shares.
312 Supports normal NFS and AMD mounts.
313 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
314 ****************************************************************************/
317 #include <rpc/types.h>
318 #include <rpcsvc/rquota.h>
319 #include <rpc/nettype.h>
322 static int quotastat;
324 static int xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
326 if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
328 if (!xdr_int(xdrsp, &args->gqa_uid))
333 static int xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
335 if (!xdr_int(xdrsp, "astat)) {
336 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
339 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
340 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
343 if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
344 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
347 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
348 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
351 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
352 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
355 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
356 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
362 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
363 static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
365 uid_t uid = euser_id;
367 char *mnttype = nfspath;
369 struct getquota_rslt gqr;
370 struct getquota_args args;
371 char *cutstr, *pathname, *host, *testpath;
373 static struct timeval timeout = {2,0};
374 enum clnt_stat clnt_stat;
377 *bsize = *dfree = *dsize = (SMB_BIG_UINT)0;
379 len=strcspn(mnttype, ":");
380 pathname=strstr(mnttype, ":");
381 cutstr = (char *) malloc(sizeof(char) * len );
385 host = strncat(cutstr,mnttype, sizeof(char) * len );
386 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
387 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
388 testpath=strchr_m(mnttype, ':');
389 args.gqa_pathp = testpath+1;
392 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
394 if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
399 clnt->cl_auth = authunix_create_default();
400 DEBUG(9,("nfs_quotas: auth_success\n"));
402 clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, xdr_getquota_args, (caddr_t)&args, xdr_getquota_rslt, (caddr_t)&gqr, timeout);
404 if (clnt_stat != RPC_SUCCESS) {
405 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
411 * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
412 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
413 * something sensible.
416 switch ( quotastat ) {
418 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat ));
423 DEBUG(9,("nfs_quotas: Good quota data\n"));
424 D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
425 D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
426 D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
431 D.dqb_bsoftlimit = 1;
433 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat ));
437 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", quotastat ));
441 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",
443 gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
444 gqr.getquota_rslt_u.gqr_rquota.rq_active,
445 gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
446 gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
447 gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
449 *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
450 *dsize = D.dqb_bsoftlimit;
452 if (D.dqb_curblocks == D.dqb_curblocks == 1)
455 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
457 *dsize = D.dqb_curblocks;
459 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
465 auth_destroy(clnt->cl_auth);
469 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
472 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
477 /****************************************************************************
478 try to get the disk space from disk quotas (SunOS & Solaris2 version)
479 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
480 ****************************************************************************/
482 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
488 struct quotctl command;
490 static struct mnttab mnt;
498 SMB_STRUCT_STAT sbuf;
500 static SMB_DEV_T devno_cached = 0 ;
503 euser_id = geteuid();
505 if ( sys_stat(path,&sbuf) == -1 )
508 devno = sbuf.st_dev ;
509 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,(unsigned int)devno));
510 if ( devno != devno_cached ) {
511 devno_cached = devno ;
513 if ((fd = sys_fopen(MNTTAB, "r")) == NULL)
517 slprintf(devopt, sizeof(devopt) - 1, "dev=%x", (unsigned int)devno);
518 while (getmntent(fd, &mnt) == 0) {
519 if( !hasmntopt(&mnt, devopt) )
522 DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt));
524 /* quotas are only on vxfs, UFS or NFS */
525 if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
526 strcmp( mnt.mnt_fstype, "nfs" ) == 0 ||
527 strcmp( mnt.mnt_fstype, "vxfs" ) == 0 ) {
533 pstrcpy(name,mnt.mnt_mountp) ;
534 pstrcat(name,"/quotas") ;
537 if ((fd = setmntent(MOUNTED, "r")) == NULL)
541 while ((mnt = getmntent(fd)) != NULL) {
542 if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
544 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt->mnt_dir,(unsigned int)sbuf.st_dev));
545 if (sbuf.st_dev == devno) {
551 pstrcpy(name,mnt->mnt_fsname) ;
560 set_effective_uid(0);
563 if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) {
565 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special));
566 retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize);
571 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
572 if((file=sys_open(name, O_RDONLY,0))<0) {
576 command.op = Q_GETQUOTA;
577 command.uid = euser_id;
578 command.addr = (caddr_t) &D;
579 ret = ioctl(file, Q_QUOTACTL, &command);
582 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
583 ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
589 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) ));
591 #if defined(SUNOS5) && defined(VXFS_QUOTA)
592 /* If normal quotactl() fails, try vxfs private calls */
593 set_effective_uid(euser_id);
594 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
595 if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
597 retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize);
605 /* If softlimit is zero, set it equal to hardlimit.
608 if (D.dqb_bsoftlimit==0)
609 D.dqb_bsoftlimit = D.dqb_bhardlimit;
611 /* Use softlimit to determine disk space. A user exceeding the quota is told
612 * that there's no space left. Writes might actually work for a bit if the
613 * hardlimit is set higher than softlimit. Effectively the disk becomes
614 * made of rubber latex and begins to expand to accommodate the user :-)
617 if (D.dqb_bsoftlimit==0)
620 *dsize = D.dqb_bsoftlimit;
622 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
624 *dsize = D.dqb_curblocks;
626 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
628 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
629 path,(double)*bsize,(double)*dfree,(double)*dsize));
636 #include <ufs/quota.h>
638 /****************************************************************************
639 try to get the disk space from disk quotas - OSF1 version
640 ****************************************************************************/
642 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
650 * This code presumes that OSF1 will only
651 * give out quota info when the real uid
652 * matches the effective uid. JRA.
654 euser_id = geteuid();
656 if (set_re_uid() != 0) return False;
658 r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D);
669 if (save_errno == EDQUOT) /* disk quota exceeded */
672 *dsize = D.dqb_curblocks;
679 /* If softlimit is zero, set it equal to hardlimit.
682 if (D.dqb_bsoftlimit==0)
683 D.dqb_bsoftlimit = D.dqb_bhardlimit;
685 /* Use softlimit to determine disk space, except when it has been exceeded */
687 if (D.dqb_bsoftlimit==0)
690 if ((D.dqb_curblocks>D.dqb_bsoftlimit)) {
692 *dsize = D.dqb_curblocks;
694 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
695 *dsize = D.dqb_bsoftlimit;
700 #elif defined (IRIX6)
701 /****************************************************************************
702 try to get the disk space from disk quotas (IRIX 6.2 version)
703 ****************************************************************************/
705 #include <sys/quota.h>
708 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
713 struct fs_disk_quota F;
720 /* find the block device file */
722 if ( sys_stat(path, &S) == -1 ) {
728 fp = setmntent(MOUNTED,"r");
731 while ((mnt = getmntent(fp))) {
732 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
734 if (S.st_dev == devno) {
747 set_effective_uid(0);
749 /* Use softlimit to determine disk space, except when it has been exceeded */
753 if ( 0 == strcmp ( mnt->mnt_type, "efs" ))
755 r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);
762 /* Use softlimit to determine disk space, except when it has been exceeded */
764 (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
765 (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
766 (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) ||
767 (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit)
771 *dsize = D.dqb_curblocks;
773 else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
779 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
780 *dsize = D.dqb_bsoftlimit;
784 else if ( 0 == strcmp ( mnt->mnt_type, "xfs" ))
786 r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);
793 /* Use softlimit to determine disk space, except when it has been exceeded */
795 (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) ||
796 (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) ||
797 (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) ||
798 (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit)
804 else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0)
810 *dfree = (F.d_blk_softlimit - F.d_bcount);
811 *dsize = F.d_blk_softlimit;
827 #if defined(__FreeBSD__) || defined(__OpenBSD__)
828 #include <ufs/ufs/quota.h>
829 #include <machine/param.h>
831 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
832 #include <jfs/quota.h>
833 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
834 #define dqb_curfiles dqb_curinodes
835 #define dqb_fhardlimit dqb_ihardlimit
836 #define dqb_fsoftlimit dqb_isoftlimit
837 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
838 #include <sys/quota.h>
842 /****************************************************************************
843 try to get the disk space from disk quotas - default version
844 ****************************************************************************/
846 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
851 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__)
854 /* find the block device file */
855 if ((sys_stat(path, &S)<0) ||
856 (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False);
859 euser_id = geteuid();
862 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
864 if (set_re_uid() != 0) return False;
866 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
870 #if defined(__FreeBSD__) || defined(__OpenBSD__)
872 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
876 set_effective_uid(0);
879 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
881 /* As FreeBSD has group quotas, if getting the user
882 quota fails, try getting the group instead. */
884 r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
890 /* AIX has both USER and GROUP quotas:
891 Get the USER quota (ohnielse@fysik.dtu.dk) */
892 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
893 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
894 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
895 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
898 /* Use softlimit to determine disk space, except when it has been exceeded */
899 #if defined(__FreeBSD__) || defined(__OpenBSD__)
901 #else /* !__FreeBSD__ && !__OpenBSD__ */
903 #endif /*!__FreeBSD__ && !__OpenBSD__ */
910 *dsize =D.dqb_curblocks;
916 /* If softlimit is zero, set it equal to hardlimit.
919 if (D.dqb_bsoftlimit==0)
920 D.dqb_bsoftlimit = D.dqb_bhardlimit;
922 if (D.dqb_bsoftlimit==0)
924 /* Use softlimit to determine disk space, except when it has been exceeded */
925 if ((D.dqb_curblocks>D.dqb_bsoftlimit)
926 #if !defined(__FreeBSD__) && !defined(__OpenBSD__)
927 ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
931 *dsize = D.dqb_curblocks;
934 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
935 *dsize = D.dqb_bsoftlimit;
942 #if defined(VXFS_QUOTA)
944 /****************************************************************************
945 Try to get the disk space from Veritas disk quotas.
946 David Lee <T.D.Lee@durham.ac.uk> August 1999.
948 Background assumptions:
949 Potentially under many Operating Systems. Initially Solaris 2.
951 My guess is that Veritas is largely, though not entirely,
952 independent of OS. So I have separated it out.
954 There may be some details. For example, OS-specific "include" files.
956 It is understood that HPUX 10 somehow gets Veritas quotas without
957 any special effort; if so, this routine need not be compiled in.
958 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
961 It is understood that Veritas do not publicly support this ioctl interface.
962 Rather their preference would be for the user (us) to call the native
963 OS and then for the OS itself to call through to the VxFS filesystem.
964 Presumably HPUX 10, see above, does this.
967 Add your OS to "IFLIST" below.
968 Get it to compile successfully:
969 Almost certainly "include"s require attention: see SUNOS5.
970 In the main code above, arrange for it to be called: see SUNOS5.
973 ****************************************************************************/
976 * This "if" is a list of ports:
977 * if defined(OS1) || defined(OS2) || ...
982 #include <sys/fs/vx_solaris.h>
984 #include <sys/fs/vx_machdep.h>
985 #include <sys/fs/vx_layout.h>
986 #include <sys/fs/vx_quota.h>
987 #include <sys/fs/vx_aioctl.h>
988 #include <sys/fs/vx_ioctl.h>
990 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
992 uid_t user_id, euser_id;
995 struct vx_quotctl quotabuf;
996 struct vx_genioctl genbuf;
1001 * "name" may or may not include a trailing "/quotas".
1002 * Arranging consistency of calling here in "quotas.c" may not be easy and
1003 * it might be easier to examine and adjust it here.
1004 * Fortunately, VxFS seems not to mind at present.
1006 pstrcpy(qfname, name) ;
1007 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
1009 euser_id = geteuid();
1010 set_effective_uid(0);
1012 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
1013 if((file=sys_open(qfname, O_RDONLY,0))<0) {
1014 set_effective_uid(euser_id);
1017 genbuf.ioc_cmd = VX_QUOTACTL;
1018 genbuf.ioc_up = (void *) "abuf;
1020 quotabuf.cmd = VX_GETQUOTA;
1021 quotabuf.uid = euser_id;
1022 quotabuf.addr = (caddr_t) &D;
1023 ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
1026 set_effective_uid(euser_id);
1029 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
1033 /* If softlimit is zero, set it equal to hardlimit.
1036 if (D.dqb_bsoftlimit==0)
1037 D.dqb_bsoftlimit = D.dqb_bhardlimit;
1039 /* Use softlimit to determine disk space. A user exceeding the quota is told
1040 * that there's no space left. Writes might actually work for a bit if the
1041 * hardlimit is set higher than softlimit. Effectively the disk becomes
1042 * made of rubber latex and begins to expand to accommodate the user :-)
1044 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
1045 path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
1046 D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));
1048 if (D.dqb_bsoftlimit==0)
1051 *dsize = D.dqb_bsoftlimit;
1053 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
1055 *dsize = D.dqb_curblocks;
1057 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
1059 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
1060 path,(double)*bsize,(double)*dfree,(double)*dsize));
1065 #endif /* SUNOS5 || ... */
1067 #endif /* VXFS_QUOTA */