s3:quota: don't force the block size to 512
[Samba/gbeck.git] / source3 / smbd / quotas.c
blob3d1056d31031db912eafaed1cf1927c9afc1b3cf
1 /*
2 Unix SMB/CIFS implementation.
3 support for quotas
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/>.
21 /*
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
24 * things :-(
27 #include "includes.h"
28 #include "smbd/smbd.h"
29 #include "system/filesys.h"
31 #undef DBGC_CLASS
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
39 #endif
41 #ifdef WITH_QUOTAS
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)
57 #include <fcntl.h>
58 #include <sys/param.h>
59 #if defined(SUNOS5)
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>
65 #include <mntent.h>
66 #endif
68 #if defined(SUNOS5)
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 ****************************************************************************/
76 #include <rpc/rpc.h>
77 #include <rpc/types.h>
78 #include <rpcsvc/rquota.h>
79 #include <rpc/nettype.h>
80 #include <rpc/xdr.h>
82 static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
84 int quotastat;
86 if (!xdr_int(xdrsp, &quotastat)) {
87 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
88 return 0;
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"));
94 return 0;
96 if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
97 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
98 return 0;
100 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
101 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
102 return 0;
104 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
105 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
106 return 0;
108 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
109 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
110 return 0;
112 return (1);
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;
119 struct dqblk D;
120 char *mnttype = nfspath;
121 CLIENT *clnt;
122 struct getquota_rslt gqr;
123 struct getquota_args args;
124 char *cutstr, *pathname, *host, *testpath;
125 int len;
126 static struct timeval timeout = {2,0};
127 enum clnt_stat clnt_stat;
128 bool ret = True;
130 *bsize = *dfree = *dsize = (uint64_t)0;
132 len=strcspn(mnttype, ":");
133 pathname=strstr(mnttype, ":");
134 cutstr = (char *) SMB_MALLOC(len+1);
135 if (!cutstr)
136 return False;
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;
144 args.gqa_uid = uid;
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) {
149 ret = False;
150 goto out;
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"));
160 ret = False;
161 goto out;
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) {
171 case 0:
172 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr.status));
173 ret = False;
174 goto out;
176 case 1:
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;
181 break;
183 case 2:
184 case 3:
185 D.dqb_bsoftlimit = 1;
186 D.dqb_curblocks = 1;
187 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr.status));
188 break;
190 default:
191 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr.status ));
192 break;
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",
196 gqr.status,
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 > D.dqb_bsoftlimit) {
207 *dfree = 0;
208 *dsize = D.dqb_curblocks;
209 } else
210 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
212 out:
214 if (clnt) {
215 if (clnt->cl_auth)
216 auth_destroy(clnt->cl_auth);
217 clnt_destroy(clnt);
220 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
222 SAFE_FREE(cutstr);
223 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
224 return ret;
226 #endif
228 /****************************************************************************
229 try to get the disk space from disk quotas (SunOS & Solaris2 version)
230 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
231 ****************************************************************************/
233 bool disk_quotas(const char *path,
234 uint64_t *bsize,
235 uint64_t *dfree,
236 uint64_t *dsize)
238 uid_t euser_id;
239 int ret;
240 struct dqblk D;
241 #if defined(SUNOS5)
242 struct quotctl command;
243 int file;
244 struct mnttab mnt;
245 #else /* SunOS4 */
246 struct mntent *mnt;
247 #endif
248 char *name = NULL;
249 FILE *fd;
250 SMB_STRUCT_STAT sbuf;
251 SMB_DEV_T devno;
252 bool found = false;
254 euser_id = geteuid();
256 if (sys_stat(path, &sbuf, false) == -1) {
257 return false;
260 devno = sbuf.st_ex_dev ;
261 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
262 path, (unsigned int)devno));
263 #if defined(SUNOS5)
264 if ((fd = fopen(MNTTAB, "r")) == NULL) {
265 return false;
268 while (getmntent(fd, &mnt) == 0) {
269 if (sys_stat(mnt.mnt_mountp, &sbuf, false) == -1) {
270 continue;
273 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
274 mnt.mnt_mountp, (unsigned int)devno));
276 /* quotas are only on vxfs, UFS or NFS */
277 if ((sbuf.st_ex_dev == devno) && (
278 strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
279 strcmp( mnt.mnt_fstype, "nfs" ) == 0 ||
280 strcmp( mnt.mnt_fstype, "vxfs" ) == 0 )) {
281 found = true;
282 name = talloc_asprintf(talloc_tos(),
283 "%s/quotas",
284 mnt.mnt_mountp);
285 break;
289 fclose(fd);
290 #else /* SunOS4 */
291 if ((fd = setmntent(MOUNTED, "r")) == NULL) {
292 return false;
295 while ((mnt = getmntent(fd)) != NULL) {
296 if (sys_stat(mnt->mnt_dir, &sbuf, false) == -1) {
297 continue;
299 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
300 mnt->mnt_dir,
301 (unsigned int)sbuf.st_ex_dev));
302 if (sbuf.st_ex_dev == devno) {
303 found = true;
304 name = talloc_strdup(talloc_tos(),
305 mnt->mnt_fsname);
306 break;
310 endmntent(fd);
311 #endif
312 if (!found) {
313 return false;
316 if (!name) {
317 return false;
319 become_root();
321 #if defined(SUNOS5)
322 if (strcmp(mnt.mnt_fstype, "nfs") == 0) {
323 bool retval;
324 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n",
325 mnt.mnt_special));
326 retval = nfs_quotas(mnt.mnt_special,
327 euser_id, bsize, dfree, dsize);
328 unbecome_root();
329 return retval;
332 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
333 if((file=open(name, O_RDONLY,0))<0) {
334 unbecome_root();
335 return false;
337 command.op = Q_GETQUOTA;
338 command.uid = euser_id;
339 command.addr = (caddr_t) &D;
340 ret = ioctl(file, Q_QUOTACTL, &command);
341 close(file);
342 #else
343 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
344 ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
345 #endif
347 unbecome_root();
349 if (ret < 0) {
350 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n",
351 strerror(errno) ));
353 #if defined(SUNOS5) && defined(VXFS_QUOTA)
354 /* If normal quotactl() fails, try vxfs private calls */
355 set_effective_uid(euser_id);
356 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
357 if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
358 bool retval;
359 retval = disk_quotas_vxfs(name, path,
360 bsize, dfree, dsize);
361 return retval;
363 #else
364 return false;
365 #endif
368 /* If softlimit is zero, set it equal to hardlimit.
371 if (D.dqb_bsoftlimit==0) {
372 D.dqb_bsoftlimit = D.dqb_bhardlimit;
375 /* Use softlimit to determine disk space. A user exceeding the quota
376 * is told that there's no space left. Writes might actually work for
377 * a bit if the hardlimit is set higher than softlimit. Effectively
378 * the disk becomes made of rubber latex and begins to expand to
379 * accommodate the user :-)
382 if (D.dqb_bsoftlimit==0)
383 return(False);
384 *bsize = DEV_BSIZE;
385 *dsize = D.dqb_bsoftlimit;
387 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
388 *dfree = 0;
389 *dsize = D.dqb_curblocks;
390 } else {
391 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
394 DEBUG(5,("disk_quotas for path \"%s\" returning "
395 "bsize %.0f, dfree %.0f, dsize %.0f\n",
396 path,(double)*bsize,(double)*dfree,(double)*dsize));
398 return true;
402 #elif defined(OSF1)
403 #include <ufs/quota.h>
405 /****************************************************************************
406 try to get the disk space from disk quotas - OSF1 version
407 ****************************************************************************/
409 bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
411 int r, save_errno;
412 struct dqblk D;
413 SMB_STRUCT_STAT S;
414 uid_t euser_id;
417 * This code presumes that OSF1 will only
418 * give out quota info when the real uid
419 * matches the effective uid. JRA.
421 euser_id = geteuid();
422 save_re_uid();
423 if (set_re_uid() != 0) return False;
425 r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D);
426 if (r) {
427 save_errno = errno;
430 restore_re_uid();
432 *bsize = DEV_BSIZE;
434 if (r)
436 if (save_errno == EDQUOT) /* disk quota exceeded */
438 *dfree = 0;
439 *dsize = D.dqb_curblocks;
440 return (True);
442 else
443 return (False);
446 /* If softlimit is zero, set it equal to hardlimit.
449 if (D.dqb_bsoftlimit==0)
450 D.dqb_bsoftlimit = D.dqb_bhardlimit;
452 /* Use softlimit to determine disk space, except when it has been exceeded */
454 if (D.dqb_bsoftlimit==0)
455 return(False);
457 if ((D.dqb_curblocks>D.dqb_bsoftlimit)) {
458 *dfree = 0;
459 *dsize = D.dqb_curblocks;
460 } else {
461 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
462 *dsize = D.dqb_bsoftlimit;
464 return (True);
467 #else
469 #if AIX
470 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
471 #include <jfs/quota.h>
472 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
473 #define dqb_curfiles dqb_curinodes
474 #define dqb_fhardlimit dqb_ihardlimit
475 #define dqb_fsoftlimit dqb_isoftlimit
476 #ifdef _AIXVERSION_530
477 #include <sys/statfs.h>
478 #include <sys/vmount.h>
479 #endif /* AIX 5.3 */
480 #else /* !AIX */
481 #include <sys/quota.h>
482 #include <devnm.h>
483 #endif
486 /****************************************************************************
487 try to get the disk space from disk quotas - default version
488 ****************************************************************************/
490 bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
492 int r;
493 struct dqblk D;
494 uid_t euser_id;
495 #if !defined(AIX)
496 char dev_disk[256];
497 SMB_STRUCT_STAT S;
499 /* find the block device file */
501 if ((sys_stat(path, &S, false)<0)
502 || (devnm(S_IFBLK, S.st_ex_dev, dev_disk, 256, 0)<0))
503 return (False);
505 #endif /* !defined(AIX) */
507 euser_id = geteuid();
509 #if defined(AIX)
510 /* AIX has both USER and GROUP quotas:
511 Get the USER quota (ohnielse@fysik.dtu.dk) */
512 #ifdef _AIXVERSION_530
514 struct statfs statbuf;
515 quota64_t user_quota;
516 if (statfs(path,&statbuf) != 0)
517 return False;
518 if(statbuf.f_vfstype == MNT_J2)
520 /* For some reason we need to be root for jfs2 */
521 become_root();
522 r = quotactl(path,QCMD(Q_J2GETQUOTA,USRQUOTA),euser_id,(char *) &user_quota);
523 unbecome_root();
524 /* Copy results to old struct to let the following code work as before */
525 D.dqb_curblocks = user_quota.bused;
526 D.dqb_bsoftlimit = user_quota.bsoft;
527 D.dqb_bhardlimit = user_quota.bhard;
528 D.dqb_curfiles = user_quota.iused;
529 D.dqb_fsoftlimit = user_quota.isoft;
530 D.dqb_fhardlimit = user_quota.ihard;
532 else if(statbuf.f_vfstype == MNT_JFS)
534 #endif /* AIX 5.3 */
535 save_re_uid();
536 if (set_re_uid() != 0)
537 return False;
538 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
539 restore_re_uid();
540 #ifdef _AIXVERSION_530
542 else
543 r = 1; /* Fail for other FS-types */
545 #endif /* AIX 5.3 */
546 #else /* !AIX */
547 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
548 #endif /* !AIX */
550 /* Use softlimit to determine disk space, except when it has been exceeded */
551 *bsize = 1024;
553 if (r)
555 if (errno == EDQUOT)
557 *dfree =0;
558 *dsize =D.dqb_curblocks;
559 return (True);
561 else return(False);
564 /* If softlimit is zero, set it equal to hardlimit.
567 if (D.dqb_bsoftlimit==0)
568 D.dqb_bsoftlimit = D.dqb_bhardlimit;
570 if (D.dqb_bsoftlimit==0)
571 return(False);
572 /* Use softlimit to determine disk space, except when it has been exceeded */
573 if ((D.dqb_curblocks>D.dqb_bsoftlimit)
574 ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
576 *dfree = 0;
577 *dsize = D.dqb_curblocks;
579 else {
580 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
581 *dsize = D.dqb_bsoftlimit;
583 return (True);
586 #endif
588 #if defined(SUNOS)
589 static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
591 if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
592 return(0);
593 if (!xdr_int(xdrsp, &args->gqa_uid))
594 return(0);
595 return (1);
597 #endif
599 #if defined(VXFS_QUOTA)
601 /****************************************************************************
602 Try to get the disk space from Veritas disk quotas.
603 David Lee <T.D.Lee@durham.ac.uk> August 1999.
605 Background assumptions:
606 Potentially under many Operating Systems. Initially Solaris 2.
608 My guess is that Veritas is largely, though not entirely,
609 independent of OS. So I have separated it out.
611 There may be some details. For example, OS-specific "include" files.
613 It is understood that HPUX 10 somehow gets Veritas quotas without
614 any special effort; if so, this routine need not be compiled in.
615 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
617 Warning:
618 It is understood that Veritas do not publicly support this ioctl interface.
619 Rather their preference would be for the user (us) to call the native
620 OS and then for the OS itself to call through to the VxFS filesystem.
621 Presumably HPUX 10, see above, does this.
623 Hints for porting:
624 Add your OS to "IFLIST" below.
625 Get it to compile successfully:
626 Almost certainly "include"s require attention: see SUNOS5.
627 In the main code above, arrange for it to be called: see SUNOS5.
628 Test!
630 ****************************************************************************/
632 /* "IFLIST"
633 * This "if" is a list of ports:
634 * if defined(OS1) || defined(OS2) || ...
636 #if defined(SUNOS5)
638 #if defined(SUNOS5)
639 #include <sys/fs/vx_solaris.h>
640 #endif
641 #include <sys/fs/vx_machdep.h>
642 #include <sys/fs/vx_layout.h>
643 #include <sys/fs/vx_quota.h>
644 #include <sys/fs/vx_aioctl.h>
645 #include <sys/fs/vx_ioctl.h>
647 bool disk_quotas_vxfs(const char *name, char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
649 uid_t user_id, euser_id;
650 int ret;
651 struct vx_dqblk D;
652 struct vx_quotctl quotabuf;
653 struct vx_genioctl genbuf;
654 char *qfname;
655 int file;
658 * "name" may or may not include a trailing "/quotas".
659 * Arranging consistency of calling here in "quotas.c" may not be easy and
660 * it might be easier to examine and adjust it here.
661 * Fortunately, VxFS seems not to mind at present.
663 qfname = talloc_strdup(talloc_tos(), name);
664 if (!qfname) {
665 return false;
667 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
669 euser_id = geteuid();
670 set_effective_uid(0);
672 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
673 if((file=open(qfname, O_RDONLY,0))<0) {
674 set_effective_uid(euser_id);
675 return(False);
677 genbuf.ioc_cmd = VX_QUOTACTL;
678 genbuf.ioc_up = (void *) &quotabuf;
680 quotabuf.cmd = VX_GETQUOTA;
681 quotabuf.uid = euser_id;
682 quotabuf.addr = (caddr_t) &D;
683 ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
684 close(file);
686 set_effective_uid(euser_id);
688 if (ret < 0) {
689 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
690 return(False);
693 /* If softlimit is zero, set it equal to hardlimit.
696 if (D.dqb_bsoftlimit==0)
697 D.dqb_bsoftlimit = D.dqb_bhardlimit;
699 /* Use softlimit to determine disk space. A user exceeding the quota is told
700 * that there's no space left. Writes might actually work for a bit if the
701 * hardlimit is set higher than softlimit. Effectively the disk becomes
702 * made of rubber latex and begins to expand to accommodate the user :-)
704 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
705 path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
706 D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));
708 if (D.dqb_bsoftlimit==0)
709 return(False);
710 *bsize = DEV_BSIZE;
711 *dsize = D.dqb_bsoftlimit;
713 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
714 *dfree = 0;
715 *dsize = D.dqb_curblocks;
716 } else
717 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
719 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
720 path,(double)*bsize,(double)*dfree,(double)*dsize));
722 return(True);
725 #endif /* SUNOS5 || ... */
727 #endif /* VXFS_QUOTA */
729 #else /* WITH_QUOTAS */
731 bool disk_quotas(const char *path,uint64_t *bsize,uint64_t *dfree,uint64_t *dsize)
733 (*bsize) = 512; /* This value should be ignored */
735 /* And just to be sure we set some values that hopefully */
736 /* will be larger that any possible real-world value */
737 (*dfree) = (uint64_t)-1;
738 (*dsize) = (uint64_t)-1;
740 /* As we have select not to use quotas, allways fail */
741 return false;
743 #endif /* WITH_QUOTAS */
745 #else /* HAVE_SYS_QUOTAS */
746 /* wrapper to the new sys_quota interface
747 this file should be removed later
749 bool disk_quotas(const char *path,uint64_t *bsize,uint64_t *dfree,uint64_t *dsize)
751 int r;
752 SMB_DISK_QUOTA D;
753 unid_t id;
755 id.uid = geteuid();
757 ZERO_STRUCT(D);
758 r=sys_get_quota(path, SMB_USER_QUOTA_TYPE, id, &D);
760 /* Use softlimit to determine disk space, except when it has been exceeded */
761 *bsize = D.bsize;
762 if (r == -1) {
763 if (errno == EDQUOT) {
764 *dfree =0;
765 *dsize =D.curblocks;
766 return (True);
767 } else {
768 goto try_group_quota;
772 /* Use softlimit to determine disk space, except when it has been exceeded */
773 if (
774 (D.softlimit && D.curblocks >= D.softlimit) ||
775 (D.hardlimit && D.curblocks >= D.hardlimit) ||
776 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
777 (D.ihardlimit && D.curinodes>=D.ihardlimit)
779 *dfree = 0;
780 *dsize = D.curblocks;
781 } else if (D.softlimit==0 && D.hardlimit==0) {
782 goto try_group_quota;
783 } else {
784 if (D.softlimit == 0)
785 D.softlimit = D.hardlimit;
786 *dfree = D.softlimit - D.curblocks;
787 *dsize = D.softlimit;
790 return True;
792 try_group_quota:
793 id.gid = getegid();
795 ZERO_STRUCT(D);
796 r=sys_get_quota(path, SMB_GROUP_QUOTA_TYPE, id, &D);
798 /* Use softlimit to determine disk space, except when it has been exceeded */
799 *bsize = D.bsize;
800 if (r == -1) {
801 if (errno == EDQUOT) {
802 *dfree =0;
803 *dsize =D.curblocks;
804 return (True);
805 } else {
806 return False;
810 /* Use softlimit to determine disk space, except when it has been exceeded */
811 if (
812 (D.softlimit && D.curblocks >= D.softlimit) ||
813 (D.hardlimit && D.curblocks >= D.hardlimit) ||
814 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
815 (D.ihardlimit && D.curinodes>=D.ihardlimit)
817 *dfree = 0;
818 *dsize = D.curblocks;
819 } else if (D.softlimit==0 && D.hardlimit==0) {
820 return False;
821 } else {
822 if (D.softlimit == 0)
823 D.softlimit = D.hardlimit;
824 *dfree = D.softlimit - D.curblocks;
825 *dsize = D.softlimit;
828 return (True);
830 #endif /* HAVE_SYS_QUOTAS */