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 3 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, see <http://www.gnu.org/licenses/>.
22 * This is one of the most system dependent parts of Samba, and its
23 * done a litle differently. Each system has its own way of doing
30 #define DBGC_CLASS DBGC_QUOTA
32 #ifndef HAVE_SYS_QUOTAS
34 /* just a quick hack because sysquotas.h is included before linux/quota.h */
35 #ifdef QUOTABLOCK_SIZE
36 #undef QUOTABLOCK_SIZE
41 #if defined(VXFS_QUOTA)
44 * In addition to their native filesystems, some systems have Veritas VxFS.
45 * Declare here, define at end: reduces likely "include" interaction problems.
46 * David Lee <T.D.Lee@durham.ac.uk>
48 bool disk_quotas_vxfs(const char *name
, char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
);
50 #endif /* VXFS_QUOTA */
54 #include <sys/types.h>
58 * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
59 * So we include all the files has *should* be in the system into a large,
60 * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA.
63 #include "samba_linux_quota.h"
65 typedef struct _LINUX_SMB_DISK_QUOTA
{
67 uint64_t hardlimit
; /* In bsize units. */
68 uint64_t softlimit
; /* In bsize units. */
69 uint64_t curblocks
; /* In bsize units. */
70 uint64_t ihardlimit
; /* inode hard limit. */
71 uint64_t isoftlimit
; /* inode soft limit. */
72 uint64_t curinodes
; /* Current used inodes. */
73 } LINUX_SMB_DISK_QUOTA
;
78 * (essentially taken from FreeBSD / SUNOS5 section)
81 #include <rpc/types.h>
82 #include <rpcsvc/rquota.h>
83 #ifdef HAVE_RPC_NETTYPE_H
84 #include <rpc/nettype.h>
88 static int my_xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
90 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
92 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
97 static int my_xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
101 if (!xdr_int(xdrsp
, "astat
)) {
102 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
105 gqr
->status
= quotastat
;
107 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
108 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
111 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
112 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
115 if (!xdr_int(xdrsp
, (int *)&gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
116 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
119 if (!xdr_int(xdrsp
, (int *)&gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
120 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
123 if (!xdr_int(xdrsp
, (int *)&gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
124 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
130 static bool nfs_quotas(char *nfspath
, uid_t euser_id
, uint64_t *bsize
,
131 uint64_t *dfree
, uint64_t *dsize
)
133 uid_t uid
= euser_id
;
134 LINUX_SMB_DISK_QUOTA D
;
135 char *mnttype
= nfspath
;
137 struct getquota_rslt gqr
;
138 struct getquota_args args
;
139 char *cutstr
, *pathname
, *host
, *testpath
;
141 static struct timeval timeout
= {2,0};
142 enum clnt_stat clnt_stat
;
145 *bsize
= *dfree
= *dsize
= (uint64_t)0;
147 len
=strcspn(mnttype
, ":");
148 pathname
=strstr(mnttype
, ":");
149 cutstr
= (char *) SMB_MALLOC(len
+1);
153 memset(cutstr
, '\0', len
+1);
154 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
155 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
156 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
157 testpath
=strchr_m(mnttype
, ':');
158 args
.gqa_pathp
= testpath
+1;
161 DEBUG(5, ("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers "
162 "\"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
,
165 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
170 clnt
->cl_auth
= authunix_create_default();
171 DEBUG(9,("nfs_quotas: auth_success\n"));
173 clnt_stat
=clnt_call(clnt
,
175 (const xdrproc_t
)my_xdr_getquota_args
,
177 (const xdrproc_t
)my_xdr_getquota_rslt
,
178 (caddr_t
)&gqr
, timeout
);
180 if (clnt_stat
!= RPC_SUCCESS
) {
181 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
187 * gqr.status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
188 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
189 * something sensible.
192 switch (gqr
.status
) {
194 DEBUG(9, ("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n",
200 DEBUG(9,("nfs_quotas: Good quota data\n"));
201 D
.softlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
202 D
.hardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
203 D
.curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
210 DEBUG(9, ("nfs_quotas: Remote Quotas returned \"%i\" \n",
215 DEBUG(9, ("nfs_quotas: Remote Quotas Questionable! "
216 "Error \"%i\" \n", gqr
.status
));
220 DEBUG(10, ("nfs_quotas: Let`s look at D a bit closer... "
221 "status \"%i\" bsize \"%i\" active? \"%i\" bhard "
222 "\"%i\" bsoft \"%i\" curb \"%i\" \n",
224 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
225 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
226 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
227 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
228 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
230 if (D
.softlimit
== 0)
231 D
.softlimit
= D
.hardlimit
;
232 if (D
.softlimit
== 0)
235 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
236 *dsize
= D
.softlimit
;
238 if (D
.curblocks
== 1)
241 if (D
.curblocks
> D
.softlimit
) {
243 *dsize
= D
.curblocks
;
245 *dfree
= D
.softlimit
- D
.curblocks
;
251 auth_destroy(clnt
->cl_auth
);
255 DEBUG(5, ("nfs_quotas: For path \"%s\" returning "
256 "bsize %.0f, dfree %.0f, dsize %.0f\n",
257 args
.gqa_pathp
, (double)*bsize
, (double)*dfree
,
261 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
265 /* end of nfs quota section */
267 #ifdef HAVE_LINUX_DQBLK_XFS_H
268 #include <linux/dqblk_xfs.h>
270 /****************************************************************************
271 Abstract out the XFS Quota Manager quota get call.
272 ****************************************************************************/
274 static int get_smb_linux_xfs_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
276 struct fs_disk_quota D
;
281 ret
= quotactl(QCMD(Q_XGETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
284 ret
= quotactl(QCMD(Q_XGETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
289 dp
->bsize
= (uint64_t)512;
290 dp
->softlimit
= (uint64_t)D
.d_blk_softlimit
;
291 dp
->hardlimit
= (uint64_t)D
.d_blk_hardlimit
;
292 dp
->ihardlimit
= (uint64_t)D
.d_ino_hardlimit
;
293 dp
->isoftlimit
= (uint64_t)D
.d_ino_softlimit
;
294 dp
->curinodes
= (uint64_t)D
.d_icount
;
295 dp
->curblocks
= (uint64_t)D
.d_bcount
;
300 static int get_smb_linux_xfs_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
302 DEBUG(0,("XFS quota support not available\n"));
309 /****************************************************************************
310 Abstract out the old and new Linux quota get calls.
311 ****************************************************************************/
313 static int get_smb_linux_v1_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
315 struct v1_kern_dqblk D
;
320 ret
= quotactl(QCMD(Q_V1_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
322 if (ret
&& errno
!= EDQUOT
)
323 ret
= quotactl(QCMD(Q_V1_GETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
325 if (ret
&& errno
!= EDQUOT
)
328 dp
->bsize
= (uint64_t)QUOTABLOCK_SIZE
;
329 dp
->softlimit
= (uint64_t)D
.dqb_bsoftlimit
;
330 dp
->hardlimit
= (uint64_t)D
.dqb_bhardlimit
;
331 dp
->ihardlimit
= (uint64_t)D
.dqb_ihardlimit
;
332 dp
->isoftlimit
= (uint64_t)D
.dqb_isoftlimit
;
333 dp
->curinodes
= (uint64_t)D
.dqb_curinodes
;
334 dp
->curblocks
= (uint64_t)D
.dqb_curblocks
;
339 static int get_smb_linux_v2_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
341 struct v2_kern_dqblk D
;
346 ret
= quotactl(QCMD(Q_V2_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
348 if (ret
&& errno
!= EDQUOT
)
349 ret
= quotactl(QCMD(Q_V2_GETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
351 if (ret
&& errno
!= EDQUOT
)
354 dp
->bsize
= (uint64_t)QUOTABLOCK_SIZE
;
355 dp
->softlimit
= (uint64_t)D
.dqb_bsoftlimit
;
356 dp
->hardlimit
= (uint64_t)D
.dqb_bhardlimit
;
357 dp
->ihardlimit
= (uint64_t)D
.dqb_ihardlimit
;
358 dp
->isoftlimit
= (uint64_t)D
.dqb_isoftlimit
;
359 dp
->curinodes
= (uint64_t)D
.dqb_curinodes
;
360 dp
->curblocks
= ((uint64_t)D
.dqb_curspace
) / dp
->bsize
;
365 /****************************************************************************
366 Brand-new generic quota interface.
367 ****************************************************************************/
369 static int get_smb_linux_gen_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
376 ret
= quotactl(QCMD(Q_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
378 if (ret
&& errno
!= EDQUOT
)
379 ret
= quotactl(QCMD(Q_GETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
381 if (ret
&& errno
!= EDQUOT
)
384 dp
->bsize
= (uint64_t)QUOTABLOCK_SIZE
;
385 dp
->softlimit
= (uint64_t)D
.dqb_bsoftlimit
;
386 dp
->hardlimit
= (uint64_t)D
.dqb_bhardlimit
;
387 dp
->ihardlimit
= (uint64_t)D
.dqb_ihardlimit
;
388 dp
->isoftlimit
= (uint64_t)D
.dqb_isoftlimit
;
389 dp
->curinodes
= (uint64_t)D
.dqb_curinodes
;
390 dp
->curblocks
= ((uint64_t)D
.dqb_curspace
) / dp
->bsize
;
395 /****************************************************************************
396 Try to get the disk space from disk quotas (LINUX version).
397 ****************************************************************************/
399 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
404 LINUX_SMB_DISK_QUOTA D
;
413 euser_id
= geteuid();
416 /* find the block device file */
418 if (sys_stat(path
, &S
, false) == -1 )
421 devno
= S
.st_ex_dev
;
423 if ((fp
= setmntent(MOUNTED
,"r")) == NULL
)
428 while ((mnt
= getmntent(fp
))) {
429 if (sys_stat(mnt
->mnt_dir
, &S
, false) == -1)
432 if (S
.st_ex_dev
== devno
) {
445 if (strcmp(mnt
->mnt_type
, "nfs") == 0) {
447 retval
= nfs_quotas(mnt
->mnt_fsname
, euser_id
, bsize
, dfree
, dsize
);
452 if (strcmp(mnt
->mnt_type
, "xfs")==0) {
453 r
=get_smb_linux_xfs_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
455 r
=get_smb_linux_gen_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
456 if (r
== -1 && errno
!= EDQUOT
) {
457 r
=get_smb_linux_v2_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
458 if (r
== -1 && errno
!= EDQUOT
)
459 r
=get_smb_linux_v1_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
465 /* Use softlimit to determine disk space, except when it has been exceeded */
468 if (errno
== EDQUOT
) {
477 /* Use softlimit to determine disk space, except when it has been exceeded */
479 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
480 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
481 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
482 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
485 *dsize
= D
.curblocks
;
486 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
489 if (D
.softlimit
== 0)
490 D
.softlimit
= D
.hardlimit
;
491 *dfree
= D
.softlimit
- D
.curblocks
;
492 *dsize
= D
.softlimit
;
500 #include <sys/quota.h>
503 /****************************************************************************
504 try to get the disk space from disk quotas (CRAY VERSION)
505 ****************************************************************************/
507 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
511 SMB_STRUCT_STAT sbuf
;
513 struct q_request request
;
514 struct qf_header header
;
515 int quota_default
= 0 ;
518 if (sys_stat(path
, &sbuf
, false) == -1) {
522 devno
= sbuf
.st_ex_dev
;
524 if ((fd
= setmntent(KMTAB
)) == NULL
) {
528 while ((mnt
= getmntent(fd
)) != NULL
) {
529 if (sys_stat(mnt
->mnt_dir
, &sbuf
, false) == -1) {
532 if (sbuf
.st_ex_dev
== devno
) {
538 name
= talloc_strdup(talloc_tos(), mnt
->mnt_dir
);
548 request
.qf_magic
= QF_MAGIC
;
549 request
.qf_entry
.id
= geteuid() ;
551 if (quotactl(name
, Q_GETQUOTA
, &request
) == -1) {
559 if (request
.qf_entry
.user_q
.f_quota
== QFV_DEFAULT
) {
560 if (!quota_default
) {
561 if (quotactl(name
, Q_GETHEADER
, &header
) == -1) {
564 quota_default
= header
.user_h
.def_fq
;
567 *dfree
= quota_default
;
568 } else if (request
.qf_entry
.user_q
.f_quota
== QFV_PREVENT
) {
571 *dfree
= request
.qf_entry
.user_q
.f_quota
;
574 *dsize
= request
.qf_entry
.user_q
.f_use
;
576 if (*dfree
< *dsize
) {
582 *bsize
= 4096 ; /* Cray blocksize */
587 #elif defined(SUNOS5) || defined(SUNOS4)
590 #include <sys/param.h>
592 #include <sys/fs/ufs_quota.h>
593 #include <sys/mnttab.h>
594 #include <sys/mntent.h>
595 #else /* defined(SUNOS4) */
596 #include <ufs/quota.h>
602 /****************************************************************************
603 Allows querying of remote hosts for quotas on NFS mounted shares.
604 Supports normal NFS and AMD mounts.
605 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
606 ****************************************************************************/
609 #include <rpc/types.h>
610 #include <rpcsvc/rquota.h>
611 #include <rpc/nettype.h>
614 static int my_xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
616 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
618 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
623 static int my_xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
627 if (!xdr_int(xdrsp
, "astat
)) {
628 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
631 gqr
->status
= quotastat
;
633 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
634 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
637 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
638 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
641 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
642 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
645 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
646 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
649 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
650 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
656 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
657 static bool nfs_quotas(char *nfspath
, uid_t euser_id
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
659 uid_t uid
= euser_id
;
661 char *mnttype
= nfspath
;
663 struct getquota_rslt gqr
;
664 struct getquota_args args
;
665 char *cutstr
, *pathname
, *host
, *testpath
;
667 static struct timeval timeout
= {2,0};
668 enum clnt_stat clnt_stat
;
671 *bsize
= *dfree
= *dsize
= (uint64_t)0;
673 len
=strcspn(mnttype
, ":");
674 pathname
=strstr(mnttype
, ":");
675 cutstr
= (char *) SMB_MALLOC(len
+1);
679 memset(cutstr
, '\0', len
+1);
680 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
681 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
682 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
683 testpath
=strchr_m(mnttype
, ':');
684 args
.gqa_pathp
= testpath
+1;
687 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
, "udp"));
689 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
694 clnt
->cl_auth
= authunix_create_default();
695 DEBUG(9,("nfs_quotas: auth_success\n"));
697 clnt_stat
=clnt_call(clnt
, RQUOTAPROC_GETQUOTA
, my_xdr_getquota_args
, (caddr_t
)&args
, my_xdr_getquota_rslt
, (caddr_t
)&gqr
, timeout
);
699 if (clnt_stat
!= RPC_SUCCESS
) {
700 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
706 * gqr.status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
707 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
708 * something sensible.
711 switch (gqr
.status
) {
713 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr
.status
));
718 DEBUG(9,("nfs_quotas: Good quota data\n"));
719 D
.dqb_bsoftlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
720 D
.dqb_bhardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
721 D
.dqb_curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
726 D
.dqb_bsoftlimit
= 1;
728 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr
.status
));
732 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr
.status
));
736 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",
738 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
739 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
740 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
741 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
742 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
744 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
745 *dsize
= D
.dqb_bsoftlimit
;
747 if (D
.dqb_curblocks
== 1)
750 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
752 *dsize
= D
.dqb_curblocks
;
754 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
760 auth_destroy(clnt
->cl_auth
);
764 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args
.gqa_pathp
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
767 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
772 /****************************************************************************
773 try to get the disk space from disk quotas (SunOS & Solaris2 version)
774 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
775 ****************************************************************************/
777 bool disk_quotas(const char *path
,
786 struct quotctl command
;
794 SMB_STRUCT_STAT sbuf
;
798 euser_id
= geteuid();
800 if (sys_stat(path
, &sbuf
, false) == -1) {
804 devno
= sbuf
.st_ex_dev
;
805 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
806 path
, (unsigned int)devno
));
808 if ((fd
= sys_fopen(MNTTAB
, "r")) == NULL
) {
812 while (getmntent(fd
, &mnt
) == 0) {
813 if (sys_stat(mnt
.mnt_mountp
, &sbuf
, false) == -1) {
817 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
818 mnt
.mnt_mountp
, (unsigned int)devno
));
820 /* quotas are only on vxfs, UFS or NFS */
821 if ((sbuf
.st_ex_dev
== devno
) && (
822 strcmp( mnt
.mnt_fstype
, MNTTYPE_UFS
) == 0 ||
823 strcmp( mnt
.mnt_fstype
, "nfs" ) == 0 ||
824 strcmp( mnt
.mnt_fstype
, "vxfs" ) == 0 )) {
826 name
= talloc_asprintf(talloc_tos(),
835 if ((fd
= setmntent(MOUNTED
, "r")) == NULL
) {
839 while ((mnt
= getmntent(fd
)) != NULL
) {
840 if (sys_stat(mnt
->mnt_dir
, &sbuf
, false) == -1) {
843 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
845 (unsigned int)sbuf
.st_ex_dev
));
846 if (sbuf
.st_ex_dev
== devno
) {
848 name
= talloc_strdup(talloc_tos(),
866 if (strcmp(mnt
.mnt_fstype
, "nfs") == 0) {
868 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n",
870 retval
= nfs_quotas(mnt
.mnt_special
,
871 euser_id
, bsize
, dfree
, dsize
);
876 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name
));
877 if((file
=sys_open(name
, O_RDONLY
,0))<0) {
881 command
.op
= Q_GETQUOTA
;
882 command
.uid
= euser_id
;
883 command
.addr
= (caddr_t
) &D
;
884 ret
= ioctl(file
, Q_QUOTACTL
, &command
);
887 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name
));
888 ret
= quotactl(Q_GETQUOTA
, name
, euser_id
, &D
);
894 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n",
897 #if defined(SUNOS5) && defined(VXFS_QUOTA)
898 /* If normal quotactl() fails, try vxfs private calls */
899 set_effective_uid(euser_id
);
900 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt
.mnt_fstype
));
901 if ( 0 == strcmp ( mnt
.mnt_fstype
, "vxfs" )) {
903 retval
= disk_quotas_vxfs(name
, path
,
904 bsize
, dfree
, dsize
);
912 /* If softlimit is zero, set it equal to hardlimit.
915 if (D
.dqb_bsoftlimit
==0) {
916 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
919 /* Use softlimit to determine disk space. A user exceeding the quota
920 * is told that there's no space left. Writes might actually work for
921 * a bit if the hardlimit is set higher than softlimit. Effectively
922 * the disk becomes made of rubber latex and begins to expand to
923 * accommodate the user :-)
926 if (D
.dqb_bsoftlimit
==0)
929 *dsize
= D
.dqb_bsoftlimit
;
931 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
933 *dsize
= D
.dqb_curblocks
;
935 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
938 DEBUG(5,("disk_quotas for path \"%s\" returning "
939 "bsize %.0f, dfree %.0f, dsize %.0f\n",
940 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
947 #include <ufs/quota.h>
949 /****************************************************************************
950 try to get the disk space from disk quotas - OSF1 version
951 ****************************************************************************/
953 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
961 * This code presumes that OSF1 will only
962 * give out quota info when the real uid
963 * matches the effective uid. JRA.
965 euser_id
= geteuid();
967 if (set_re_uid() != 0) return False
;
969 r
= quotactl(path
,QCMD(Q_GETQUOTA
, USRQUOTA
),euser_id
,(char *) &D
);
980 if (save_errno
== EDQUOT
) /* disk quota exceeded */
983 *dsize
= D
.dqb_curblocks
;
990 /* If softlimit is zero, set it equal to hardlimit.
993 if (D
.dqb_bsoftlimit
==0)
994 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
996 /* Use softlimit to determine disk space, except when it has been exceeded */
998 if (D
.dqb_bsoftlimit
==0)
1001 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)) {
1003 *dsize
= D
.dqb_curblocks
;
1005 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1006 *dsize
= D
.dqb_bsoftlimit
;
1011 #elif defined (IRIX6)
1012 /****************************************************************************
1013 try to get the disk space from disk quotas (IRIX 6.2 version)
1014 ****************************************************************************/
1016 #include <sys/quota.h>
1019 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1024 struct fs_disk_quota F
;
1031 /* find the block device file */
1033 if ( sys_stat(path
, &S
, false) == -1 ) {
1037 devno
= S
.st_ex_dev
;
1039 fp
= setmntent(MOUNTED
,"r");
1042 while ((mnt
= getmntent(fp
))) {
1043 if ( sys_stat(mnt
->mnt_dir
, &S
, false) == -1 )
1045 if (S
.st_ex_dev
== devno
) {
1059 /* Use softlimit to determine disk space, except when it has been exceeded */
1063 if ( 0 == strcmp ( mnt
->mnt_type
, "efs" ))
1065 r
=quotactl (Q_GETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &D
);
1072 /* Use softlimit to determine disk space, except when it has been exceeded */
1074 (D
.dqb_bsoftlimit
&& D
.dqb_curblocks
>=D
.dqb_bsoftlimit
) ||
1075 (D
.dqb_bhardlimit
&& D
.dqb_curblocks
>=D
.dqb_bhardlimit
) ||
1076 (D
.dqb_fsoftlimit
&& D
.dqb_curfiles
>=D
.dqb_fsoftlimit
) ||
1077 (D
.dqb_fhardlimit
&& D
.dqb_curfiles
>=D
.dqb_fhardlimit
)
1081 *dsize
= D
.dqb_curblocks
;
1083 else if (D
.dqb_bsoftlimit
==0 && D
.dqb_bhardlimit
==0)
1089 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1090 *dsize
= D
.dqb_bsoftlimit
;
1094 else if ( 0 == strcmp ( mnt
->mnt_type
, "xfs" ))
1096 r
=quotactl (Q_XGETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &F
);
1102 DEBUG(5, ("quotactl for uid=%u: %s", euser_id
, strerror(errno
)));
1106 /* No quota for this user. */
1107 if (F
.d_blk_softlimit
==0 && F
.d_blk_hardlimit
==0)
1112 /* Use softlimit to determine disk space, except when it has been exceeded */
1114 (F
.d_blk_softlimit
&& F
.d_bcount
>=F
.d_blk_softlimit
) ||
1115 (F
.d_blk_hardlimit
&& F
.d_bcount
>=F
.d_blk_hardlimit
) ||
1116 (F
.d_ino_softlimit
&& F
.d_icount
>=F
.d_ino_softlimit
) ||
1117 (F
.d_ino_hardlimit
&& F
.d_icount
>=F
.d_ino_hardlimit
)
1121 *dsize
= F
.d_bcount
;
1125 *dfree
= (F
.d_blk_softlimit
- F
.d_bcount
);
1126 *dsize
= F
.d_blk_softlimit
? F
.d_blk_softlimit
: F
.d_blk_hardlimit
;
1142 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1143 #include <ufs/ufs/quota.h>
1144 #include <machine/param.h>
1146 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
1147 #include <jfs/quota.h>
1148 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
1149 #define dqb_curfiles dqb_curinodes
1150 #define dqb_fhardlimit dqb_ihardlimit
1151 #define dqb_fsoftlimit dqb_isoftlimit
1152 #ifdef _AIXVERSION_530
1153 #include <sys/statfs.h>
1154 #include <sys/vmount.h>
1155 #endif /* AIX 5.3 */
1156 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1157 #include <sys/quota.h>
1161 #if defined(__FreeBSD__) || defined(__DragonFly__)
1163 #include <rpc/rpc.h>
1164 #include <rpc/types.h>
1165 #include <rpcsvc/rquota.h>
1166 #ifdef HAVE_RPC_NETTYPE_H
1167 #include <rpc/nettype.h>
1169 #include <rpc/xdr.h>
1171 static int my_xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
1173 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
1175 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
1180 static int my_xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
1184 if (!xdr_int(xdrsp
, "astat
)) {
1185 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
1188 gqr
->status
= quotastat
;
1190 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
1191 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
1194 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
1195 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
1198 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
1199 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
1202 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
1203 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
1206 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
1207 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
1213 /* Works on FreeBSD, too. :-) */
1214 static bool nfs_quotas(char *nfspath
, uid_t euser_id
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1216 uid_t uid
= euser_id
;
1218 char *mnttype
= nfspath
;
1220 struct getquota_rslt gqr
;
1221 struct getquota_args args
;
1222 char *cutstr
, *pathname
, *host
, *testpath
;
1224 static struct timeval timeout
= {2,0};
1225 enum clnt_stat clnt_stat
;
1228 *bsize
= *dfree
= *dsize
= (uint64_t)0;
1230 len
=strcspn(mnttype
, ":");
1231 pathname
=strstr(mnttype
, ":");
1232 cutstr
= (char *) SMB_MALLOC(len
+1);
1236 memset(cutstr
, '\0', len
+1);
1237 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
1238 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
1239 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
1240 testpath
=strchr_m(mnttype
, ':');
1241 args
.gqa_pathp
= testpath
+1;
1244 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
, "udp"));
1246 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
1251 clnt
->cl_auth
= authunix_create_default();
1252 DEBUG(9,("nfs_quotas: auth_success\n"));
1254 clnt_stat
=clnt_call(clnt
, RQUOTAPROC_GETQUOTA
, (const xdrproc_t
) my_xdr_getquota_args
, (caddr_t
)&args
, (const xdrproc_t
) my_xdr_getquota_rslt
, (caddr_t
)&gqr
, timeout
);
1256 if (clnt_stat
!= RPC_SUCCESS
) {
1257 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
1263 * gqr->status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
1264 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
1265 * something sensible.
1268 switch (gqr
.status
) {
1270 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr
.status
));
1275 DEBUG(9,("nfs_quotas: Good quota data\n"));
1276 D
.dqb_bsoftlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
1277 D
.dqb_bhardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
1278 D
.dqb_curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
1283 D
.dqb_bsoftlimit
= 1;
1284 D
.dqb_curblocks
= 1;
1285 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr
.status
));
1289 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr
.status
));
1293 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",
1295 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
1296 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
1297 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
1298 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
1299 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
1301 if (D
.dqb_bsoftlimit
== 0)
1302 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1303 if (D
.dqb_bsoftlimit
== 0)
1306 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
1307 *dsize
= D
.dqb_bsoftlimit
;
1309 if (D
.dqb_curblocks
== 1)
1312 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
1314 *dsize
= D
.dqb_curblocks
;
1316 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1322 auth_destroy(clnt
->cl_auth
);
1326 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args
.gqa_pathp
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
1329 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
1335 /****************************************************************************
1336 try to get the disk space from disk quotas - default version
1337 ****************************************************************************/
1339 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1344 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__)
1348 /* find the block device file */
1351 /* Need to set the cache flag to 1 for HPUX. Seems
1352 * to have a significant performance boost when
1353 * lstat calls on /dev access this function.
1355 if ((sys_stat(path
, &S
, false)<0)
1356 || (devnm(S_IFBLK
, S
.st_ex_dev
, dev_disk
, 256, 1)<0))
1358 if ((sys_stat(path
, &S
, false)<0)
1359 || (devnm(S_IFBLK
, S
.st_ex_dev
, dev_disk
, 256, 0)<0))
1361 #endif /* ifdef HPUX */
1363 #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__) */
1365 euser_id
= geteuid();
1368 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
1370 if (set_re_uid() != 0) return False
;
1372 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
1376 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1378 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
1380 #if defined(__FreeBSD__) || defined(__DragonFly__)
1382 struct statfs
*mnts
;
1386 if (sys_stat(path
, &st
, false) < 0)
1388 devno
= st
.st_ex_dev
;
1390 mntsize
= getmntinfo(&mnts
,MNT_NOWAIT
);
1394 for (i
= 0; i
< mntsize
; i
++) {
1395 if (sys_stat(mnts
[i
].f_mntonname
, &st
, false) < 0)
1397 if (st
.st_ex_dev
== devno
)
1406 #if defined(__FreeBSD__) || defined(__DragonFly__)
1407 if (strcmp(mnts
[i
].f_fstypename
,"nfs") == 0) {
1409 retval
= nfs_quotas(mnts
[i
].f_mntfromname
,euser_id
,bsize
,dfree
,dsize
);
1415 egrp_id
= getegid();
1416 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
1418 /* As FreeBSD has group quotas, if getting the user
1419 quota fails, try getting the group instead. */
1421 r
= quotactl(path
,QCMD(Q_GETQUOTA
,GRPQUOTA
),egrp_id
,(char *) &D
);
1427 /* AIX has both USER and GROUP quotas:
1428 Get the USER quota (ohnielse@fysik.dtu.dk) */
1429 #ifdef _AIXVERSION_530
1431 struct statfs statbuf
;
1432 quota64_t user_quota
;
1433 if (statfs(path
,&statbuf
) != 0)
1435 if(statbuf
.f_vfstype
== MNT_J2
)
1437 /* For some reason we need to be root for jfs2 */
1439 r
= quotactl(path
,QCMD(Q_J2GETQUOTA
,USRQUOTA
),euser_id
,(char *) &user_quota
);
1441 /* Copy results to old struct to let the following code work as before */
1442 D
.dqb_curblocks
= user_quota
.bused
;
1443 D
.dqb_bsoftlimit
= user_quota
.bsoft
;
1444 D
.dqb_bhardlimit
= user_quota
.bhard
;
1445 D
.dqb_curfiles
= user_quota
.iused
;
1446 D
.dqb_fsoftlimit
= user_quota
.isoft
;
1447 D
.dqb_fhardlimit
= user_quota
.ihard
;
1449 else if(statbuf
.f_vfstype
== MNT_JFS
)
1451 #endif /* AIX 5.3 */
1453 if (set_re_uid() != 0)
1455 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
1457 #ifdef _AIXVERSION_530
1460 r
= 1; /* Fail for other FS-types */
1462 #endif /* AIX 5.3 */
1463 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1464 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
1465 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1468 /* Use softlimit to determine disk space, except when it has been exceeded */
1469 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1471 #else /* !__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
1473 #endif /*!__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
1477 if (errno
== EDQUOT
)
1480 *dsize
=D
.dqb_curblocks
;
1486 /* If softlimit is zero, set it equal to hardlimit.
1489 if (D
.dqb_bsoftlimit
==0)
1490 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1492 if (D
.dqb_bsoftlimit
==0)
1494 /* Use softlimit to determine disk space, except when it has been exceeded */
1495 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)
1496 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__)
1497 ||((D
.dqb_curfiles
>D
.dqb_fsoftlimit
) && (D
.dqb_fsoftlimit
!= 0))
1501 *dsize
= D
.dqb_curblocks
;
1504 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1505 *dsize
= D
.dqb_bsoftlimit
;
1512 #if defined(VXFS_QUOTA)
1514 /****************************************************************************
1515 Try to get the disk space from Veritas disk quotas.
1516 David Lee <T.D.Lee@durham.ac.uk> August 1999.
1518 Background assumptions:
1519 Potentially under many Operating Systems. Initially Solaris 2.
1521 My guess is that Veritas is largely, though not entirely,
1522 independent of OS. So I have separated it out.
1524 There may be some details. For example, OS-specific "include" files.
1526 It is understood that HPUX 10 somehow gets Veritas quotas without
1527 any special effort; if so, this routine need not be compiled in.
1528 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
1531 It is understood that Veritas do not publicly support this ioctl interface.
1532 Rather their preference would be for the user (us) to call the native
1533 OS and then for the OS itself to call through to the VxFS filesystem.
1534 Presumably HPUX 10, see above, does this.
1537 Add your OS to "IFLIST" below.
1538 Get it to compile successfully:
1539 Almost certainly "include"s require attention: see SUNOS5.
1540 In the main code above, arrange for it to be called: see SUNOS5.
1543 ****************************************************************************/
1546 * This "if" is a list of ports:
1547 * if defined(OS1) || defined(OS2) || ...
1552 #include <sys/fs/vx_solaris.h>
1554 #include <sys/fs/vx_machdep.h>
1555 #include <sys/fs/vx_layout.h>
1556 #include <sys/fs/vx_quota.h>
1557 #include <sys/fs/vx_aioctl.h>
1558 #include <sys/fs/vx_ioctl.h>
1560 bool disk_quotas_vxfs(const char *name
, char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1562 uid_t user_id
, euser_id
;
1565 struct vx_quotctl quotabuf
;
1566 struct vx_genioctl genbuf
;
1571 * "name" may or may not include a trailing "/quotas".
1572 * Arranging consistency of calling here in "quotas.c" may not be easy and
1573 * it might be easier to examine and adjust it here.
1574 * Fortunately, VxFS seems not to mind at present.
1576 qfname
= talloc_strdup(talloc_tos(), name
);
1580 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
1582 euser_id
= geteuid();
1583 set_effective_uid(0);
1585 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname
));
1586 if((file
=sys_open(qfname
, O_RDONLY
,0))<0) {
1587 set_effective_uid(euser_id
);
1590 genbuf
.ioc_cmd
= VX_QUOTACTL
;
1591 genbuf
.ioc_up
= (void *) "abuf
;
1593 quotabuf
.cmd
= VX_GETQUOTA
;
1594 quotabuf
.uid
= euser_id
;
1595 quotabuf
.addr
= (caddr_t
) &D
;
1596 ret
= ioctl(file
, VX_ADMIN_IOCTL
, &genbuf
);
1599 set_effective_uid(euser_id
);
1602 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno
) ));
1606 /* If softlimit is zero, set it equal to hardlimit.
1609 if (D
.dqb_bsoftlimit
==0)
1610 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1612 /* Use softlimit to determine disk space. A user exceeding the quota is told
1613 * that there's no space left. Writes might actually work for a bit if the
1614 * hardlimit is set higher than softlimit. Effectively the disk becomes
1615 * made of rubber latex and begins to expand to accommodate the user :-)
1617 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
1618 path
, D
.dqb_curblocks
, D
.dqb_bsoftlimit
, D
.dqb_bhardlimit
,
1619 D
.dqb_curfiles
, D
.dqb_fsoftlimit
, D
.dqb_fhardlimit
));
1621 if (D
.dqb_bsoftlimit
==0)
1624 *dsize
= D
.dqb_bsoftlimit
;
1626 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
1628 *dsize
= D
.dqb_curblocks
;
1630 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1632 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
1633 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
1638 #endif /* SUNOS5 || ... */
1640 #endif /* VXFS_QUOTA */
1642 #else /* WITH_QUOTAS */
1644 bool disk_quotas(const char *path
,uint64_t *bsize
,uint64_t *dfree
,uint64_t *dsize
)
1646 (*bsize
) = 512; /* This value should be ignored */
1648 /* And just to be sure we set some values that hopefully */
1649 /* will be larger that any possible real-world value */
1650 (*dfree
) = (uint64_t)-1;
1651 (*dsize
) = (uint64_t)-1;
1653 /* As we have select not to use quotas, allways fail */
1656 #endif /* WITH_QUOTAS */
1658 #else /* HAVE_SYS_QUOTAS */
1659 /* wrapper to the new sys_quota interface
1660 this file should be removed later
1662 bool disk_quotas(const char *path
,uint64_t *bsize
,uint64_t *dfree
,uint64_t *dsize
)
1671 r
=sys_get_quota(path
, SMB_USER_QUOTA_TYPE
, id
, &D
);
1673 /* Use softlimit to determine disk space, except when it has been exceeded */
1676 if (errno
== EDQUOT
) {
1678 *dsize
=D
.curblocks
;
1681 goto try_group_quota
;
1685 /* Use softlimit to determine disk space, except when it has been exceeded */
1687 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
1688 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
1689 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
1690 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
1693 *dsize
= D
.curblocks
;
1694 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
1695 goto try_group_quota
;
1697 if (D
.softlimit
== 0)
1698 D
.softlimit
= D
.hardlimit
;
1699 *dfree
= D
.softlimit
- D
.curblocks
;
1700 *dsize
= D
.softlimit
;
1709 r
=sys_get_quota(path
, SMB_GROUP_QUOTA_TYPE
, id
, &D
);
1711 /* Use softlimit to determine disk space, except when it has been exceeded */
1714 if (errno
== EDQUOT
) {
1716 *dsize
=D
.curblocks
;
1723 /* Use softlimit to determine disk space, except when it has been exceeded */
1725 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
1726 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
1727 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
1728 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
1731 *dsize
= D
.curblocks
;
1732 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
1735 if (D
.softlimit
== 0)
1736 D
.softlimit
= D
.hardlimit
;
1737 *dfree
= D
.softlimit
- D
.curblocks
;
1738 *dsize
= D
.softlimit
;
1743 #endif /* HAVE_SYS_QUOTAS */