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 */
56 #include <sys/types.h>
60 * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
61 * So we include all the files has *should* be in the system into a large,
62 * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA.
65 #include "samba_linux_quota.h"
67 typedef struct _LINUX_SMB_DISK_QUOTA
{
69 uint64_t hardlimit
; /* In bsize units. */
70 uint64_t softlimit
; /* In bsize units. */
71 uint64_t curblocks
; /* In bsize units. */
72 uint64_t ihardlimit
; /* inode hard limit. */
73 uint64_t isoftlimit
; /* inode soft limit. */
74 uint64_t curinodes
; /* Current used inodes. */
75 } LINUX_SMB_DISK_QUOTA
;
80 * (essentially taken from FreeBSD / SUNOS5 section)
83 #include <rpc/types.h>
84 #include <rpcsvc/rquota.h>
85 #ifdef HAVE_RPC_NETTYPE_H
86 #include <rpc/nettype.h>
90 static int my_xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
92 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
94 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
99 static int my_xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
103 if (!xdr_int(xdrsp
, "astat
)) {
104 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
107 gqr
->status
= quotastat
;
109 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
110 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
113 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
114 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
117 if (!xdr_int(xdrsp
, (int *)&gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
118 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
121 if (!xdr_int(xdrsp
, (int *)&gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
122 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
125 if (!xdr_int(xdrsp
, (int *)&gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
126 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
132 static bool nfs_quotas(char *nfspath
, uid_t euser_id
, uint64_t *bsize
,
133 uint64_t *dfree
, uint64_t *dsize
)
135 uid_t uid
= euser_id
;
136 LINUX_SMB_DISK_QUOTA D
;
137 char *mnttype
= nfspath
;
139 struct getquota_rslt gqr
;
140 struct getquota_args args
;
141 char *cutstr
, *pathname
, *host
, *testpath
;
143 static struct timeval timeout
= {2,0};
144 enum clnt_stat clnt_stat
;
147 *bsize
= *dfree
= *dsize
= (uint64_t)0;
149 len
=strcspn(mnttype
, ":");
150 pathname
=strstr(mnttype
, ":");
151 cutstr
= (char *) SMB_MALLOC(len
+1);
155 memset(cutstr
, '\0', len
+1);
156 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
157 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
158 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
159 testpath
=strchr_m(mnttype
, ':');
160 args
.gqa_pathp
= testpath
+1;
163 DEBUG(5, ("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers "
164 "\"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
,
167 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
172 clnt
->cl_auth
= authunix_create_default();
173 DEBUG(9,("nfs_quotas: auth_success\n"));
175 clnt_stat
=clnt_call(clnt
,
177 (const xdrproc_t
)my_xdr_getquota_args
,
179 (const xdrproc_t
)my_xdr_getquota_rslt
,
180 (caddr_t
)&gqr
, timeout
);
182 if (clnt_stat
!= RPC_SUCCESS
) {
183 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
189 * gqr.status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
190 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
191 * something sensible.
194 switch (gqr
.status
) {
196 DEBUG(9, ("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n",
202 DEBUG(9,("nfs_quotas: Good quota data\n"));
203 D
.softlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
204 D
.hardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
205 D
.curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
212 DEBUG(9, ("nfs_quotas: Remote Quotas returned \"%i\" \n",
217 DEBUG(9, ("nfs_quotas: Remote Quotas Questionable! "
218 "Error \"%i\" \n", gqr
.status
));
222 DEBUG(10, ("nfs_quotas: Let`s look at D a bit closer... "
223 "status \"%i\" bsize \"%i\" active? \"%i\" bhard "
224 "\"%i\" bsoft \"%i\" curb \"%i\" \n",
226 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
227 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
228 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
229 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
230 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
232 if (D
.softlimit
== 0)
233 D
.softlimit
= D
.hardlimit
;
234 if (D
.softlimit
== 0)
237 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
238 *dsize
= D
.softlimit
;
240 if (D
.curblocks
== 1)
243 if (D
.curblocks
> D
.softlimit
) {
245 *dsize
= D
.curblocks
;
247 *dfree
= D
.softlimit
- D
.curblocks
;
253 auth_destroy(clnt
->cl_auth
);
257 DEBUG(5, ("nfs_quotas: For path \"%s\" returning "
258 "bsize %.0f, dfree %.0f, dsize %.0f\n",
259 args
.gqa_pathp
, (double)*bsize
, (double)*dfree
,
263 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
267 /* end of nfs quota section */
269 #ifdef HAVE_LINUX_DQBLK_XFS_H
270 #include <linux/dqblk_xfs.h>
272 /****************************************************************************
273 Abstract out the XFS Quota Manager quota get call.
274 ****************************************************************************/
276 static int get_smb_linux_xfs_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
278 struct fs_disk_quota D
;
283 ret
= quotactl(QCMD(Q_XGETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
286 ret
= quotactl(QCMD(Q_XGETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
291 dp
->bsize
= (uint64_t)512;
292 dp
->softlimit
= (uint64_t)D
.d_blk_softlimit
;
293 dp
->hardlimit
= (uint64_t)D
.d_blk_hardlimit
;
294 dp
->ihardlimit
= (uint64_t)D
.d_ino_hardlimit
;
295 dp
->isoftlimit
= (uint64_t)D
.d_ino_softlimit
;
296 dp
->curinodes
= (uint64_t)D
.d_icount
;
297 dp
->curblocks
= (uint64_t)D
.d_bcount
;
302 static int get_smb_linux_xfs_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
304 DEBUG(0,("XFS quota support not available\n"));
311 /****************************************************************************
312 Abstract out the old and new Linux quota get calls.
313 ****************************************************************************/
315 static int get_smb_linux_v1_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
317 struct v1_kern_dqblk D
;
322 ret
= quotactl(QCMD(Q_V1_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
324 if (ret
&& errno
!= EDQUOT
)
325 ret
= quotactl(QCMD(Q_V1_GETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
327 if (ret
&& errno
!= EDQUOT
)
330 dp
->bsize
= (uint64_t)QUOTABLOCK_SIZE
;
331 dp
->softlimit
= (uint64_t)D
.dqb_bsoftlimit
;
332 dp
->hardlimit
= (uint64_t)D
.dqb_bhardlimit
;
333 dp
->ihardlimit
= (uint64_t)D
.dqb_ihardlimit
;
334 dp
->isoftlimit
= (uint64_t)D
.dqb_isoftlimit
;
335 dp
->curinodes
= (uint64_t)D
.dqb_curinodes
;
336 dp
->curblocks
= (uint64_t)D
.dqb_curblocks
;
341 static int get_smb_linux_v2_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
343 struct v2_kern_dqblk D
;
348 ret
= quotactl(QCMD(Q_V2_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
350 if (ret
&& errno
!= EDQUOT
)
351 ret
= quotactl(QCMD(Q_V2_GETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
353 if (ret
&& errno
!= EDQUOT
)
356 dp
->bsize
= (uint64_t)QUOTABLOCK_SIZE
;
357 dp
->softlimit
= (uint64_t)D
.dqb_bsoftlimit
;
358 dp
->hardlimit
= (uint64_t)D
.dqb_bhardlimit
;
359 dp
->ihardlimit
= (uint64_t)D
.dqb_ihardlimit
;
360 dp
->isoftlimit
= (uint64_t)D
.dqb_isoftlimit
;
361 dp
->curinodes
= (uint64_t)D
.dqb_curinodes
;
362 dp
->curblocks
= ((uint64_t)D
.dqb_curspace
) / dp
->bsize
;
367 /****************************************************************************
368 Brand-new generic quota interface.
369 ****************************************************************************/
371 static int get_smb_linux_gen_quota(char *path
, uid_t euser_id
, gid_t egrp_id
, LINUX_SMB_DISK_QUOTA
*dp
)
378 ret
= quotactl(QCMD(Q_GETQUOTA
,USRQUOTA
), path
, euser_id
, (caddr_t
)&D
);
380 if (ret
&& errno
!= EDQUOT
)
381 ret
= quotactl(QCMD(Q_GETQUOTA
,GRPQUOTA
), path
, egrp_id
, (caddr_t
)&D
);
383 if (ret
&& errno
!= EDQUOT
)
386 dp
->bsize
= (uint64_t)QUOTABLOCK_SIZE
;
387 dp
->softlimit
= (uint64_t)D
.dqb_bsoftlimit
;
388 dp
->hardlimit
= (uint64_t)D
.dqb_bhardlimit
;
389 dp
->ihardlimit
= (uint64_t)D
.dqb_ihardlimit
;
390 dp
->isoftlimit
= (uint64_t)D
.dqb_isoftlimit
;
391 dp
->curinodes
= (uint64_t)D
.dqb_curinodes
;
392 dp
->curblocks
= ((uint64_t)D
.dqb_curspace
) / dp
->bsize
;
397 /****************************************************************************
398 Try to get the disk space from disk quotas (LINUX version).
399 ****************************************************************************/
401 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
406 LINUX_SMB_DISK_QUOTA D
;
415 euser_id
= geteuid();
418 /* find the block device file */
420 if (sys_stat(path
, &S
, false) == -1 )
423 devno
= S
.st_ex_dev
;
425 if ((fp
= setmntent(MOUNTED
,"r")) == NULL
)
430 while ((mnt
= getmntent(fp
))) {
431 if (sys_stat(mnt
->mnt_dir
, &S
, false) == -1)
434 if (S
.st_ex_dev
== devno
) {
447 if (strcmp(mnt
->mnt_type
, "nfs") == 0) {
449 retval
= nfs_quotas(mnt
->mnt_fsname
, euser_id
, bsize
, dfree
, dsize
);
454 if (strcmp(mnt
->mnt_type
, "xfs")==0) {
455 r
=get_smb_linux_xfs_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
457 r
=get_smb_linux_gen_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
458 if (r
== -1 && errno
!= EDQUOT
) {
459 r
=get_smb_linux_v2_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
460 if (r
== -1 && errno
!= EDQUOT
)
461 r
=get_smb_linux_v1_quota(mnt
->mnt_fsname
, euser_id
, egrp_id
, &D
);
467 /* Use softlimit to determine disk space, except when it has been exceeded */
470 if (errno
== EDQUOT
) {
479 /* Use softlimit to determine disk space, except when it has been exceeded */
481 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
482 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
483 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
484 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
487 *dsize
= D
.curblocks
;
488 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
491 if (D
.softlimit
== 0)
492 D
.softlimit
= D
.hardlimit
;
493 *dfree
= D
.softlimit
- D
.curblocks
;
494 *dsize
= D
.softlimit
;
502 #include <sys/quota.h>
505 /****************************************************************************
506 try to get the disk space from disk quotas (CRAY VERSION)
507 ****************************************************************************/
509 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
513 SMB_STRUCT_STAT sbuf
;
515 struct q_request request
;
516 struct qf_header header
;
517 int quota_default
= 0 ;
520 if (sys_stat(path
, &sbuf
, false) == -1) {
524 devno
= sbuf
.st_ex_dev
;
526 if ((fd
= setmntent(KMTAB
)) == NULL
) {
530 while ((mnt
= getmntent(fd
)) != NULL
) {
531 if (sys_stat(mnt
->mnt_dir
, &sbuf
, false) == -1) {
534 if (sbuf
.st_ex_dev
== devno
) {
540 name
= talloc_strdup(talloc_tos(), mnt
->mnt_dir
);
550 request
.qf_magic
= QF_MAGIC
;
551 request
.qf_entry
.id
= geteuid() ;
553 if (quotactl(name
, Q_GETQUOTA
, &request
) == -1) {
561 if (request
.qf_entry
.user_q
.f_quota
== QFV_DEFAULT
) {
562 if (!quota_default
) {
563 if (quotactl(name
, Q_GETHEADER
, &header
) == -1) {
566 quota_default
= header
.user_h
.def_fq
;
569 *dfree
= quota_default
;
570 } else if (request
.qf_entry
.user_q
.f_quota
== QFV_PREVENT
) {
573 *dfree
= request
.qf_entry
.user_q
.f_quota
;
576 *dsize
= request
.qf_entry
.user_q
.f_use
;
578 if (*dfree
< *dsize
) {
584 *bsize
= 4096 ; /* Cray blocksize */
589 #elif defined(SUNOS5) || defined(SUNOS4)
592 #include <sys/param.h>
594 #include <sys/fs/ufs_quota.h>
595 #include <sys/mnttab.h>
596 #include <sys/mntent.h>
597 #else /* defined(SUNOS4) */
598 #include <ufs/quota.h>
604 /****************************************************************************
605 Allows querying of remote hosts for quotas on NFS mounted shares.
606 Supports normal NFS and AMD mounts.
607 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
608 ****************************************************************************/
611 #include <rpc/types.h>
612 #include <rpcsvc/rquota.h>
613 #include <rpc/nettype.h>
616 static int my_xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
618 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
620 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
625 static int my_xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
629 if (!xdr_int(xdrsp
, "astat
)) {
630 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
633 gqr
->status
= quotastat
;
635 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
636 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
639 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
640 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
643 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
644 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
647 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
648 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
651 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
652 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
658 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
659 static bool nfs_quotas(char *nfspath
, uid_t euser_id
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
661 uid_t uid
= euser_id
;
663 char *mnttype
= nfspath
;
665 struct getquota_rslt gqr
;
666 struct getquota_args args
;
667 char *cutstr
, *pathname
, *host
, *testpath
;
669 static struct timeval timeout
= {2,0};
670 enum clnt_stat clnt_stat
;
673 *bsize
= *dfree
= *dsize
= (uint64_t)0;
675 len
=strcspn(mnttype
, ":");
676 pathname
=strstr(mnttype
, ":");
677 cutstr
= (char *) SMB_MALLOC(len
+1);
681 memset(cutstr
, '\0', len
+1);
682 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
683 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
684 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
685 testpath
=strchr_m(mnttype
, ':');
686 args
.gqa_pathp
= testpath
+1;
689 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
, "udp"));
691 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
696 clnt
->cl_auth
= authunix_create_default();
697 DEBUG(9,("nfs_quotas: auth_success\n"));
699 clnt_stat
=clnt_call(clnt
, RQUOTAPROC_GETQUOTA
, my_xdr_getquota_args
, (caddr_t
)&args
, my_xdr_getquota_rslt
, (caddr_t
)&gqr
, timeout
);
701 if (clnt_stat
!= RPC_SUCCESS
) {
702 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
708 * gqr.status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
709 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
710 * something sensible.
713 switch (gqr
.status
) {
715 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr
.status
));
720 DEBUG(9,("nfs_quotas: Good quota data\n"));
721 D
.dqb_bsoftlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
722 D
.dqb_bhardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
723 D
.dqb_curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
728 D
.dqb_bsoftlimit
= 1;
730 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr
.status
));
734 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr
.status
));
738 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",
740 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
741 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
742 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
743 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
744 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
746 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
747 *dsize
= D
.dqb_bsoftlimit
;
749 if (D
.dqb_curblocks
== 1)
752 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
754 *dsize
= D
.dqb_curblocks
;
756 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
762 auth_destroy(clnt
->cl_auth
);
766 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args
.gqa_pathp
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
769 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
774 /****************************************************************************
775 try to get the disk space from disk quotas (SunOS & Solaris2 version)
776 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
777 ****************************************************************************/
779 bool disk_quotas(const char *path
,
788 struct quotctl command
;
796 SMB_STRUCT_STAT sbuf
;
800 euser_id
= geteuid();
802 if (sys_stat(path
, &sbuf
, false) == -1) {
806 devno
= sbuf
.st_ex_dev
;
807 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
808 path
, (unsigned int)devno
));
810 if ((fd
= sys_fopen(MNTTAB
, "r")) == NULL
) {
814 while (getmntent(fd
, &mnt
) == 0) {
815 if (sys_stat(mnt
.mnt_mountp
, &sbuf
, false) == -1) {
819 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
820 mnt
.mnt_mountp
, (unsigned int)devno
));
822 /* quotas are only on vxfs, UFS or NFS */
823 if ((sbuf
.st_ex_dev
== devno
) && (
824 strcmp( mnt
.mnt_fstype
, MNTTYPE_UFS
) == 0 ||
825 strcmp( mnt
.mnt_fstype
, "nfs" ) == 0 ||
826 strcmp( mnt
.mnt_fstype
, "vxfs" ) == 0 )) {
828 name
= talloc_asprintf(talloc_tos(),
837 if ((fd
= setmntent(MOUNTED
, "r")) == NULL
) {
841 while ((mnt
= getmntent(fd
)) != NULL
) {
842 if (sys_stat(mnt
->mnt_dir
, &sbuf
, false) == -1) {
845 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
847 (unsigned int)sbuf
.st_ex_dev
));
848 if (sbuf
.st_ex_dev
== devno
) {
850 name
= talloc_strdup(talloc_tos(),
868 if (strcmp(mnt
.mnt_fstype
, "nfs") == 0) {
870 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n",
872 retval
= nfs_quotas(mnt
.mnt_special
,
873 euser_id
, bsize
, dfree
, dsize
);
878 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name
));
879 if((file
=sys_open(name
, O_RDONLY
,0))<0) {
883 command
.op
= Q_GETQUOTA
;
884 command
.uid
= euser_id
;
885 command
.addr
= (caddr_t
) &D
;
886 ret
= ioctl(file
, Q_QUOTACTL
, &command
);
889 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name
));
890 ret
= quotactl(Q_GETQUOTA
, name
, euser_id
, &D
);
896 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n",
899 #if defined(SUNOS5) && defined(VXFS_QUOTA)
900 /* If normal quotactl() fails, try vxfs private calls */
901 set_effective_uid(euser_id
);
902 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt
.mnt_fstype
));
903 if ( 0 == strcmp ( mnt
.mnt_fstype
, "vxfs" )) {
905 retval
= disk_quotas_vxfs(name
, path
,
906 bsize
, dfree
, dsize
);
914 /* If softlimit is zero, set it equal to hardlimit.
917 if (D
.dqb_bsoftlimit
==0) {
918 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
921 /* Use softlimit to determine disk space. A user exceeding the quota
922 * is told that there's no space left. Writes might actually work for
923 * a bit if the hardlimit is set higher than softlimit. Effectively
924 * the disk becomes made of rubber latex and begins to expand to
925 * accommodate the user :-)
928 if (D
.dqb_bsoftlimit
==0)
931 *dsize
= D
.dqb_bsoftlimit
;
933 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
935 *dsize
= D
.dqb_curblocks
;
937 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
940 DEBUG(5,("disk_quotas for path \"%s\" returning "
941 "bsize %.0f, dfree %.0f, dsize %.0f\n",
942 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
949 #include <ufs/quota.h>
951 /****************************************************************************
952 try to get the disk space from disk quotas - OSF1 version
953 ****************************************************************************/
955 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
963 * This code presumes that OSF1 will only
964 * give out quota info when the real uid
965 * matches the effective uid. JRA.
967 euser_id
= geteuid();
969 if (set_re_uid() != 0) return False
;
971 r
= quotactl(path
,QCMD(Q_GETQUOTA
, USRQUOTA
),euser_id
,(char *) &D
);
982 if (save_errno
== EDQUOT
) /* disk quota exceeded */
985 *dsize
= D
.dqb_curblocks
;
992 /* If softlimit is zero, set it equal to hardlimit.
995 if (D
.dqb_bsoftlimit
==0)
996 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
998 /* Use softlimit to determine disk space, except when it has been exceeded */
1000 if (D
.dqb_bsoftlimit
==0)
1003 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)) {
1005 *dsize
= D
.dqb_curblocks
;
1007 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1008 *dsize
= D
.dqb_bsoftlimit
;
1013 #elif defined (IRIX6)
1014 /****************************************************************************
1015 try to get the disk space from disk quotas (IRIX 6.2 version)
1016 ****************************************************************************/
1018 #include <sys/quota.h>
1021 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1026 struct fs_disk_quota F
;
1033 /* find the block device file */
1035 if ( sys_stat(path
, &S
, false) == -1 ) {
1039 devno
= S
.st_ex_dev
;
1041 fp
= setmntent(MOUNTED
,"r");
1044 while ((mnt
= getmntent(fp
))) {
1045 if ( sys_stat(mnt
->mnt_dir
, &S
, false) == -1 )
1047 if (S
.st_ex_dev
== devno
) {
1061 /* Use softlimit to determine disk space, except when it has been exceeded */
1065 if ( 0 == strcmp ( mnt
->mnt_type
, "efs" ))
1067 r
=quotactl (Q_GETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &D
);
1074 /* Use softlimit to determine disk space, except when it has been exceeded */
1076 (D
.dqb_bsoftlimit
&& D
.dqb_curblocks
>=D
.dqb_bsoftlimit
) ||
1077 (D
.dqb_bhardlimit
&& D
.dqb_curblocks
>=D
.dqb_bhardlimit
) ||
1078 (D
.dqb_fsoftlimit
&& D
.dqb_curfiles
>=D
.dqb_fsoftlimit
) ||
1079 (D
.dqb_fhardlimit
&& D
.dqb_curfiles
>=D
.dqb_fhardlimit
)
1083 *dsize
= D
.dqb_curblocks
;
1085 else if (D
.dqb_bsoftlimit
==0 && D
.dqb_bhardlimit
==0)
1091 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1092 *dsize
= D
.dqb_bsoftlimit
;
1096 else if ( 0 == strcmp ( mnt
->mnt_type
, "xfs" ))
1098 r
=quotactl (Q_XGETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &F
);
1104 DEBUG(5, ("quotactl for uid=%u: %s", euser_id
, strerror(errno
)));
1108 /* No quota for this user. */
1109 if (F
.d_blk_softlimit
==0 && F
.d_blk_hardlimit
==0)
1114 /* Use softlimit to determine disk space, except when it has been exceeded */
1116 (F
.d_blk_softlimit
&& F
.d_bcount
>=F
.d_blk_softlimit
) ||
1117 (F
.d_blk_hardlimit
&& F
.d_bcount
>=F
.d_blk_hardlimit
) ||
1118 (F
.d_ino_softlimit
&& F
.d_icount
>=F
.d_ino_softlimit
) ||
1119 (F
.d_ino_hardlimit
&& F
.d_icount
>=F
.d_ino_hardlimit
)
1123 *dsize
= F
.d_bcount
;
1127 *dfree
= (F
.d_blk_softlimit
- F
.d_bcount
);
1128 *dsize
= F
.d_blk_softlimit
? F
.d_blk_softlimit
: F
.d_blk_hardlimit
;
1144 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1145 #include <ufs/ufs/quota.h>
1146 #include <machine/param.h>
1148 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
1149 #include <jfs/quota.h>
1150 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
1151 #define dqb_curfiles dqb_curinodes
1152 #define dqb_fhardlimit dqb_ihardlimit
1153 #define dqb_fsoftlimit dqb_isoftlimit
1154 #ifdef _AIXVERSION_530
1155 #include <sys/statfs.h>
1156 #include <sys/vmount.h>
1157 #endif /* AIX 5.3 */
1158 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1159 #include <sys/quota.h>
1163 #if defined(__FreeBSD__) || defined(__DragonFly__)
1165 #include <rpc/rpc.h>
1166 #include <rpc/types.h>
1167 #include <rpcsvc/rquota.h>
1168 #ifdef HAVE_RPC_NETTYPE_H
1169 #include <rpc/nettype.h>
1171 #include <rpc/xdr.h>
1173 static int my_xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
1175 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
1177 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
1182 static int my_xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
1186 if (!xdr_int(xdrsp
, "astat
)) {
1187 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
1190 gqr
->status
= quotastat
;
1192 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
1193 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
1196 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
1197 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
1200 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
1201 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
1204 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
1205 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
1208 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
1209 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
1215 /* Works on FreeBSD, too. :-) */
1216 static bool nfs_quotas(char *nfspath
, uid_t euser_id
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1218 uid_t uid
= euser_id
;
1220 char *mnttype
= nfspath
;
1222 struct getquota_rslt gqr
;
1223 struct getquota_args args
;
1224 char *cutstr
, *pathname
, *host
, *testpath
;
1226 static struct timeval timeout
= {2,0};
1227 enum clnt_stat clnt_stat
;
1230 *bsize
= *dfree
= *dsize
= (uint64_t)0;
1232 len
=strcspn(mnttype
, ":");
1233 pathname
=strstr(mnttype
, ":");
1234 cutstr
= (char *) SMB_MALLOC(len
+1);
1238 memset(cutstr
, '\0', len
+1);
1239 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
1240 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
1241 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
1242 testpath
=strchr_m(mnttype
, ':');
1243 args
.gqa_pathp
= testpath
+1;
1246 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
, "udp"));
1248 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
1253 clnt
->cl_auth
= authunix_create_default();
1254 DEBUG(9,("nfs_quotas: auth_success\n"));
1256 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
);
1258 if (clnt_stat
!= RPC_SUCCESS
) {
1259 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
1265 * gqr->status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
1266 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
1267 * something sensible.
1270 switch (gqr
.status
) {
1272 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr
.status
));
1277 DEBUG(9,("nfs_quotas: Good quota data\n"));
1278 D
.dqb_bsoftlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
1279 D
.dqb_bhardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
1280 D
.dqb_curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
1285 D
.dqb_bsoftlimit
= 1;
1286 D
.dqb_curblocks
= 1;
1287 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr
.status
));
1291 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr
.status
));
1295 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",
1297 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
1298 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
1299 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
1300 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
1301 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
1303 if (D
.dqb_bsoftlimit
== 0)
1304 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1305 if (D
.dqb_bsoftlimit
== 0)
1308 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
1309 *dsize
= D
.dqb_bsoftlimit
;
1311 if (D
.dqb_curblocks
== 1)
1314 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
1316 *dsize
= D
.dqb_curblocks
;
1318 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1324 auth_destroy(clnt
->cl_auth
);
1328 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args
.gqa_pathp
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
1331 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
1337 /****************************************************************************
1338 try to get the disk space from disk quotas - default version
1339 ****************************************************************************/
1341 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1346 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__)
1350 /* find the block device file */
1353 /* Need to set the cache flag to 1 for HPUX. Seems
1354 * to have a significant performance boost when
1355 * lstat calls on /dev access this function.
1357 if ((sys_stat(path
, &S
, false)<0)
1358 || (devnm(S_IFBLK
, S
.st_ex_dev
, dev_disk
, 256, 1)<0))
1360 if ((sys_stat(path
, &S
, false)<0)
1361 || (devnm(S_IFBLK
, S
.st_ex_dev
, dev_disk
, 256, 0)<0))
1363 #endif /* ifdef HPUX */
1365 #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__) */
1367 euser_id
= geteuid();
1370 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
1372 if (set_re_uid() != 0) return False
;
1374 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
1378 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1380 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
1382 #if defined(__FreeBSD__) || defined(__DragonFly__)
1384 struct statfs
*mnts
;
1388 if (sys_stat(path
, &st
, false) < 0)
1390 devno
= st
.st_ex_dev
;
1392 mntsize
= getmntinfo(&mnts
,MNT_NOWAIT
);
1396 for (i
= 0; i
< mntsize
; i
++) {
1397 if (sys_stat(mnts
[i
].f_mntonname
, &st
, false) < 0)
1399 if (st
.st_ex_dev
== devno
)
1408 #if defined(__FreeBSD__) || defined(__DragonFly__)
1409 if (strcmp(mnts
[i
].f_fstypename
,"nfs") == 0) {
1411 retval
= nfs_quotas(mnts
[i
].f_mntfromname
,euser_id
,bsize
,dfree
,dsize
);
1417 egrp_id
= getegid();
1418 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
1420 /* As FreeBSD has group quotas, if getting the user
1421 quota fails, try getting the group instead. */
1423 r
= quotactl(path
,QCMD(Q_GETQUOTA
,GRPQUOTA
),egrp_id
,(char *) &D
);
1429 /* AIX has both USER and GROUP quotas:
1430 Get the USER quota (ohnielse@fysik.dtu.dk) */
1431 #ifdef _AIXVERSION_530
1433 struct statfs statbuf
;
1434 quota64_t user_quota
;
1435 if (statfs(path
,&statbuf
) != 0)
1437 if(statbuf
.f_vfstype
== MNT_J2
)
1439 /* For some reason we need to be root for jfs2 */
1441 r
= quotactl(path
,QCMD(Q_J2GETQUOTA
,USRQUOTA
),euser_id
,(char *) &user_quota
);
1443 /* Copy results to old struct to let the following code work as before */
1444 D
.dqb_curblocks
= user_quota
.bused
;
1445 D
.dqb_bsoftlimit
= user_quota
.bsoft
;
1446 D
.dqb_bhardlimit
= user_quota
.bhard
;
1447 D
.dqb_curfiles
= user_quota
.iused
;
1448 D
.dqb_fsoftlimit
= user_quota
.isoft
;
1449 D
.dqb_fhardlimit
= user_quota
.ihard
;
1451 else if(statbuf
.f_vfstype
== MNT_JFS
)
1453 #endif /* AIX 5.3 */
1455 if (set_re_uid() != 0)
1457 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
1459 #ifdef _AIXVERSION_530
1462 r
= 1; /* Fail for other FS-types */
1464 #endif /* AIX 5.3 */
1465 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1466 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
1467 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
1470 /* Use softlimit to determine disk space, except when it has been exceeded */
1471 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
1473 #else /* !__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
1475 #endif /*!__FreeBSD__ && !__OpenBSD__ && !__DragonFly__ */
1479 if (errno
== EDQUOT
)
1482 *dsize
=D
.dqb_curblocks
;
1488 /* If softlimit is zero, set it equal to hardlimit.
1491 if (D
.dqb_bsoftlimit
==0)
1492 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1494 if (D
.dqb_bsoftlimit
==0)
1496 /* Use softlimit to determine disk space, except when it has been exceeded */
1497 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)
1498 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__)
1499 ||((D
.dqb_curfiles
>D
.dqb_fsoftlimit
) && (D
.dqb_fsoftlimit
!= 0))
1503 *dsize
= D
.dqb_curblocks
;
1506 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1507 *dsize
= D
.dqb_bsoftlimit
;
1514 #if defined(VXFS_QUOTA)
1516 /****************************************************************************
1517 Try to get the disk space from Veritas disk quotas.
1518 David Lee <T.D.Lee@durham.ac.uk> August 1999.
1520 Background assumptions:
1521 Potentially under many Operating Systems. Initially Solaris 2.
1523 My guess is that Veritas is largely, though not entirely,
1524 independent of OS. So I have separated it out.
1526 There may be some details. For example, OS-specific "include" files.
1528 It is understood that HPUX 10 somehow gets Veritas quotas without
1529 any special effort; if so, this routine need not be compiled in.
1530 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
1533 It is understood that Veritas do not publicly support this ioctl interface.
1534 Rather their preference would be for the user (us) to call the native
1535 OS and then for the OS itself to call through to the VxFS filesystem.
1536 Presumably HPUX 10, see above, does this.
1539 Add your OS to "IFLIST" below.
1540 Get it to compile successfully:
1541 Almost certainly "include"s require attention: see SUNOS5.
1542 In the main code above, arrange for it to be called: see SUNOS5.
1545 ****************************************************************************/
1548 * This "if" is a list of ports:
1549 * if defined(OS1) || defined(OS2) || ...
1554 #include <sys/fs/vx_solaris.h>
1556 #include <sys/fs/vx_machdep.h>
1557 #include <sys/fs/vx_layout.h>
1558 #include <sys/fs/vx_quota.h>
1559 #include <sys/fs/vx_aioctl.h>
1560 #include <sys/fs/vx_ioctl.h>
1562 bool disk_quotas_vxfs(const char *name
, char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
1564 uid_t user_id
, euser_id
;
1567 struct vx_quotctl quotabuf
;
1568 struct vx_genioctl genbuf
;
1573 * "name" may or may not include a trailing "/quotas".
1574 * Arranging consistency of calling here in "quotas.c" may not be easy and
1575 * it might be easier to examine and adjust it here.
1576 * Fortunately, VxFS seems not to mind at present.
1578 qfname
= talloc_strdup(talloc_tos(), name
);
1582 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
1584 euser_id
= geteuid();
1585 set_effective_uid(0);
1587 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname
));
1588 if((file
=sys_open(qfname
, O_RDONLY
,0))<0) {
1589 set_effective_uid(euser_id
);
1592 genbuf
.ioc_cmd
= VX_QUOTACTL
;
1593 genbuf
.ioc_up
= (void *) "abuf
;
1595 quotabuf
.cmd
= VX_GETQUOTA
;
1596 quotabuf
.uid
= euser_id
;
1597 quotabuf
.addr
= (caddr_t
) &D
;
1598 ret
= ioctl(file
, VX_ADMIN_IOCTL
, &genbuf
);
1601 set_effective_uid(euser_id
);
1604 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno
) ));
1608 /* If softlimit is zero, set it equal to hardlimit.
1611 if (D
.dqb_bsoftlimit
==0)
1612 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
1614 /* Use softlimit to determine disk space. A user exceeding the quota is told
1615 * that there's no space left. Writes might actually work for a bit if the
1616 * hardlimit is set higher than softlimit. Effectively the disk becomes
1617 * made of rubber latex and begins to expand to accommodate the user :-)
1619 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
1620 path
, D
.dqb_curblocks
, D
.dqb_bsoftlimit
, D
.dqb_bhardlimit
,
1621 D
.dqb_curfiles
, D
.dqb_fsoftlimit
, D
.dqb_fhardlimit
));
1623 if (D
.dqb_bsoftlimit
==0)
1626 *dsize
= D
.dqb_bsoftlimit
;
1628 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
1630 *dsize
= D
.dqb_curblocks
;
1632 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
1634 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
1635 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
1640 #endif /* SUNOS5 || ... */
1642 #endif /* VXFS_QUOTA */
1644 #else /* WITH_QUOTAS */
1646 bool disk_quotas(const char *path
,uint64_t *bsize
,uint64_t *dfree
,uint64_t *dsize
)
1648 (*bsize
) = 512; /* This value should be ignored */
1650 /* And just to be sure we set some values that hopefully */
1651 /* will be larger that any possible real-world value */
1652 (*dfree
) = (uint64_t)-1;
1653 (*dsize
) = (uint64_t)-1;
1655 /* As we have select not to use quotas, allways fail */
1658 #endif /* WITH_QUOTAS */
1660 #else /* HAVE_SYS_QUOTAS */
1661 /* wrapper to the new sys_quota interface
1662 this file should be removed later
1664 bool disk_quotas(const char *path
,uint64_t *bsize
,uint64_t *dfree
,uint64_t *dsize
)
1673 r
=sys_get_quota(path
, SMB_USER_QUOTA_TYPE
, id
, &D
);
1675 /* Use softlimit to determine disk space, except when it has been exceeded */
1678 if (errno
== EDQUOT
) {
1680 *dsize
=D
.curblocks
;
1683 goto try_group_quota
;
1687 /* Use softlimit to determine disk space, except when it has been exceeded */
1689 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
1690 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
1691 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
1692 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
1695 *dsize
= D
.curblocks
;
1696 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
1697 goto try_group_quota
;
1699 if (D
.softlimit
== 0)
1700 D
.softlimit
= D
.hardlimit
;
1701 *dfree
= D
.softlimit
- D
.curblocks
;
1702 *dsize
= D
.softlimit
;
1711 r
=sys_get_quota(path
, SMB_GROUP_QUOTA_TYPE
, id
, &D
);
1713 /* Use softlimit to determine disk space, except when it has been exceeded */
1716 if (errno
== EDQUOT
) {
1718 *dsize
=D
.curblocks
;
1725 /* Use softlimit to determine disk space, except when it has been exceeded */
1727 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
1728 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
1729 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
1730 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
1733 *dsize
= D
.curblocks
;
1734 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
1737 if (D
.softlimit
== 0)
1738 D
.softlimit
= D
.hardlimit
;
1739 *dfree
= D
.softlimit
- D
.curblocks
;
1740 *dsize
= D
.softlimit
;
1745 #endif /* HAVE_SYS_QUOTAS */