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 #ifndef HAVE_SYS_QUOTAS
32 /* just a quick hack because sysquotas.h is included before linux/quota.h */
33 #ifdef QUOTABLOCK_SIZE
34 #undef QUOTABLOCK_SIZE
39 #if defined(VXFS_QUOTA)
42 * In addition to their native filesystems, some systems have Veritas VxFS.
43 * Declare here, define at end: reduces likely "include" interaction problems.
44 * David Lee <T.D.Lee@durham.ac.uk>
46 BOOL
disk_quotas_vxfs(const pstring name
, char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
);
48 #endif /* VXFS_QUOTA */
52 #include <sys/types.h>
53 #include <asm/types.h>
56 * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
57 * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk
58 * rather than the struct dqblk defined in /usr/include/sys/quota.h.
59 * This means we must include linux/quota.h to have a hope of working on
60 * RH7.1 systems. And it also means this breaks if the kernel is upgraded
61 * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until
62 * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA.
65 #include <linux/quota.h>
66 #ifdef HAVE_LINUX_XQM_H
67 #include <linux/xqm.h>
71 #define HAVE_LINUX_XQM_H
76 #include <linux/unistd.h>
79 #define LINUX_QUOTAS_2
81 typedef struct _LINUX_SMB_DISK_QUOTA
{
83 SMB_BIG_UINT hardlimit
; /* In bsize units. */
84 SMB_BIG_UINT softlimit
; /* In bsize units. */
85 SMB_BIG_UINT curblocks
; /* In bsize units. */
86 SMB_BIG_UINT ihardlimit
; /* inode hard limit. */
87 SMB_BIG_UINT isoftlimit
; /* inode soft limit. */
88 SMB_BIG_UINT curinodes
; /* Current used inodes. */
89 } LINUX_SMB_DISK_QUOTA
;
91 /****************************************************************************
92 Abstract out the XFS Quota Manager quota get call.
93 ****************************************************************************/
95 static int get_smb_linux_xfs_quota(char *path
, uid_t euser_id
, LINUX_SMB_DISK_QUOTA
*dp
)
98 #ifdef HAVE_LINUX_XQM_H
99 struct fs_disk_quota D
;
102 if ((ret
= quotactl(QCMD(Q_XGETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
)))
105 dp
->bsize
= (SMB_BIG_UINT
)512;
106 dp
->softlimit
= (SMB_BIG_UINT
)D
.d_blk_softlimit
;
107 dp
->hardlimit
= (SMB_BIG_UINT
)D
.d_blk_hardlimit
;
108 dp
->ihardlimit
= (SMB_BIG_UINT
)D
.d_ino_hardlimit
;
109 dp
->isoftlimit
= (SMB_BIG_UINT
)D
.d_ino_softlimit
;
110 dp
->curinodes
= (SMB_BIG_UINT
)D
.d_icount
;
111 dp
->curblocks
= (SMB_BIG_UINT
)D
.d_bcount
;
116 /****************************************************************************
117 Abstract out the old and new Linux quota get calls.
118 ****************************************************************************/
120 static int get_smb_linux_vfs_quota(char *path
, uid_t euser_id
, LINUX_SMB_DISK_QUOTA
*dp
)
123 #ifdef LINUX_QUOTAS_1
126 dp
->bsize
= (SMB_BIG_UINT
)1024;
127 #else /* LINUX_QUOTAS_2 */
130 #ifndef QUOTABLOCK_SIZE
131 #define QUOTABLOCK_SIZE 1024
133 dp
->bsize
= (SMB_BIG_UINT
)QUOTABLOCK_SIZE
;
136 if ((ret
= quotactl(QCMD(Q_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
)))
139 dp
->softlimit
= (SMB_BIG_UINT
)D
.dqb_bsoftlimit
;
140 dp
->hardlimit
= (SMB_BIG_UINT
)D
.dqb_bhardlimit
;
141 dp
->ihardlimit
= (SMB_BIG_UINT
)D
.dqb_ihardlimit
;
142 dp
->isoftlimit
= (SMB_BIG_UINT
)D
.dqb_isoftlimit
;
143 dp
->curinodes
= (SMB_BIG_UINT
)D
.dqb_curinodes
;
145 #ifdef LINUX_QUOTAS_1
146 dp
->curblocks
= (SMB_BIG_UINT
)D
.dqb_curblocks
;
147 #else /* LINUX_QUOTAS_2 */
148 dp
->curblocks
= ((SMB_BIG_UINT
)D
.dqb_curspace
)/ dp
->bsize
;
154 /****************************************************************************
155 try to get the disk space from disk quotas (LINUX version)
156 ****************************************************************************/
158 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
163 LINUX_SMB_DISK_QUOTA D
;
169 euser_id
= geteuid();
171 /* find the block device file */
173 if ( sys_stat(path
, &S
) == -1 )
178 fp
= setmntent(MOUNTED
,"r");
181 while ((mnt
= getmntent(fp
))) {
182 if ( sys_stat(mnt
->mnt_dir
,&S
) == -1 )
185 if (S
.st_dev
== devno
) {
197 set_effective_uid(0);
198 if (strcmp(mnt
->mnt_type
, "xfs") == 0)
199 r
=get_smb_linux_xfs_quota(mnt
->mnt_fsname
, euser_id
, &D
);
201 r
=get_smb_linux_vfs_quota(mnt
->mnt_fsname
, euser_id
, &D
);
204 /* Use softlimit to determine disk space, except when it has been exceeded */
207 if (errno
== EDQUOT
) {
216 /* Use softlimit to determine disk space, except when it has been exceeded */
218 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
219 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
220 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
221 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
224 *dsize
= D
.curblocks
;
225 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
228 if (D
.softlimit
== 0)
229 D
.softlimit
= D
.hardlimit
;
230 *dfree
= D
.softlimit
- D
.curblocks
;
231 *dsize
= D
.softlimit
;
239 #include <sys/quota.h>
242 /****************************************************************************
243 try to get the disk space from disk quotas (CRAY VERSION)
244 ****************************************************************************/
246 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
250 SMB_STRUCT_STAT sbuf
;
252 static SMB_DEV_T devno_cached
= 0 ;
254 struct q_request request
;
255 struct qf_header header
;
256 static int quota_default
= 0 ;
259 if ( sys_stat(path
,&sbuf
) == -1 )
262 devno
= sbuf
.st_dev
;
264 if ( devno
!= devno_cached
) {
266 devno_cached
= devno
;
268 if ((fd
= setmntent(KMTAB
)) == NULL
)
273 while ((mnt
= getmntent(fd
)) != NULL
) {
275 if ( sys_stat(mnt
->mnt_dir
,&sbuf
) == -1 )
278 if (sbuf
.st_dev
== devno
) {
287 pstrcpy(name
,mnt
->mnt_dir
) ;
294 request
.qf_magic
= QF_MAGIC
;
295 request
.qf_entry
.id
= geteuid() ;
297 if (quotactl(name
, Q_GETQUOTA
, &request
) == -1)
300 if ( ! request
.user
)
303 if ( request
.qf_entry
.user_q
.f_quota
== QFV_DEFAULT
) {
305 if ( ! quota_default
) {
307 if ( quotactl(name
, Q_GETHEADER
, &header
) == -1 )
310 quota_default
= header
.user_h
.def_fq
;
313 *dfree
= quota_default
;
315 }else if ( request
.qf_entry
.user_q
.f_quota
== QFV_PREVENT
) {
321 *dfree
= request
.qf_entry
.user_q
.f_quota
;
325 *dsize
= request
.qf_entry
.user_q
.f_use
;
327 if ( *dfree
< *dsize
)
332 *bsize
= 4096 ; /* Cray blocksize */
339 #elif defined(SUNOS5) || defined(SUNOS4)
342 #include <sys/param.h>
344 #include <sys/fs/ufs_quota.h>
345 #include <sys/mnttab.h>
346 #include <sys/mntent.h>
347 #else /* defined(SUNOS4) */
348 #include <ufs/quota.h>
354 /****************************************************************************
355 Allows querying of remote hosts for quotas on NFS mounted shares.
356 Supports normal NFS and AMD mounts.
357 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
358 ****************************************************************************/
361 #include <rpc/types.h>
362 #include <rpcsvc/rquota.h>
363 #include <rpc/nettype.h>
366 static int quotastat
;
368 static int xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
370 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
372 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
377 static int xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
379 if (!xdr_int(xdrsp
, "astat
)) {
380 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
383 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
384 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
387 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
388 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
391 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
392 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
395 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
396 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
399 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
400 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
406 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
407 static BOOL
nfs_quotas(char *nfspath
, uid_t euser_id
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
409 uid_t uid
= euser_id
;
411 char *mnttype
= nfspath
;
413 struct getquota_rslt gqr
;
414 struct getquota_args args
;
415 char *cutstr
, *pathname
, *host
, *testpath
;
417 static struct timeval timeout
= {2,0};
418 enum clnt_stat clnt_stat
;
421 *bsize
= *dfree
= *dsize
= (SMB_BIG_UINT
)0;
423 len
=strcspn(mnttype
, ":");
424 pathname
=strstr(mnttype
, ":");
425 cutstr
= (char *) malloc(len
+1);
429 memset(cutstr
, '\0', len
+1);
430 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
431 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
432 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
433 testpath
=strchr_m(mnttype
, ':');
434 args
.gqa_pathp
= testpath
+1;
437 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
, "udp"));
439 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
444 clnt
->cl_auth
= authunix_create_default();
445 DEBUG(9,("nfs_quotas: auth_success\n"));
447 clnt_stat
=clnt_call(clnt
, RQUOTAPROC_GETQUOTA
, xdr_getquota_args
, (caddr_t
)&args
, xdr_getquota_rslt
, (caddr_t
)&gqr
, timeout
);
449 if (clnt_stat
!= RPC_SUCCESS
) {
450 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
456 * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
457 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
458 * something sensible.
461 switch ( quotastat
) {
463 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat
));
468 DEBUG(9,("nfs_quotas: Good quota data\n"));
469 D
.dqb_bsoftlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
470 D
.dqb_bhardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
471 D
.dqb_curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
476 D
.dqb_bsoftlimit
= 1;
478 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat
));
482 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", quotastat
));
486 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",
488 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
489 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
490 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
491 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
492 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
494 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
495 *dsize
= D
.dqb_bsoftlimit
;
497 if (D
.dqb_curblocks
== D
.dqb_curblocks
== 1)
500 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
502 *dsize
= D
.dqb_curblocks
;
504 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
510 auth_destroy(clnt
->cl_auth
);
514 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args
.gqa_pathp
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
517 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
522 /****************************************************************************
523 try to get the disk space from disk quotas (SunOS & Solaris2 version)
524 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
525 ****************************************************************************/
527 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
533 struct quotctl command
;
535 static struct mnttab mnt
;
543 SMB_STRUCT_STAT sbuf
;
545 static SMB_DEV_T devno_cached
= 0 ;
548 euser_id
= geteuid();
550 if ( sys_stat(path
,&sbuf
) == -1 )
553 devno
= sbuf
.st_dev
;
554 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path
,(unsigned int)devno
));
555 if ( devno
!= devno_cached
) {
556 devno_cached
= devno
;
558 if ((fd
= sys_fopen(MNTTAB
, "r")) == NULL
)
562 slprintf(devopt
, sizeof(devopt
) - 1, "dev=%x", (unsigned int)devno
);
563 while (getmntent(fd
, &mnt
) == 0) {
564 if( !hasmntopt(&mnt
, devopt
) )
567 DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt
.mnt_mountp
,devopt
));
569 /* quotas are only on vxfs, UFS or NFS */
570 if ( strcmp( mnt
.mnt_fstype
, MNTTYPE_UFS
) == 0 ||
571 strcmp( mnt
.mnt_fstype
, "nfs" ) == 0 ||
572 strcmp( mnt
.mnt_fstype
, "vxfs" ) == 0 ) {
578 pstrcpy(name
,mnt
.mnt_mountp
) ;
579 pstrcat(name
,"/quotas") ;
582 if ((fd
= setmntent(MOUNTED
, "r")) == NULL
)
586 while ((mnt
= getmntent(fd
)) != NULL
) {
587 if ( sys_stat(mnt
->mnt_dir
,&sbuf
) == -1 )
589 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt
->mnt_dir
,(unsigned int)sbuf
.st_dev
));
590 if (sbuf
.st_dev
== devno
) {
596 pstrcpy(name
,mnt
->mnt_fsname
) ;
605 set_effective_uid(0);
608 if ( strcmp( mnt
.mnt_fstype
, "nfs" ) == 0) {
610 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt
.mnt_special
));
611 retval
= nfs_quotas(mnt
.mnt_special
, euser_id
, bsize
, dfree
, dsize
);
616 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name
));
617 if((file
=sys_open(name
, O_RDONLY
,0))<0) {
621 command
.op
= Q_GETQUOTA
;
622 command
.uid
= euser_id
;
623 command
.addr
= (caddr_t
) &D
;
624 ret
= ioctl(file
, Q_QUOTACTL
, &command
);
627 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name
));
628 ret
= quotactl(Q_GETQUOTA
, name
, euser_id
, &D
);
634 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno
) ));
636 #if defined(SUNOS5) && defined(VXFS_QUOTA)
637 /* If normal quotactl() fails, try vxfs private calls */
638 set_effective_uid(euser_id
);
639 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt
.mnt_fstype
));
640 if ( 0 == strcmp ( mnt
.mnt_fstype
, "vxfs" )) {
642 retval
= disk_quotas_vxfs(name
, path
, bsize
, dfree
, dsize
);
650 /* If softlimit is zero, set it equal to hardlimit.
653 if (D
.dqb_bsoftlimit
==0)
654 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
656 /* Use softlimit to determine disk space. A user exceeding the quota is told
657 * that there's no space left. Writes might actually work for a bit if the
658 * hardlimit is set higher than softlimit. Effectively the disk becomes
659 * made of rubber latex and begins to expand to accommodate the user :-)
662 if (D
.dqb_bsoftlimit
==0)
665 *dsize
= D
.dqb_bsoftlimit
;
667 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
669 *dsize
= D
.dqb_curblocks
;
671 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
673 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
674 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
681 #include <ufs/quota.h>
683 /****************************************************************************
684 try to get the disk space from disk quotas - OSF1 version
685 ****************************************************************************/
687 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
695 * This code presumes that OSF1 will only
696 * give out quota info when the real uid
697 * matches the effective uid. JRA.
699 euser_id
= geteuid();
701 if (set_re_uid() != 0) return False
;
703 r
= quotactl(path
,QCMD(Q_GETQUOTA
, USRQUOTA
),euser_id
,(char *) &D
);
714 if (save_errno
== EDQUOT
) /* disk quota exceeded */
717 *dsize
= D
.dqb_curblocks
;
724 /* If softlimit is zero, set it equal to hardlimit.
727 if (D
.dqb_bsoftlimit
==0)
728 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
730 /* Use softlimit to determine disk space, except when it has been exceeded */
732 if (D
.dqb_bsoftlimit
==0)
735 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)) {
737 *dsize
= D
.dqb_curblocks
;
739 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
740 *dsize
= D
.dqb_bsoftlimit
;
745 #elif defined (IRIX6)
746 /****************************************************************************
747 try to get the disk space from disk quotas (IRIX 6.2 version)
748 ****************************************************************************/
750 #include <sys/quota.h>
753 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
758 struct fs_disk_quota F
;
765 /* find the block device file */
767 if ( sys_stat(path
, &S
) == -1 ) {
773 fp
= setmntent(MOUNTED
,"r");
776 while ((mnt
= getmntent(fp
))) {
777 if ( sys_stat(mnt
->mnt_dir
,&S
) == -1 )
779 if (S
.st_dev
== devno
) {
792 set_effective_uid(0);
794 /* Use softlimit to determine disk space, except when it has been exceeded */
798 if ( 0 == strcmp ( mnt
->mnt_type
, "efs" ))
800 r
=quotactl (Q_GETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &D
);
807 /* Use softlimit to determine disk space, except when it has been exceeded */
809 (D
.dqb_bsoftlimit
&& D
.dqb_curblocks
>=D
.dqb_bsoftlimit
) ||
810 (D
.dqb_bhardlimit
&& D
.dqb_curblocks
>=D
.dqb_bhardlimit
) ||
811 (D
.dqb_fsoftlimit
&& D
.dqb_curfiles
>=D
.dqb_fsoftlimit
) ||
812 (D
.dqb_fhardlimit
&& D
.dqb_curfiles
>=D
.dqb_fhardlimit
)
816 *dsize
= D
.dqb_curblocks
;
818 else if (D
.dqb_bsoftlimit
==0 && D
.dqb_bhardlimit
==0)
824 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
825 *dsize
= D
.dqb_bsoftlimit
;
829 else if ( 0 == strcmp ( mnt
->mnt_type
, "xfs" ))
831 r
=quotactl (Q_XGETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &F
);
838 /* Use softlimit to determine disk space, except when it has been exceeded */
840 (F
.d_blk_softlimit
&& F
.d_bcount
>=F
.d_blk_softlimit
) ||
841 (F
.d_blk_hardlimit
&& F
.d_bcount
>=F
.d_blk_hardlimit
) ||
842 (F
.d_ino_softlimit
&& F
.d_icount
>=F
.d_ino_softlimit
) ||
843 (F
.d_ino_hardlimit
&& F
.d_icount
>=F
.d_ino_hardlimit
)
849 else if (F
.d_blk_softlimit
==0 && F
.d_blk_hardlimit
==0)
855 *dfree
= (F
.d_blk_softlimit
- F
.d_bcount
);
856 *dsize
= F
.d_blk_softlimit
;
872 #if defined(__FreeBSD__) || defined(__OpenBSD__)
873 #include <ufs/ufs/quota.h>
874 #include <machine/param.h>
876 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
877 #include <jfs/quota.h>
878 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
879 #define dqb_curfiles dqb_curinodes
880 #define dqb_fhardlimit dqb_ihardlimit
881 #define dqb_fsoftlimit dqb_isoftlimit
882 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
883 #include <sys/quota.h>
887 /****************************************************************************
888 try to get the disk space from disk quotas - default version
889 ****************************************************************************/
891 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
896 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__)
900 /* find the block device file */
903 /* Need to set the cache flag to 1 for HPUX. Seems
904 * to have a significant performance boost when
905 * lstat calls on /dev access this function.
907 if ((sys_stat(path
, &S
)<0) || (devnm(S_IFBLK
, S
.st_dev
, dev_disk
, 256, 1)<0))
909 if ((sys_stat(path
, &S
)<0) || (devnm(S_IFBLK
, S
.st_dev
, dev_disk
, 256, 0)<0))
910 #endif /* ifdef HPUX */
913 #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */
915 euser_id
= geteuid();
918 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
920 if (set_re_uid() != 0) return False
;
922 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
926 #if defined(__FreeBSD__) || defined(__OpenBSD__)
928 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
932 set_effective_uid(0);
935 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
937 /* As FreeBSD has group quotas, if getting the user
938 quota fails, try getting the group instead. */
940 r
= quotactl(path
,QCMD(Q_GETQUOTA
,GRPQUOTA
),egrp_id
,(char *) &D
);
946 /* AIX has both USER and GROUP quotas:
947 Get the USER quota (ohnielse@fysik.dtu.dk) */
948 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
949 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
950 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
951 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
954 /* Use softlimit to determine disk space, except when it has been exceeded */
955 #if defined(__FreeBSD__) || defined(__OpenBSD__)
957 #else /* !__FreeBSD__ && !__OpenBSD__ */
959 #endif /*!__FreeBSD__ && !__OpenBSD__ */
966 *dsize
=D
.dqb_curblocks
;
972 /* If softlimit is zero, set it equal to hardlimit.
975 if (D
.dqb_bsoftlimit
==0)
976 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
978 if (D
.dqb_bsoftlimit
==0)
980 /* Use softlimit to determine disk space, except when it has been exceeded */
981 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)
982 #if !defined(__FreeBSD__) && !defined(__OpenBSD__)
983 ||((D
.dqb_curfiles
>D
.dqb_fsoftlimit
) && (D
.dqb_fsoftlimit
!= 0))
987 *dsize
= D
.dqb_curblocks
;
990 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
991 *dsize
= D
.dqb_bsoftlimit
;
998 #if defined(VXFS_QUOTA)
1000 /****************************************************************************
1001 Try to get the disk space from Veritas disk quotas.
1002 David Lee <T.D.Lee@durham.ac.uk> August 1999.
1004 Background assumptions:
1005 Potentially under many Operating Systems. Initially Solaris 2.
1007 My guess is that Veritas is largely, though not entirely,
1008 independent of OS. So I have separated it out.
1010 There may be some details. For example, OS-specific "include" files.
1012 It is understood that HPUX 10 somehow gets Veritas quotas without
1013 any special effort; if so, this routine need not be compiled in.
1014 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
1017 It is understood that Veritas do not publicly support this ioctl interface.
1018 Rather their preference would be for the user (us) to call the native
1019 OS and then for the OS itself to call through to the VxFS filesystem.
1020 Presumably HPUX 10, see above, does this.
1023 Add your OS to "IFLIST" below.
1024 Get it to compile successfully:
1025 Almost certainly "include"s require attention: see SUNOS5.
1026 In the main code above, arrange for it to be called: see SUNOS5.
1029 ****************************************************************************/
1032 * This "if" is a list of ports:
1033 * if defined(OS1) || defined(OS2) || ...
1038 #include <sys/fs/vx_solaris.h>
1040 #include <sys/fs/vx_machdep.h>
1041 #include <sys/fs/vx_layout.h>
1042 #include <sys/fs/vx_quota.h>
1043 #include <sys/fs/vx_aioctl.h>
1044 #include <sys/fs/vx_ioctl.h>
1046 BOOL
disk_quotas_vxfs(const pstring name
, char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
1048 uid_t user_id
, euser_id
;
1051 struct vx_quotctl quotabuf
;
1052 struct vx_genioctl genbuf
;
1057 * "name" may or may not include a trailing "/quotas".
1058 * Arranging consistency of calling here in "quotas.c" may not be easy and
1059 * it might be easier to examine and adjust it here.
1060 * Fortunately, VxFS seems not to mind at present.
1062 pstrcpy(qfname
, name
) ;
1063 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
1065 euser_id
= geteuid();
1066 set_effective_uid(0);
1068 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname
));
1069 if((file
=sys_open(qfname
, O_RDONLY
,0))<0) {
1070 set_effective_uid(euser_id
);
1073 genbuf
.ioc_cmd
= VX_QUOTACTL
;
1074 genbuf
.ioc_up
= (void *) "abuf
;
1076 quotabuf
.cmd
= VX_GETQUOTA
;
1077 quotabuf
.uid
= euser_id
;
1078 quotabuf
.addr
= (caddr_t
) &D
;
1079 ret
= ioctl(file
, VX_ADMIN_IOCTL
, &genbuf
);
1082 set_effective_uid(euser_id
);
1085 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno
) ));
1089 /* If softlimit is zero, set it equal to hardlimit.
1092 if (D
.dqb_bsoftlimit
==0)
1093 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1095 /* Use softlimit to determine disk space. A user exceeding the quota is told
1096 * that there's no space left. Writes might actually work for a bit if the
1097 * hardlimit is set higher than softlimit. Effectively the disk becomes
1098 * made of rubber latex and begins to expand to accommodate the user :-)
1100 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
1101 path
, D
.dqb_curblocks
, D
.dqb_bsoftlimit
, D
.dqb_bhardlimit
,
1102 D
.dqb_curfiles
, D
.dqb_fsoftlimit
, D
.dqb_fhardlimit
));
1104 if (D
.dqb_bsoftlimit
==0)
1107 *dsize
= D
.dqb_bsoftlimit
;
1109 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
1111 *dsize
= D
.dqb_curblocks
;
1113 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1115 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
1116 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
1121 #endif /* SUNOS5 || ... */
1123 #endif /* VXFS_QUOTA */
1125 #else /* WITH_QUOTAS */
1127 BOOL
disk_quotas(const char *path
,SMB_BIG_UINT
*bsize
,SMB_BIG_UINT
*dfree
,SMB_BIG_UINT
*dsize
)
1129 (*bsize
) = 512; /* This value should be ignored */
1131 /* And just to be sure we set some values that hopefully */
1132 /* will be larger that any possible real-world value */
1133 (*dfree
) = (SMB_BIG_UINT
)-1;
1134 (*dsize
) = (SMB_BIG_UINT
)-1;
1136 /* As we have select not to use quotas, allways fail */
1139 #endif /* WITH_QUOTAS */
1141 #else /* HAVE_SYS_QUOTAS */
1142 /* wrapper to the new sys_quota interface
1143 this file should be removed later
1145 BOOL
disk_quotas(const char *path
,SMB_BIG_UINT
*bsize
,SMB_BIG_UINT
*dfree
,SMB_BIG_UINT
*dsize
)
1153 r
=sys_get_quota(path
, SMB_USER_QUOTA_TYPE
, id
, &D
);
1155 /* Use softlimit to determine disk space, except when it has been exceeded */
1158 if (errno
== EDQUOT
) {
1160 *dsize
=D
.curblocks
;
1163 goto try_group_quota
;
1167 /* Use softlimit to determine disk space, except when it has been exceeded */
1169 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
1170 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
1171 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
1172 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
1175 *dsize
= D
.curblocks
;
1176 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
1177 goto try_group_quota
;
1179 if (D
.softlimit
== 0)
1180 D
.softlimit
= D
.hardlimit
;
1181 *dfree
= D
.softlimit
- D
.curblocks
;
1182 *dsize
= D
.softlimit
;
1188 #ifdef HAVE_GROUP_QUOTA
1191 r
=sys_get_quota(path
, SMB_GROUP_QUOTA_TYPE
, id
, &D
);
1193 /* Use softlimit to determine disk space, except when it has been exceeded */
1196 if (errno
== EDQUOT
) {
1198 *dsize
=D
.curblocks
;
1205 /* Use softlimit to determine disk space, except when it has been exceeded */
1207 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
1208 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
1209 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
1210 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
1213 *dsize
= D
.curblocks
;
1214 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
1217 if (D
.softlimit
== 0)
1218 D
.softlimit
= D
.hardlimit
;
1219 *dfree
= D
.softlimit
- D
.curblocks
;
1220 *dsize
= D
.softlimit
;
1224 #else /* HAVE_GROUP_QUOTA */
1226 #endif /* HAVE_GROUP_QUOTA */
1228 #endif /* HAVE_SYS_QUOTAS */