smbd/quotas: Remove invalid quota status switch case
[gd/samba-autobuild/.git] / source3 / smbd / quotas.c
1 /* 
2    Unix SMB/CIFS implementation.
3    support for quotas
4    Copyright (C) Andrew Tridgell 1992-1998
5    
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.
10    
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.
15    
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/>.
18 */
19
20
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 :-(
25  */
26
27 #include "includes.h"
28 #include "smbd/smbd.h"
29 #include "system/filesys.h"
30
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_QUOTA
33
34 #ifndef HAVE_SYS_QUOTAS
35
36 /* just a quick hack because sysquotas.h is included before linux/quota.h */
37 #ifdef QUOTABLOCK_SIZE
38 #undef QUOTABLOCK_SIZE
39 #endif
40
41 #ifdef WITH_QUOTAS
42
43 #if defined(VXFS_QUOTA)
44
45 /*
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>
49  */
50 bool disk_quotas_vxfs(const char *name, char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize);
51
52 #endif /* VXFS_QUOTA */
53
54
55 #if defined(SUNOS5) || defined(SUNOS4)
56
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
67
68 #if defined(SUNOS5)
69
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 ****************************************************************************/
75
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>
81
82 static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
83 {
84         int quotastat;
85
86         if (!xdr_int(xdrsp, &quotastat)) {
87                 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
88                 return 0;
89         }
90         gqr->status = quotastat;
91
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;
95         }
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;
99         }
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;
103         }
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;
107         }
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;
111         }
112         return (1);
113 }
114
115 static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
116 {
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);
122 }
123
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)
126 {
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;
138
139         *bsize = *dfree = *dsize = (uint64_t)0;
140
141         len=strcspn(mnttype, ":");
142         pathname=strstr(mnttype, ":");
143         cutstr = (char *) SMB_MALLOC(len+1);
144         if (!cutstr)
145                 return False;
146
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;
154
155         DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
156
157         if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
158                 ret = False;
159                 goto out;
160         }
161
162         clnt->cl_auth = authunix_create_default();
163         DEBUG(9,("nfs_quotas: auth_success\n"));
164
165         clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, my_xdr_getquota_args, (caddr_t)&args, my_xdr_getquota_rslt, (caddr_t)&gqr, timeout);
166
167         if (clnt_stat != RPC_SUCCESS) {
168                 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
169                 ret = False;
170                 goto out;
171         }
172
173         /*
174          * gqr.status returns 1 if quotas exist, 2 if there is
175          * no quota set, and 3 if no permission to get the quota.
176          * If 3, return something sensible.
177          */
178
179         switch (gqr.status) {
180         case 1:
181                 DEBUG(9,("nfs_quotas: Good quota data\n"));
182                 D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
183                 D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
184                 D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
185                 break;
186
187         case 2:
188         case 3:
189                 D.dqb_bsoftlimit = 1;
190                 D.dqb_curblocks = 1;
191                 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", gqr.status));
192                 break;
193
194         default:
195                 DEBUG(9, ("nfs_quotas: Unknown Remote Quota Status \"%i\"\n",
196                                 gqr.status));
197                 ret = false;
198                 goto out;
199         }
200
201         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",
202                         gqr.status,
203                         gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
204                         gqr.getquota_rslt_u.gqr_rquota.rq_active,
205                         gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
206                         gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
207                         gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
208
209         *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
210         *dsize = D.dqb_bsoftlimit;
211
212         if (D.dqb_curblocks > D.dqb_bsoftlimit) {
213                 *dfree = 0;
214                 *dsize = D.dqb_curblocks;
215         } else
216                 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
217
218   out:
219
220         if (clnt) {
221                 if (clnt->cl_auth)
222                         auth_destroy(clnt->cl_auth);
223                 clnt_destroy(clnt);
224         }
225
226         DEBUG(5,("nfs_quotas: For path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
227
228         SAFE_FREE(cutstr);
229         DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
230         return ret;
231 }
232 #endif
233
234 /****************************************************************************
235 try to get the disk space from disk quotas (SunOS & Solaris2 version)
236 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
237 ****************************************************************************/
238
239 bool disk_quotas(const char *path,
240                 uint64_t *bsize,
241                 uint64_t *dfree,
242                 uint64_t *dsize)
243 {
244         uid_t euser_id;
245         int ret;
246         struct dqblk D;
247 #if defined(SUNOS5)
248         struct quotctl command;
249         int file;
250         struct mnttab mnt;
251 #else /* SunOS4 */
252         struct mntent *mnt;
253 #endif
254         char *name = NULL;
255         FILE *fd;
256         SMB_STRUCT_STAT sbuf;
257         SMB_DEV_T devno;
258         bool found = false;
259
260         euser_id = geteuid();
261
262         if (sys_stat(path, &sbuf, false) == -1) {
263                 return false;
264         }
265
266         devno = sbuf.st_ex_dev ;
267         DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
268                 path, (unsigned int)devno));
269 #if defined(SUNOS5)
270         if ((fd = fopen(MNTTAB, "r")) == NULL) {
271                 return false;
272         }
273
274         while (getmntent(fd, &mnt) == 0) {
275                 if (sys_stat(mnt.mnt_mountp, &sbuf, false) == -1) {
276                         continue;
277                 }
278
279                 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
280                         mnt.mnt_mountp, (unsigned int)devno));
281
282                 /* quotas are only on vxfs, UFS or NFS */
283                 if ((sbuf.st_ex_dev == devno) && (
284                         strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
285                         strcmp( mnt.mnt_fstype, "nfs" ) == 0    ||
286                         strcmp( mnt.mnt_fstype, "vxfs" ) == 0 )) {
287                                 found = true;
288                                 name = talloc_asprintf(talloc_tos(),
289                                                 "%s/quotas",
290                                                 mnt.mnt_mountp);
291                                 break;
292                 }
293         }
294
295         fclose(fd);
296 #else /* SunOS4 */
297         if ((fd = setmntent(MOUNTED, "r")) == NULL) {
298                 return false;
299         }
300
301         while ((mnt = getmntent(fd)) != NULL) {
302                 if (sys_stat(mnt->mnt_dir, &sbuf, false) == -1) {
303                         continue;
304                 }
305                 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
306                                         mnt->mnt_dir,
307                                         (unsigned int)sbuf.st_ex_dev));
308                 if (sbuf.st_ex_dev == devno) {
309                         found = true;
310                         name = talloc_strdup(talloc_tos(),
311                                         mnt->mnt_fsname);
312                         break;
313                 }
314         }
315
316         endmntent(fd);
317 #endif
318         if (!found) {
319                 return false;
320         }
321
322         if (!name) {
323                 return false;
324         }
325         become_root();
326
327 #if defined(SUNOS5)
328         if (strcmp(mnt.mnt_fstype, "nfs") == 0) {
329                 bool retval;
330                 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n",
331                                         mnt.mnt_special));
332                 retval = nfs_quotas(mnt.mnt_special,
333                                 euser_id, bsize, dfree, dsize);
334                 unbecome_root();
335                 return retval;
336         }
337
338         DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
339         if((file=open(name, O_RDONLY,0))<0) {
340                 unbecome_root();
341                 return false;
342         }
343         command.op = Q_GETQUOTA;
344         command.uid = euser_id;
345         command.addr = (caddr_t) &D;
346         ret = ioctl(file, Q_QUOTACTL, &command);
347         close(file);
348 #else
349         DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
350         ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
351 #endif
352
353         unbecome_root();
354
355         if (ret < 0) {
356                 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n",
357                                         strerror(errno) ));
358
359 #if defined(SUNOS5) && defined(VXFS_QUOTA)
360                 /* If normal quotactl() fails, try vxfs private calls */
361                 set_effective_uid(euser_id);
362                 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
363                 if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
364                         bool retval;
365                         retval = disk_quotas_vxfs(name, path,
366                                         bsize, dfree, dsize);
367                         return retval;
368                 }
369 #else
370                 return false;
371 #endif
372         }
373
374         /* If softlimit is zero, set it equal to hardlimit.
375          */
376
377         if (D.dqb_bsoftlimit==0) {
378                 D.dqb_bsoftlimit = D.dqb_bhardlimit;
379         }
380
381         /* Use softlimit to determine disk space. A user exceeding the quota
382          * is told that there's no space left. Writes might actually work for
383          * a bit if the hardlimit is set higher than softlimit. Effectively
384          * the disk becomes made of rubber latex and begins to expand to
385          * accommodate the user :-)
386          */
387
388         if (D.dqb_bsoftlimit==0)
389                 return(False);
390         *bsize = DEV_BSIZE;
391         *dsize = D.dqb_bsoftlimit;
392
393         if (D.dqb_curblocks > D.dqb_bsoftlimit) {
394                 *dfree = 0;
395                 *dsize = D.dqb_curblocks;
396         } else {
397                 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
398         }
399
400         DEBUG(5,("disk_quotas for path \"%s\" returning "
401                 "bsize %.0f, dfree %.0f, dsize %.0f\n",
402                 path,(double)*bsize,(double)*dfree,(double)*dsize));
403
404         return true;
405 }
406
407
408 #else
409
410 #if           AIX
411 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
412 #include <jfs/quota.h>
413 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
414 #define dqb_curfiles dqb_curinodes
415 #define dqb_fhardlimit dqb_ihardlimit
416 #define dqb_fsoftlimit dqb_isoftlimit
417 #ifdef _AIXVERSION_530 
418 #include <sys/statfs.h>
419 #include <sys/vmount.h>
420 #endif /* AIX 5.3 */
421 #else /* !AIX */
422 #include <sys/quota.h>
423 #include <devnm.h>
424 #endif
425
426
427 /****************************************************************************
428 try to get the disk space from disk quotas - default version
429 ****************************************************************************/
430
431 bool disk_quotas(const char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
432 {
433   int r;
434   struct dqblk D;
435   uid_t euser_id;
436 #if !defined(AIX)
437   char dev_disk[256];
438   SMB_STRUCT_STAT S;
439
440   /* find the block device file */
441
442   if ((sys_stat(path, &S, false)<0)
443       || (devnm(S_IFBLK, S.st_ex_dev, dev_disk, 256, 0)<0))
444         return (False);
445
446 #endif /* !defined(AIX) */
447
448   euser_id = geteuid();
449
450 #if   defined(AIX)
451   /* AIX has both USER and GROUP quotas: 
452      Get the USER quota (ohnielse@fysik.dtu.dk) */
453 #ifdef _AIXVERSION_530
454   {
455     struct statfs statbuf;
456     quota64_t user_quota;
457     if (statfs(path,&statbuf) != 0)
458       return False;
459     if(statbuf.f_vfstype == MNT_J2)
460     {
461     /* For some reason we need to be root for jfs2 */
462       become_root();
463       r = quotactl(path,QCMD(Q_J2GETQUOTA,USRQUOTA),euser_id,(char *) &user_quota);
464       unbecome_root();
465     /* Copy results to old struct to let the following code work as before */
466       D.dqb_curblocks  = user_quota.bused;
467       D.dqb_bsoftlimit = user_quota.bsoft;
468       D.dqb_bhardlimit = user_quota.bhard;
469       D.dqb_curfiles   = user_quota.iused;
470       D.dqb_fsoftlimit = user_quota.isoft;
471       D.dqb_fhardlimit = user_quota.ihard;
472     }
473     else if(statbuf.f_vfstype == MNT_JFS)
474     {
475 #endif /* AIX 5.3 */
476   save_re_uid();
477   if (set_re_uid() != 0) 
478     return False;
479   r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
480   restore_re_uid();
481 #ifdef _AIXVERSION_530
482     }
483     else
484       r = 1; /* Fail for other FS-types */
485   }
486 #endif /* AIX 5.3 */
487 #else /* !AIX */
488   r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
489 #endif /* !AIX */
490
491   /* Use softlimit to determine disk space, except when it has been exceeded */
492   *bsize = 1024;
493
494   if (r)
495     {
496       if (errno == EDQUOT) 
497         {
498           *dfree =0;
499           *dsize =D.dqb_curblocks;
500           return (True);
501         }
502       else return(False);
503     }
504
505   /* If softlimit is zero, set it equal to hardlimit.
506    */
507
508   if (D.dqb_bsoftlimit==0)
509     D.dqb_bsoftlimit = D.dqb_bhardlimit;
510
511   if (D.dqb_bsoftlimit==0)
512     return(False);
513   /* Use softlimit to determine disk space, except when it has been exceeded */
514   if ((D.dqb_curblocks>D.dqb_bsoftlimit)
515 ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
516     ) {
517       *dfree = 0;
518       *dsize = D.dqb_curblocks;
519     }
520   else {
521     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
522     *dsize = D.dqb_bsoftlimit;
523   }
524   return (True);
525 }
526
527 #endif
528
529 #if defined(VXFS_QUOTA)
530
531 /****************************************************************************
532 Try to get the disk space from Veritas disk quotas.
533     David Lee <T.D.Lee@durham.ac.uk> August 1999.
534
535 Background assumptions:
536     Potentially under many Operating Systems.  Initially Solaris 2.
537
538     My guess is that Veritas is largely, though not entirely,
539     independent of OS.  So I have separated it out.
540
541     There may be some details.  For example, OS-specific "include" files.
542
543     It is understood that HPUX 10 somehow gets Veritas quotas without
544     any special effort; if so, this routine need not be compiled in.
545         Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
546
547 Warning:
548     It is understood that Veritas do not publicly support this ioctl interface.
549     Rather their preference would be for the user (us) to call the native
550     OS and then for the OS itself to call through to the VxFS filesystem.
551     Presumably HPUX 10, see above, does this.
552
553 Hints for porting:
554     Add your OS to "IFLIST" below.
555     Get it to compile successfully:
556         Almost certainly "include"s require attention: see SUNOS5.
557     In the main code above, arrange for it to be called: see SUNOS5.
558     Test!
559     
560 ****************************************************************************/
561
562 /* "IFLIST"
563  * This "if" is a list of ports:
564  *      if defined(OS1) || defined(OS2) || ...
565  */
566 #if defined(SUNOS5)
567
568 #if defined(SUNOS5)
569 #include <sys/fs/vx_solaris.h>
570 #endif
571 #include <sys/fs/vx_machdep.h>
572 #include <sys/fs/vx_layout.h>
573 #include <sys/fs/vx_quota.h>
574 #include <sys/fs/vx_aioctl.h>
575 #include <sys/fs/vx_ioctl.h>
576
577 bool disk_quotas_vxfs(const char *name, char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
578 {
579   uid_t user_id, euser_id;
580   int ret;
581   struct vx_dqblk D;
582   struct vx_quotctl quotabuf;
583   struct vx_genioctl genbuf;
584   char *qfname;
585   int file;
586
587   /*
588    * "name" may or may not include a trailing "/quotas".
589    * Arranging consistency of calling here in "quotas.c" may not be easy and
590    * it might be easier to examine and adjust it here.
591    * Fortunately, VxFS seems not to mind at present.
592    */
593   qfname = talloc_strdup(talloc_tos(), name);
594   if (!qfname) {
595           return false;
596   }
597   /* pstrcat(qfname, "/quotas") ; */    /* possibly examine and adjust "name" */
598
599   euser_id = geteuid();
600   set_effective_uid(0);
601
602   DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
603   if((file=open(qfname, O_RDONLY,0))<0) {
604     set_effective_uid(euser_id);
605     return(False);
606   }
607   genbuf.ioc_cmd = VX_QUOTACTL;
608   genbuf.ioc_up = (void *) &quotabuf;
609
610   quotabuf.cmd = VX_GETQUOTA;
611   quotabuf.uid = euser_id;
612   quotabuf.addr = (caddr_t) &D;
613   ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
614   close(file);
615
616   set_effective_uid(euser_id);
617
618   if (ret < 0) {
619     DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
620     return(False);
621   }
622
623   /* If softlimit is zero, set it equal to hardlimit.
624    */
625
626   if (D.dqb_bsoftlimit==0)
627     D.dqb_bsoftlimit = D.dqb_bhardlimit;
628
629   /* Use softlimit to determine disk space. A user exceeding the quota is told
630    * that there's no space left. Writes might actually work for a bit if the
631    * hardlimit is set higher than softlimit. Effectively the disk becomes
632    * made of rubber latex and begins to expand to accommodate the user :-)
633    */
634   DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
635          path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
636          D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));
637
638   if (D.dqb_bsoftlimit==0)
639     return(False);
640   *bsize = DEV_BSIZE;
641   *dsize = D.dqb_bsoftlimit;
642
643   if (D.dqb_curblocks > D.dqb_bsoftlimit) {
644      *dfree = 0;
645      *dsize = D.dqb_curblocks;
646   } else
647     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
648       
649   DEBUG(5,("disk_quotas for path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",
650          path,(double)*bsize,(double)*dfree,(double)*dsize));
651
652   return(True);
653 }
654
655 #endif /* SUNOS5 || ... */
656
657 #endif /* VXFS_QUOTA */
658
659 #else /* WITH_QUOTAS */
660
661 bool disk_quotas(const char *path,uint64_t *bsize,uint64_t *dfree,uint64_t *dsize)
662 {
663         (*bsize) = 512; /* This value should be ignored */
664
665         /* And just to be sure we set some values that hopefully */
666         /* will be larger that any possible real-world value     */
667         (*dfree) = (uint64_t)-1;
668         (*dsize) = (uint64_t)-1;
669
670         /* As we have select not to use quotas, allways fail */
671         return false;
672 }
673 #endif /* WITH_QUOTAS */
674
675 #else /* HAVE_SYS_QUOTAS */
676 /* wrapper to the new sys_quota interface
677    this file should be removed later
678    */
679 bool disk_quotas(const char *path,uint64_t *bsize,uint64_t *dfree,uint64_t *dsize)
680 {
681         int r;
682         SMB_DISK_QUOTA D;
683         unid_t id;
684
685         id.uid = geteuid();
686
687         ZERO_STRUCT(D);
688         r=sys_get_quota(path, SMB_USER_QUOTA_TYPE, id, &D);
689
690         /* Use softlimit to determine disk space, except when it has been exceeded */
691         *bsize = D.bsize;
692         if (r == -1) {
693                 if (errno == EDQUOT) {
694                         *dfree =0;
695                         *dsize =D.curblocks;
696                         return (True);
697                 } else {
698                         goto try_group_quota;
699                 }
700         }
701
702         /* Use softlimit to determine disk space, except when it has been exceeded */
703         if (
704                 (D.softlimit && D.curblocks >= D.softlimit) ||
705                 (D.hardlimit && D.curblocks >= D.hardlimit) ||
706                 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
707                 (D.ihardlimit && D.curinodes>=D.ihardlimit)
708         ) {
709                 *dfree = 0;
710                 *dsize = D.curblocks;
711         } else if (D.softlimit==0 && D.hardlimit==0) {
712                 goto try_group_quota;
713         } else {
714                 if (D.softlimit == 0)
715                         D.softlimit = D.hardlimit;
716                 *dfree = D.softlimit - D.curblocks;
717                 *dsize = D.softlimit;
718         }
719
720         return True;
721         
722 try_group_quota:
723         id.gid = getegid();
724
725         ZERO_STRUCT(D);
726         r=sys_get_quota(path, SMB_GROUP_QUOTA_TYPE, id, &D);
727
728         /* Use softlimit to determine disk space, except when it has been exceeded */
729         *bsize = D.bsize;
730         if (r == -1) {
731                 if (errno == EDQUOT) {
732                         *dfree =0;
733                         *dsize =D.curblocks;
734                         return (True);
735                 } else {
736                         return False;
737                 }
738         }
739
740         /* Use softlimit to determine disk space, except when it has been exceeded */
741         if (
742                 (D.softlimit && D.curblocks >= D.softlimit) ||
743                 (D.hardlimit && D.curblocks >= D.hardlimit) ||
744                 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
745                 (D.ihardlimit && D.curinodes>=D.ihardlimit)
746         ) {
747                 *dfree = 0;
748                 *dsize = D.curblocks;
749         } else if (D.softlimit==0 && D.hardlimit==0) {
750                 return False;
751         } else {
752                 if (D.softlimit == 0)
753                         D.softlimit = D.hardlimit;
754                 *dfree = D.softlimit - D.curblocks;
755                 *dsize = D.softlimit;
756         }
757
758         return (True);
759 }
760 #endif /* HAVE_SYS_QUOTAS */