2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * This is one of the most system dependent parts of Samba, and its
24 * done a litle differently. Each system has its own way of doing
30 #if defined(VXFS_QUOTA)
33 * In addition to their native filesystems, some systems have Veritas VxFS.
34 * Declare here, define at end: reduces likely "include" interaction problems.
35 * David Lee <T.D.Lee@durham.ac.uk>
37 BOOL
disk_quotas_vxfs(const pstring name
, char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
);
39 #endif /* VXFS_QUOTA */
43 #include <sys/types.h>
44 #include <asm/types.h>
47 * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
48 * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk
49 * rather than the struct dqblk defined in /usr/include/sys/quota.h.
50 * This means we must include linux/quota.h to have a hope of working on
51 * RH7.1 systems. And it also means this breaks if the kernel is upgraded
52 * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until
53 * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA.
56 #include <linux/quota.h>
57 #ifdef HAVE_LINUX_XQM_H
58 #include <linux/xqm.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 XFS Quota Manager quota get call.
79 ****************************************************************************/
81 static int get_smb_linux_xfs_quota(char *path
, uid_t euser_id
, LINUX_SMB_DISK_QUOTA
*dp
)
84 #ifdef HAVE_LINUX_XQM_H
85 struct fs_disk_quota D
;
88 if ((ret
= quotactl(QCMD(Q_XGETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
)))
91 dp
->bsize
= (SMB_BIG_UINT
)512;
92 dp
->softlimit
= (SMB_BIG_UINT
)D
.d_blk_softlimit
;
93 dp
->hardlimit
= (SMB_BIG_UINT
)D
.d_blk_hardlimit
;
94 dp
->ihardlimit
= (SMB_BIG_UINT
)D
.d_ino_hardlimit
;
95 dp
->isoftlimit
= (SMB_BIG_UINT
)D
.d_ino_softlimit
;
96 dp
->curinodes
= (SMB_BIG_UINT
)D
.d_icount
;
97 dp
->curblocks
= (SMB_BIG_UINT
)D
.d_bcount
;
102 /****************************************************************************
103 Abstract out the old and new Linux quota get calls.
104 ****************************************************************************/
106 static int get_smb_linux_vfs_quota(char *path
, uid_t euser_id
, LINUX_SMB_DISK_QUOTA
*dp
)
109 #ifdef LINUX_QUOTAS_1
112 dp
->bsize
= (SMB_BIG_UINT
)1024;
113 #else /* LINUX_QUOTAS_2 */
116 #ifndef QUOTABLOCK_SIZE
117 #define QUOTABLOCK_SIZE 1024
119 dp
->bsize
= (SMB_BIG_UINT
)QUOTABLOCK_SIZE
;
122 if ((ret
= quotactl(QCMD(Q_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
)))
125 dp
->softlimit
= (SMB_BIG_UINT
)D
.dqb_bsoftlimit
;
126 dp
->hardlimit
= (SMB_BIG_UINT
)D
.dqb_bhardlimit
;
127 dp
->ihardlimit
= (SMB_BIG_UINT
)D
.dqb_ihardlimit
;
128 dp
->isoftlimit
= (SMB_BIG_UINT
)D
.dqb_isoftlimit
;
129 dp
->curinodes
= (SMB_BIG_UINT
)D
.dqb_curinodes
;
131 #ifdef LINUX_QUOTAS_1
132 dp
->curblocks
= (SMB_BIG_UINT
)D
.dqb_curblocks
;
133 #else /* LINUX_QUOTAS_2 */
134 dp
->curblocks
= ((SMB_BIG_UINT
)D
.dqb_curspace
)/ dp
->bsize
;
140 /****************************************************************************
141 try to get the disk space from disk quotas (LINUX version)
142 ****************************************************************************/
144 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
149 LINUX_SMB_DISK_QUOTA D
;
155 euser_id
= geteuid();
157 /* find the block device file */
159 if ( sys_stat(path
, &S
) == -1 )
164 fp
= setmntent(MOUNTED
,"r");
167 while ((mnt
= getmntent(fp
))) {
168 if ( sys_stat(mnt
->mnt_dir
,&S
) == -1 )
171 if (S
.st_dev
== devno
) {
183 set_effective_uid(0);
184 if (strcmp(mnt
->mnt_type
, "xfs") == 0)
185 r
=get_smb_linux_xfs_quota(mnt
->mnt_fsname
, euser_id
, &D
);
187 r
=get_smb_linux_vfs_quota(mnt
->mnt_fsname
, euser_id
, &D
);
190 /* Use softlimit to determine disk space, except when it has been exceeded */
193 if (errno
== EDQUOT
) {
202 /* Use softlimit to determine disk space, except when it has been exceeded */
204 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
205 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
206 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
207 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
210 *dsize
= D
.curblocks
;
211 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
214 if (D
.softlimit
== 0)
215 D
.softlimit
= D
.hardlimit
;
216 *dfree
= D
.softlimit
- D
.curblocks
;
217 *dsize
= D
.softlimit
;
225 #include <sys/quota.h>
228 /****************************************************************************
229 try to get the disk space from disk quotas (CRAY VERSION)
230 ****************************************************************************/
232 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
236 SMB_STRUCT_STAT sbuf
;
238 static SMB_DEV_T devno_cached
= 0 ;
240 struct q_request request
;
241 struct qf_header header
;
242 static int quota_default
= 0 ;
245 if ( sys_stat(path
,&sbuf
) == -1 )
248 devno
= sbuf
.st_dev
;
250 if ( devno
!= devno_cached
) {
252 devno_cached
= devno
;
254 if ((fd
= setmntent(KMTAB
)) == NULL
)
259 while ((mnt
= getmntent(fd
)) != NULL
) {
261 if ( sys_stat(mnt
->mnt_dir
,&sbuf
) == -1 )
264 if (sbuf
.st_dev
== devno
) {
273 pstrcpy(name
,mnt
->mnt_dir
) ;
280 request
.qf_magic
= QF_MAGIC
;
281 request
.qf_entry
.id
= geteuid() ;
283 if (quotactl(name
, Q_GETQUOTA
, &request
) == -1)
286 if ( ! request
.user
)
289 if ( request
.qf_entry
.user_q
.f_quota
== QFV_DEFAULT
) {
291 if ( ! quota_default
) {
293 if ( quotactl(name
, Q_GETHEADER
, &header
) == -1 )
296 quota_default
= header
.user_h
.def_fq
;
299 *dfree
= quota_default
;
301 }else if ( request
.qf_entry
.user_q
.f_quota
== QFV_PREVENT
) {
307 *dfree
= request
.qf_entry
.user_q
.f_quota
;
311 *dsize
= request
.qf_entry
.user_q
.f_use
;
313 if ( *dfree
< *dsize
)
318 *bsize
= 4096 ; /* Cray blocksize */
325 #elif defined(SUNOS5) || defined(SUNOS4)
328 #include <sys/param.h>
330 #include <sys/fs/ufs_quota.h>
331 #include <sys/mnttab.h>
332 #include <sys/mntent.h>
333 #else /* defined(SUNOS4) */
334 #include <ufs/quota.h>
340 /****************************************************************************
341 Allows querying of remote hosts for quotas on NFS mounted shares.
342 Supports normal NFS and AMD mounts.
343 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
344 ****************************************************************************/
347 #include <rpc/types.h>
348 #include <rpcsvc/rquota.h>
349 #include <rpc/nettype.h>
352 static int quotastat
;
354 static int xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
356 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
358 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
363 static int xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
365 if (!xdr_int(xdrsp
, "astat
)) {
366 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
369 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
370 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
373 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
374 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
377 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
378 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
381 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
382 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
385 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
386 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
392 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
393 static BOOL
nfs_quotas(char *nfspath
, uid_t euser_id
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
395 uid_t uid
= euser_id
;
397 char *mnttype
= nfspath
;
399 struct getquota_rslt gqr
;
400 struct getquota_args args
;
401 char *cutstr
, *pathname
, *host
, *testpath
;
403 static struct timeval timeout
= {2,0};
404 enum clnt_stat clnt_stat
;
407 *bsize
= *dfree
= *dsize
= (SMB_BIG_UINT
)0;
409 len
=strcspn(mnttype
, ":");
410 pathname
=strstr(mnttype
, ":");
411 cutstr
= (char *) malloc(sizeof(char) * len
);
415 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
416 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
417 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
418 testpath
=strchr_m(mnttype
, ':');
419 args
.gqa_pathp
= testpath
+1;
422 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
, "udp"));
424 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
429 clnt
->cl_auth
= authunix_create_default();
430 DEBUG(9,("nfs_quotas: auth_success\n"));
432 clnt_stat
=clnt_call(clnt
, RQUOTAPROC_GETQUOTA
, xdr_getquota_args
, (caddr_t
)&args
, xdr_getquota_rslt
, (caddr_t
)&gqr
, timeout
);
434 if (clnt_stat
!= RPC_SUCCESS
) {
435 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
441 * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
442 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
443 * something sensible.
446 switch ( quotastat
) {
448 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat
));
453 DEBUG(9,("nfs_quotas: Good quota data\n"));
454 D
.dqb_bsoftlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
455 D
.dqb_bhardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
456 D
.dqb_curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
461 D
.dqb_bsoftlimit
= 1;
463 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat
));
467 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", quotastat
));
471 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",
473 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
474 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
475 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
476 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
477 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
479 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
480 *dsize
= D
.dqb_bsoftlimit
;
482 if (D
.dqb_curblocks
== D
.dqb_curblocks
== 1)
485 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
487 *dsize
= D
.dqb_curblocks
;
489 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
495 auth_destroy(clnt
->cl_auth
);
499 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args
.gqa_pathp
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
502 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
507 /****************************************************************************
508 try to get the disk space from disk quotas (SunOS & Solaris2 version)
509 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
510 ****************************************************************************/
512 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
518 struct quotctl command
;
520 static struct mnttab mnt
;
528 SMB_STRUCT_STAT sbuf
;
530 static SMB_DEV_T devno_cached
= 0 ;
533 euser_id
= geteuid();
535 if ( sys_stat(path
,&sbuf
) == -1 )
538 devno
= sbuf
.st_dev
;
539 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path
,(unsigned int)devno
));
540 if ( devno
!= devno_cached
) {
541 devno_cached
= devno
;
543 if ((fd
= sys_fopen(MNTTAB
, "r")) == NULL
)
547 slprintf(devopt
, sizeof(devopt
) - 1, "dev=%x", (unsigned int)devno
);
548 while (getmntent(fd
, &mnt
) == 0) {
549 if( !hasmntopt(&mnt
, devopt
) )
552 DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt
.mnt_mountp
,devopt
));
554 /* quotas are only on vxfs, UFS or NFS */
555 if ( strcmp( mnt
.mnt_fstype
, MNTTYPE_UFS
) == 0 ||
556 strcmp( mnt
.mnt_fstype
, "nfs" ) == 0 ||
557 strcmp( mnt
.mnt_fstype
, "vxfs" ) == 0 ) {
563 pstrcpy(name
,mnt
.mnt_mountp
) ;
564 pstrcat(name
,"/quotas") ;
567 if ((fd
= setmntent(MOUNTED
, "r")) == NULL
)
571 while ((mnt
= getmntent(fd
)) != NULL
) {
572 if ( sys_stat(mnt
->mnt_dir
,&sbuf
) == -1 )
574 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt
->mnt_dir
,(unsigned int)sbuf
.st_dev
));
575 if (sbuf
.st_dev
== devno
) {
581 pstrcpy(name
,mnt
->mnt_fsname
) ;
590 set_effective_uid(0);
593 if ( strcmp( mnt
.mnt_fstype
, "nfs" ) == 0) {
595 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt
.mnt_special
));
596 retval
= nfs_quotas(mnt
.mnt_special
, euser_id
, bsize
, dfree
, dsize
);
601 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name
));
602 if((file
=sys_open(name
, O_RDONLY
,0))<0) {
606 command
.op
= Q_GETQUOTA
;
607 command
.uid
= euser_id
;
608 command
.addr
= (caddr_t
) &D
;
609 ret
= ioctl(file
, Q_QUOTACTL
, &command
);
612 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name
));
613 ret
= quotactl(Q_GETQUOTA
, name
, euser_id
, &D
);
619 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno
) ));
621 #if defined(SUNOS5) && defined(VXFS_QUOTA)
622 /* If normal quotactl() fails, try vxfs private calls */
623 set_effective_uid(euser_id
);
624 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt
.mnt_fstype
));
625 if ( 0 == strcmp ( mnt
.mnt_fstype
, "vxfs" )) {
627 retval
= disk_quotas_vxfs(name
, path
, bsize
, dfree
, dsize
);
635 /* If softlimit is zero, set it equal to hardlimit.
638 if (D
.dqb_bsoftlimit
==0)
639 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
641 /* Use softlimit to determine disk space. A user exceeding the quota is told
642 * that there's no space left. Writes might actually work for a bit if the
643 * hardlimit is set higher than softlimit. Effectively the disk becomes
644 * made of rubber latex and begins to expand to accommodate the user :-)
647 if (D
.dqb_bsoftlimit
==0)
650 *dsize
= D
.dqb_bsoftlimit
;
652 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
654 *dsize
= D
.dqb_curblocks
;
656 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
658 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
659 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
666 #include <ufs/quota.h>
668 /****************************************************************************
669 try to get the disk space from disk quotas - OSF1 version
670 ****************************************************************************/
672 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
680 * This code presumes that OSF1 will only
681 * give out quota info when the real uid
682 * matches the effective uid. JRA.
684 euser_id
= geteuid();
686 if (set_re_uid() != 0) return False
;
688 r
= quotactl(path
,QCMD(Q_GETQUOTA
, USRQUOTA
),euser_id
,(char *) &D
);
699 if (save_errno
== EDQUOT
) /* disk quota exceeded */
702 *dsize
= D
.dqb_curblocks
;
709 /* If softlimit is zero, set it equal to hardlimit.
712 if (D
.dqb_bsoftlimit
==0)
713 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
715 /* Use softlimit to determine disk space, except when it has been exceeded */
717 if (D
.dqb_bsoftlimit
==0)
720 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)) {
722 *dsize
= D
.dqb_curblocks
;
724 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
725 *dsize
= D
.dqb_bsoftlimit
;
730 #elif defined (IRIX6)
731 /****************************************************************************
732 try to get the disk space from disk quotas (IRIX 6.2 version)
733 ****************************************************************************/
735 #include <sys/quota.h>
738 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
743 struct fs_disk_quota F
;
750 /* find the block device file */
752 if ( sys_stat(path
, &S
) == -1 ) {
758 fp
= setmntent(MOUNTED
,"r");
761 while ((mnt
= getmntent(fp
))) {
762 if ( sys_stat(mnt
->mnt_dir
,&S
) == -1 )
764 if (S
.st_dev
== devno
) {
777 set_effective_uid(0);
779 /* Use softlimit to determine disk space, except when it has been exceeded */
783 if ( 0 == strcmp ( mnt
->mnt_type
, "efs" ))
785 r
=quotactl (Q_GETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &D
);
792 /* Use softlimit to determine disk space, except when it has been exceeded */
794 (D
.dqb_bsoftlimit
&& D
.dqb_curblocks
>=D
.dqb_bsoftlimit
) ||
795 (D
.dqb_bhardlimit
&& D
.dqb_curblocks
>=D
.dqb_bhardlimit
) ||
796 (D
.dqb_fsoftlimit
&& D
.dqb_curfiles
>=D
.dqb_fsoftlimit
) ||
797 (D
.dqb_fhardlimit
&& D
.dqb_curfiles
>=D
.dqb_fhardlimit
)
801 *dsize
= D
.dqb_curblocks
;
803 else if (D
.dqb_bsoftlimit
==0 && D
.dqb_bhardlimit
==0)
809 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
810 *dsize
= D
.dqb_bsoftlimit
;
814 else if ( 0 == strcmp ( mnt
->mnt_type
, "xfs" ))
816 r
=quotactl (Q_XGETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &F
);
823 /* Use softlimit to determine disk space, except when it has been exceeded */
825 (F
.d_blk_softlimit
&& F
.d_bcount
>=F
.d_blk_softlimit
) ||
826 (F
.d_blk_hardlimit
&& F
.d_bcount
>=F
.d_blk_hardlimit
) ||
827 (F
.d_ino_softlimit
&& F
.d_icount
>=F
.d_ino_softlimit
) ||
828 (F
.d_ino_hardlimit
&& F
.d_icount
>=F
.d_ino_hardlimit
)
834 else if (F
.d_blk_softlimit
==0 && F
.d_blk_hardlimit
==0)
840 *dfree
= (F
.d_blk_softlimit
- F
.d_bcount
);
841 *dsize
= F
.d_blk_softlimit
;
857 #if defined(__FreeBSD__) || defined(__OpenBSD__)
858 #include <ufs/ufs/quota.h>
859 #include <machine/param.h>
861 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
862 #include <jfs/quota.h>
863 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
864 #define dqb_curfiles dqb_curinodes
865 #define dqb_fhardlimit dqb_ihardlimit
866 #define dqb_fsoftlimit dqb_isoftlimit
867 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
868 #include <sys/quota.h>
872 /****************************************************************************
873 try to get the disk space from disk quotas - default version
874 ****************************************************************************/
876 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
881 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__)
884 /* find the block device file */
885 if ((sys_stat(path
, &S
)<0) ||
886 (devnm(S_IFBLK
, S
.st_dev
, dev_disk
, 256, 0)<0)) return (False
);
889 euser_id
= geteuid();
892 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
894 if (set_re_uid() != 0) return False
;
896 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
900 #if defined(__FreeBSD__) || defined(__OpenBSD__)
902 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
906 set_effective_uid(0);
909 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
911 /* As FreeBSD has group quotas, if getting the user
912 quota fails, try getting the group instead. */
914 r
= quotactl(path
,QCMD(Q_GETQUOTA
,GRPQUOTA
),egrp_id
,(char *) &D
);
920 /* AIX has both USER and GROUP quotas:
921 Get the USER quota (ohnielse@fysik.dtu.dk) */
922 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
923 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
924 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
925 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
928 /* Use softlimit to determine disk space, except when it has been exceeded */
929 #if defined(__FreeBSD__) || defined(__OpenBSD__)
931 #else /* !__FreeBSD__ && !__OpenBSD__ */
933 #endif /*!__FreeBSD__ && !__OpenBSD__ */
940 *dsize
=D
.dqb_curblocks
;
946 /* If softlimit is zero, set it equal to hardlimit.
949 if (D
.dqb_bsoftlimit
==0)
950 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
952 if (D
.dqb_bsoftlimit
==0)
954 /* Use softlimit to determine disk space, except when it has been exceeded */
955 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)
956 #if !defined(__FreeBSD__) && !defined(__OpenBSD__)
957 ||((D
.dqb_curfiles
>D
.dqb_fsoftlimit
) && (D
.dqb_fsoftlimit
!= 0))
961 *dsize
= D
.dqb_curblocks
;
964 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
965 *dsize
= D
.dqb_bsoftlimit
;
972 #if defined(VXFS_QUOTA)
974 /****************************************************************************
975 Try to get the disk space from Veritas disk quotas.
976 David Lee <T.D.Lee@durham.ac.uk> August 1999.
978 Background assumptions:
979 Potentially under many Operating Systems. Initially Solaris 2.
981 My guess is that Veritas is largely, though not entirely,
982 independent of OS. So I have separated it out.
984 There may be some details. For example, OS-specific "include" files.
986 It is understood that HPUX 10 somehow gets Veritas quotas without
987 any special effort; if so, this routine need not be compiled in.
988 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
991 It is understood that Veritas do not publicly support this ioctl interface.
992 Rather their preference would be for the user (us) to call the native
993 OS and then for the OS itself to call through to the VxFS filesystem.
994 Presumably HPUX 10, see above, does this.
997 Add your OS to "IFLIST" below.
998 Get it to compile successfully:
999 Almost certainly "include"s require attention: see SUNOS5.
1000 In the main code above, arrange for it to be called: see SUNOS5.
1003 ****************************************************************************/
1006 * This "if" is a list of ports:
1007 * if defined(OS1) || defined(OS2) || ...
1012 #include <sys/fs/vx_solaris.h>
1014 #include <sys/fs/vx_machdep.h>
1015 #include <sys/fs/vx_layout.h>
1016 #include <sys/fs/vx_quota.h>
1017 #include <sys/fs/vx_aioctl.h>
1018 #include <sys/fs/vx_ioctl.h>
1020 BOOL
disk_quotas_vxfs(const pstring name
, char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
1022 uid_t user_id
, euser_id
;
1025 struct vx_quotctl quotabuf
;
1026 struct vx_genioctl genbuf
;
1031 * "name" may or may not include a trailing "/quotas".
1032 * Arranging consistency of calling here in "quotas.c" may not be easy and
1033 * it might be easier to examine and adjust it here.
1034 * Fortunately, VxFS seems not to mind at present.
1036 pstrcpy(qfname
, name
) ;
1037 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
1039 euser_id
= geteuid();
1040 set_effective_uid(0);
1042 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname
));
1043 if((file
=sys_open(qfname
, O_RDONLY
,0))<0) {
1044 set_effective_uid(euser_id
);
1047 genbuf
.ioc_cmd
= VX_QUOTACTL
;
1048 genbuf
.ioc_up
= (void *) "abuf
;
1050 quotabuf
.cmd
= VX_GETQUOTA
;
1051 quotabuf
.uid
= euser_id
;
1052 quotabuf
.addr
= (caddr_t
) &D
;
1053 ret
= ioctl(file
, VX_ADMIN_IOCTL
, &genbuf
);
1056 set_effective_uid(euser_id
);
1059 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno
) ));
1063 /* If softlimit is zero, set it equal to hardlimit.
1066 if (D
.dqb_bsoftlimit
==0)
1067 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1069 /* Use softlimit to determine disk space. A user exceeding the quota is told
1070 * that there's no space left. Writes might actually work for a bit if the
1071 * hardlimit is set higher than softlimit. Effectively the disk becomes
1072 * made of rubber latex and begins to expand to accommodate the user :-)
1074 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
1075 path
, D
.dqb_curblocks
, D
.dqb_bsoftlimit
, D
.dqb_bhardlimit
,
1076 D
.dqb_curfiles
, D
.dqb_fsoftlimit
, D
.dqb_fhardlimit
));
1078 if (D
.dqb_bsoftlimit
==0)
1081 *dsize
= D
.dqb_bsoftlimit
;
1083 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
1085 *dsize
= D
.dqb_curblocks
;
1087 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1089 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
1090 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
1095 #endif /* SUNOS5 || ... */
1097 #endif /* VXFS_QUOTA */