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
28 #include "smbd/smbd.h"
29 #include "system/filesys.h"
32 #define DBGC_CLASS DBGC_QUOTA
34 #ifndef HAVE_SYS_QUOTAS
36 /* just a quick hack because sysquotas.h is included before linux/quota.h */
37 #ifdef QUOTABLOCK_SIZE
38 #undef QUOTABLOCK_SIZE
43 #if defined(VXFS_QUOTA)
46 * In addition to their native filesystems, some systems have Veritas VxFS.
47 * Declare here, define at end: reduces likely "include" interaction problems.
48 * David Lee <T.D.Lee@durham.ac.uk>
50 bool disk_quotas_vxfs(const char *name
, char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
);
52 #endif /* VXFS_QUOTA */
57 #include <sys/types.h>
61 * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
62 * So we include all the files has *should* be in the system into a large,
63 * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA.
66 #include "samba_linux_quota.h"
68 typedef struct _LINUX_SMB_DISK_QUOTA
{
70 uint64_t hardlimit
; /* In bsize units. */
71 uint64_t softlimit
; /* In bsize units. */
72 uint64_t curblocks
; /* In bsize units. */
73 uint64_t ihardlimit
; /* inode hard limit. */
74 uint64_t isoftlimit
; /* inode soft limit. */
75 uint64_t curinodes
; /* Current used inodes. */
76 } LINUX_SMB_DISK_QUOTA
;
81 * (essentially taken from FreeBSD / SUNOS5 section)
84 #include <rpc/types.h>
85 #include <rpcsvc/rquota.h>
86 #ifdef HAVE_RPC_NETTYPE_H
87 #include <rpc/nettype.h>
91 static int my_xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
95 if (!xdr_int(xdrsp
, "astat
)) {
96 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
99 gqr
->status
= quotastat
;
101 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
102 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
105 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
106 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
109 if (!xdr_int(xdrsp
, (int *)&gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
110 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
113 if (!xdr_int(xdrsp
, (int *)&gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
114 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
117 if (!xdr_int(xdrsp
, (int *)&gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
118 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
124 static bool nfs_quotas(char *nfspath
, uid_t euser_id
, uint64_t *bsize
,
125 uint64_t *dfree
, uint64_t *dsize
)
127 uid_t uid
= euser_id
;
128 LINUX_SMB_DISK_QUOTA D
;
129 char *mnttype
= nfspath
;
131 struct getquota_rslt gqr
;
132 struct getquota_args args
;
133 char *cutstr
, *pathname
, *host
, *testpath
;
135 static struct timeval timeout
= {2,0};
136 enum clnt_stat clnt_stat
;
139 *bsize
= *dfree
= *dsize
= (uint64_t)0;
141 len
=strcspn(mnttype
, ":");
142 pathname
=strstr(mnttype
, ":");
143 cutstr
= (char *) SMB_MALLOC(len
+1);
147 memset(cutstr
, '\0', len
+1);
148 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
149 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
150 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
151 testpath
=strchr_m(mnttype
, ':');
152 args
.gqa_pathp
= testpath
+1;
155 DEBUG(5, ("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers "
156 "\"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
,
159 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
164 clnt
->cl_auth
= authunix_create_default();
165 DEBUG(9,("nfs_quotas: auth_success\n"));
167 clnt_stat
=clnt_call(clnt
,
169 (const xdrproc_t
)my_xdr_getquota_args
,
171 (const xdrproc_t
)my_xdr_getquota_rslt
,
172 (caddr_t
)&gqr
, timeout
);
174 if (clnt_stat
!= RPC_SUCCESS
) {
175 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
181 * gqr.status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
182 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
183 * something sensible.
186 switch (gqr
.status
) {
188 DEBUG(9, ("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n",
194 DEBUG(9,("nfs_quotas: Good quota data\n"));
195 D
.softlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
196 D
.hardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
197 D
.curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
204 DEBUG(9, ("nfs_quotas: Remote Quotas returned \"%i\" \n",
209 DEBUG(9, ("nfs_quotas: Remote Quotas Questionable! "
210 "Error \"%i\" \n", gqr
.status
));
214 DEBUG(10, ("nfs_quotas: Let`s look at D a bit closer... "
215 "status \"%i\" bsize \"%i\" active? \"%i\" bhard "
216 "\"%i\" bsoft \"%i\" curb \"%i\" \n",
218 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
219 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
220 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
221 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
222 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
224 if (D
.softlimit
== 0)
225 D
.softlimit
= D
.hardlimit
;
226 if (D
.softlimit
== 0)
229 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
230 *dsize
= D
.softlimit
;
232 if (D
.curblocks
== 1)
235 if (D
.curblocks
> D
.softlimit
) {
237 *dsize
= D
.curblocks
;
239 *dfree
= D
.softlimit
- D
.curblocks
;
245 auth_destroy(clnt
->cl_auth
);
249 DEBUG(5, ("nfs_quotas: For path \"%s\" returning "
250 "bsize %.0f, dfree %.0f, dsize %.0f\n",
251 args
.gqa_pathp
, (double)*bsize
, (double)*dfree
,
255 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
259 /* end of nfs quota section */
261 #ifdef HAVE_LINUX_DQBLK_XFS_H
262 #include <linux/dqblk_xfs.h>
264 /****************************************************************************
265 Abstract out the XFS Quota Manager quota get call.
266 ****************************************************************************/
268 static int get_smb_linux_xfs_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
270 struct fs_disk_quota D
;
275 ret
= quotactl(QCMD(Q_XGETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
278 ret
= quotactl(QCMD(Q_XGETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
283 dp
->bsize
= (uint64_t)512;
284 dp
->softlimit
= (uint64_t)D
.d_blk_softlimit
;
285 dp
->hardlimit
= (uint64_t)D
.d_blk_hardlimit
;
286 dp
->ihardlimit
= (uint64_t)D
.d_ino_hardlimit
;
287 dp
->isoftlimit
= (uint64_t)D
.d_ino_softlimit
;
288 dp
->curinodes
= (uint64_t)D
.d_icount
;
289 dp
->curblocks
= (uint64_t)D
.d_bcount
;
294 static int get_smb_linux_xfs_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
296 DEBUG(0,("XFS quota support not available\n"));
303 /****************************************************************************
304 Abstract out the old and new Linux quota get calls.
305 ****************************************************************************/
307 static int get_smb_linux_v1_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
309 struct v1_kern_dqblk D
;
314 ret
= quotactl(QCMD(Q_V1_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
316 if (ret
&& errno
!= EDQUOT
)
317 ret
= quotactl(QCMD(Q_V1_GETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
319 if (ret
&& errno
!= EDQUOT
)
322 dp
->bsize
= (uint64_t)QUOTABLOCK_SIZE
;
323 dp
->softlimit
= (uint64_t)D
.dqb_bsoftlimit
;
324 dp
->hardlimit
= (uint64_t)D
.dqb_bhardlimit
;
325 dp
->ihardlimit
= (uint64_t)D
.dqb_ihardlimit
;
326 dp
->isoftlimit
= (uint64_t)D
.dqb_isoftlimit
;
327 dp
->curinodes
= (uint64_t)D
.dqb_curinodes
;
328 dp
->curblocks
= (uint64_t)D
.dqb_curblocks
;
333 static int get_smb_linux_v2_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
335 struct v2_kern_dqblk D
;
340 ret
= quotactl(QCMD(Q_V2_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
342 if (ret
&& errno
!= EDQUOT
)
343 ret
= quotactl(QCMD(Q_V2_GETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
345 if (ret
&& errno
!= EDQUOT
)
348 dp
->bsize
= (uint64_t)QUOTABLOCK_SIZE
;
349 dp
->softlimit
= (uint64_t)D
.dqb_bsoftlimit
;
350 dp
->hardlimit
= (uint64_t)D
.dqb_bhardlimit
;
351 dp
->ihardlimit
= (uint64_t)D
.dqb_ihardlimit
;
352 dp
->isoftlimit
= (uint64_t)D
.dqb_isoftlimit
;
353 dp
->curinodes
= (uint64_t)D
.dqb_curinodes
;
354 dp
->curblocks
= ((uint64_t)D
.dqb_curspace
) / dp
->bsize
;
359 /****************************************************************************
360 Brand-new generic quota interface.
361 ****************************************************************************/
363 static int get_smb_linux_gen_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
370 ret
= quotactl(QCMD(Q_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
372 if (ret
&& errno
!= EDQUOT
)
373 ret
= quotactl(QCMD(Q_GETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
375 if (ret
&& errno
!= EDQUOT
)
378 dp
->bsize
= (uint64_t)QUOTABLOCK_SIZE
;
379 dp
->softlimit
= (uint64_t)D
.dqb_bsoftlimit
;
380 dp
->hardlimit
= (uint64_t)D
.dqb_bhardlimit
;
381 dp
->ihardlimit
= (uint64_t)D
.dqb_ihardlimit
;
382 dp
->isoftlimit
= (uint64_t)D
.dqb_isoftlimit
;
383 dp
->curinodes
= (uint64_t)D
.dqb_curinodes
;
384 dp
->curblocks
= ((uint64_t)D
.dqb_curspace
) / dp
->bsize
;
389 /****************************************************************************
390 Try to get the disk space from disk quotas (LINUX version).
391 ****************************************************************************/
393 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
398 LINUX_SMB_DISK_QUOTA D
;
407 euser_id
= geteuid();
410 /* find the block device file */
412 if (sys_stat(path
, &S
, false) == -1 )
415 devno
= S
.st_ex_dev
;
417 if ((fp
= setmntent(MOUNTED
,"r")) == NULL
)
422 while ((mnt
= getmntent(fp
))) {
423 if (sys_stat(mnt
->mnt_dir
, &S
, false) == -1)
426 if (S
.st_ex_dev
== devno
) {
439 if (strcmp(mnt
->mnt_type
, "nfs") == 0) {
441 retval
= nfs_quotas(mnt
->mnt_fsname
, euser_id
, bsize
, dfree
, dsize
);
446 if (strcmp(mnt
->mnt_type
, "xfs")==0) {
447 r
=get_smb_linux_xfs_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
449 r
=get_smb_linux_gen_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
450 if (r
== -1 && errno
!= EDQUOT
) {
451 r
=get_smb_linux_v2_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
452 if (r
== -1 && errno
!= EDQUOT
)
453 r
=get_smb_linux_v1_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
459 /* Use softlimit to determine disk space, except when it has been exceeded */
462 if (errno
== EDQUOT
) {
471 /* Use softlimit to determine disk space, except when it has been exceeded */
473 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
474 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
475 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
476 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
479 *dsize
= D
.curblocks
;
480 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
483 if (D
.softlimit
== 0)
484 D
.softlimit
= D
.hardlimit
;
485 *dfree
= D
.softlimit
- D
.curblocks
;
486 *dsize
= D
.softlimit
;
492 #elif defined(SUNOS5) || defined(SUNOS4)
495 #include <sys/param.h>
497 #include <sys/fs/ufs_quota.h>
498 #include <sys/mnttab.h>
499 #include <sys/mntent.h>
500 #else /* defined(SUNOS4) */
501 #include <ufs/quota.h>
507 /****************************************************************************
508 Allows querying of remote hosts for quotas on NFS mounted shares.
509 Supports normal NFS and AMD mounts.
510 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
511 ****************************************************************************/
514 #include <rpc/types.h>
515 #include <rpcsvc/rquota.h>
516 #include <rpc/nettype.h>
519 static int my_xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
523 if (!xdr_int(xdrsp
, "astat
)) {
524 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
527 gqr
->status
= quotastat
;
529 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
530 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
533 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
534 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
537 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
538 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
541 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
542 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
545 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
546 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
552 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
553 static bool nfs_quotas(char *nfspath
, uid_t euser_id
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
555 uid_t uid
= euser_id
;
557 char *mnttype
= nfspath
;
559 struct getquota_rslt gqr
;
560 struct getquota_args args
;
561 char *cutstr
, *pathname
, *host
, *testpath
;
563 static struct timeval timeout
= {2,0};
564 enum clnt_stat clnt_stat
;
567 *bsize
= *dfree
= *dsize
= (uint64_t)0;
569 len
=strcspn(mnttype
, ":");
570 pathname
=strstr(mnttype
, ":");
571 cutstr
= (char *) SMB_MALLOC(len
+1);
575 memset(cutstr
, '\0', len
+1);
576 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
577 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
578 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
579 testpath
=strchr_m(mnttype
, ':');
580 args
.gqa_pathp
= testpath
+1;
583 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
, "udp"));
585 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
590 clnt
->cl_auth
= authunix_create_default();
591 DEBUG(9,("nfs_quotas: auth_success\n"));
593 clnt_stat
=clnt_call(clnt
, RQUOTAPROC_GETQUOTA
, my_xdr_getquota_args
, (caddr_t
)&args
, my_xdr_getquota_rslt
, (caddr_t
)&gqr
, timeout
);
595 if (clnt_stat
!= RPC_SUCCESS
) {
596 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
602 * gqr.status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
603 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
604 * something sensible.
607 switch (gqr
.status
) {
609 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr
.status
));
614 DEBUG(9,("nfs_quotas: Good quota data\n"));
615 D
.dqb_bsoftlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
616 D
.dqb_bhardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
617 D
.dqb_curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
622 D
.dqb_bsoftlimit
= 1;
624 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr
.status
));
628 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr
.status
));
632 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",
634 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
635 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
636 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
637 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
638 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
640 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
641 *dsize
= D
.dqb_bsoftlimit
;
643 if (D
.dqb_curblocks
== 1)
646 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
648 *dsize
= D
.dqb_curblocks
;
650 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
656 auth_destroy(clnt
->cl_auth
);
660 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args
.gqa_pathp
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
663 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
668 /****************************************************************************
669 try to get the disk space from disk quotas (SunOS & Solaris2 version)
670 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
671 ****************************************************************************/
673 bool disk_quotas(const char *path
,
682 struct quotctl command
;
690 SMB_STRUCT_STAT sbuf
;
694 euser_id
= geteuid();
696 if (sys_stat(path
, &sbuf
, false) == -1) {
700 devno
= sbuf
.st_ex_dev
;
701 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
702 path
, (unsigned int)devno
));
704 if ((fd
= fopen(MNTTAB
, "r")) == NULL
) {
708 while (getmntent(fd
, &mnt
) == 0) {
709 if (sys_stat(mnt
.mnt_mountp
, &sbuf
, false) == -1) {
713 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
714 mnt
.mnt_mountp
, (unsigned int)devno
));
716 /* quotas are only on vxfs, UFS or NFS */
717 if ((sbuf
.st_ex_dev
== devno
) && (
718 strcmp( mnt
.mnt_fstype
, MNTTYPE_UFS
) == 0 ||
719 strcmp( mnt
.mnt_fstype
, "nfs" ) == 0 ||
720 strcmp( mnt
.mnt_fstype
, "vxfs" ) == 0 )) {
722 name
= talloc_asprintf(talloc_tos(),
731 if ((fd
= setmntent(MOUNTED
, "r")) == NULL
) {
735 while ((mnt
= getmntent(fd
)) != NULL
) {
736 if (sys_stat(mnt
->mnt_dir
, &sbuf
, false) == -1) {
739 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
741 (unsigned int)sbuf
.st_ex_dev
));
742 if (sbuf
.st_ex_dev
== devno
) {
744 name
= talloc_strdup(talloc_tos(),
762 if (strcmp(mnt
.mnt_fstype
, "nfs") == 0) {
764 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n",
766 retval
= nfs_quotas(mnt
.mnt_special
,
767 euser_id
, bsize
, dfree
, dsize
);
772 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name
));
773 if((file
=open(name
, O_RDONLY
,0))<0) {
777 command
.op
= Q_GETQUOTA
;
778 command
.uid
= euser_id
;
779 command
.addr
= (caddr_t
) &D
;
780 ret
= ioctl(file
, Q_QUOTACTL
, &command
);
783 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name
));
784 ret
= quotactl(Q_GETQUOTA
, name
, euser_id
, &D
);
790 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n",
793 #if defined(SUNOS5) && defined(VXFS_QUOTA)
794 /* If normal quotactl() fails, try vxfs private calls */
795 set_effective_uid(euser_id
);
796 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt
.mnt_fstype
));
797 if ( 0 == strcmp ( mnt
.mnt_fstype
, "vxfs" )) {
799 retval
= disk_quotas_vxfs(name
, path
,
800 bsize
, dfree
, dsize
);
808 /* If softlimit is zero, set it equal to hardlimit.
811 if (D
.dqb_bsoftlimit
==0) {
812 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
815 /* Use softlimit to determine disk space. A user exceeding the quota
816 * is told that there's no space left. Writes might actually work for
817 * a bit if the hardlimit is set higher than softlimit. Effectively
818 * the disk becomes made of rubber latex and begins to expand to
819 * accommodate the user :-)
822 if (D
.dqb_bsoftlimit
==0)
825 *dsize
= D
.dqb_bsoftlimit
;
827 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
829 *dsize
= D
.dqb_curblocks
;
831 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
834 DEBUG(5,("disk_quotas for path \"%s\" returning "
835 "bsize %.0f, dfree %.0f, dsize %.0f\n",
836 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
843 #include <ufs/quota.h>
845 /****************************************************************************
846 try to get the disk space from disk quotas - OSF1 version
847 ****************************************************************************/
849 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
857 * This code presumes that OSF1 will only
858 * give out quota info when the real uid
859 * matches the effective uid. JRA.
861 euser_id
= geteuid();
863 if (set_re_uid() != 0) return False
;
865 r
= quotactl(path
,QCMD(Q_GETQUOTA
, USRQUOTA
),euser_id
,(char *) &D
);
876 if (save_errno
== EDQUOT
) /* disk quota exceeded */
879 *dsize
= D
.dqb_curblocks
;
886 /* If softlimit is zero, set it equal to hardlimit.
889 if (D
.dqb_bsoftlimit
==0)
890 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
892 /* Use softlimit to determine disk space, except when it has been exceeded */
894 if (D
.dqb_bsoftlimit
==0)
897 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)) {
899 *dsize
= D
.dqb_curblocks
;
901 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
902 *dsize
= D
.dqb_bsoftlimit
;
907 #elif defined (IRIX6)
908 /****************************************************************************
909 try to get the disk space from disk quotas (IRIX 6.2 version)
910 ****************************************************************************/
912 #include <sys/quota.h>
915 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
920 struct fs_disk_quota F
;
927 /* find the block device file */
929 if ( sys_stat(path
, &S
, false) == -1 ) {
933 devno
= S
.st_ex_dev
;
935 fp
= setmntent(MOUNTED
,"r");
938 while ((mnt
= getmntent(fp
))) {
939 if ( sys_stat(mnt
->mnt_dir
, &S
, false) == -1 )
941 if (S
.st_ex_dev
== devno
) {
955 /* Use softlimit to determine disk space, except when it has been exceeded */
959 if ( 0 == strcmp ( mnt
->mnt_type
, "efs" ))
961 r
=quotactl (Q_GETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &D
);
968 /* Use softlimit to determine disk space, except when it has been exceeded */
970 (D
.dqb_bsoftlimit
&& D
.dqb_curblocks
>=D
.dqb_bsoftlimit
) ||
971 (D
.dqb_bhardlimit
&& D
.dqb_curblocks
>=D
.dqb_bhardlimit
) ||
972 (D
.dqb_fsoftlimit
&& D
.dqb_curfiles
>=D
.dqb_fsoftlimit
) ||
973 (D
.dqb_fhardlimit
&& D
.dqb_curfiles
>=D
.dqb_fhardlimit
)
977 *dsize
= D
.dqb_curblocks
;
979 else if (D
.dqb_bsoftlimit
==0 && D
.dqb_bhardlimit
==0)
985 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
986 *dsize
= D
.dqb_bsoftlimit
;
990 else if ( 0 == strcmp ( mnt
->mnt_type
, "xfs" ))
992 r
=quotactl (Q_XGETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &F
);
998 DEBUG(5, ("quotactl for uid=%u: %s", euser_id
, strerror(errno
)));
1002 /* No quota for this user. */
1003 if (F
.d_blk_softlimit
==0 && F
.d_blk_hardlimit
==0)
1008 /* Use softlimit to determine disk space, except when it has been exceeded */
1010 (F
.d_blk_softlimit
&& F
.d_bcount
>=F
.d_blk_softlimit
) ||
1011 (F
.d_blk_hardlimit
&& F
.d_bcount
>=F
.d_blk_hardlimit
) ||
1012 (F
.d_ino_softlimit
&& F
.d_icount
>=F
.d_ino_softlimit
) ||
1013 (F
.d_ino_hardlimit
&& F
.d_icount
>=F
.d_ino_hardlimit
)
1017 *dsize
= F
.d_bcount
;
1021 *dfree
= (F
.d_blk_softlimit
- F
.d_bcount
);
1022 *dsize
= F
.d_blk_softlimit
? F
.d_blk_softlimit
: F
.d_blk_hardlimit
;
1038 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1039 #include <ufs/ufs/quota.h>
1040 #include <machine/param.h>
1042 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
1043 #include <jfs/quota.h>
1044 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
1045 #define dqb_curfiles dqb_curinodes
1046 #define dqb_fhardlimit dqb_ihardlimit
1047 #define dqb_fsoftlimit dqb_isoftlimit
1048 #ifdef _AIXVERSION_530
1049 #include <sys/statfs.h>
1050 #include <sys/vmount.h>
1051 #endif /* AIX 5.3 */
1052 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1053 #include <sys/quota.h>
1057 #if defined(__FreeBSD__) || defined(__DragonFly__)
1059 #include <rpc/rpc.h>
1060 #include <rpc/types.h>
1061 #include <rpcsvc/rquota.h>
1062 #ifdef HAVE_RPC_NETTYPE_H
1063 #include <rpc/nettype.h>
1065 #include <rpc/xdr.h>
1067 static int my_xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
1071 if (!xdr_int(xdrsp
, "astat
)) {
1072 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
1075 gqr
->status
= quotastat
;
1077 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
1078 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
1081 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
1082 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
1085 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
1086 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
1089 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
1090 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
1093 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
1094 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
1100 /* Works on FreeBSD, too. :-) */
1101 static bool nfs_quotas(char *nfspath
, uid_t euser_id
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1103 uid_t uid
= euser_id
;
1105 char *mnttype
= nfspath
;
1107 struct getquota_rslt gqr
;
1108 struct getquota_args args
;
1109 char *cutstr
, *pathname
, *host
, *testpath
;
1111 static struct timeval timeout
= {2,0};
1112 enum clnt_stat clnt_stat
;
1115 *bsize
= *dfree
= *dsize
= (uint64_t)0;
1117 len
=strcspn(mnttype
, ":");
1118 pathname
=strstr(mnttype
, ":");
1119 cutstr
= (char *) SMB_MALLOC(len
+1);
1123 memset(cutstr
, '\0', len
+1);
1124 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
1125 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
1126 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
1127 testpath
=strchr_m(mnttype
, ':');
1128 args
.gqa_pathp
= testpath
+1;
1131 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
, "udp"));
1133 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
1138 clnt
->cl_auth
= authunix_create_default();
1139 DEBUG(9,("nfs_quotas: auth_success\n"));
1141 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
);
1143 if (clnt_stat
!= RPC_SUCCESS
) {
1144 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
1150 * gqr->status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
1151 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
1152 * something sensible.
1155 switch (gqr
.status
) {
1157 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr
.status
));
1162 DEBUG(9,("nfs_quotas: Good quota data\n"));
1163 D
.dqb_bsoftlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
1164 D
.dqb_bhardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
1165 D
.dqb_curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
1170 D
.dqb_bsoftlimit
= 1;
1171 D
.dqb_curblocks
= 1;
1172 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr
.status
));
1176 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr
.status
));
1180 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",
1182 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
1183 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
1184 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
1185 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
1186 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
1188 if (D
.dqb_bsoftlimit
== 0)
1189 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1190 if (D
.dqb_bsoftlimit
== 0)
1193 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
1194 *dsize
= D
.dqb_bsoftlimit
;
1196 if (D
.dqb_curblocks
== 1)
1199 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
1201 *dsize
= D
.dqb_curblocks
;
1203 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1209 auth_destroy(clnt
->cl_auth
);
1213 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args
.gqa_pathp
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
1216 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
1222 /****************************************************************************
1223 try to get the disk space from disk quotas - default version
1224 ****************************************************************************/
1226 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1231 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__)
1235 /* find the block device file */
1238 /* Need to set the cache flag to 1 for HPUX. Seems
1239 * to have a significant performance boost when
1240 * lstat calls on /dev access this function.
1242 if ((sys_stat(path
, &S
, false)<0)
1243 || (devnm(S_IFBLK
, S
.st_ex_dev
, dev_disk
, 256, 1)<0))
1245 if ((sys_stat(path
, &S
, false)<0)
1246 || (devnm(S_IFBLK
, S
.st_ex_dev
, dev_disk
, 256, 0)<0))
1248 #endif /* ifdef HPUX */
1250 #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__) */
1252 euser_id
= geteuid();
1255 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
1257 if (set_re_uid() != 0) return False
;
1259 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
1263 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1265 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
1267 #if defined(__FreeBSD__) || defined(__DragonFly__)
1269 struct statfs
*mnts
;
1273 if (sys_stat(path
, &st
, false) < 0)
1275 devno
= st
.st_ex_dev
;
1277 mntsize
= getmntinfo(&mnts
,MNT_NOWAIT
);
1281 for (i
= 0; i
< mntsize
; i
++) {
1282 if (sys_stat(mnts
[i
].f_mntonname
, &st
, false) < 0)
1284 if (st
.st_ex_dev
== devno
)
1293 #if defined(__FreeBSD__) || defined(__DragonFly__)
1294 if (strcmp(mnts
[i
].f_fstypename
,"nfs") == 0) {
1296 retval
= nfs_quotas(mnts
[i
].f_mntfromname
,euser_id
,bsize
,dfree
,dsize
);
1302 egrp_id
= getegid();
1303 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
1305 /* As FreeBSD has group quotas, if getting the user
1306 quota fails, try getting the group instead. */
1308 r
= quotactl(path
,QCMD(Q_GETQUOTA
,GRPQUOTA
),egrp_id
,(char *) &D
);
1314 /* AIX has both USER and GROUP quotas:
1315 Get the USER quota (ohnielse@fysik.dtu.dk) */
1316 #ifdef _AIXVERSION_530
1318 struct statfs statbuf
;
1319 quota64_t user_quota
;
1320 if (statfs(path
,&statbuf
) != 0)
1322 if(statbuf
.f_vfstype
== MNT_J2
)
1324 /* For some reason we need to be root for jfs2 */
1326 r
= quotactl(path
,QCMD(Q_J2GETQUOTA
,USRQUOTA
),euser_id
,(char *) &user_quota
);
1328 /* Copy results to old struct to let the following code work as before */
1329 D
.dqb_curblocks
= user_quota
.bused
;
1330 D
.dqb_bsoftlimit
= user_quota
.bsoft
;
1331 D
.dqb_bhardlimit
= user_quota
.bhard
;
1332 D
.dqb_curfiles
= user_quota
.iused
;
1333 D
.dqb_fsoftlimit
= user_quota
.isoft
;
1334 D
.dqb_fhardlimit
= user_quota
.ihard
;
1336 else if(statbuf
.f_vfstype
== MNT_JFS
)
1338 #endif /* AIX 5.3 */
1340 if (set_re_uid() != 0)
1342 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
1344 #ifdef _AIXVERSION_530
1347 r
= 1; /* Fail for other FS-types */
1349 #endif /* AIX 5.3 */
1350 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1351 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
1352 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1355 /* Use softlimit to determine disk space, except when it has been exceeded */
1356 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1358 #else /* !__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
1360 #endif /*!__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
1364 if (errno
== EDQUOT
)
1367 *dsize
=D
.dqb_curblocks
;
1373 /* If softlimit is zero, set it equal to hardlimit.
1376 if (D
.dqb_bsoftlimit
==0)
1377 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1379 if (D
.dqb_bsoftlimit
==0)
1381 /* Use softlimit to determine disk space, except when it has been exceeded */
1382 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)
1383 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__)
1384 ||((D
.dqb_curfiles
>D
.dqb_fsoftlimit
) && (D
.dqb_fsoftlimit
!= 0))
1388 *dsize
= D
.dqb_curblocks
;
1391 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1392 *dsize
= D
.dqb_bsoftlimit
;
1399 #if definedr(LINUX) || defined(SUNOS) || defined (__FreeBSD__) || defined(__DragonFly__)
1400 static int my_xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
1402 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
1404 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
1410 #if defined(VXFS_QUOTA)
1412 /****************************************************************************
1413 Try to get the disk space from Veritas disk quotas.
1414 David Lee <T.D.Lee@durham.ac.uk> August 1999.
1416 Background assumptions:
1417 Potentially under many Operating Systems. Initially Solaris 2.
1419 My guess is that Veritas is largely, though not entirely,
1420 independent of OS. So I have separated it out.
1422 There may be some details. For example, OS-specific "include" files.
1424 It is understood that HPUX 10 somehow gets Veritas quotas without
1425 any special effort; if so, this routine need not be compiled in.
1426 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
1429 It is understood that Veritas do not publicly support this ioctl interface.
1430 Rather their preference would be for the user (us) to call the native
1431 OS and then for the OS itself to call through to the VxFS filesystem.
1432 Presumably HPUX 10, see above, does this.
1435 Add your OS to "IFLIST" below.
1436 Get it to compile successfully:
1437 Almost certainly "include"s require attention: see SUNOS5.
1438 In the main code above, arrange for it to be called: see SUNOS5.
1441 ****************************************************************************/
1444 * This "if" is a list of ports:
1445 * if defined(OS1) || defined(OS2) || ...
1450 #include <sys/fs/vx_solaris.h>
1452 #include <sys/fs/vx_machdep.h>
1453 #include <sys/fs/vx_layout.h>
1454 #include <sys/fs/vx_quota.h>
1455 #include <sys/fs/vx_aioctl.h>
1456 #include <sys/fs/vx_ioctl.h>
1458 bool disk_quotas_vxfs(const char *name
, char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1460 uid_t user_id
, euser_id
;
1463 struct vx_quotctl quotabuf
;
1464 struct vx_genioctl genbuf
;
1469 * "name" may or may not include a trailing "/quotas".
1470 * Arranging consistency of calling here in "quotas.c" may not be easy and
1471 * it might be easier to examine and adjust it here.
1472 * Fortunately, VxFS seems not to mind at present.
1474 qfname
= talloc_strdup(talloc_tos(), name
);
1478 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
1480 euser_id
= geteuid();
1481 set_effective_uid(0);
1483 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname
));
1484 if((file
=open(qfname
, O_RDONLY
,0))<0) {
1485 set_effective_uid(euser_id
);
1488 genbuf
.ioc_cmd
= VX_QUOTACTL
;
1489 genbuf
.ioc_up
= (void *) "abuf
;
1491 quotabuf
.cmd
= VX_GETQUOTA
;
1492 quotabuf
.uid
= euser_id
;
1493 quotabuf
.addr
= (caddr_t
) &D
;
1494 ret
= ioctl(file
, VX_ADMIN_IOCTL
, &genbuf
);
1497 set_effective_uid(euser_id
);
1500 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno
) ));
1504 /* If softlimit is zero, set it equal to hardlimit.
1507 if (D
.dqb_bsoftlimit
==0)
1508 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1510 /* Use softlimit to determine disk space. A user exceeding the quota is told
1511 * that there's no space left. Writes might actually work for a bit if the
1512 * hardlimit is set higher than softlimit. Effectively the disk becomes
1513 * made of rubber latex and begins to expand to accommodate the user :-)
1515 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
1516 path
, D
.dqb_curblocks
, D
.dqb_bsoftlimit
, D
.dqb_bhardlimit
,
1517 D
.dqb_curfiles
, D
.dqb_fsoftlimit
, D
.dqb_fhardlimit
));
1519 if (D
.dqb_bsoftlimit
==0)
1522 *dsize
= D
.dqb_bsoftlimit
;
1524 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
1526 *dsize
= D
.dqb_curblocks
;
1528 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1530 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
1531 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
1536 #endif /* SUNOS5 || ... */
1538 #endif /* VXFS_QUOTA */
1540 #else /* WITH_QUOTAS */
1542 bool disk_quotas(const char *path
,uint64_t *bsize
,uint64_t *dfree
,uint64_t *dsize
)
1544 (*bsize
) = 512; /* This value should be ignored */
1546 /* And just to be sure we set some values that hopefully */
1547 /* will be larger that any possible real-world value */
1548 (*dfree
) = (uint64_t)-1;
1549 (*dsize
) = (uint64_t)-1;
1551 /* As we have select not to use quotas, allways fail */
1554 #endif /* WITH_QUOTAS */
1556 #else /* HAVE_SYS_QUOTAS */
1557 /* wrapper to the new sys_quota interface
1558 this file should be removed later
1560 bool disk_quotas(const char *path
,uint64_t *bsize
,uint64_t *dfree
,uint64_t *dsize
)
1569 r
=sys_get_quota(path
, SMB_USER_QUOTA_TYPE
, id
, &D
);
1571 /* Use softlimit to determine disk space, except when it has been exceeded */
1574 if (errno
== EDQUOT
) {
1576 *dsize
=D
.curblocks
;
1579 goto try_group_quota
;
1583 /* Use softlimit to determine disk space, except when it has been exceeded */
1585 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
1586 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
1587 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
1588 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
1591 *dsize
= D
.curblocks
;
1592 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
1593 goto try_group_quota
;
1595 if (D
.softlimit
== 0)
1596 D
.softlimit
= D
.hardlimit
;
1597 *dfree
= D
.softlimit
- D
.curblocks
;
1598 *dsize
= D
.softlimit
;
1607 r
=sys_get_quota(path
, SMB_GROUP_QUOTA_TYPE
, id
, &D
);
1609 /* Use softlimit to determine disk space, except when it has been exceeded */
1612 if (errno
== EDQUOT
) {
1614 *dsize
=D
.curblocks
;
1621 /* Use softlimit to determine disk space, except when it has been exceeded */
1623 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
1624 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
1625 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
1626 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
1629 *dsize
= D
.curblocks
;
1630 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
1633 if (D
.softlimit
== 0)
1634 D
.softlimit
= D
.hardlimit
;
1635 *dfree
= D
.softlimit
- D
.curblocks
;
1636 *dsize
= D
.softlimit
;
1641 #endif /* HAVE_SYS_QUOTAS */