Removed NFS quotas code for Solaris as Alan wants to re-write it.
[ira/wip.git] / source3 / smbd / quotas.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    support for quotas
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22
23 /* 
24  * This is one of the most system dependent parts of Samba, and its
25  * done a litle differently. Each system has its own way of doing 
26  * things :-(
27  */
28
29 #include "includes.h"
30
31 extern int DEBUGLEVEL;
32
33 #if defined(VXFS_QUOTA)
34
35 /*
36  * In addition to their native filesystems, some systems have Veritas VxFS.
37  * Declare here, define at end: reduces likely "include" interaction problems.
38  *      David Lee <T.D.Lee@durham.ac.uk>
39  */
40 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
41
42 #endif /* VXFS_QUOTA */
43
44 #ifdef LINUX
45
46 #include <sys/types.h>
47 #include <asm/types.h>
48 #include <sys/quota.h>
49
50 #include <mntent.h>
51 #include <linux/unistd.h>
52
53 _syscall4(int, quotactl, int, cmd, const char *, special, int, id, caddr_t, addr);
54
55 /****************************************************************************
56 try to get the disk space from disk quotas (LINUX version)
57 ****************************************************************************/
58
59 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
60 {
61   int r;
62   struct dqblk D;
63   SMB_STRUCT_STAT S;
64   FILE *fp;
65   struct mntent *mnt;
66   SMB_DEV_T devno;
67   int found;
68   uid_t euser_id;
69
70   euser_id = geteuid();
71   
72   /* find the block device file */
73   
74   if ( sys_stat(path, &S) == -1 ) {
75     return(False) ;
76   }
77
78   devno = S.st_dev ;
79   
80   fp = setmntent(MOUNTED,"r");
81   found = False ;
82   
83   while ((mnt = getmntent(fp))) {
84     if ( sys_stat(mnt->mnt_dir,&S) == -1 )
85       continue ;
86     if (S.st_dev == devno) {
87       found = True ;
88       break ;
89     }
90   }
91   endmntent(fp) ;
92   
93   if (!found) {
94       return(False);
95     }
96
97   save_re_uid();
98   set_effective_uid(0);  
99   r=quotactl(QCMD(Q_GETQUOTA,USRQUOTA), mnt->mnt_fsname, euser_id, (caddr_t)&D);
100   restore_re_uid();
101
102   /* Use softlimit to determine disk space, except when it has been exceeded */
103   *bsize = 1024;
104   if (r)
105     {
106       if (errno == EDQUOT) 
107        {
108          *dfree =0;
109          *dsize =D.dqb_curblocks;
110          return (True);
111     }
112       else return(False);
113   }
114   /* Use softlimit to determine disk space, except when it has been exceeded */
115   if (
116       (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
117       (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
118       (D.dqb_isoftlimit && D.dqb_curinodes>=D.dqb_isoftlimit) ||
119       (D.dqb_ihardlimit && D.dqb_curinodes>=D.dqb_ihardlimit)
120      )
121     {
122       *dfree = 0;
123       *dsize = D.dqb_curblocks;
124     }
125   else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
126     {
127       return(False);
128     }
129   else {
130     if (D.dqb_bsoftlimit == 0)
131       D.dqb_bsoftlimit = D.dqb_bhardlimit;
132     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
133     *dsize = D.dqb_bsoftlimit;
134   }
135   return (True);
136 }
137
138 #elif defined(CRAY)
139
140 #include <sys/quota.h>
141 #include <mntent.h>
142
143 /****************************************************************************
144 try to get the disk space from disk quotas (CRAY VERSION)
145 ****************************************************************************/
146
147 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
148 {
149   struct mntent *mnt;
150   FILE *fd;
151   SMB_STRUCT_STAT sbuf;
152   SMB_DEV_T devno ;
153   static SMB_DEV_T devno_cached = 0 ;
154   static pstring name;
155   struct q_request request ;
156   struct qf_header header ;
157   static int quota_default = 0 ;
158   int found ;
159   
160   if ( sys_stat(path,&sbuf) == -1 )
161     return(False) ;
162   
163   devno = sbuf.st_dev ;
164   
165   if ( devno != devno_cached ) {
166     
167     devno_cached = devno ;
168     
169     if ((fd = setmntent(KMTAB)) == NULL)
170       return(False) ;
171     
172     found = False ;
173     
174     while ((mnt = getmntent(fd)) != NULL) {
175       
176       if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
177         continue ;
178       
179       if (sbuf.st_dev == devno) {
180         
181         found = True ;
182         break ;
183         
184       }
185       
186     }
187     
188     pstrcpy(name,mnt->mnt_dir) ;
189     endmntent(fd) ;
190     
191     if ( ! found )
192       return(False) ;
193   }
194   
195   request.qf_magic = QF_MAGIC ;
196   request.qf_entry.id = geteuid() ;
197   
198   if (quotactl(name, Q_GETQUOTA, &request) == -1)
199     return(False) ;
200   
201   if ( ! request.user )
202     return(False) ;
203   
204   if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
205     
206     if ( ! quota_default ) {
207       
208       if ( quotactl(name, Q_GETHEADER, &header) == -1 )
209         return(False) ;
210       else
211         quota_default = header.user_h.def_fq ;
212     }
213     
214     *dfree = quota_default ;
215     
216   }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
217     
218     *dfree = 0 ;
219     
220   }else{
221     
222     *dfree = request.qf_entry.user_q.f_quota ;
223     
224   }
225   
226   *dsize = request.qf_entry.user_q.f_use ;
227   
228   if ( *dfree < *dsize )
229     *dfree = 0 ;
230   else
231     *dfree -= *dsize ;
232   
233   *bsize = 4096 ;  /* Cray blocksize */
234   
235   return(True) ;
236   
237 }
238
239
240 #elif defined(SUNOS5) || defined(SUNOS4)
241
242 #include <fcntl.h>
243 #include <sys/param.h>
244 #if defined(SUNOS5)
245 #include <sys/fs/ufs_quota.h>
246 #include <sys/mnttab.h>
247 #include <sys/mntent.h>
248 #else /* defined(SUNOS4) */
249 #include <ufs/quota.h>
250 #include <mntent.h>
251 #endif
252
253 /****************************************************************************
254 try to get the disk space from disk quotas (SunOS & Solaris2 version)
255 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
256 ****************************************************************************/
257
258 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
259 {
260   uid_t euser_id;
261   int ret;
262   struct dqblk D;
263 #if defined(SUNOS5)
264   struct quotctl command;
265   int file;
266   static struct mnttab mnt;
267   static pstring name;
268   pstring devopt;
269 #else /* SunOS4 */
270   struct mntent *mnt;
271   static pstring name;
272 #endif
273   FILE *fd;
274   SMB_STRUCT_STAT sbuf;
275   SMB_DEV_T devno ;
276   static SMB_DEV_T devno_cached = 0 ;
277   static int found ;
278
279   euser_id = geteuid();
280   
281   if ( sys_stat(path,&sbuf) == -1 )
282     return(False) ;
283   
284   devno = sbuf.st_dev ;
285   DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,devno));
286   if ( devno != devno_cached ) {
287     devno_cached = devno ;
288 #if defined(SUNOS5)
289     if ((fd = sys_fopen(MNTTAB, "r")) == NULL)
290       return(False) ;
291     
292     found = False ;
293     slprintf(devopt, sizeof(devopt) - 1, "dev=%x", devno);
294     while (getmntent(fd, &mnt) == 0) {
295       if( !hasmntopt(&mnt, devopt) )
296         continue;
297
298       DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt));
299
300       /* quotas are only on vxfs, UFS or NFS, but nfs is not supported here */
301       if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 || 
302            strcmp( mnt.mnt_fstype, "vxfs" ) == 0  )
303       { 
304         found = True ;
305         break ;
306       }
307     }
308     
309     pstrcpy(name,mnt.mnt_mountp) ;
310     pstrcat(name,"/quotas") ;
311     fclose(fd) ;
312 #else /* SunOS4 */
313     if ((fd = setmntent(MOUNTED, "r")) == NULL)
314       return(False) ;
315     
316     found = False ;
317     while ((mnt = getmntent(fd)) != NULL) {
318       if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
319         continue ;
320       DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", 
321                mnt->mnt_dir,sbuf.st_dev));
322       if (sbuf.st_dev == devno) {
323         found = True ;
324         break ;
325       }
326     }
327     
328     pstrcpy(name,mnt->mnt_fsname) ;
329     endmntent(fd) ;
330 #endif
331     
332   }
333
334   if ( ! found )
335       return(False) ;
336
337   save_re_uid();
338   set_effective_uid(0);
339
340 #if defined(SUNOS5)
341   DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
342   if((file=sys_open(name, O_RDONLY,0))<0) {
343           restore_re_uid();
344           return(False);
345   }
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
355
356   restore_re_uid();
357
358   if (ret < 0) {
359     DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) ));
360
361 #if defined(SUNOS5) && defined(VXFS_QUOTA)
362     /* If normal quotactl() fails, try vxfs private calls */
363     set_effective_uid(euser_id);
364     DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
365     if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
366       ret = disk_quotas_vxfs(name, path, bsize, dfree, dsize);
367       return(ret);
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   /* Use softlimit to determine disk space. A user exceeding the quota is told
381    * that there's no space left. Writes might actually work for a bit if the
382    * hardlimit is set higher than softlimit. Effectively the disk becomes
383    * made of rubber latex and begins to expand to 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   DEBUG(5,("disk_quotas for path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",
398          path,(double)*bsize,(double)*dfree,(double)*dsize));
399
400       return(True);
401 }
402
403
404 #elif defined(OSF1)
405 #include <ufs/quota.h>
406
407 /****************************************************************************
408 try to get the disk space from disk quotas - OSF1 version
409 ****************************************************************************/
410
411 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
412 {
413   int r, save_errno;
414   struct dqblk D;
415   SMB_STRUCT_STAT S;
416   uid_t euser_id;
417
418   /*
419    * This code presumes that OSF1 will only
420    * give out quota info when the real uid 
421    * matches the effective uid. JRA.
422    */
423   euser_id = geteuid();
424   save_re_uid();
425   if (set_re_uid() != 0) return False;
426
427   r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D);
428   if (r) {
429      save_errno = errno;
430   }
431
432   restore_re_uid();
433
434   *bsize = DEV_BSIZE;
435
436   if (r)
437   {
438       if (save_errno == EDQUOT)   /* disk quota exceeded */
439       {
440          *dfree = 0;
441          *dsize = D.dqb_curblocks;
442          return (True);
443       }
444       else
445          return (False);  
446   }
447
448   /* If softlimit is zero, set it equal to hardlimit.
449    */
450
451   if (D.dqb_bsoftlimit==0)
452     D.dqb_bsoftlimit = D.dqb_bhardlimit;
453
454   /* Use softlimit to determine disk space, except when it has been exceeded */
455
456   if (D.dqb_bsoftlimit==0)
457     return(False);
458
459   if ((D.dqb_curblocks>D.dqb_bsoftlimit)) {
460     *dfree = 0;
461     *dsize = D.dqb_curblocks;
462   } else {
463     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
464     *dsize = D.dqb_bsoftlimit;
465   }
466   return (True);
467 }
468
469 #elif defined (IRIX6)
470 /****************************************************************************
471 try to get the disk space from disk quotas (IRIX 6.2 version)
472 ****************************************************************************/
473
474 #include <sys/quota.h>
475 #include <mntent.h>
476
477 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
478 {
479   uid_t euser_id;
480   int r;
481   struct dqblk D;
482   struct fs_disk_quota        F;
483   SMB_STRUCT_STAT S;
484   FILE *fp;
485   struct mntent *mnt;
486   SMB_DEV_T devno;
487   int found;
488   
489   /* find the block device file */
490   
491   if ( sys_stat(path, &S) == -1 ) {
492     return(False) ;
493   }
494
495   devno = S.st_dev ;
496   
497   fp = setmntent(MOUNTED,"r");
498   found = False ;
499   
500   while ((mnt = getmntent(fp))) {
501     if ( sys_stat(mnt->mnt_dir,&S) == -1 )
502       continue ;
503     if (S.st_dev == devno) {
504       found = True ;
505       break ;
506     }
507   }
508   endmntent(fp) ;
509   
510   if (!found) {
511     return(False);
512   }
513
514   euser_id=geteuid();
515   save_re_uid();
516   set_effective_uid(0);  
517
518   /* Use softlimit to determine disk space, except when it has been exceeded */
519
520   *bsize = 512;
521
522   if ( 0 == strcmp ( mnt->mnt_type, "efs" ))
523   {
524     r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);
525
526     restore_re_uid();
527
528     if (r==-1)
529       return(False);
530         
531     /* Use softlimit to determine disk space, except when it has been exceeded */
532     if (
533         (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
534         (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
535         (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) ||
536         (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit)
537        )
538     {
539       *dfree = 0;
540       *dsize = D.dqb_curblocks;
541     }
542     else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
543     {
544       return(False);
545     }
546     else 
547     {
548       *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
549       *dsize = D.dqb_bsoftlimit;
550     }
551
552   }
553   else if ( 0 == strcmp ( mnt->mnt_type, "xfs" ))
554   {
555     r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);
556
557     restore_re_uid();
558
559     if (r==-1)
560       return(False);
561         
562     /* Use softlimit to determine disk space, except when it has been exceeded */
563     if (
564         (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) ||
565         (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) ||
566         (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) ||
567         (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit)
568        )
569     {
570       *dfree = 0;
571       *dsize = F.d_bcount;
572     }
573     else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0)
574     {
575       return(False);
576     }
577     else 
578     {
579       *dfree = (F.d_blk_softlimit - F.d_bcount);
580       *dsize = F.d_blk_softlimit;
581     }
582
583   }
584   else
585   {
586           restore_re_uid();
587           return(False);
588   }
589
590   return (True);
591
592 }
593
594 #else
595
596 #if    defined(__FreeBSD__) || defined(__OpenBSD__)
597 #include <ufs/ufs/quota.h>
598 #include <machine/param.h>
599 #elif         AIX
600 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
601 #include <jfs/quota.h>
602 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
603 #define dqb_curfiles dqb_curinodes
604 #define dqb_fhardlimit dqb_ihardlimit
605 #define dqb_fsoftlimit dqb_isoftlimit
606 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
607 #include <sys/quota.h>
608 #include <devnm.h>
609 #endif
610
611 /****************************************************************************
612 try to get the disk space from disk quotas - default version
613 ****************************************************************************/
614
615 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
616 {
617   int r;
618   struct dqblk D;
619   uid_t euser_id;
620 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__)
621   char dev_disk[256];
622   SMB_STRUCT_STAT S;
623   /* find the block device file */
624   if ((sys_stat(path, &S)<0) ||
625       (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False);
626 #endif
627
628   euser_id = geteuid();
629
630 #ifdef HPUX
631   /* for HPUX, real uid must be same as euid to execute quotactl for euid */
632   save_re_uid();
633   if (set_re_uid() != 0) return False;
634   
635   r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
636
637   restore_re_uid();
638 #else 
639 #if defined(__FreeBSD__) || defined(__OpenBSD__)
640   {
641     /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
642     gid_t egrp_id;
643  
644     save_re_uid();
645     set_effective_uid(0);
646
647     egrp_id = getegid();
648     r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
649
650     /* As FreeBSD has group quotas, if getting the user
651        quota fails, try getting the group instead. */
652     if (r) {
653             r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
654     }
655
656     restore_re_uid();
657   }
658 #elif defined(AIX)
659   /* AIX has both USER and GROUP quotas: 
660      Get the USER quota (ohnielse@fysik.dtu.dk) */
661   r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
662 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
663   r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
664 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
665 #endif /* HPUX */
666
667   /* Use softlimit to determine disk space, except when it has been exceeded */
668 #if defined(__FreeBSD__) || defined(__OpenBSD__)
669   *bsize = DEV_BSIZE;
670 #else /* !__FreeBSD__ && !__OpenBSD__ */
671   *bsize = 1024;
672 #endif /*!__FreeBSD__ && !__OpenBSD__ */
673
674   if (r)
675     {
676       if (errno == EDQUOT) 
677         {
678           *dfree =0;
679           *dsize =D.dqb_curblocks;
680           return (True);
681         }
682       else return(False);
683     }
684
685   /* If softlimit is zero, set it equal to hardlimit.
686    */
687
688   if (D.dqb_bsoftlimit==0)
689     D.dqb_bsoftlimit = D.dqb_bhardlimit;
690
691   if (D.dqb_bsoftlimit==0)
692     return(False);
693   /* Use softlimit to determine disk space, except when it has been exceeded */
694   if ((D.dqb_curblocks>D.dqb_bsoftlimit)
695 #if !defined(__FreeBSD__) && !defined(__OpenBSD__)
696 ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
697 #endif
698     ) {
699       *dfree = 0;
700       *dsize = D.dqb_curblocks;
701     }
702   else {
703     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
704     *dsize = D.dqb_bsoftlimit;
705   }
706   return (True);
707 }
708
709 #endif
710
711 #if defined(VXFS_QUOTA)
712
713 /****************************************************************************
714 Try to get the disk space from Veritas disk quotas.
715     David Lee <T.D.Lee@durham.ac.uk> August 1999.
716
717 Background assumptions:
718     Potentially under many Operating Systems.  Initially Solaris 2.
719
720     My guess is that Veritas is largely, though not entirely,
721     independent of OS.  So I have separated it out.
722
723     There may be some details.  For example, OS-specific "include" files.
724
725     It is understood that HPUX 10 somehow gets Veritas quotas without
726     any special effort; if so, this routine need not be compiled in.
727         Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
728
729 Warning:
730     It is understood that Veritas do not publicly support this ioctl interface.
731     Rather their preference would be for the user (us) to call the native
732     OS and then for the OS itself to call through to the VxFS filesystem.
733     Presumably HPUX 10, see above, does this.
734
735 Hints for porting:
736     Add your OS to "IFLIST" below.
737     Get it to compile successfully:
738         Almost certainly "include"s require attention: see SUNOS5.
739     In the main code above, arrange for it to be called: see SUNOS5.
740     Test!
741     
742 ****************************************************************************/
743
744 /* "IFLIST"
745  * This "if" is a list of ports:
746  *      if defined(OS1) || defined(OS2) || ...
747  */
748 #if defined(SUNOS5)
749
750 #if defined(SUNOS5)
751 #include <sys/fs/vx_solaris.h>
752 #endif
753 #include <sys/fs/vx_machdep.h>
754 #include <sys/fs/vx_layout.h>
755 #include <sys/fs/vx_quota.h>
756 #include <sys/fs/vx_aioctl.h>
757 #include <sys/fs/vx_ioctl.h>
758
759 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
760 {
761   uid_t user_id, euser_id;
762   int ret;
763   struct vx_dqblk D;
764   struct vx_quotctl quotabuf;
765   struct vx_genioctl genbuf;
766   pstring qfname;
767   int file;
768
769   /*
770    * "name" may or may not include a trailing "/quotas".
771    * Arranging consistency of calling here in "quotas.c" may not be easy and
772    * it might be easier to examine and adjust it here.
773    * Fortunately, VxFS seems not to mind at present.
774    */
775   pstrcpy(qfname, name) ;
776   /* pstrcat(qfname, "/quotas") ; */    /* possibly examine and adjust "name" */
777
778   euser_id = geteuid();
779   set_effective_uid(0);
780
781   DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
782   if((file=sys_open(qfname, O_RDONLY,0))<0) {
783     set_effective_uid(euser_id);
784     return(False);
785   }
786   genbuf.ioc_cmd = VX_QUOTACTL;
787   genbuf.ioc_up = (void *) &quotabuf;
788
789   quotabuf.cmd = VX_GETQUOTA;
790   quotabuf.uid = euser_id;
791   quotabuf.addr = (caddr_t) &D;
792   ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
793   close(file);
794
795   set_effective_uid(euser_id);
796
797   if (ret < 0) {
798     DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
799     return(False);
800   }
801
802   /* If softlimit is zero, set it equal to hardlimit.
803    */
804
805   if (D.dqb_bsoftlimit==0)
806     D.dqb_bsoftlimit = D.dqb_bhardlimit;
807
808   /* Use softlimit to determine disk space. A user exceeding the quota is told
809    * that there's no space left. Writes might actually work for a bit if the
810    * hardlimit is set higher than softlimit. Effectively the disk becomes
811    * made of rubber latex and begins to expand to accommodate the user :-)
812    */
813   DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
814          path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
815          D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));
816
817   if (D.dqb_bsoftlimit==0)
818     return(False);
819   *bsize = DEV_BSIZE;
820   *dsize = D.dqb_bsoftlimit;
821
822   if (D.dqb_curblocks > D.dqb_bsoftlimit) {
823      *dfree = 0;
824      *dsize = D.dqb_curblocks;
825   } else
826     *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
827       
828   DEBUG(5,("disk_quotas for path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",
829          path,(double)*bsize,(double)*dfree,(double)*dsize));
830
831   return(True);
832 }
833
834 #endif /* SUNOS5 || ... */
835
836 #endif /* VXFS_QUOTA */