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>
48 * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
49 * So we include all the files has *should* be in the system into a large,
50 * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA.
53 #include "samba_linux_quota.h"
55 typedef struct _LINUX_SMB_DISK_QUOTA
{
57 SMB_BIG_UINT hardlimit
; /* In bsize units. */
58 SMB_BIG_UINT softlimit
; /* In bsize units. */
59 SMB_BIG_UINT curblocks
; /* In bsize units. */
60 SMB_BIG_UINT ihardlimit
; /* inode hard limit. */
61 SMB_BIG_UINT isoftlimit
; /* inode soft limit. */
62 SMB_BIG_UINT curinodes
; /* Current used inodes. */
63 } LINUX_SMB_DISK_QUOTA
;
65 /****************************************************************************
66 Abstract out the XFS Quota Manager quota get call.
67 ****************************************************************************/
69 static int get_smb_linux_xfs_quota(char *path
, uid_t euser_id
, LINUX_SMB_DISK_QUOTA
*dp
)
72 struct fs_disk_quota D
;
75 if ((ret
= quotactl(QCMD(Q_XGETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
)))
78 dp
->bsize
= (SMB_BIG_UINT
)512;
79 dp
->softlimit
= (SMB_BIG_UINT
)D
.d_blk_softlimit
;
80 dp
->hardlimit
= (SMB_BIG_UINT
)D
.d_blk_hardlimit
;
81 dp
->ihardlimit
= (SMB_BIG_UINT
)D
.d_ino_hardlimit
;
82 dp
->isoftlimit
= (SMB_BIG_UINT
)D
.d_ino_softlimit
;
83 dp
->curinodes
= (SMB_BIG_UINT
)D
.d_icount
;
84 dp
->curblocks
= (SMB_BIG_UINT
)D
.d_bcount
;
88 /****************************************************************************
89 Abstract out the old and new Linux quota get calls.
90 ****************************************************************************/
92 static int get_smb_linux_v1_quota(char *path
, uid_t euser_id
, LINUX_SMB_DISK_QUOTA
*dp
)
94 struct v1_kern_dqblk D
;
98 dp
->bsize
= (SMB_BIG_UINT
)QUOTABLOCK_SIZE
;
100 if ((ret
= quotactl(QCMD(Q_V1_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
)))
103 dp
->softlimit
= (SMB_BIG_UINT
)D
.dqb_bsoftlimit
;
104 dp
->hardlimit
= (SMB_BIG_UINT
)D
.dqb_bhardlimit
;
105 dp
->ihardlimit
= (SMB_BIG_UINT
)D
.dqb_ihardlimit
;
106 dp
->isoftlimit
= (SMB_BIG_UINT
)D
.dqb_isoftlimit
;
107 dp
->curinodes
= (SMB_BIG_UINT
)D
.dqb_curinodes
;
108 dp
->curblocks
= (SMB_BIG_UINT
)D
.dqb_curblocks
;
113 static int get_smb_linux_v2_quota(char *path
, uid_t euser_id
, LINUX_SMB_DISK_QUOTA
*dp
)
115 struct v2_kern_dqblk D
;
119 dp
->bsize
= (SMB_BIG_UINT
)QUOTABLOCK_SIZE
;
121 if ((ret
= quotactl(QCMD(Q_V2_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
)))
124 dp
->softlimit
= (SMB_BIG_UINT
)D
.dqb_bsoftlimit
;
125 dp
->hardlimit
= (SMB_BIG_UINT
)D
.dqb_bhardlimit
;
126 dp
->ihardlimit
= (SMB_BIG_UINT
)D
.dqb_ihardlimit
;
127 dp
->isoftlimit
= (SMB_BIG_UINT
)D
.dqb_isoftlimit
;
128 dp
->curinodes
= (SMB_BIG_UINT
)D
.dqb_curinodes
;
129 dp
->curblocks
= ((SMB_BIG_UINT
)D
.dqb_curspace
) / dp
->bsize
;
134 /****************************************************************************
135 Brand-new generic quota interface.
136 ****************************************************************************/
138 static int get_smb_linux_gen_quota(char *path
, uid_t euser_id
, LINUX_SMB_DISK_QUOTA
*dp
)
144 dp
->bsize
= (SMB_BIG_UINT
)QUOTABLOCK_SIZE
;
146 if ((ret
= quotactl(QCMD(Q_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
)))
149 dp
->softlimit
= (SMB_BIG_UINT
)D
.dqb_bsoftlimit
;
150 dp
->hardlimit
= (SMB_BIG_UINT
)D
.dqb_bhardlimit
;
151 dp
->ihardlimit
= (SMB_BIG_UINT
)D
.dqb_ihardlimit
;
152 dp
->isoftlimit
= (SMB_BIG_UINT
)D
.dqb_isoftlimit
;
153 dp
->curinodes
= (SMB_BIG_UINT
)D
.dqb_curinodes
;
154 dp
->curblocks
= ((SMB_BIG_UINT
)D
.dqb_curspace
) / dp
->bsize
;
159 /****************************************************************************
160 Try to get the disk space from disk quotas (LINUX version).
161 ****************************************************************************/
163 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
168 LINUX_SMB_DISK_QUOTA D
;
174 euser_id
= geteuid();
176 /* find the block device file */
178 if ( sys_stat(path
, &S
) == -1 )
183 fp
= setmntent(MOUNTED
,"r");
186 while ((mnt
= getmntent(fp
))) {
187 if ( sys_stat(mnt
->mnt_dir
,&S
) == -1 )
190 if (S
.st_dev
== devno
) {
202 set_effective_uid(0);
204 if (strcmp(mnt
->mnt_type
, "xfs")) {
205 r
=get_smb_linux_gen_quota(mnt
->mnt_fsname
, euser_id
, &D
);
207 r
=get_smb_linux_v2_quota(mnt
->mnt_fsname
, euser_id
, &D
);
209 r
=get_smb_linux_v1_quota(mnt
->mnt_fsname
, euser_id
, &D
);
212 r
=get_smb_linux_xfs_quota(mnt
->mnt_fsname
, euser_id
, &D
);
217 /* Use softlimit to determine disk space, except when it has been exceeded */
220 if (errno
== EDQUOT
) {
229 /* Use softlimit to determine disk space, except when it has been exceeded */
231 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
232 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
233 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
234 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
237 *dsize
= D
.curblocks
;
238 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
241 if (D
.softlimit
== 0)
242 D
.softlimit
= D
.hardlimit
;
243 *dfree
= D
.softlimit
- D
.curblocks
;
244 *dsize
= D
.softlimit
;
252 #include <sys/quota.h>
255 /****************************************************************************
256 try to get the disk space from disk quotas (CRAY VERSION)
257 ****************************************************************************/
259 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
263 SMB_STRUCT_STAT sbuf
;
265 static SMB_DEV_T devno_cached
= 0 ;
267 struct q_request request
;
268 struct qf_header header
;
269 static int quota_default
= 0 ;
272 if ( sys_stat(path
,&sbuf
) == -1 )
275 devno
= sbuf
.st_dev
;
277 if ( devno
!= devno_cached
) {
279 devno_cached
= devno
;
281 if ((fd
= setmntent(KMTAB
)) == NULL
)
286 while ((mnt
= getmntent(fd
)) != NULL
) {
288 if ( sys_stat(mnt
->mnt_dir
,&sbuf
) == -1 )
291 if (sbuf
.st_dev
== devno
) {
300 pstrcpy(name
,mnt
->mnt_dir
) ;
307 request
.qf_magic
= QF_MAGIC
;
308 request
.qf_entry
.id
= geteuid() ;
310 if (quotactl(name
, Q_GETQUOTA
, &request
) == -1)
313 if ( ! request
.user
)
316 if ( request
.qf_entry
.user_q
.f_quota
== QFV_DEFAULT
) {
318 if ( ! quota_default
) {
320 if ( quotactl(name
, Q_GETHEADER
, &header
) == -1 )
323 quota_default
= header
.user_h
.def_fq
;
326 *dfree
= quota_default
;
328 }else if ( request
.qf_entry
.user_q
.f_quota
== QFV_PREVENT
) {
334 *dfree
= request
.qf_entry
.user_q
.f_quota
;
338 *dsize
= request
.qf_entry
.user_q
.f_use
;
340 if ( *dfree
< *dsize
)
345 *bsize
= 4096 ; /* Cray blocksize */
352 #elif defined(SUNOS5) || defined(SUNOS4)
355 #include <sys/param.h>
357 #include <sys/fs/ufs_quota.h>
358 #include <sys/mnttab.h>
359 #include <sys/mntent.h>
360 #else /* defined(SUNOS4) */
361 #include <ufs/quota.h>
367 /****************************************************************************
368 Allows querying of remote hosts for quotas on NFS mounted shares.
369 Supports normal NFS and AMD mounts.
370 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
371 ****************************************************************************/
374 #include <rpc/types.h>
375 #include <rpcsvc/rquota.h>
376 #include <rpc/nettype.h>
379 static int quotastat
;
381 static int xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
383 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
385 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
390 static int xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
392 if (!xdr_int(xdrsp
, "astat
)) {
393 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
396 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
397 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
400 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
401 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
404 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
405 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
408 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
409 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
412 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
413 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
419 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
420 static BOOL
nfs_quotas(char *nfspath
, uid_t euser_id
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
422 uid_t uid
= euser_id
;
424 char *mnttype
= nfspath
;
426 struct getquota_rslt gqr
;
427 struct getquota_args args
;
428 char *cutstr
, *pathname
, *host
, *testpath
;
430 static struct timeval timeout
= {2,0};
431 enum clnt_stat clnt_stat
;
434 *bsize
= *dfree
= *dsize
= (SMB_BIG_UINT
)0;
436 len
=strcspn(mnttype
, ":");
437 pathname
=strstr(mnttype
, ":");
438 cutstr
= (char *) malloc(sizeof(char) * len
);
442 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
443 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
444 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
445 testpath
=strchr(mnttype
, ':');
446 args
.gqa_pathp
= testpath
+1;
449 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
, "udp"));
451 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
456 clnt
->cl_auth
= authunix_create_default();
457 DEBUG(9,("nfs_quotas: auth_success\n"));
459 clnt_stat
=clnt_call(clnt
, RQUOTAPROC_GETQUOTA
, xdr_getquota_args
, (caddr_t
)&args
, xdr_getquota_rslt
, (caddr_t
)&gqr
, timeout
);
461 if (clnt_stat
!= RPC_SUCCESS
) {
462 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
468 * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
469 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
470 * something sensible.
473 switch ( quotastat
) {
475 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat
));
480 DEBUG(9,("nfs_quotas: Good quota data\n"));
481 D
.dqb_bsoftlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
482 D
.dqb_bhardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
483 D
.dqb_curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
488 D
.dqb_bsoftlimit
= 1;
490 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat
));
494 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", quotastat
));
498 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",
500 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
501 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
502 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
503 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
504 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
506 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
507 *dsize
= D
.dqb_bsoftlimit
;
509 if (D
.dqb_curblocks
== D
.dqb_curblocks
== 1)
512 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
514 *dsize
= D
.dqb_curblocks
;
516 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
522 auth_destroy(clnt
->cl_auth
);
526 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args
.gqa_pathp
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
529 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
534 /****************************************************************************
535 try to get the disk space from disk quotas (SunOS & Solaris2 version)
536 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
537 ****************************************************************************/
539 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
545 struct quotctl command
;
547 static struct mnttab mnt
;
555 SMB_STRUCT_STAT sbuf
;
557 static SMB_DEV_T devno_cached
= 0 ;
560 euser_id
= geteuid();
562 if ( sys_stat(path
,&sbuf
) == -1 )
565 devno
= sbuf
.st_dev
;
566 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path
,(unsigned int)devno
));
567 if ( devno
!= devno_cached
) {
568 devno_cached
= devno
;
570 if ((fd
= sys_fopen(MNTTAB
, "r")) == NULL
)
574 slprintf(devopt
, sizeof(devopt
) - 1, "dev=%x", (unsigned int)devno
);
575 while (getmntent(fd
, &mnt
) == 0) {
576 if( !hasmntopt(&mnt
, devopt
) )
579 DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt
.mnt_mountp
,devopt
));
581 /* quotas are only on vxfs, UFS or NFS */
582 if ( strcmp( mnt
.mnt_fstype
, MNTTYPE_UFS
) == 0 ||
583 strcmp( mnt
.mnt_fstype
, "nfs" ) == 0 ||
584 strcmp( mnt
.mnt_fstype
, "vxfs" ) == 0 ) {
590 pstrcpy(name
,mnt
.mnt_mountp
) ;
591 pstrcat(name
,"/quotas") ;
594 if ((fd
= setmntent(MOUNTED
, "r")) == NULL
)
598 while ((mnt
= getmntent(fd
)) != NULL
) {
599 if ( sys_stat(mnt
->mnt_dir
,&sbuf
) == -1 )
601 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt
->mnt_dir
,(unsigned int)sbuf
.st_dev
));
602 if (sbuf
.st_dev
== devno
) {
608 pstrcpy(name
,mnt
->mnt_fsname
) ;
617 set_effective_uid(0);
620 if ( strcmp( mnt
.mnt_fstype
, "nfs" ) == 0) {
622 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt
.mnt_special
));
623 retval
= nfs_quotas(mnt
.mnt_special
, euser_id
, bsize
, dfree
, dsize
);
628 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name
));
629 if((file
=sys_open(name
, O_RDONLY
,0))<0) {
633 command
.op
= Q_GETQUOTA
;
634 command
.uid
= euser_id
;
635 command
.addr
= (caddr_t
) &D
;
636 ret
= ioctl(file
, Q_QUOTACTL
, &command
);
639 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name
));
640 ret
= quotactl(Q_GETQUOTA
, name
, euser_id
, &D
);
646 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno
) ));
648 #if defined(SUNOS5) && defined(VXFS_QUOTA)
649 /* If normal quotactl() fails, try vxfs private calls */
650 set_effective_uid(euser_id
);
651 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt
.mnt_fstype
));
652 if ( 0 == strcmp ( mnt
.mnt_fstype
, "vxfs" )) {
654 retval
= disk_quotas_vxfs(name
, path
, bsize
, dfree
, dsize
);
662 /* If softlimit is zero, set it equal to hardlimit.
665 if (D
.dqb_bsoftlimit
==0)
666 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
668 /* Use softlimit to determine disk space. A user exceeding the quota is told
669 * that there's no space left. Writes might actually work for a bit if the
670 * hardlimit is set higher than softlimit. Effectively the disk becomes
671 * made of rubber latex and begins to expand to accommodate the user :-)
674 if (D
.dqb_bsoftlimit
==0)
677 *dsize
= D
.dqb_bsoftlimit
;
679 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
681 *dsize
= D
.dqb_curblocks
;
683 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
685 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
686 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
693 #include <ufs/quota.h>
695 /****************************************************************************
696 try to get the disk space from disk quotas - OSF1 version
697 ****************************************************************************/
699 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
707 * This code presumes that OSF1 will only
708 * give out quota info when the real uid
709 * matches the effective uid. JRA.
711 euser_id
= geteuid();
713 if (set_re_uid() != 0) return False
;
715 r
= quotactl(path
,QCMD(Q_GETQUOTA
, USRQUOTA
),euser_id
,(char *) &D
);
726 if (save_errno
== EDQUOT
) /* disk quota exceeded */
729 *dsize
= D
.dqb_curblocks
;
736 /* If softlimit is zero, set it equal to hardlimit.
739 if (D
.dqb_bsoftlimit
==0)
740 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
742 /* Use softlimit to determine disk space, except when it has been exceeded */
744 if (D
.dqb_bsoftlimit
==0)
747 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)) {
749 *dsize
= D
.dqb_curblocks
;
751 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
752 *dsize
= D
.dqb_bsoftlimit
;
757 #elif defined (IRIX6)
758 /****************************************************************************
759 try to get the disk space from disk quotas (IRIX 6.2 version)
760 ****************************************************************************/
762 #include <sys/quota.h>
765 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
770 struct fs_disk_quota F
;
777 /* find the block device file */
779 if ( sys_stat(path
, &S
) == -1 ) {
785 fp
= setmntent(MOUNTED
,"r");
788 while ((mnt
= getmntent(fp
))) {
789 if ( sys_stat(mnt
->mnt_dir
,&S
) == -1 )
791 if (S
.st_dev
== devno
) {
804 set_effective_uid(0);
806 /* Use softlimit to determine disk space, except when it has been exceeded */
810 if ( 0 == strcmp ( mnt
->mnt_type
, "efs" ))
812 r
=quotactl (Q_GETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &D
);
819 /* Use softlimit to determine disk space, except when it has been exceeded */
821 (D
.dqb_bsoftlimit
&& D
.dqb_curblocks
>=D
.dqb_bsoftlimit
) ||
822 (D
.dqb_bhardlimit
&& D
.dqb_curblocks
>=D
.dqb_bhardlimit
) ||
823 (D
.dqb_fsoftlimit
&& D
.dqb_curfiles
>=D
.dqb_fsoftlimit
) ||
824 (D
.dqb_fhardlimit
&& D
.dqb_curfiles
>=D
.dqb_fhardlimit
)
828 *dsize
= D
.dqb_curblocks
;
830 else if (D
.dqb_bsoftlimit
==0 && D
.dqb_bhardlimit
==0)
836 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
837 *dsize
= D
.dqb_bsoftlimit
;
841 else if ( 0 == strcmp ( mnt
->mnt_type
, "xfs" ))
843 r
=quotactl (Q_XGETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &F
);
850 /* Use softlimit to determine disk space, except when it has been exceeded */
852 (F
.d_blk_softlimit
&& F
.d_bcount
>=F
.d_blk_softlimit
) ||
853 (F
.d_blk_hardlimit
&& F
.d_bcount
>=F
.d_blk_hardlimit
) ||
854 (F
.d_ino_softlimit
&& F
.d_icount
>=F
.d_ino_softlimit
) ||
855 (F
.d_ino_hardlimit
&& F
.d_icount
>=F
.d_ino_hardlimit
)
861 else if (F
.d_blk_softlimit
==0 && F
.d_blk_hardlimit
==0)
867 *dfree
= (F
.d_blk_softlimit
- F
.d_bcount
);
868 *dsize
= F
.d_blk_softlimit
;
884 #if defined(__FreeBSD__) || defined(__OpenBSD__)
885 #include <ufs/ufs/quota.h>
886 #include <machine/param.h>
888 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
889 #include <jfs/quota.h>
890 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
891 #define dqb_curfiles dqb_curinodes
892 #define dqb_fhardlimit dqb_ihardlimit
893 #define dqb_fsoftlimit dqb_isoftlimit
894 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
895 #include <sys/quota.h>
899 /****************************************************************************
900 try to get the disk space from disk quotas - default version
901 ****************************************************************************/
903 BOOL
disk_quotas(const char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
908 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__)
912 /* find the block device file */
915 /* Need to set the cache flag to 1 for HPUX. Seems
916 * to have a significant performance boost when
917 * lstat calls on /dev access this function.
919 if ((sys_stat(path
, &S
)<0) || (devnm(S_IFBLK
, S
.st_dev
, dev_disk
, 256, 1)<0))
921 if ((sys_stat(path
, &S
)<0) || (devnm(S_IFBLK
, S
.st_dev
, dev_disk
, 256, 0)<0))
923 #endif /* ifdef HPUX */
925 #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */
927 euser_id
= geteuid();
930 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
932 if (set_re_uid() != 0) return False
;
934 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
938 #if defined(__FreeBSD__) || defined(__OpenBSD__)
940 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
944 set_effective_uid(0);
947 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
949 /* As FreeBSD has group quotas, if getting the user
950 quota fails, try getting the group instead. */
952 r
= quotactl(path
,QCMD(Q_GETQUOTA
,GRPQUOTA
),egrp_id
,(char *) &D
);
958 /* AIX has both USER and GROUP quotas:
959 Get the USER quota (ohnielse@fysik.dtu.dk) */
960 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
961 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
962 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
963 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
966 /* Use softlimit to determine disk space, except when it has been exceeded */
967 #if defined(__FreeBSD__) || defined(__OpenBSD__)
969 #else /* !__FreeBSD__ && !__OpenBSD__ */
971 #endif /*!__FreeBSD__ && !__OpenBSD__ */
978 *dsize
=D
.dqb_curblocks
;
984 /* If softlimit is zero, set it equal to hardlimit.
987 if (D
.dqb_bsoftlimit
==0)
988 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
990 if (D
.dqb_bsoftlimit
==0)
992 /* Use softlimit to determine disk space, except when it has been exceeded */
993 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)
994 #if !defined(__FreeBSD__) && !defined(__OpenBSD__)
995 ||((D
.dqb_curfiles
>D
.dqb_fsoftlimit
) && (D
.dqb_fsoftlimit
!= 0))
999 *dsize
= D
.dqb_curblocks
;
1002 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1003 *dsize
= D
.dqb_bsoftlimit
;
1010 #if defined(VXFS_QUOTA)
1012 /****************************************************************************
1013 Try to get the disk space from Veritas disk quotas.
1014 David Lee <T.D.Lee@durham.ac.uk> August 1999.
1016 Background assumptions:
1017 Potentially under many Operating Systems. Initially Solaris 2.
1019 My guess is that Veritas is largely, though not entirely,
1020 independent of OS. So I have separated it out.
1022 There may be some details. For example, OS-specific "include" files.
1024 It is understood that HPUX 10 somehow gets Veritas quotas without
1025 any special effort; if so, this routine need not be compiled in.
1026 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
1029 It is understood that Veritas do not publicly support this ioctl interface.
1030 Rather their preference would be for the user (us) to call the native
1031 OS and then for the OS itself to call through to the VxFS filesystem.
1032 Presumably HPUX 10, see above, does this.
1035 Add your OS to "IFLIST" below.
1036 Get it to compile successfully:
1037 Almost certainly "include"s require attention: see SUNOS5.
1038 In the main code above, arrange for it to be called: see SUNOS5.
1041 ****************************************************************************/
1044 * This "if" is a list of ports:
1045 * if defined(OS1) || defined(OS2) || ...
1050 #include <sys/fs/vx_solaris.h>
1052 #include <sys/fs/vx_machdep.h>
1053 #include <sys/fs/vx_layout.h>
1054 #include <sys/fs/vx_quota.h>
1055 #include <sys/fs/vx_aioctl.h>
1056 #include <sys/fs/vx_ioctl.h>
1058 BOOL
disk_quotas_vxfs(const pstring name
, char *path
, SMB_BIG_UINT
*bsize
, SMB_BIG_UINT
*dfree
, SMB_BIG_UINT
*dsize
)
1060 uid_t user_id
, euser_id
;
1063 struct vx_quotctl quotabuf
;
1064 struct vx_genioctl genbuf
;
1069 * "name" may or may not include a trailing "/quotas".
1070 * Arranging consistency of calling here in "quotas.c" may not be easy and
1071 * it might be easier to examine and adjust it here.
1072 * Fortunately, VxFS seems not to mind at present.
1074 pstrcpy(qfname
, name
) ;
1075 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
1077 euser_id
= geteuid();
1078 set_effective_uid(0);
1080 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname
));
1081 if((file
=sys_open(qfname
, O_RDONLY
,0))<0) {
1082 set_effective_uid(euser_id
);
1085 genbuf
.ioc_cmd
= VX_QUOTACTL
;
1086 genbuf
.ioc_up
= (void *) "abuf
;
1088 quotabuf
.cmd
= VX_GETQUOTA
;
1089 quotabuf
.uid
= euser_id
;
1090 quotabuf
.addr
= (caddr_t
) &D
;
1091 ret
= ioctl(file
, VX_ADMIN_IOCTL
, &genbuf
);
1094 set_effective_uid(euser_id
);
1097 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno
) ));
1101 /* If softlimit is zero, set it equal to hardlimit.
1104 if (D
.dqb_bsoftlimit
==0)
1105 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1107 /* Use softlimit to determine disk space. A user exceeding the quota is told
1108 * that there's no space left. Writes might actually work for a bit if the
1109 * hardlimit is set higher than softlimit. Effectively the disk becomes
1110 * made of rubber latex and begins to expand to accommodate the user :-)
1112 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
1113 path
, D
.dqb_curblocks
, D
.dqb_bsoftlimit
, D
.dqb_bhardlimit
,
1114 D
.dqb_curfiles
, D
.dqb_fsoftlimit
, D
.dqb_fhardlimit
));
1116 if (D
.dqb_bsoftlimit
==0)
1119 *dsize
= D
.dqb_bsoftlimit
;
1121 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
1123 *dsize
= D
.dqb_curblocks
;
1125 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1127 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
1128 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
1133 #endif /* SUNOS5 || ... */
1135 #endif /* VXFS_QUOTA */