disk_quotas: style fix
[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(connection_struct *conn, const char *path, uint64_t *bsize,
240                  uint64_t *dfree, uint64_t *dsize)
241 {
242         uid_t euser_id;
243         int ret;
244         struct dqblk D;
245 #if defined(SUNOS5)
246         struct quotctl command;
247         int file;
248         struct mnttab mnt;
249 #else /* SunOS4 */
250         struct mntent *mnt;
251 #endif
252         char *name = NULL;
253         FILE *fd;
254         SMB_STRUCT_STAT sbuf;
255         SMB_DEV_T devno;
256         bool found = false;
257
258         euser_id = geteuid();
259
260         if (sys_stat(path, &sbuf, false) == -1) {
261                 return false;
262         }
263
264         devno = sbuf.st_ex_dev ;
265         DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n",
266                 path, (unsigned int)devno));
267 #if defined(SUNOS5)
268         if ((fd = fopen(MNTTAB, "r")) == NULL) {
269                 return false;
270         }
271
272         while (getmntent(fd, &mnt) == 0) {
273                 if (sys_stat(mnt.mnt_mountp, &sbuf, false) == -1) {
274                         continue;
275                 }
276
277                 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
278                         mnt.mnt_mountp, (unsigned int)devno));
279
280                 /* quotas are only on vxfs, UFS or NFS */
281                 if ((sbuf.st_ex_dev == devno) && (
282                         strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
283                         strcmp( mnt.mnt_fstype, "nfs" ) == 0    ||
284                         strcmp( mnt.mnt_fstype, "vxfs" ) == 0 )) {
285                                 found = true;
286                                 name = talloc_asprintf(talloc_tos(),
287                                                 "%s/quotas",
288                                                 mnt.mnt_mountp);
289                                 break;
290                 }
291         }
292
293         fclose(fd);
294 #else /* SunOS4 */
295         if ((fd = setmntent(MOUNTED, "r")) == NULL) {
296                 return false;
297         }
298
299         while ((mnt = getmntent(fd)) != NULL) {
300                 if (sys_stat(mnt->mnt_dir, &sbuf, false) == -1) {
301                         continue;
302                 }
303                 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n",
304                                         mnt->mnt_dir,
305                                         (unsigned int)sbuf.st_ex_dev));
306                 if (sbuf.st_ex_dev == devno) {
307                         found = true;
308                         name = talloc_strdup(talloc_tos(),
309                                         mnt->mnt_fsname);
310                         break;
311                 }
312         }
313
314         endmntent(fd);
315 #endif
316         if (!found) {
317                 return false;
318         }
319
320         if (!name) {
321                 return false;
322         }
323         become_root();
324
325 #if defined(SUNOS5)
326         if (strcmp(mnt.mnt_fstype, "nfs") == 0) {
327                 bool retval;
328                 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n",
329                                         mnt.mnt_special));
330                 retval = nfs_quotas(mnt.mnt_special,
331                                 euser_id, bsize, dfree, dsize);
332                 unbecome_root();
333                 return retval;
334         }
335
336         DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
337         if((file=open(name, O_RDONLY,0))<0) {
338                 unbecome_root();
339                 return false;
340         }
341         command.op = Q_GETQUOTA;
342         command.uid = euser_id;
343         command.addr = (caddr_t) &D;
344         ret = ioctl(file, Q_QUOTACTL, &command);
345         close(file);
346 #else
347         DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
348         ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
349 #endif
350
351         unbecome_root();
352
353         if (ret < 0) {
354                 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n",
355                                         strerror(errno) ));
356
357 #if defined(SUNOS5) && defined(VXFS_QUOTA)
358                 /* If normal quotactl() fails, try vxfs private calls */
359                 set_effective_uid(euser_id);
360                 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
361                 if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
362                         bool retval;
363                         retval = disk_quotas_vxfs(name, path,
364                                         bsize, dfree, dsize);
365                         return retval;
366                 }
367 #else
368                 return false;
369 #endif
370         }
371
372         /* If softlimit is zero, set it equal to hardlimit.
373          */
374
375         if (D.dqb_bsoftlimit==0) {
376                 D.dqb_bsoftlimit = D.dqb_bhardlimit;
377         }
378
379         /* Use softlimit to determine disk space. A user exceeding the quota
380          * is told that there's no space left. Writes might actually work for
381          * a bit if the hardlimit is set higher than softlimit. Effectively
382          * the disk becomes made of rubber latex and begins to expand to
383          * accommodate the user :-)
384          */
385
386         if (D.dqb_bsoftlimit==0)
387                 return(False);
388         *bsize = DEV_BSIZE;
389         *dsize = D.dqb_bsoftlimit;
390
391         if (D.dqb_curblocks > D.dqb_bsoftlimit) {
392                 *dfree = 0;
393                 *dsize = D.dqb_curblocks;
394         } else {
395                 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
396         }
397
398         DEBUG(5,("disk_quotas for path \"%s\" returning "
399                 "bsize %.0f, dfree %.0f, dsize %.0f\n",
400                 path,(double)*bsize,(double)*dfree,(double)*dsize));
401
402         return true;
403 }
404
405
406 #else
407
408 #if           AIX
409 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
410 #include <jfs/quota.h>
411 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
412 #define dqb_curfiles dqb_curinodes
413 #define dqb_fhardlimit dqb_ihardlimit
414 #define dqb_fsoftlimit dqb_isoftlimit
415 #ifdef _AIXVERSION_530 
416 #include <sys/statfs.h>
417 #include <sys/vmount.h>
418 #endif /* AIX 5.3 */
419 #else /* !AIX */
420 #include <sys/quota.h>
421 #include <devnm.h>
422 #endif
423
424
425 /****************************************************************************
426 try to get the disk space from disk quotas - default version
427 ****************************************************************************/
428
429 bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
430                  uint64_t *dfree, uint64_t *dsize)
431 {
432   int r;
433   struct dqblk D;
434   uid_t euser_id;
435 #if !defined(AIX)
436   char dev_disk[256];
437   SMB_STRUCT_STAT S;
438
439   /* find the block device file */
440
441   if ((sys_stat(path, &S, false)<0)
442       || (devnm(S_IFBLK, S.st_ex_dev, dev_disk, 256, 0)<0))
443         return (False);
444
445 #endif /* !defined(AIX) */
446
447   euser_id = geteuid();
448
449 #if   defined(AIX)
450   /* AIX has both USER and GROUP quotas: 
451      Get the USER quota (ohnielse@fysik.dtu.dk) */
452 #ifdef _AIXVERSION_530
453   {
454     struct statfs statbuf;
455     quota64_t user_quota;
456     if (statfs(path,&statbuf) != 0)
457       return False;
458     if(statbuf.f_vfstype == MNT_J2)
459     {
460     /* For some reason we need to be root for jfs2 */
461       become_root();
462       r = quotactl(path,QCMD(Q_J2GETQUOTA,USRQUOTA),euser_id,(char *) &user_quota);
463       unbecome_root();
464     /* Copy results to old struct to let the following code work as before */
465       D.dqb_curblocks  = user_quota.bused;
466       D.dqb_bsoftlimit = user_quota.bsoft;
467       D.dqb_bhardlimit = user_quota.bhard;
468       D.dqb_curfiles   = user_quota.iused;
469       D.dqb_fsoftlimit = user_quota.isoft;
470       D.dqb_fhardlimit = user_quota.ihard;
471     }
472     else if(statbuf.f_vfstype == MNT_JFS)
473     {
474 #endif /* AIX 5.3 */
475   save_re_uid();
476   if (set_re_uid() != 0) 
477     return False;
478   r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
479   restore_re_uid();
480 #ifdef _AIXVERSION_530
481     }
482     else
483       r = 1; /* Fail for other FS-types */
484   }
485 #endif /* AIX 5.3 */
486 #else /* !AIX */
487   r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
488 #endif /* !AIX */
489
490   /* Use softlimit to determine disk space, except when it has been exceeded */
491   *bsize = 1024;
492
493   if (r)
494     {
495       if (errno == EDQUOT) 
496         {
497           *dfree =0;
498           *dsize =D.dqb_curblocks;
499           return (True);
500         }
501       else return(False);
502     }
503
504   /* If softlimit is zero, set it equal to hardlimit.
505    */
506
507   if (D.dqb_bsoftlimit==0)
508     D.dqb_bsoftlimit = D.dqb_bhardlimit;
509
510   if (D.dqb_bsoftlimit==0)
511     return(False);
512   /* Use softlimit to determine disk space, except when it has been exceeded */
513   if ((D.dqb_curblocks>D.dqb_bsoftlimit)
514 ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
515     ) {
516       *dfree = 0;
517       *dsize = D.dqb_curblocks;
518     }
519   else {
520     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
521     *dsize = D.dqb_bsoftlimit;
522   }
523   return (True);
524 }
525
526 #endif
527
528 #if defined(VXFS_QUOTA)
529
530 /****************************************************************************
531 Try to get the disk space from Veritas disk quotas.
532     David Lee <T.D.Lee@durham.ac.uk> August 1999.
533
534 Background assumptions:
535     Potentially under many Operating Systems.  Initially Solaris 2.
536
537     My guess is that Veritas is largely, though not entirely,
538     independent of OS.  So I have separated it out.
539
540     There may be some details.  For example, OS-specific "include" files.
541
542     It is understood that HPUX 10 somehow gets Veritas quotas without
543     any special effort; if so, this routine need not be compiled in.
544         Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
545
546 Warning:
547     It is understood that Veritas do not publicly support this ioctl interface.
548     Rather their preference would be for the user (us) to call the native
549     OS and then for the OS itself to call through to the VxFS filesystem.
550     Presumably HPUX 10, see above, does this.
551
552 Hints for porting:
553     Add your OS to "IFLIST" below.
554     Get it to compile successfully:
555         Almost certainly "include"s require attention: see SUNOS5.
556     In the main code above, arrange for it to be called: see SUNOS5.
557     Test!
558     
559 ****************************************************************************/
560
561 /* "IFLIST"
562  * This "if" is a list of ports:
563  *      if defined(OS1) || defined(OS2) || ...
564  */
565 #if defined(SUNOS5)
566
567 #if defined(SUNOS5)
568 #include <sys/fs/vx_solaris.h>
569 #endif
570 #include <sys/fs/vx_machdep.h>
571 #include <sys/fs/vx_layout.h>
572 #include <sys/fs/vx_quota.h>
573 #include <sys/fs/vx_aioctl.h>
574 #include <sys/fs/vx_ioctl.h>
575
576 bool disk_quotas_vxfs(const char *name, char *path, uint64_t *bsize, uint64_t *dfree, uint64_t *dsize)
577 {
578   uid_t user_id, euser_id;
579   int ret;
580   struct vx_dqblk D;
581   struct vx_quotctl quotabuf;
582   struct vx_genioctl genbuf;
583   char *qfname;
584   int file;
585
586   /*
587    * "name" may or may not include a trailing "/quotas".
588    * Arranging consistency of calling here in "quotas.c" may not be easy and
589    * it might be easier to examine and adjust it here.
590    * Fortunately, VxFS seems not to mind at present.
591    */
592   qfname = talloc_strdup(talloc_tos(), name);
593   if (!qfname) {
594           return false;
595   }
596   /* pstrcat(qfname, "/quotas") ; */    /* possibly examine and adjust "name" */
597
598   euser_id = geteuid();
599   set_effective_uid(0);
600
601   DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
602   if((file=open(qfname, O_RDONLY,0))<0) {
603     set_effective_uid(euser_id);
604     return(False);
605   }
606   genbuf.ioc_cmd = VX_QUOTACTL;
607   genbuf.ioc_up = (void *) &quotabuf;
608
609   quotabuf.cmd = VX_GETQUOTA;
610   quotabuf.uid = euser_id;
611   quotabuf.addr = (caddr_t) &D;
612   ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
613   close(file);
614
615   set_effective_uid(euser_id);
616
617   if (ret < 0) {
618     DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
619     return(False);
620   }
621
622   /* If softlimit is zero, set it equal to hardlimit.
623    */
624
625   if (D.dqb_bsoftlimit==0)
626     D.dqb_bsoftlimit = D.dqb_bhardlimit;
627
628   /* Use softlimit to determine disk space. A user exceeding the quota is told
629    * that there's no space left. Writes might actually work for a bit if the
630    * hardlimit is set higher than softlimit. Effectively the disk becomes
631    * made of rubber latex and begins to expand to accommodate the user :-)
632    */
633   DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
634          path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
635          D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));
636
637   if (D.dqb_bsoftlimit==0)
638     return(False);
639   *bsize = DEV_BSIZE;
640   *dsize = D.dqb_bsoftlimit;
641
642   if (D.dqb_curblocks > D.dqb_bsoftlimit) {
643      *dfree = 0;
644      *dsize = D.dqb_curblocks;
645   } else
646     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
647       
648   DEBUG(5,("disk_quotas for path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",
649          path,(double)*bsize,(double)*dfree,(double)*dsize));
650
651   return(True);
652 }
653
654 #endif /* SUNOS5 || ... */
655
656 #endif /* VXFS_QUOTA */
657
658 #else /* WITH_QUOTAS */
659
660 bool disk_quotas(connection_struct *conn, const char *path, uint64_t *bsize,
661                  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(connection_struct *conn, const char *path, uint64_t *bsize,
680                  uint64_t *dfree, uint64_t *dsize)
681 {
682         int r;
683         SMB_DISK_QUOTA D;
684         unid_t id;
685
686         id.uid = geteuid();
687
688         ZERO_STRUCT(D);
689         r = SMB_VFS_GET_QUOTA(conn, path, SMB_USER_QUOTA_TYPE, id, &D);
690
691         /* Use softlimit to determine disk space, except when it has been exceeded */
692         *bsize = D.bsize;
693         if (r == -1) {
694                 if (errno == EDQUOT) {
695                         *dfree =0;
696                         *dsize =D.curblocks;
697                         return (True);
698                 } else {
699                         goto try_group_quota;
700                 }
701         }
702
703         /* Use softlimit to determine disk space, except when it has been exceeded */
704         if (
705                 (D.softlimit && D.curblocks >= D.softlimit) ||
706                 (D.hardlimit && D.curblocks >= D.hardlimit) ||
707                 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
708                 (D.ihardlimit && D.curinodes>=D.ihardlimit)
709         ) {
710                 *dfree = 0;
711                 *dsize = D.curblocks;
712         } else if (D.softlimit==0 && D.hardlimit==0) {
713                 goto try_group_quota;
714         } else {
715                 if (D.softlimit == 0) {
716                         D.softlimit = D.hardlimit;
717                 }
718                 *dfree = D.softlimit - D.curblocks;
719                 *dsize = D.softlimit;
720         }
721
722         return True;
723         
724 try_group_quota:
725         id.gid = getegid();
726
727         ZERO_STRUCT(D);
728         r = SMB_VFS_GET_QUOTA(conn, path, SMB_GROUP_QUOTA_TYPE, id, &D);
729
730         /* Use softlimit to determine disk space, except when it has been exceeded */
731         *bsize = D.bsize;
732         if (r == -1) {
733                 if (errno == EDQUOT) {
734                         *dfree =0;
735                         *dsize =D.curblocks;
736                         return (True);
737                 } else {
738                         return False;
739                 }
740         }
741
742         /* Use softlimit to determine disk space, except when it has been exceeded */
743         if (
744                 (D.softlimit && D.curblocks >= D.softlimit) ||
745                 (D.hardlimit && D.curblocks >= D.hardlimit) ||
746                 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
747                 (D.ihardlimit && D.curinodes>=D.ihardlimit)
748         ) {
749                 *dfree = 0;
750                 *dsize = D.curblocks;
751         } else if (D.softlimit==0 && D.hardlimit==0) {
752                 return False;
753         } else {
754                 if (D.softlimit == 0) {
755                         D.softlimit = D.hardlimit;
756                 }
757                 *dfree = D.softlimit - D.curblocks;
758                 *dsize = D.softlimit;
759         }
760
761         return (True);
762 }
763 #endif /* HAVE_SYS_QUOTAS */