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 */
55 #if defined(SUNOS5) || defined(SUNOS4)
58 #include <sys/param.h>
60 #include <sys/fs/ufs_quota.h>
61 #include <sys/mnttab.h>
62 #include <sys/mntent.h>
63 #else /* defined(SUNOS4) */
64 #include <ufs/quota.h>
70 /****************************************************************************
71 Allows querying of remote hosts for quotas on NFS mounted shares.
72 Supports normal NFS and AMD mounts.
73 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
74 ****************************************************************************/
77 #include <rpc/types.h>
78 #include <rpcsvc/rquota.h>
79 #include <rpc/nettype.h>
82 static int my_xdr_getquota_rslt(XDR
*xdrsp
, struct getquota_rslt
*gqr
)
86 if (!xdr_int(xdrsp
, "astat
)) {
87 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
90 gqr
->status
= quotastat
;
92 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsize
)) {
93 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
96 if (!xdr_bool(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_active
)) {
97 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
100 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
)) {
101 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
104 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
)) {
105 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
108 if (!xdr_int(xdrsp
, &gqr
->getquota_rslt_u
.gqr_rquota
.rq_curblocks
)) {
109 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
115 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
116 static bool nfs_quotas(char *nfspath
, uid_t euser_id
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
118 uid_t uid
= euser_id
;
120 char *mnttype
= nfspath
;
122 struct getquota_rslt gqr
;
123 struct getquota_args args
;
124 char *cutstr
, *pathname
, *host
, *testpath
;
126 static struct timeval timeout
= {2,0};
127 enum clnt_stat clnt_stat
;
130 *bsize
= *dfree
= *dsize
= (uint64_t)0;
132 len
=strcspn(mnttype
, ":");
133 pathname
=strstr(mnttype
, ":");
134 cutstr
= (char *) SMB_MALLOC(len
+1);
138 memset(cutstr
, '\0', len
+1);
139 host
= strncat(cutstr
,mnttype
, sizeof(char) * len
);
140 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr
));
141 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype
));
142 testpath
=strchr_m(mnttype
, ':');
143 args
.gqa_pathp
= testpath
+1;
146 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host
, RQUOTAPROG
, RQUOTAVERS
, "udp"));
148 if ((clnt
= clnt_create(host
, RQUOTAPROG
, RQUOTAVERS
, "udp")) == NULL
) {
153 clnt
->cl_auth
= authunix_create_default();
154 DEBUG(9,("nfs_quotas: auth_success\n"));
156 clnt_stat
=clnt_call(clnt
, RQUOTAPROC_GETQUOTA
, my_xdr_getquota_args
, (caddr_t
)&args
, my_xdr_getquota_rslt
, (caddr_t
)&gqr
, timeout
);
158 if (clnt_stat
!= RPC_SUCCESS
) {
159 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
165 * gqr.status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
166 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
167 * something sensible.
170 switch (gqr
.status
) {
172 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr
.status
));
177 DEBUG(9,("nfs_quotas: Good quota data\n"));
178 D
.dqb_bsoftlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
;
179 D
.dqb_bhardlimit
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
;
180 D
.dqb_curblocks
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
;
185 D
.dqb_bsoftlimit
= 1;
187 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr
.status
));
191 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr
.status
));
195 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",
197 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
,
198 gqr
.getquota_rslt_u
.gqr_rquota
.rq_active
,
199 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bhardlimit
,
200 gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsoftlimit
,
201 gqr
.getquota_rslt_u
.gqr_rquota
.rq_curblocks
));
203 *bsize
= gqr
.getquota_rslt_u
.gqr_rquota
.rq_bsize
;
204 *dsize
= D
.dqb_bsoftlimit
;
206 if (D
.dqb_curblocks
== 1)
209 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
211 *dsize
= D
.dqb_curblocks
;
213 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
219 auth_destroy(clnt
->cl_auth
);
223 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args
.gqa_pathp
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
226 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
231 /****************************************************************************
232 try to get the disk space from disk quotas (SunOS & Solaris2 version)
233 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
234 ****************************************************************************/
236 bool disk_quotas(const char *path
,
245 struct quotctl command
;
253 SMB_STRUCT_STAT sbuf
;
257 euser_id
= geteuid();
259 if (sys_stat(path
, &sbuf
, false) == -1) {
263 devno
= sbuf
.st_ex_dev
;
264 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
265 path
, (unsigned int)devno
));
267 if ((fd
= fopen(MNTTAB
, "r")) == NULL
) {
271 while (getmntent(fd
, &mnt
) == 0) {
272 if (sys_stat(mnt
.mnt_mountp
, &sbuf
, false) == -1) {
276 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
277 mnt
.mnt_mountp
, (unsigned int)devno
));
279 /* quotas are only on vxfs, UFS or NFS */
280 if ((sbuf
.st_ex_dev
== devno
) && (
281 strcmp( mnt
.mnt_fstype
, MNTTYPE_UFS
) == 0 ||
282 strcmp( mnt
.mnt_fstype
, "nfs" ) == 0 ||
283 strcmp( mnt
.mnt_fstype
, "vxfs" ) == 0 )) {
285 name
= talloc_asprintf(talloc_tos(),
294 if ((fd
= setmntent(MOUNTED
, "r")) == NULL
) {
298 while ((mnt
= getmntent(fd
)) != NULL
) {
299 if (sys_stat(mnt
->mnt_dir
, &sbuf
, false) == -1) {
302 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
304 (unsigned int)sbuf
.st_ex_dev
));
305 if (sbuf
.st_ex_dev
== devno
) {
307 name
= talloc_strdup(talloc_tos(),
325 if (strcmp(mnt
.mnt_fstype
, "nfs") == 0) {
327 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n",
329 retval
= nfs_quotas(mnt
.mnt_special
,
330 euser_id
, bsize
, dfree
, dsize
);
335 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name
));
336 if((file
=open(name
, O_RDONLY
,0))<0) {
340 command
.op
= Q_GETQUOTA
;
341 command
.uid
= euser_id
;
342 command
.addr
= (caddr_t
) &D
;
343 ret
= ioctl(file
, Q_QUOTACTL
, &command
);
346 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name
));
347 ret
= quotactl(Q_GETQUOTA
, name
, euser_id
, &D
);
353 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n",
356 #if defined(SUNOS5) && defined(VXFS_QUOTA)
357 /* If normal quotactl() fails, try vxfs private calls */
358 set_effective_uid(euser_id
);
359 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt
.mnt_fstype
));
360 if ( 0 == strcmp ( mnt
.mnt_fstype
, "vxfs" )) {
362 retval
= disk_quotas_vxfs(name
, path
,
363 bsize
, dfree
, dsize
);
371 /* If softlimit is zero, set it equal to hardlimit.
374 if (D
.dqb_bsoftlimit
==0) {
375 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
378 /* Use softlimit to determine disk space. A user exceeding the quota
379 * is told that there's no space left. Writes might actually work for
380 * a bit if the hardlimit is set higher than softlimit. Effectively
381 * the disk becomes made of rubber latex and begins to expand to
382 * accommodate the user :-)
385 if (D
.dqb_bsoftlimit
==0)
388 *dsize
= D
.dqb_bsoftlimit
;
390 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
392 *dsize
= D
.dqb_curblocks
;
394 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
397 DEBUG(5,("disk_quotas for path \"%s\" returning "
398 "bsize %.0f, dfree %.0f, dsize %.0f\n",
399 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
406 #include <ufs/quota.h>
408 /****************************************************************************
409 try to get the disk space from disk quotas - OSF1 version
410 ****************************************************************************/
412 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
420 * This code presumes that OSF1 will only
421 * give out quota info when the real uid
422 * matches the effective uid. JRA.
424 euser_id
= geteuid();
426 if (set_re_uid() != 0) return False
;
428 r
= quotactl(path
,QCMD(Q_GETQUOTA
, USRQUOTA
),euser_id
,(char *) &D
);
439 if (save_errno
== EDQUOT
) /* disk quota exceeded */
442 *dsize
= D
.dqb_curblocks
;
449 /* If softlimit is zero, set it equal to hardlimit.
452 if (D
.dqb_bsoftlimit
==0)
453 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
455 /* Use softlimit to determine disk space, except when it has been exceeded */
457 if (D
.dqb_bsoftlimit
==0)
460 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)) {
462 *dsize
= D
.dqb_curblocks
;
464 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
465 *dsize
= D
.dqb_bsoftlimit
;
470 #elif defined (IRIX6)
471 /****************************************************************************
472 try to get the disk space from disk quotas (IRIX 6.2 version)
473 ****************************************************************************/
475 #include <sys/quota.h>
478 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
483 struct fs_disk_quota F
;
490 /* find the block device file */
492 if ( sys_stat(path
, &S
, false) == -1 ) {
496 devno
= S
.st_ex_dev
;
498 fp
= setmntent(MOUNTED
,"r");
501 while ((mnt
= getmntent(fp
))) {
502 if ( sys_stat(mnt
->mnt_dir
, &S
, false) == -1 )
504 if (S
.st_ex_dev
== devno
) {
518 /* Use softlimit to determine disk space, except when it has been exceeded */
522 if ( 0 == strcmp ( mnt
->mnt_type
, "efs" ))
524 r
=quotactl (Q_GETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &D
);
531 /* Use softlimit to determine disk space, except when it has been exceeded */
533 (D
.dqb_bsoftlimit
&& D
.dqb_curblocks
>=D
.dqb_bsoftlimit
) ||
534 (D
.dqb_bhardlimit
&& D
.dqb_curblocks
>=D
.dqb_bhardlimit
) ||
535 (D
.dqb_fsoftlimit
&& D
.dqb_curfiles
>=D
.dqb_fsoftlimit
) ||
536 (D
.dqb_fhardlimit
&& D
.dqb_curfiles
>=D
.dqb_fhardlimit
)
540 *dsize
= D
.dqb_curblocks
;
542 else if (D
.dqb_bsoftlimit
==0 && D
.dqb_bhardlimit
==0)
548 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
549 *dsize
= D
.dqb_bsoftlimit
;
553 else if ( 0 == strcmp ( mnt
->mnt_type
, "xfs" ))
555 r
=quotactl (Q_XGETQUOTA
, mnt
->mnt_fsname
, euser_id
, (caddr_t
) &F
);
561 DEBUG(5, ("quotactl for uid=%u: %s", euser_id
, strerror(errno
)));
565 /* No quota for this user. */
566 if (F
.d_blk_softlimit
==0 && F
.d_blk_hardlimit
==0)
571 /* Use softlimit to determine disk space, except when it has been exceeded */
573 (F
.d_blk_softlimit
&& F
.d_bcount
>=F
.d_blk_softlimit
) ||
574 (F
.d_blk_hardlimit
&& F
.d_bcount
>=F
.d_blk_hardlimit
) ||
575 (F
.d_ino_softlimit
&& F
.d_icount
>=F
.d_ino_softlimit
) ||
576 (F
.d_ino_hardlimit
&& F
.d_icount
>=F
.d_ino_hardlimit
)
584 *dfree
= (F
.d_blk_softlimit
- F
.d_bcount
);
585 *dsize
= F
.d_blk_softlimit
? F
.d_blk_softlimit
: F
.d_blk_hardlimit
;
602 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
603 #include <jfs/quota.h>
604 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
605 #define dqb_curfiles dqb_curinodes
606 #define dqb_fhardlimit dqb_ihardlimit
607 #define dqb_fsoftlimit dqb_isoftlimit
608 #ifdef _AIXVERSION_530
609 #include <sys/statfs.h>
610 #include <sys/vmount.h>
612 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
613 #include <sys/quota.h>
618 /****************************************************************************
619 try to get the disk space from disk quotas - default version
620 ****************************************************************************/
622 bool disk_quotas(const char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
627 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__)
631 /* find the block device file */
634 /* Need to set the cache flag to 1 for HPUX. Seems
635 * to have a significant performance boost when
636 * lstat calls on /dev access this function.
638 if ((sys_stat(path
, &S
, false)<0)
639 || (devnm(S_IFBLK
, S
.st_ex_dev
, dev_disk
, 256, 1)<0))
641 if ((sys_stat(path
, &S
, false)<0)
642 || (devnm(S_IFBLK
, S
.st_ex_dev
, dev_disk
, 256, 0)<0))
644 #endif /* ifdef HPUX */
646 #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) && !defined(__DragonFly__) */
648 euser_id
= geteuid();
651 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
653 if (set_re_uid() != 0) return False
;
655 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
660 /* AIX has both USER and GROUP quotas:
661 Get the USER quota (ohnielse@fysik.dtu.dk) */
662 #ifdef _AIXVERSION_530
664 struct statfs statbuf
;
665 quota64_t user_quota
;
666 if (statfs(path
,&statbuf
) != 0)
668 if(statbuf
.f_vfstype
== MNT_J2
)
670 /* For some reason we need to be root for jfs2 */
672 r
= quotactl(path
,QCMD(Q_J2GETQUOTA
,USRQUOTA
),euser_id
,(char *) &user_quota
);
674 /* Copy results to old struct to let the following code work as before */
675 D
.dqb_curblocks
= user_quota
.bused
;
676 D
.dqb_bsoftlimit
= user_quota
.bsoft
;
677 D
.dqb_bhardlimit
= user_quota
.bhard
;
678 D
.dqb_curfiles
= user_quota
.iused
;
679 D
.dqb_fsoftlimit
= user_quota
.isoft
;
680 D
.dqb_fhardlimit
= user_quota
.ihard
;
682 else if(statbuf
.f_vfstype
== MNT_JFS
)
686 if (set_re_uid() != 0)
688 r
= quotactl(path
,QCMD(Q_GETQUOTA
,USRQUOTA
),euser_id
,(char *) &D
);
690 #ifdef _AIXVERSION_530
693 r
= 1; /* Fail for other FS-types */
696 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
697 r
=quotactl(Q_GETQUOTA
, dev_disk
, euser_id
, &D
);
698 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ && !__DragonFly__ */
701 /* Use softlimit to determine disk space, except when it has been exceeded */
709 *dsize
=D
.dqb_curblocks
;
715 /* If softlimit is zero, set it equal to hardlimit.
718 if (D
.dqb_bsoftlimit
==0)
719 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
721 if (D
.dqb_bsoftlimit
==0)
723 /* Use softlimit to determine disk space, except when it has been exceeded */
724 if ((D
.dqb_curblocks
>D
.dqb_bsoftlimit
)
725 ||((D
.dqb_curfiles
>D
.dqb_fsoftlimit
) && (D
.dqb_fsoftlimit
!= 0))
728 *dsize
= D
.dqb_curblocks
;
731 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
732 *dsize
= D
.dqb_bsoftlimit
;
739 #if definedr(LINUX) || defined(SUNOS) || defined (__FreeBSD__) || defined(__DragonFly__)
740 static int my_xdr_getquota_args(XDR
*xdrsp
, struct getquota_args
*args
)
742 if (!xdr_string(xdrsp
, &args
->gqa_pathp
, RQ_PATHLEN
))
744 if (!xdr_int(xdrsp
, &args
->gqa_uid
))
750 #if defined(VXFS_QUOTA)
752 /****************************************************************************
753 Try to get the disk space from Veritas disk quotas.
754 David Lee <T.D.Lee@durham.ac.uk> August 1999.
756 Background assumptions:
757 Potentially under many Operating Systems. Initially Solaris 2.
759 My guess is that Veritas is largely, though not entirely,
760 independent of OS. So I have separated it out.
762 There may be some details. For example, OS-specific "include" files.
764 It is understood that HPUX 10 somehow gets Veritas quotas without
765 any special effort; if so, this routine need not be compiled in.
766 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
769 It is understood that Veritas do not publicly support this ioctl interface.
770 Rather their preference would be for the user (us) to call the native
771 OS and then for the OS itself to call through to the VxFS filesystem.
772 Presumably HPUX 10, see above, does this.
775 Add your OS to "IFLIST" below.
776 Get it to compile successfully:
777 Almost certainly "include"s require attention: see SUNOS5.
778 In the main code above, arrange for it to be called: see SUNOS5.
781 ****************************************************************************/
784 * This "if" is a list of ports:
785 * if defined(OS1) || defined(OS2) || ...
790 #include <sys/fs/vx_solaris.h>
792 #include <sys/fs/vx_machdep.h>
793 #include <sys/fs/vx_layout.h>
794 #include <sys/fs/vx_quota.h>
795 #include <sys/fs/vx_aioctl.h>
796 #include <sys/fs/vx_ioctl.h>
798 bool disk_quotas_vxfs(const char *name
, char *path
, uint64_t *bsize
, uint64_t *dfree
, uint64_t *dsize
)
800 uid_t user_id
, euser_id
;
803 struct vx_quotctl quotabuf
;
804 struct vx_genioctl genbuf
;
809 * "name" may or may not include a trailing "/quotas".
810 * Arranging consistency of calling here in "quotas.c" may not be easy and
811 * it might be easier to examine and adjust it here.
812 * Fortunately, VxFS seems not to mind at present.
814 qfname
= talloc_strdup(talloc_tos(), name
);
818 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
820 euser_id
= geteuid();
821 set_effective_uid(0);
823 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname
));
824 if((file
=open(qfname
, O_RDONLY
,0))<0) {
825 set_effective_uid(euser_id
);
828 genbuf
.ioc_cmd
= VX_QUOTACTL
;
829 genbuf
.ioc_up
= (void *) "abuf
;
831 quotabuf
.cmd
= VX_GETQUOTA
;
832 quotabuf
.uid
= euser_id
;
833 quotabuf
.addr
= (caddr_t
) &D
;
834 ret
= ioctl(file
, VX_ADMIN_IOCTL
, &genbuf
);
837 set_effective_uid(euser_id
);
840 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno
) ));
844 /* If softlimit is zero, set it equal to hardlimit.
847 if (D
.dqb_bsoftlimit
==0)
848 D
.dqb_bsoftlimit
= D
.dqb_bhardlimit
;
850 /* Use softlimit to determine disk space. A user exceeding the quota is told
851 * that there's no space left. Writes might actually work for a bit if the
852 * hardlimit is set higher than softlimit. Effectively the disk becomes
853 * made of rubber latex and begins to expand to accommodate the user :-)
855 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
856 path
, D
.dqb_curblocks
, D
.dqb_bsoftlimit
, D
.dqb_bhardlimit
,
857 D
.dqb_curfiles
, D
.dqb_fsoftlimit
, D
.dqb_fhardlimit
));
859 if (D
.dqb_bsoftlimit
==0)
862 *dsize
= D
.dqb_bsoftlimit
;
864 if (D
.dqb_curblocks
> D
.dqb_bsoftlimit
) {
866 *dsize
= D
.dqb_curblocks
;
868 *dfree
= D
.dqb_bsoftlimit
- D
.dqb_curblocks
;
870 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
871 path
,(double)*bsize
,(double)*dfree
,(double)*dsize
));
876 #endif /* SUNOS5 || ... */
878 #endif /* VXFS_QUOTA */
880 #else /* WITH_QUOTAS */
882 bool disk_quotas(const char *path
,uint64_t *bsize
,uint64_t *dfree
,uint64_t *dsize
)
884 (*bsize
) = 512; /* This value should be ignored */
886 /* And just to be sure we set some values that hopefully */
887 /* will be larger that any possible real-world value */
888 (*dfree
) = (uint64_t)-1;
889 (*dsize
) = (uint64_t)-1;
891 /* As we have select not to use quotas, allways fail */
894 #endif /* WITH_QUOTAS */
896 #else /* HAVE_SYS_QUOTAS */
897 /* wrapper to the new sys_quota interface
898 this file should be removed later
900 bool disk_quotas(const char *path
,uint64_t *bsize
,uint64_t *dfree
,uint64_t *dsize
)
909 r
=sys_get_quota(path
, SMB_USER_QUOTA_TYPE
, id
, &D
);
911 /* Use softlimit to determine disk space, except when it has been exceeded */
914 if (errno
== EDQUOT
) {
919 goto try_group_quota
;
923 /* Use softlimit to determine disk space, except when it has been exceeded */
925 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
926 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
927 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
928 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
931 *dsize
= D
.curblocks
;
932 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
933 goto try_group_quota
;
935 if (D
.softlimit
== 0)
936 D
.softlimit
= D
.hardlimit
;
937 *dfree
= D
.softlimit
- D
.curblocks
;
938 *dsize
= D
.softlimit
;
947 r
=sys_get_quota(path
, SMB_GROUP_QUOTA_TYPE
, id
, &D
);
949 /* Use softlimit to determine disk space, except when it has been exceeded */
952 if (errno
== EDQUOT
) {
961 /* Use softlimit to determine disk space, except when it has been exceeded */
963 (D
.softlimit
&& D
.curblocks
>= D
.softlimit
) ||
964 (D
.hardlimit
&& D
.curblocks
>= D
.hardlimit
) ||
965 (D
.isoftlimit
&& D
.curinodes
>= D
.isoftlimit
) ||
966 (D
.ihardlimit
&& D
.curinodes
>=D
.ihardlimit
)
969 *dsize
= D
.curblocks
;
970 } else if (D
.softlimit
==0 && D
.hardlimit
==0) {
973 if (D
.softlimit
== 0)
974 D
.softlimit
= D
.hardlimit
;
975 *dfree
= D
.softlimit
- D
.curblocks
;
976 *dsize
= D
.softlimit
;
981 #endif /* HAVE_SYS_QUOTAS */