s4-join: factorize code, add info
[Samba/gbeck.git] / source3 / smbd / quotas.c
blobc64b63a4a36146b7e7a24205d310f4fbcb2f68ff
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 static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
117 if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
118 return(0);
119 if (!xdr_int(xdrsp, &args->gqa_uid))
120 return(0);
121 return (1);
124 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
125 static bool nfs_quotas(char *nfspath, uid_t euser_id, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
127 uid_t uid = euser_id;
128 struct dqblk D;
129 char *mnttype = nfspath;
130 CLIENT *clnt;
131 struct getquota_rslt gqr;
132 struct getquota_args args;
133 char *cutstr, *pathname, *host, *testpath;
134 int len;
135 static struct timeval timeout = {2,0};
136 enum clnt_stat clnt_stat;
137 bool ret = True;
139 *bsize = *dfree = *dsize = (uint64_t)0;
141 len=strcspn(mnttype, ":");
142 pathname=strstr(mnttype, ":");
143 cutstr = (char *) SMB_MALLOC(len+1);
144 if (!cutstr)
145 return False;
147 memset(cutstr, '\0', len+1);
148 host = strncat(cutstr,mnttype, sizeof(char) * len );
149 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
150 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
151 testpath=strchr_m(mnttype, ':');
152 args.gqa_pathp = testpath+1;
153 args.gqa_uid = uid;
155 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
157 if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
158 ret = False;
159 goto out;
162 clnt->cl_auth = authunix_create_default();
163 DEBUG(9,("nfs_quotas: auth_success\n"));
165 clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, my_xdr_getquota_args, (caddr_t)&args, my_xdr_getquota_rslt, (caddr_t)&gqr, timeout);
167 if (clnt_stat != RPC_SUCCESS) {
168 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
169 ret = False;
170 goto out;
174 * gqr.status returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
175 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
176 * something sensible.
179 switch (gqr.status) {
180 case 0:
181 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", gqr.status));
182 ret = False;
183 goto out;
185 case 1:
186 DEBUG(9,("nfs_quotas: Good quota data\n"));
187 D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
188 D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
189 D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
190 break;
192 case 2:
193 case 3:
194 D.dqb_bsoftlimit = 1;
195 D.dqb_curblocks = 1;
196 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr.status));
197 break;
199 default:
200 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", gqr.status ));
201 break;
204 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",
205 gqr.status,
206 gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
207 gqr.getquota_rslt_u.gqr_rquota.rq_active,
208 gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
209 gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
210 gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
212 *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
213 *dsize = D.dqb_bsoftlimit;
215 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
216 *dfree = 0;
217 *dsize = D.dqb_curblocks;
218 } else
219 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
221 out:
223 if (clnt) {
224 if (clnt->cl_auth)
225 auth_destroy(clnt->cl_auth);
226 clnt_destroy(clnt);
229 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
231 SAFE_FREE(cutstr);
232 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
233 return ret;
235 #endif
237 /****************************************************************************
238 try to get the disk space from disk quotas (SunOS & Solaris2 version)
239 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
240 ****************************************************************************/
242 bool disk_quotas(const char *path,
243 uint64_t *bsize,
244 uint64_t *dfree,
245 uint64_t *dsize)
247 uid_t euser_id;
248 int ret;
249 struct dqblk D;
250 #if defined(SUNOS5)
251 struct quotctl command;
252 int file;
253 struct mnttab mnt;
254 #else /* SunOS4 */
255 struct mntent *mnt;
256 #endif
257 char *name = NULL;
258 FILE *fd;
259 SMB_STRUCT_STAT sbuf;
260 SMB_DEV_T devno;
261 bool found = false;
263 euser_id = geteuid();
265 if (sys_stat(path, &sbuf, false) == -1) {
266 return false;
269 devno = sbuf.st_ex_dev ;
270 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
271 path, (unsigned int)devno));
272 #if defined(SUNOS5)
273 if ((fd = fopen(MNTTAB, "r")) == NULL) {
274 return false;
277 while (getmntent(fd, &mnt) == 0) {
278 if (sys_stat(mnt.mnt_mountp, &sbuf, false) == -1) {
279 continue;
282 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
283 mnt.mnt_mountp, (unsigned int)devno));
285 /* quotas are only on vxfs, UFS or NFS */
286 if ((sbuf.st_ex_dev == devno) && (
287 strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
288 strcmp( mnt.mnt_fstype, "nfs" ) == 0 ||
289 strcmp( mnt.mnt_fstype, "vxfs" ) == 0 )) {
290 found = true;
291 name = talloc_asprintf(talloc_tos(),
292 "%s/quotas",
293 mnt.mnt_mountp);
294 break;
298 fclose(fd);
299 #else /* SunOS4 */
300 if ((fd = setmntent(MOUNTED, "r")) == NULL) {
301 return false;
304 while ((mnt = getmntent(fd)) != NULL) {
305 if (sys_stat(mnt->mnt_dir, &sbuf, false) == -1) {
306 continue;
308 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
309 mnt->mnt_dir,
310 (unsigned int)sbuf.st_ex_dev));
311 if (sbuf.st_ex_dev == devno) {
312 found = true;
313 name = talloc_strdup(talloc_tos(),
314 mnt->mnt_fsname);
315 break;
319 endmntent(fd);
320 #endif
321 if (!found) {
322 return false;
325 if (!name) {
326 return false;
328 become_root();
330 #if defined(SUNOS5)
331 if (strcmp(mnt.mnt_fstype, "nfs") == 0) {
332 bool retval;
333 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n",
334 mnt.mnt_special));
335 retval = nfs_quotas(mnt.mnt_special,
336 euser_id, bsize, dfree, dsize);
337 unbecome_root();
338 return retval;
341 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
342 if((file=open(name, O_RDONLY,0))<0) {
343 unbecome_root();
344 return false;
346 command.op = Q_GETQUOTA;
347 command.uid = euser_id;
348 command.addr = (caddr_t) &D;
349 ret = ioctl(file, Q_QUOTACTL, &command);
350 close(file);
351 #else
352 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
353 ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
354 #endif
356 unbecome_root();
358 if (ret < 0) {
359 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n",
360 strerror(errno) ));
362 #if defined(SUNOS5) && defined(VXFS_QUOTA)
363 /* If normal quotactl() fails, try vxfs private calls */
364 set_effective_uid(euser_id);
365 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
366 if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
367 bool retval;
368 retval = disk_quotas_vxfs(name, path,
369 bsize, dfree, dsize);
370 return retval;
372 #else
373 return false;
374 #endif
377 /* If softlimit is zero, set it equal to hardlimit.
380 if (D.dqb_bsoftlimit==0) {
381 D.dqb_bsoftlimit = D.dqb_bhardlimit;
384 /* Use softlimit to determine disk space. A user exceeding the quota
385 * is told that there's no space left. Writes might actually work for
386 * a bit if the hardlimit is set higher than softlimit. Effectively
387 * the disk becomes made of rubber latex and begins to expand to
388 * accommodate the user :-)
391 if (D.dqb_bsoftlimit==0)
392 return(False);
393 *bsize = DEV_BSIZE;
394 *dsize = D.dqb_bsoftlimit;
396 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
397 *dfree = 0;
398 *dsize = D.dqb_curblocks;
399 } else {
400 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
403 DEBUG(5,("disk_quotas for path \"%s\" returning "
404 "bsize %.0f, dfree %.0f, dsize %.0f\n",
405 path,(double)*bsize,(double)*dfree,(double)*dsize));
407 return true;
411 #else
413 #if AIX
414 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
415 #include <jfs/quota.h>
416 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
417 #define dqb_curfiles dqb_curinodes
418 #define dqb_fhardlimit dqb_ihardlimit
419 #define dqb_fsoftlimit dqb_isoftlimit
420 #ifdef _AIXVERSION_530
421 #include <sys/statfs.h>
422 #include <sys/vmount.h>
423 #endif /* AIX 5.3 */
424 #else /* !AIX */
425 #include <sys/quota.h>
426 #include <devnm.h>
427 #endif
430 /****************************************************************************
431 try to get the disk space from disk quotas - default version
432 ****************************************************************************/
434 bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
436 int r;
437 struct dqblk D;
438 uid_t euser_id;
439 #if !defined(AIX)
440 char dev_disk[256];
441 SMB_STRUCT_STAT S;
443 /* find the block device file */
445 if ((sys_stat(path, &S, false)<0)
446 || (devnm(S_IFBLK, S.st_ex_dev, dev_disk, 256, 0)<0))
447 return (False);
449 #endif /* !defined(AIX) */
451 euser_id = geteuid();
453 #if defined(AIX)
454 /* AIX has both USER and GROUP quotas:
455 Get the USER quota (ohnielse@fysik.dtu.dk) */
456 #ifdef _AIXVERSION_530
458 struct statfs statbuf;
459 quota64_t user_quota;
460 if (statfs(path,&statbuf) != 0)
461 return False;
462 if(statbuf.f_vfstype == MNT_J2)
464 /* For some reason we need to be root for jfs2 */
465 become_root();
466 r = quotactl(path,QCMD(Q_J2GETQUOTA,USRQUOTA),euser_id,(char *) &user_quota);
467 unbecome_root();
468 /* Copy results to old struct to let the following code work as before */
469 D.dqb_curblocks = user_quota.bused;
470 D.dqb_bsoftlimit = user_quota.bsoft;
471 D.dqb_bhardlimit = user_quota.bhard;
472 D.dqb_curfiles = user_quota.iused;
473 D.dqb_fsoftlimit = user_quota.isoft;
474 D.dqb_fhardlimit = user_quota.ihard;
476 else if(statbuf.f_vfstype == MNT_JFS)
478 #endif /* AIX 5.3 */
479 save_re_uid();
480 if (set_re_uid() != 0)
481 return False;
482 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
483 restore_re_uid();
484 #ifdef _AIXVERSION_530
486 else
487 r = 1; /* Fail for other FS-types */
489 #endif /* AIX 5.3 */
490 #else /* !AIX */
491 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
492 #endif /* !AIX */
494 /* Use softlimit to determine disk space, except when it has been exceeded */
495 *bsize = 1024;
497 if (r)
499 if (errno == EDQUOT)
501 *dfree =0;
502 *dsize =D.dqb_curblocks;
503 return (True);
505 else return(False);
508 /* If softlimit is zero, set it equal to hardlimit.
511 if (D.dqb_bsoftlimit==0)
512 D.dqb_bsoftlimit = D.dqb_bhardlimit;
514 if (D.dqb_bsoftlimit==0)
515 return(False);
516 /* Use softlimit to determine disk space, except when it has been exceeded */
517 if ((D.dqb_curblocks>D.dqb_bsoftlimit)
518 ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
520 *dfree = 0;
521 *dsize = D.dqb_curblocks;
523 else {
524 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
525 *dsize = D.dqb_bsoftlimit;
527 return (True);
530 #endif
532 #if defined(VXFS_QUOTA)
534 /****************************************************************************
535 Try to get the disk space from Veritas disk quotas.
536 David Lee <T.D.Lee@durham.ac.uk> August 1999.
538 Background assumptions:
539 Potentially under many Operating Systems. Initially Solaris 2.
541 My guess is that Veritas is largely, though not entirely,
542 independent of OS. So I have separated it out.
544 There may be some details. For example, OS-specific "include" files.
546 It is understood that HPUX 10 somehow gets Veritas quotas without
547 any special effort; if so, this routine need not be compiled in.
548 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
550 Warning:
551 It is understood that Veritas do not publicly support this ioctl interface.
552 Rather their preference would be for the user (us) to call the native
553 OS and then for the OS itself to call through to the VxFS filesystem.
554 Presumably HPUX 10, see above, does this.
556 Hints for porting:
557 Add your OS to "IFLIST" below.
558 Get it to compile successfully:
559 Almost certainly "include"s require attention: see SUNOS5.
560 In the main code above, arrange for it to be called: see SUNOS5.
561 Test!
563 ****************************************************************************/
565 /* "IFLIST"
566 * This "if" is a list of ports:
567 * if defined(OS1) || defined(OS2) || ...
569 #if defined(SUNOS5)
571 #if defined(SUNOS5)
572 #include <sys/fs/vx_solaris.h>
573 #endif
574 #include <sys/fs/vx_machdep.h>
575 #include <sys/fs/vx_layout.h>
576 #include <sys/fs/vx_quota.h>
577 #include <sys/fs/vx_aioctl.h>
578 #include <sys/fs/vx_ioctl.h>
580 bool disk_quotas_vxfs(const char *name, char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
582 uid_t user_id, euser_id;
583 int ret;
584 struct vx_dqblk D;
585 struct vx_quotctl quotabuf;
586 struct vx_genioctl genbuf;
587 char *qfname;
588 int file;
591 * "name" may or may not include a trailing "/quotas".
592 * Arranging consistency of calling here in "quotas.c" may not be easy and
593 * it might be easier to examine and adjust it here.
594 * Fortunately, VxFS seems not to mind at present.
596 qfname = talloc_strdup(talloc_tos(), name);
597 if (!qfname) {
598 return false;
600 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
602 euser_id = geteuid();
603 set_effective_uid(0);
605 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
606 if((file=open(qfname, O_RDONLY,0))<0) {
607 set_effective_uid(euser_id);
608 return(False);
610 genbuf.ioc_cmd = VX_QUOTACTL;
611 genbuf.ioc_up = (void *) &quotabuf;
613 quotabuf.cmd = VX_GETQUOTA;
614 quotabuf.uid = euser_id;
615 quotabuf.addr = (caddr_t) &D;
616 ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
617 close(file);
619 set_effective_uid(euser_id);
621 if (ret < 0) {
622 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
623 return(False);
626 /* If softlimit is zero, set it equal to hardlimit.
629 if (D.dqb_bsoftlimit==0)
630 D.dqb_bsoftlimit = D.dqb_bhardlimit;
632 /* Use softlimit to determine disk space. A user exceeding the quota is told
633 * that there's no space left. Writes might actually work for a bit if the
634 * hardlimit is set higher than softlimit. Effectively the disk becomes
635 * made of rubber latex and begins to expand to accommodate the user :-)
637 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
638 path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
639 D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));
641 if (D.dqb_bsoftlimit==0)
642 return(False);
643 *bsize = DEV_BSIZE;
644 *dsize = D.dqb_bsoftlimit;
646 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
647 *dfree = 0;
648 *dsize = D.dqb_curblocks;
649 } else
650 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
652 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
653 path,(double)*bsize,(double)*dfree,(double)*dsize));
655 return(True);
658 #endif /* SUNOS5 || ... */
660 #endif /* VXFS_QUOTA */
662 #else /* WITH_QUOTAS */
664 bool disk_quotas(const char *path,uint64_t *bsize,uint64_t *dfree,uint64_t *dsize)
666 (*bsize) = 512; /* This value should be ignored */
668 /* And just to be sure we set some values that hopefully */
669 /* will be larger that any possible real-world value */
670 (*dfree) = (uint64_t)-1;
671 (*dsize) = (uint64_t)-1;
673 /* As we have select not to use quotas, allways fail */
674 return false;
676 #endif /* WITH_QUOTAS */
678 #else /* HAVE_SYS_QUOTAS */
679 /* wrapper to the new sys_quota interface
680 this file should be removed later
682 bool disk_quotas(const char *path,uint64_t *bsize,uint64_t *dfree,uint64_t *dsize)
684 int r;
685 SMB_DISK_QUOTA D;
686 unid_t id;
688 id.uid = geteuid();
690 ZERO_STRUCT(D);
691 r=sys_get_quota(path, SMB_USER_QUOTA_TYPE, id, &D);
693 /* Use softlimit to determine disk space, except when it has been exceeded */
694 *bsize = D.bsize;
695 if (r == -1) {
696 if (errno == EDQUOT) {
697 *dfree =0;
698 *dsize =D.curblocks;
699 return (True);
700 } else {
701 goto try_group_quota;
705 /* Use softlimit to determine disk space, except when it has been exceeded */
706 if (
707 (D.softlimit && D.curblocks >= D.softlimit) ||
708 (D.hardlimit && D.curblocks >= D.hardlimit) ||
709 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
710 (D.ihardlimit && D.curinodes>=D.ihardlimit)
712 *dfree = 0;
713 *dsize = D.curblocks;
714 } else if (D.softlimit==0 && D.hardlimit==0) {
715 goto try_group_quota;
716 } else {
717 if (D.softlimit == 0)
718 D.softlimit = D.hardlimit;
719 *dfree = D.softlimit - D.curblocks;
720 *dsize = D.softlimit;
723 return True;
725 try_group_quota:
726 id.gid = getegid();
728 ZERO_STRUCT(D);
729 r=sys_get_quota(path, SMB_GROUP_QUOTA_TYPE, id, &D);
731 /* Use softlimit to determine disk space, except when it has been exceeded */
732 *bsize = D.bsize;
733 if (r == -1) {
734 if (errno == EDQUOT) {
735 *dfree =0;
736 *dsize =D.curblocks;
737 return (True);
738 } else {
739 return False;
743 /* Use softlimit to determine disk space, except when it has been exceeded */
744 if (
745 (D.softlimit && D.curblocks >= D.softlimit) ||
746 (D.hardlimit && D.curblocks >= D.hardlimit) ||
747 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
748 (D.ihardlimit && D.curinodes>=D.ihardlimit)
750 *dfree = 0;
751 *dsize = D.curblocks;
752 } else if (D.softlimit==0 && D.hardlimit==0) {
753 return False;
754 } else {
755 if (D.softlimit == 0)
756 D.softlimit = D.hardlimit;
757 *dfree = D.softlimit - D.curblocks;
758 *dsize = D.softlimit;
761 return (True);
763 #endif /* HAVE_SYS_QUOTAS */