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"
31 #define DBGC_CLASS DBGC_QUOTA
33 #ifndef HAVE_SYS_QUOTAS
35 /* just a quick hack because sysquotas.h is included before linux/quota.h */
36 #ifdef QUOTABLOCK_SIZE
37 #undef QUOTABLOCK_SIZE
42 #if defined(VXFS_QUOTA)
45 * In addition to their native filesystems, some systems have Veritas VxFS.
46 * Declare here, define at end: reduces likely "include" interaction problems.
47 * David Lee <T.D.Lee@durham.ac.uk>
49 bool disk_quotas_vxfs(const char *name
, char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
);
51 #endif /* VXFS_QUOTA */
55 #include <sys/types.h>
59 * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
60 * So we include all the files has *should* be in the system into a large,
61 * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA.
64 #include "samba_linux_quota.h"
66 typedef struct _LINUX_SMB_DISK_QUOTA
{
68 uint64_t hardlimit
; /* In bsize units. */
69 uint64_t softlimit
; /* In bsize units. */
70 uint64_t curblocks
; /* In bsize units. */
71 uint64_t ihardlimit
; /* inode hard limit. */
72 uint64_t isoftlimit
; /* inode soft limit. */
73 uint64_t curinodes
; /* Current used inodes. */
74 } LINUX_SMB_DISK_QUOTA
;
79 * (essentially taken from FreeBSD / SUNOS5 section)
82 #include <rpc/types.h>
83 #include <rpcsvc/rquota.h>
84 #ifdef HAVE_RPC_NETTYPE_H
85 #include <rpc/nettype.h>
89 static int my_xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
91 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
93 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
98 static int my_xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
102 if (!xdr_int(xdrsp
, "astat
)) {
103 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
106 gqr
->status
= quotastat
;
108 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
109 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
112 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
113 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
116 if (!xdr_int(xdrsp
, (int *)&gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
117 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
120 if (!xdr_int(xdrsp
, (int *)&gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
121 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
124 if (!xdr_int(xdrsp
, (int *)&gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
125 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
131 static bool nfs_quotas(char *nfspath
, uid_t euser_id
, uint64_t *bsize
,
132 uint64_t *dfree
, uint64_t *dsize
)
134 uid_t uid
= euser_id
;
135 LINUX_SMB_DISK_QUOTA D
;
136 char *mnttype
= nfspath
;
138 struct getquota_rslt gqr
;
139 struct getquota_args args
;
140 char *cutstr
, *pathname
, *host
, *testpath
;
142 static struct timeval timeout
= {2,0};
143 enum clnt_stat clnt_stat
;
146 *bsize
= *dfree
= *dsize
= (uint64_t)0;
148 len
=strcspn(mnttype
, ":");
149 pathname
=strstr(mnttype
, ":");
150 cutstr
= (char *) SMB_MALLOC(len
+1);
154 memset(cutstr
, '\0', len
+1);
155 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
156 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
157 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
158 testpath
=strchr_m(mnttype
, ':');
159 args
.gqa_pathp
= testpath
+1;
162 DEBUG(5, ("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers "
163 "\"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
,
166 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
171 clnt
->cl_auth
= authunix_create_default();
172 DEBUG(9,("nfs_quotas: auth_success\n"));
174 clnt_stat
=clnt_call(clnt
,
176 (const xdrproc_t
)my_xdr_getquota_args
,
178 (const xdrproc_t
)my_xdr_getquota_rslt
,
179 (caddr_t
)&gqr
, timeout
);
181 if (clnt_stat
!= RPC_SUCCESS
) {
182 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
188 * gqr.status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
189 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
190 * something sensible.
193 switch (gqr
.status
) {
195 DEBUG(9, ("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n",
201 DEBUG(9,("nfs_quotas: Good quota data\n"));
202 D
.softlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
203 D
.hardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
204 D
.curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
211 DEBUG(9, ("nfs_quotas: Remote Quotas returned \"%i\" \n",
216 DEBUG(9, ("nfs_quotas: Remote Quotas Questionable! "
217 "Error \"%i\" \n", gqr
.status
));
221 DEBUG(10, ("nfs_quotas: Let`s look at D a bit closer... "
222 "status \"%i\" bsize \"%i\" active? \"%i\" bhard "
223 "\"%i\" bsoft \"%i\" curb \"%i\" \n",
225 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
226 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
227 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
228 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
229 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
231 if (D
.softlimit
== 0)
232 D
.softlimit
= D
.hardlimit
;
233 if (D
.softlimit
== 0)
236 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
237 *dsize
= D
.softlimit
;
239 if (D
.curblocks
== 1)
242 if (D
.curblocks
> D
.softlimit
) {
244 *dsize
= D
.curblocks
;
246 *dfree
= D
.softlimit
- D
.curblocks
;
252 auth_destroy(clnt
->cl_auth
);
256 DEBUG(5, ("nfs_quotas: For path \"%s\" returning "
257 "bsize %.0f, dfree %.0f, dsize %.0f\n",
258 args
.gqa_pathp
, (double)*bsize
, (double)*dfree
,
262 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
266 /* end of nfs quota section */
268 #ifdef HAVE_LINUX_DQBLK_XFS_H
269 #include <linux/dqblk_xfs.h>
271 /****************************************************************************
272 Abstract out the XFS Quota Manager quota get call.
273 ****************************************************************************/
275 static int get_smb_linux_xfs_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
277 struct fs_disk_quota D
;
282 ret
= quotactl(QCMD(Q_XGETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
285 ret
= quotactl(QCMD(Q_XGETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
290 dp
->bsize
= (uint64_t)512;
291 dp
->softlimit
= (uint64_t)D
.d_blk_softlimit
;
292 dp
->hardlimit
= (uint64_t)D
.d_blk_hardlimit
;
293 dp
->ihardlimit
= (uint64_t)D
.d_ino_hardlimit
;
294 dp
->isoftlimit
= (uint64_t)D
.d_ino_softlimit
;
295 dp
->curinodes
= (uint64_t)D
.d_icount
;
296 dp
->curblocks
= (uint64_t)D
.d_bcount
;
301 static int get_smb_linux_xfs_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
303 DEBUG(0,("XFS quota support not available\n"));
310 /****************************************************************************
311 Abstract out the old and new Linux quota get calls.
312 ****************************************************************************/
314 static int get_smb_linux_v1_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
316 struct v1_kern_dqblk D
;
321 ret
= quotactl(QCMD(Q_V1_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
323 if (ret
&& errno
!= EDQUOT
)
324 ret
= quotactl(QCMD(Q_V1_GETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
326 if (ret
&& errno
!= EDQUOT
)
329 dp
->bsize
= (uint64_t)QUOTABLOCK_SIZE
;
330 dp
->softlimit
= (uint64_t)D
.dqb_bsoftlimit
;
331 dp
->hardlimit
= (uint64_t)D
.dqb_bhardlimit
;
332 dp
->ihardlimit
= (uint64_t)D
.dqb_ihardlimit
;
333 dp
->isoftlimit
= (uint64_t)D
.dqb_isoftlimit
;
334 dp
->curinodes
= (uint64_t)D
.dqb_curinodes
;
335 dp
->curblocks
= (uint64_t)D
.dqb_curblocks
;
340 static int get_smb_linux_v2_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
342 struct v2_kern_dqblk D
;
347 ret
= quotactl(QCMD(Q_V2_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
349 if (ret
&& errno
!= EDQUOT
)
350 ret
= quotactl(QCMD(Q_V2_GETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
352 if (ret
&& errno
!= EDQUOT
)
355 dp
->bsize
= (uint64_t)QUOTABLOCK_SIZE
;
356 dp
->softlimit
= (uint64_t)D
.dqb_bsoftlimit
;
357 dp
->hardlimit
= (uint64_t)D
.dqb_bhardlimit
;
358 dp
->ihardlimit
= (uint64_t)D
.dqb_ihardlimit
;
359 dp
->isoftlimit
= (uint64_t)D
.dqb_isoftlimit
;
360 dp
->curinodes
= (uint64_t)D
.dqb_curinodes
;
361 dp
->curblocks
= ((uint64_t)D
.dqb_curspace
) / dp
->bsize
;
366 /****************************************************************************
367 Brand-new generic quota interface.
368 ****************************************************************************/
370 static int get_smb_linux_gen_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
377 ret
= quotactl(QCMD(Q_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
379 if (ret
&& errno
!= EDQUOT
)
380 ret
= quotactl(QCMD(Q_GETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
382 if (ret
&& errno
!= EDQUOT
)
385 dp
->bsize
= (uint64_t)QUOTABLOCK_SIZE
;
386 dp
->softlimit
= (uint64_t)D
.dqb_bsoftlimit
;
387 dp
->hardlimit
= (uint64_t)D
.dqb_bhardlimit
;
388 dp
->ihardlimit
= (uint64_t)D
.dqb_ihardlimit
;
389 dp
->isoftlimit
= (uint64_t)D
.dqb_isoftlimit
;
390 dp
->curinodes
= (uint64_t)D
.dqb_curinodes
;
391 dp
->curblocks
= ((uint64_t)D
.dqb_curspace
) / dp
->bsize
;
396 /****************************************************************************
397 Try to get the disk space from disk quotas (LINUX version).
398 ****************************************************************************/
400 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
405 LINUX_SMB_DISK_QUOTA D
;
414 euser_id
= geteuid();
417 /* find the block device file */
419 if (sys_stat(path
, &S
, false) == -1 )
422 devno
= S
.st_ex_dev
;
424 if ((fp
= setmntent(MOUNTED
,"r")) == NULL
)
429 while ((mnt
= getmntent(fp
))) {
430 if (sys_stat(mnt
->mnt_dir
, &S
, false) == -1)
433 if (S
.st_ex_dev
== devno
) {
446 if (strcmp(mnt
->mnt_type
, "nfs") == 0) {
448 retval
= nfs_quotas(mnt
->mnt_fsname
, euser_id
, bsize
, dfree
, dsize
);
453 if (strcmp(mnt
->mnt_type
, "xfs")==0) {
454 r
=get_smb_linux_xfs_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
456 r
=get_smb_linux_gen_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
457 if (r
== -1 && errno
!= EDQUOT
) {
458 r
=get_smb_linux_v2_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
459 if (r
== -1 && errno
!= EDQUOT
)
460 r
=get_smb_linux_v1_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
466 /* Use softlimit to determine disk space, except when it has been exceeded */
469 if (errno
== EDQUOT
) {
478 /* Use softlimit to determine disk space, except when it has been exceeded */
480 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
481 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
482 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
483 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
486 *dsize
= D
.curblocks
;
487 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
490 if (D
.softlimit
== 0)
491 D
.softlimit
= D
.hardlimit
;
492 *dfree
= D
.softlimit
- D
.curblocks
;
493 *dsize
= D
.softlimit
;
501 #include <sys/quota.h>
504 /****************************************************************************
505 try to get the disk space from disk quotas (CRAY VERSION)
506 ****************************************************************************/
508 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
512 SMB_STRUCT_STAT sbuf
;
514 struct q_request request
;
515 struct qf_header header
;
516 int quota_default
= 0 ;
519 if (sys_stat(path
, &sbuf
, false) == -1) {
523 devno
= sbuf
.st_ex_dev
;
525 if ((fd
= setmntent(KMTAB
)) == NULL
) {
529 while ((mnt
= getmntent(fd
)) != NULL
) {
530 if (sys_stat(mnt
->mnt_dir
, &sbuf
, false) == -1) {
533 if (sbuf
.st_ex_dev
== devno
) {
539 name
= talloc_strdup(talloc_tos(), mnt
->mnt_dir
);
549 request
.qf_magic
= QF_MAGIC
;
550 request
.qf_entry
.id
= geteuid() ;
552 if (quotactl(name
, Q_GETQUOTA
, &request
) == -1) {
560 if (request
.qf_entry
.user_q
.f_quota
== QFV_DEFAULT
) {
561 if (!quota_default
) {
562 if (quotactl(name
, Q_GETHEADER
, &header
) == -1) {
565 quota_default
= header
.user_h
.def_fq
;
568 *dfree
= quota_default
;
569 } else if (request
.qf_entry
.user_q
.f_quota
== QFV_PREVENT
) {
572 *dfree
= request
.qf_entry
.user_q
.f_quota
;
575 *dsize
= request
.qf_entry
.user_q
.f_use
;
577 if (*dfree
< *dsize
) {
583 *bsize
= 4096 ; /* Cray blocksize */
588 #elif defined(SUNOS5) || defined(SUNOS4)
591 #include <sys/param.h>
593 #include <sys/fs/ufs_quota.h>
594 #include <sys/mnttab.h>
595 #include <sys/mntent.h>
596 #else /* defined(SUNOS4) */
597 #include <ufs/quota.h>
603 /****************************************************************************
604 Allows querying of remote hosts for quotas on NFS mounted shares.
605 Supports normal NFS and AMD mounts.
606 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
607 ****************************************************************************/
610 #include <rpc/types.h>
611 #include <rpcsvc/rquota.h>
612 #include <rpc/nettype.h>
615 static int my_xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
617 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
619 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
624 static int my_xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
628 if (!xdr_int(xdrsp
, "astat
)) {
629 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
632 gqr
->status
= quotastat
;
634 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
635 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
638 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
639 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
642 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
643 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
646 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
647 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
650 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
651 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
657 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
658 static bool nfs_quotas(char *nfspath
, uid_t euser_id
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
660 uid_t uid
= euser_id
;
662 char *mnttype
= nfspath
;
664 struct getquota_rslt gqr
;
665 struct getquota_args args
;
666 char *cutstr
, *pathname
, *host
, *testpath
;
668 static struct timeval timeout
= {2,0};
669 enum clnt_stat clnt_stat
;
672 *bsize
= *dfree
= *dsize
= (uint64_t)0;
674 len
=strcspn(mnttype
, ":");
675 pathname
=strstr(mnttype
, ":");
676 cutstr
= (char *) SMB_MALLOC(len
+1);
680 memset(cutstr
, '\0', len
+1);
681 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
682 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
683 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
684 testpath
=strchr_m(mnttype
, ':');
685 args
.gqa_pathp
= testpath
+1;
688 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
, "udp"));
690 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
695 clnt
->cl_auth
= authunix_create_default();
696 DEBUG(9,("nfs_quotas: auth_success\n"));
698 clnt_stat
=clnt_call(clnt
, RQUOTAPROC_GETQUOTA
, my_xdr_getquota_args
, (caddr_t
)&args
, my_xdr_getquota_rslt
, (caddr_t
)&gqr
, timeout
);
700 if (clnt_stat
!= RPC_SUCCESS
) {
701 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
707 * gqr.status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
708 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
709 * something sensible.
712 switch (gqr
.status
) {
714 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr
.status
));
719 DEBUG(9,("nfs_quotas: Good quota data\n"));
720 D
.dqb_bsoftlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
721 D
.dqb_bhardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
722 D
.dqb_curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
727 D
.dqb_bsoftlimit
= 1;
729 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr
.status
));
733 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr
.status
));
737 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",
739 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
740 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
741 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
742 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
743 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
745 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
746 *dsize
= D
.dqb_bsoftlimit
;
748 if (D
.dqb_curblocks
== 1)
751 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
753 *dsize
= D
.dqb_curblocks
;
755 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
761 auth_destroy(clnt
->cl_auth
);
765 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args
.gqa_pathp
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
768 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
773 /****************************************************************************
774 try to get the disk space from disk quotas (SunOS & Solaris2 version)
775 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
776 ****************************************************************************/
778 bool disk_quotas(const char *path
,
787 struct quotctl command
;
795 SMB_STRUCT_STAT sbuf
;
799 euser_id
= geteuid();
801 if (sys_stat(path
, &sbuf
, false) == -1) {
805 devno
= sbuf
.st_ex_dev
;
806 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
807 path
, (unsigned int)devno
));
809 if ((fd
= sys_fopen(MNTTAB
, "r")) == NULL
) {
813 while (getmntent(fd
, &mnt
) == 0) {
814 if (sys_stat(mnt
.mnt_mountp
, &sbuf
, false) == -1) {
818 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
819 mnt
.mnt_mountp
, (unsigned int)devno
));
821 /* quotas are only on vxfs, UFS or NFS */
822 if ((sbuf
.st_ex_dev
== devno
) && (
823 strcmp( mnt
.mnt_fstype
, MNTTYPE_UFS
) == 0 ||
824 strcmp( mnt
.mnt_fstype
, "nfs" ) == 0 ||
825 strcmp( mnt
.mnt_fstype
, "vxfs" ) == 0 )) {
827 name
= talloc_asprintf(talloc_tos(),
836 if ((fd
= setmntent(MOUNTED
, "r")) == NULL
) {
840 while ((mnt
= getmntent(fd
)) != NULL
) {
841 if (sys_stat(mnt
->mnt_dir
, &sbuf
, false) == -1) {
844 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
846 (unsigned int)sbuf
.st_ex_dev
));
847 if (sbuf
.st_ex_dev
== devno
) {
849 name
= talloc_strdup(talloc_tos(),
867 if (strcmp(mnt
.mnt_fstype
, "nfs") == 0) {
869 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n",
871 retval
= nfs_quotas(mnt
.mnt_special
,
872 euser_id
, bsize
, dfree
, dsize
);
877 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name
));
878 if((file
=sys_open(name
, O_RDONLY
,0))<0) {
882 command
.op
= Q_GETQUOTA
;
883 command
.uid
= euser_id
;
884 command
.addr
= (caddr_t
) &D
;
885 ret
= ioctl(file
, Q_QUOTACTL
, &command
);
888 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name
));
889 ret
= quotactl(Q_GETQUOTA
, name
, euser_id
, &D
);
895 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n",
898 #if defined(SUNOS5) && defined(VXFS_QUOTA)
899 /* If normal quotactl() fails, try vxfs private calls */
900 set_effective_uid(euser_id
);
901 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt
.mnt_fstype
));
902 if ( 0 == strcmp ( mnt
.mnt_fstype
, "vxfs" )) {
904 retval
= disk_quotas_vxfs(name
, path
,
905 bsize
, dfree
, dsize
);
913 /* If softlimit is zero, set it equal to hardlimit.
916 if (D
.dqb_bsoftlimit
==0) {
917 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
920 /* Use softlimit to determine disk space. A user exceeding the quota
921 * is told that there's no space left. Writes might actually work for
922 * a bit if the hardlimit is set higher than softlimit. Effectively
923 * the disk becomes made of rubber latex and begins to expand to
924 * accommodate the user :-)
927 if (D
.dqb_bsoftlimit
==0)
930 *dsize
= D
.dqb_bsoftlimit
;
932 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
934 *dsize
= D
.dqb_curblocks
;
936 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
939 DEBUG(5,("disk_quotas for path \"%s\" returning "
940 "bsize %.0f, dfree %.0f, dsize %.0f\n",
941 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
948 #include <ufs/quota.h>
950 /****************************************************************************
951 try to get the disk space from disk quotas - OSF1 version
952 ****************************************************************************/
954 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
962 * This code presumes that OSF1 will only
963 * give out quota info when the real uid
964 * matches the effective uid. JRA.
966 euser_id
= geteuid();
968 if (set_re_uid() != 0) return False
;
970 r
= quotactl(path
,QCMD(Q_GETQUOTA
, USRQUOTA
),euser_id
,(char *) &D
);
981 if (save_errno
== EDQUOT
) /* disk quota exceeded */
984 *dsize
= D
.dqb_curblocks
;
991 /* If softlimit is zero, set it equal to hardlimit.
994 if (D
.dqb_bsoftlimit
==0)
995 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
997 /* Use softlimit to determine disk space, except when it has been exceeded */
999 if (D
.dqb_bsoftlimit
==0)
1002 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)) {
1004 *dsize
= D
.dqb_curblocks
;
1006 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1007 *dsize
= D
.dqb_bsoftlimit
;
1012 #elif defined (IRIX6)
1013 /****************************************************************************
1014 try to get the disk space from disk quotas (IRIX 6.2 version)
1015 ****************************************************************************/
1017 #include <sys/quota.h>
1020 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1025 struct fs_disk_quota F
;
1032 /* find the block device file */
1034 if ( sys_stat(path
, &S
, false) == -1 ) {
1038 devno
= S
.st_ex_dev
;
1040 fp
= setmntent(MOUNTED
,"r");
1043 while ((mnt
= getmntent(fp
))) {
1044 if ( sys_stat(mnt
->mnt_dir
, &S
, false) == -1 )
1046 if (S
.st_ex_dev
== devno
) {
1060 /* Use softlimit to determine disk space, except when it has been exceeded */
1064 if ( 0 == strcmp ( mnt
->mnt_type
, "efs" ))
1066 r
=quotactl (Q_GETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &D
);
1073 /* Use softlimit to determine disk space, except when it has been exceeded */
1075 (D
.dqb_bsoftlimit
&& D
.dqb_curblocks
>=D
.dqb_bsoftlimit
) ||
1076 (D
.dqb_bhardlimit
&& D
.dqb_curblocks
>=D
.dqb_bhardlimit
) ||
1077 (D
.dqb_fsoftlimit
&& D
.dqb_curfiles
>=D
.dqb_fsoftlimit
) ||
1078 (D
.dqb_fhardlimit
&& D
.dqb_curfiles
>=D
.dqb_fhardlimit
)
1082 *dsize
= D
.dqb_curblocks
;
1084 else if (D
.dqb_bsoftlimit
==0 && D
.dqb_bhardlimit
==0)
1090 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1091 *dsize
= D
.dqb_bsoftlimit
;
1095 else if ( 0 == strcmp ( mnt
->mnt_type
, "xfs" ))
1097 r
=quotactl (Q_XGETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &F
);
1103 DEBUG(5, ("quotactl for uid=%u: %s", euser_id
, strerror(errno
)));
1107 /* No quota for this user. */
1108 if (F
.d_blk_softlimit
==0 && F
.d_blk_hardlimit
==0)
1113 /* Use softlimit to determine disk space, except when it has been exceeded */
1115 (F
.d_blk_softlimit
&& F
.d_bcount
>=F
.d_blk_softlimit
) ||
1116 (F
.d_blk_hardlimit
&& F
.d_bcount
>=F
.d_blk_hardlimit
) ||
1117 (F
.d_ino_softlimit
&& F
.d_icount
>=F
.d_ino_softlimit
) ||
1118 (F
.d_ino_hardlimit
&& F
.d_icount
>=F
.d_ino_hardlimit
)
1122 *dsize
= F
.d_bcount
;
1126 *dfree
= (F
.d_blk_softlimit
- F
.d_bcount
);
1127 *dsize
= F
.d_blk_softlimit
? F
.d_blk_softlimit
: F
.d_blk_hardlimit
;
1143 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1144 #include <ufs/ufs/quota.h>
1145 #include <machine/param.h>
1147 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
1148 #include <jfs/quota.h>
1149 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
1150 #define dqb_curfiles dqb_curinodes
1151 #define dqb_fhardlimit dqb_ihardlimit
1152 #define dqb_fsoftlimit dqb_isoftlimit
1153 #ifdef _AIXVERSION_530
1154 #include <sys/statfs.h>
1155 #include <sys/vmount.h>
1156 #endif /* AIX 5.3 */
1157 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1158 #include <sys/quota.h>
1162 #if defined(__FreeBSD__) || defined(__DragonFly__)
1164 #include <rpc/rpc.h>
1165 #include <rpc/types.h>
1166 #include <rpcsvc/rquota.h>
1167 #ifdef HAVE_RPC_NETTYPE_H
1168 #include <rpc/nettype.h>
1170 #include <rpc/xdr.h>
1172 static int my_xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
1174 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
1176 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
1181 static int my_xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
1185 if (!xdr_int(xdrsp
, "astat
)) {
1186 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
1189 gqr
->status
= quotastat
;
1191 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
1192 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
1195 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
1196 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
1199 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
1200 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
1203 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
1204 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
1207 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
1208 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
1214 /* Works on FreeBSD, too. :-) */
1215 static bool nfs_quotas(char *nfspath
, uid_t euser_id
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1217 uid_t uid
= euser_id
;
1219 char *mnttype
= nfspath
;
1221 struct getquota_rslt gqr
;
1222 struct getquota_args args
;
1223 char *cutstr
, *pathname
, *host
, *testpath
;
1225 static struct timeval timeout
= {2,0};
1226 enum clnt_stat clnt_stat
;
1229 *bsize
= *dfree
= *dsize
= (uint64_t)0;
1231 len
=strcspn(mnttype
, ":");
1232 pathname
=strstr(mnttype
, ":");
1233 cutstr
= (char *) SMB_MALLOC(len
+1);
1237 memset(cutstr
, '\0', len
+1);
1238 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
1239 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
1240 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
1241 testpath
=strchr_m(mnttype
, ':');
1242 args
.gqa_pathp
= testpath
+1;
1245 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
, "udp"));
1247 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
1252 clnt
->cl_auth
= authunix_create_default();
1253 DEBUG(9,("nfs_quotas: auth_success\n"));
1255 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
);
1257 if (clnt_stat
!= RPC_SUCCESS
) {
1258 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
1264 * gqr->status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
1265 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
1266 * something sensible.
1269 switch (gqr
.status
) {
1271 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr
.status
));
1276 DEBUG(9,("nfs_quotas: Good quota data\n"));
1277 D
.dqb_bsoftlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
1278 D
.dqb_bhardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
1279 D
.dqb_curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
1284 D
.dqb_bsoftlimit
= 1;
1285 D
.dqb_curblocks
= 1;
1286 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr
.status
));
1290 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr
.status
));
1294 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",
1296 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
1297 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
1298 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
1299 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
1300 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
1302 if (D
.dqb_bsoftlimit
== 0)
1303 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1304 if (D
.dqb_bsoftlimit
== 0)
1307 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
1308 *dsize
= D
.dqb_bsoftlimit
;
1310 if (D
.dqb_curblocks
== 1)
1313 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
1315 *dsize
= D
.dqb_curblocks
;
1317 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1323 auth_destroy(clnt
->cl_auth
);
1327 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args
.gqa_pathp
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
1330 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
1336 /****************************************************************************
1337 try to get the disk space from disk quotas - default version
1338 ****************************************************************************/
1340 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1345 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__)
1349 /* find the block device file */
1352 /* Need to set the cache flag to 1 for HPUX. Seems
1353 * to have a significant performance boost when
1354 * lstat calls on /dev access this function.
1356 if ((sys_stat(path
, &S
, false)<0)
1357 || (devnm(S_IFBLK
, S
.st_ex_dev
, dev_disk
, 256, 1)<0))
1359 if ((sys_stat(path
, &S
, false)<0)
1360 || (devnm(S_IFBLK
, S
.st_ex_dev
, dev_disk
, 256, 0)<0))
1362 #endif /* ifdef HPUX */
1364 #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__) */
1366 euser_id
= geteuid();
1369 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
1371 if (set_re_uid() != 0) return False
;
1373 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
1377 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1379 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
1381 #if defined(__FreeBSD__) || defined(__DragonFly__)
1383 struct statfs
*mnts
;
1387 if (sys_stat(path
, &st
, false) < 0)
1389 devno
= st
.st_ex_dev
;
1391 mntsize
= getmntinfo(&mnts
,MNT_NOWAIT
);
1395 for (i
= 0; i
< mntsize
; i
++) {
1396 if (sys_stat(mnts
[i
].f_mntonname
, &st
, false) < 0)
1398 if (st
.st_ex_dev
== devno
)
1407 #if defined(__FreeBSD__) || defined(__DragonFly__)
1408 if (strcmp(mnts
[i
].f_fstypename
,"nfs") == 0) {
1410 retval
= nfs_quotas(mnts
[i
].f_mntfromname
,euser_id
,bsize
,dfree
,dsize
);
1416 egrp_id
= getegid();
1417 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
1419 /* As FreeBSD has group quotas, if getting the user
1420 quota fails, try getting the group instead. */
1422 r
= quotactl(path
,QCMD(Q_GETQUOTA
,GRPQUOTA
),egrp_id
,(char *) &D
);
1428 /* AIX has both USER and GROUP quotas:
1429 Get the USER quota (ohnielse@fysik.dtu.dk) */
1430 #ifdef _AIXVERSION_530
1432 struct statfs statbuf
;
1433 quota64_t user_quota
;
1434 if (statfs(path
,&statbuf
) != 0)
1436 if(statbuf
.f_vfstype
== MNT_J2
)
1438 /* For some reason we need to be root for jfs2 */
1440 r
= quotactl(path
,QCMD(Q_J2GETQUOTA
,USRQUOTA
),euser_id
,(char *) &user_quota
);
1442 /* Copy results to old struct to let the following code work as before */
1443 D
.dqb_curblocks
= user_quota
.bused
;
1444 D
.dqb_bsoftlimit
= user_quota
.bsoft
;
1445 D
.dqb_bhardlimit
= user_quota
.bhard
;
1446 D
.dqb_curfiles
= user_quota
.iused
;
1447 D
.dqb_fsoftlimit
= user_quota
.isoft
;
1448 D
.dqb_fhardlimit
= user_quota
.ihard
;
1450 else if(statbuf
.f_vfstype
== MNT_JFS
)
1452 #endif /* AIX 5.3 */
1454 if (set_re_uid() != 0)
1456 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
1458 #ifdef _AIXVERSION_530
1461 r
= 1; /* Fail for other FS-types */
1463 #endif /* AIX 5.3 */
1464 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1465 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
1466 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1469 /* Use softlimit to determine disk space, except when it has been exceeded */
1470 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1472 #else /* !__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
1474 #endif /*!__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
1478 if (errno
== EDQUOT
)
1481 *dsize
=D
.dqb_curblocks
;
1487 /* If softlimit is zero, set it equal to hardlimit.
1490 if (D
.dqb_bsoftlimit
==0)
1491 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1493 if (D
.dqb_bsoftlimit
==0)
1495 /* Use softlimit to determine disk space, except when it has been exceeded */
1496 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)
1497 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__)
1498 ||((D
.dqb_curfiles
>D
.dqb_fsoftlimit
) && (D
.dqb_fsoftlimit
!= 0))
1502 *dsize
= D
.dqb_curblocks
;
1505 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1506 *dsize
= D
.dqb_bsoftlimit
;
1513 #if defined(VXFS_QUOTA)
1515 /****************************************************************************
1516 Try to get the disk space from Veritas disk quotas.
1517 David Lee <T.D.Lee@durham.ac.uk> August 1999.
1519 Background assumptions:
1520 Potentially under many Operating Systems. Initially Solaris 2.
1522 My guess is that Veritas is largely, though not entirely,
1523 independent of OS. So I have separated it out.
1525 There may be some details. For example, OS-specific "include" files.
1527 It is understood that HPUX 10 somehow gets Veritas quotas without
1528 any special effort; if so, this routine need not be compiled in.
1529 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
1532 It is understood that Veritas do not publicly support this ioctl interface.
1533 Rather their preference would be for the user (us) to call the native
1534 OS and then for the OS itself to call through to the VxFS filesystem.
1535 Presumably HPUX 10, see above, does this.
1538 Add your OS to "IFLIST" below.
1539 Get it to compile successfully:
1540 Almost certainly "include"s require attention: see SUNOS5.
1541 In the main code above, arrange for it to be called: see SUNOS5.
1544 ****************************************************************************/
1547 * This "if" is a list of ports:
1548 * if defined(OS1) || defined(OS2) || ...
1553 #include <sys/fs/vx_solaris.h>
1555 #include <sys/fs/vx_machdep.h>
1556 #include <sys/fs/vx_layout.h>
1557 #include <sys/fs/vx_quota.h>
1558 #include <sys/fs/vx_aioctl.h>
1559 #include <sys/fs/vx_ioctl.h>
1561 bool disk_quotas_vxfs(const char *name
, char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1563 uid_t user_id
, euser_id
;
1566 struct vx_quotctl quotabuf
;
1567 struct vx_genioctl genbuf
;
1572 * "name" may or may not include a trailing "/quotas".
1573 * Arranging consistency of calling here in "quotas.c" may not be easy and
1574 * it might be easier to examine and adjust it here.
1575 * Fortunately, VxFS seems not to mind at present.
1577 qfname
= talloc_strdup(talloc_tos(), name
);
1581 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
1583 euser_id
= geteuid();
1584 set_effective_uid(0);
1586 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname
));
1587 if((file
=sys_open(qfname
, O_RDONLY
,0))<0) {
1588 set_effective_uid(euser_id
);
1591 genbuf
.ioc_cmd
= VX_QUOTACTL
;
1592 genbuf
.ioc_up
= (void *) "abuf
;
1594 quotabuf
.cmd
= VX_GETQUOTA
;
1595 quotabuf
.uid
= euser_id
;
1596 quotabuf
.addr
= (caddr_t
) &D
;
1597 ret
= ioctl(file
, VX_ADMIN_IOCTL
, &genbuf
);
1600 set_effective_uid(euser_id
);
1603 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno
) ));
1607 /* If softlimit is zero, set it equal to hardlimit.
1610 if (D
.dqb_bsoftlimit
==0)
1611 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1613 /* Use softlimit to determine disk space. A user exceeding the quota is told
1614 * that there's no space left. Writes might actually work for a bit if the
1615 * hardlimit is set higher than softlimit. Effectively the disk becomes
1616 * made of rubber latex and begins to expand to accommodate the user :-)
1618 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
1619 path
, D
.dqb_curblocks
, D
.dqb_bsoftlimit
, D
.dqb_bhardlimit
,
1620 D
.dqb_curfiles
, D
.dqb_fsoftlimit
, D
.dqb_fhardlimit
));
1622 if (D
.dqb_bsoftlimit
==0)
1625 *dsize
= D
.dqb_bsoftlimit
;
1627 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
1629 *dsize
= D
.dqb_curblocks
;
1631 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1633 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
1634 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
1639 #endif /* SUNOS5 || ... */
1641 #endif /* VXFS_QUOTA */
1643 #else /* WITH_QUOTAS */
1645 bool disk_quotas(const char *path
,uint64_t *bsize
,uint64_t *dfree
,uint64_t *dsize
)
1647 (*bsize
) = 512; /* This value should be ignored */
1649 /* And just to be sure we set some values that hopefully */
1650 /* will be larger that any possible real-world value */
1651 (*dfree
) = (uint64_t)-1;
1652 (*dsize
) = (uint64_t)-1;
1654 /* As we have select not to use quotas, allways fail */
1657 #endif /* WITH_QUOTAS */
1659 #else /* HAVE_SYS_QUOTAS */
1660 /* wrapper to the new sys_quota interface
1661 this file should be removed later
1663 bool disk_quotas(const char *path
,uint64_t *bsize
,uint64_t *dfree
,uint64_t *dsize
)
1672 r
=sys_get_quota(path
, SMB_USER_QUOTA_TYPE
, id
, &D
);
1674 /* Use softlimit to determine disk space, except when it has been exceeded */
1677 if (errno
== EDQUOT
) {
1679 *dsize
=D
.curblocks
;
1682 goto try_group_quota
;
1686 /* Use softlimit to determine disk space, except when it has been exceeded */
1688 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
1689 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
1690 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
1691 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
1694 *dsize
= D
.curblocks
;
1695 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
1696 goto try_group_quota
;
1698 if (D
.softlimit
== 0)
1699 D
.softlimit
= D
.hardlimit
;
1700 *dfree
= D
.softlimit
- D
.curblocks
;
1701 *dsize
= D
.softlimit
;
1710 r
=sys_get_quota(path
, SMB_GROUP_QUOTA_TYPE
, id
, &D
);
1712 /* Use softlimit to determine disk space, except when it has been exceeded */
1715 if (errno
== EDQUOT
) {
1717 *dsize
=D
.curblocks
;
1724 /* Use softlimit to determine disk space, except when it has been exceeded */
1726 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
1727 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
1728 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
1729 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
1732 *dsize
= D
.curblocks
;
1733 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
1736 if (D
.softlimit
== 0)
1737 D
.softlimit
= D
.hardlimit
;
1738 *dfree
= D
.softlimit
- D
.curblocks
;
1739 *dsize
= D
.softlimit
;
1744 #endif /* HAVE_SYS_QUOTAS */