r1333: NFS Quota support from Dan Peterson.
[Samba/gebeck_regimport.git] / source3 / smbd / quotas.c
blob3c4d4319f637c6ee3797f1f0def14b68d8f19f8f
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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 /*
23 * This is one of the most system dependent parts of Samba, and its
24 * done a litle differently. Each system has its own way of doing
25 * things :-(
28 #include "includes.h"
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_QUOTA
33 #ifndef HAVE_SYS_QUOTAS
35 /* just a quick hack because sysquotas.h is included before linux/quota.h */
36 #ifdef QUOTABLOCK_SIZE
37 #undef QUOTABLOCK_SIZE
38 #endif
40 #ifdef WITH_QUOTAS
42 #if defined(VXFS_QUOTA)
45 * In addition to their native filesystems, some systems have Veritas VxFS.
46 * Declare here, define at end: reduces likely "include" interaction problems.
47 * David Lee <T.D.Lee@durham.ac.uk>
49 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
51 #endif /* VXFS_QUOTA */
53 #ifdef LINUX
55 #include <sys/types.h>
56 #include <mntent.h>
59 * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
60 * So we include all the files has *should* be in the system into a large,
61 * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA.
64 #include "samba_linux_quota.h"
65 #include "samba_xfs_quota.h"
67 typedef struct _LINUX_SMB_DISK_QUOTA {
68 SMB_BIG_UINT bsize;
69 SMB_BIG_UINT hardlimit; /* In bsize units. */
70 SMB_BIG_UINT softlimit; /* In bsize units. */
71 SMB_BIG_UINT curblocks; /* In bsize units. */
72 SMB_BIG_UINT ihardlimit; /* inode hard limit. */
73 SMB_BIG_UINT isoftlimit; /* inode soft limit. */
74 SMB_BIG_UINT curinodes; /* Current used inodes. */
75 } LINUX_SMB_DISK_QUOTA;
77 /****************************************************************************
78 Abstract out the XFS Quota Manager quota get call.
79 ****************************************************************************/
81 static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
83 struct fs_disk_quota D;
84 int ret;
86 ZERO_STRUCT(D);
88 ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
90 if (ret)
91 ret = quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
93 if (ret)
94 return ret;
96 dp->bsize = (SMB_BIG_UINT)512;
97 dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
98 dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
99 dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
100 dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
101 dp->curinodes = (SMB_BIG_UINT)D.d_icount;
102 dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
104 return ret;
107 /****************************************************************************
108 Abstract out the old and new Linux quota get calls.
109 ****************************************************************************/
111 static int get_smb_linux_v1_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
113 struct v1_kern_dqblk D;
114 int ret;
116 ZERO_STRUCT(D);
118 ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
120 if (ret && errno != EDQUOT)
121 ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
123 if (ret && errno != EDQUOT)
124 return ret;
126 dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
127 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
128 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
129 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
130 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
131 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
132 dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
134 return ret;
137 static int get_smb_linux_v2_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
139 struct v2_kern_dqblk D;
140 int ret;
142 ZERO_STRUCT(D);
144 ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
146 if (ret && errno != EDQUOT)
147 ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
149 if (ret && errno != EDQUOT)
150 return ret;
152 dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
153 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
154 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
155 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
156 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
157 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
158 dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
160 return ret;
163 /****************************************************************************
164 Brand-new generic quota interface.
165 ****************************************************************************/
167 static int get_smb_linux_gen_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
169 struct if_dqblk D;
170 int ret;
172 ZERO_STRUCT(D);
174 ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
176 if (ret && errno != EDQUOT)
177 ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
179 if (ret && errno != EDQUOT)
180 return ret;
182 dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
183 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
184 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
185 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
186 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
187 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
188 dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
190 return ret;
193 /****************************************************************************
194 Try to get the disk space from disk quotas (LINUX version).
195 ****************************************************************************/
197 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
199 int r;
200 SMB_STRUCT_STAT S;
201 FILE *fp;
202 LINUX_SMB_DISK_QUOTA D;
203 struct mntent *mnt;
204 SMB_DEV_T devno;
205 int found;
206 uid_t euser_id;
207 gid_t egrp_id;
209 euser_id = geteuid();
210 egrp_id = getegid();
212 /* find the block device file */
214 if ( sys_stat(path, &S) == -1 )
215 return(False) ;
217 devno = S.st_dev ;
219 fp = setmntent(MOUNTED,"r");
220 found = False ;
222 while ((mnt = getmntent(fp))) {
223 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
224 continue ;
226 if (S.st_dev == devno) {
227 found = True ;
228 break;
232 endmntent(fp) ;
234 if (!found)
235 return(False);
237 save_re_uid();
238 set_effective_uid(0);
240 if (strcmp(mnt->mnt_type, "xfs")==0) {
241 r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
242 } else {
243 r=get_smb_linux_gen_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
244 if (r == -1 && errno != EDQUOT) {
245 r=get_smb_linux_v2_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
246 if (r == -1 && errno != EDQUOT)
247 r=get_smb_linux_v1_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
251 restore_re_uid();
253 /* Use softlimit to determine disk space, except when it has been exceeded */
254 *bsize = D.bsize;
255 if (r == -1) {
256 if (errno == EDQUOT) {
257 *dfree =0;
258 *dsize =D.curblocks;
259 return (True);
260 } else {
261 return(False);
265 /* Use softlimit to determine disk space, except when it has been exceeded */
266 if (
267 (D.softlimit && D.curblocks >= D.softlimit) ||
268 (D.hardlimit && D.curblocks >= D.hardlimit) ||
269 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
270 (D.ihardlimit && D.curinodes>=D.ihardlimit)
272 *dfree = 0;
273 *dsize = D.curblocks;
274 } else if (D.softlimit==0 && D.hardlimit==0) {
275 return(False);
276 } else {
277 if (D.softlimit == 0)
278 D.softlimit = D.hardlimit;
279 *dfree = D.softlimit - D.curblocks;
280 *dsize = D.softlimit;
283 return (True);
286 #elif defined(CRAY)
288 #include <sys/quota.h>
289 #include <mntent.h>
291 /****************************************************************************
292 try to get the disk space from disk quotas (CRAY VERSION)
293 ****************************************************************************/
295 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
297 struct mntent *mnt;
298 FILE *fd;
299 SMB_STRUCT_STAT sbuf;
300 SMB_DEV_T devno ;
301 static SMB_DEV_T devno_cached = 0 ;
302 static pstring name;
303 struct q_request request ;
304 struct qf_header header ;
305 static int quota_default = 0 ;
306 int found ;
308 if ( sys_stat(path,&sbuf) == -1 )
309 return(False) ;
311 devno = sbuf.st_dev ;
313 if ( devno != devno_cached ) {
315 devno_cached = devno ;
317 if ((fd = setmntent(KMTAB)) == NULL)
318 return(False) ;
320 found = False ;
322 while ((mnt = getmntent(fd)) != NULL) {
324 if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
325 continue ;
327 if (sbuf.st_dev == devno) {
329 found = True ;
330 break ;
336 pstrcpy(name,mnt->mnt_dir) ;
337 endmntent(fd) ;
339 if ( ! found )
340 return(False) ;
343 request.qf_magic = QF_MAGIC ;
344 request.qf_entry.id = geteuid() ;
346 if (quotactl(name, Q_GETQUOTA, &request) == -1)
347 return(False) ;
349 if ( ! request.user )
350 return(False) ;
352 if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
354 if ( ! quota_default ) {
356 if ( quotactl(name, Q_GETHEADER, &header) == -1 )
357 return(False) ;
358 else
359 quota_default = header.user_h.def_fq ;
362 *dfree = quota_default ;
364 }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
366 *dfree = 0 ;
368 }else{
370 *dfree = request.qf_entry.user_q.f_quota ;
374 *dsize = request.qf_entry.user_q.f_use ;
376 if ( *dfree < *dsize )
377 *dfree = 0 ;
378 else
379 *dfree -= *dsize ;
381 *bsize = 4096 ; /* Cray blocksize */
383 return(True) ;
388 #elif defined(SUNOS5) || defined(SUNOS4)
390 #include <fcntl.h>
391 #include <sys/param.h>
392 #if defined(SUNOS5)
393 #include <sys/fs/ufs_quota.h>
394 #include <sys/mnttab.h>
395 #include <sys/mntent.h>
396 #else /* defined(SUNOS4) */
397 #include <ufs/quota.h>
398 #include <mntent.h>
399 #endif
401 #if defined(SUNOS5)
403 /****************************************************************************
404 Allows querying of remote hosts for quotas on NFS mounted shares.
405 Supports normal NFS and AMD mounts.
406 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
407 ****************************************************************************/
409 #include <rpc/rpc.h>
410 #include <rpc/types.h>
411 #include <rpcsvc/rquota.h>
412 #include <rpc/nettype.h>
413 #include <rpc/xdr.h>
415 static int quotastat;
417 static int xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
419 if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
420 return(0);
421 if (!xdr_int(xdrsp, &args->gqa_uid))
422 return(0);
423 return (1);
426 static int xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
428 if (!xdr_int(xdrsp, &quotastat)) {
429 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
430 return 0;
432 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
433 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
434 return 0;
436 if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
437 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
438 return 0;
440 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
441 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
442 return 0;
444 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
445 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
446 return 0;
448 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
449 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
450 return 0;
452 return (1);
455 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
456 static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
458 uid_t uid = euser_id;
459 struct dqblk D;
460 char *mnttype = nfspath;
461 CLIENT *clnt;
462 struct getquota_rslt gqr;
463 struct getquota_args args;
464 char *cutstr, *pathname, *host, *testpath;
465 int len;
466 static struct timeval timeout = {2,0};
467 enum clnt_stat clnt_stat;
468 BOOL ret = True;
470 *bsize = *dfree = *dsize = (SMB_BIG_UINT)0;
472 len=strcspn(mnttype, ":");
473 pathname=strstr(mnttype, ":");
474 cutstr = (char *) malloc(len+1);
475 if (!cutstr)
476 return False;
478 memset(cutstr, '\0', len+1);
479 host = strncat(cutstr,mnttype, sizeof(char) * len );
480 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
481 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
482 testpath=strchr_m(mnttype, ':');
483 args.gqa_pathp = testpath+1;
484 args.gqa_uid = uid;
486 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
488 if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
489 ret = False;
490 goto out;
493 clnt->cl_auth = authunix_create_default();
494 DEBUG(9,("nfs_quotas: auth_success\n"));
496 clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, xdr_getquota_args, (caddr_t)&args, xdr_getquota_rslt, (caddr_t)&gqr, timeout);
498 if (clnt_stat != RPC_SUCCESS) {
499 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
500 ret = False;
501 goto out;
505 * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
506 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
507 * something sensible.
510 switch ( quotastat ) {
511 case 0:
512 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat ));
513 ret = False;
514 goto out;
516 case 1:
517 DEBUG(9,("nfs_quotas: Good quota data\n"));
518 D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
519 D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
520 D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
521 break;
523 case 2:
524 case 3:
525 D.dqb_bsoftlimit = 1;
526 D.dqb_curblocks = 1;
527 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat ));
528 break;
530 default:
531 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", quotastat ));
532 break;
535 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",
536 quotastat,
537 gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
538 gqr.getquota_rslt_u.gqr_rquota.rq_active,
539 gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
540 gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
541 gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
543 *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
544 *dsize = D.dqb_bsoftlimit;
546 if (D.dqb_curblocks == D.dqb_curblocks == 1)
547 *bsize = 512;
549 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
550 *dfree = 0;
551 *dsize = D.dqb_curblocks;
552 } else
553 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
555 out:
557 if (clnt) {
558 if (clnt->cl_auth)
559 auth_destroy(clnt->cl_auth);
560 clnt_destroy(clnt);
563 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
565 SAFE_FREE(cutstr);
566 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
567 return ret;
569 #endif
571 /****************************************************************************
572 try to get the disk space from disk quotas (SunOS & Solaris2 version)
573 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
574 ****************************************************************************/
576 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
578 uid_t euser_id;
579 int ret;
580 struct dqblk D;
581 #if defined(SUNOS5)
582 struct quotctl command;
583 int file;
584 static struct mnttab mnt;
585 static pstring name;
586 pstring devopt;
587 #else /* SunOS4 */
588 struct mntent *mnt;
589 static pstring name;
590 #endif
591 FILE *fd;
592 SMB_STRUCT_STAT sbuf;
593 SMB_DEV_T devno ;
594 static SMB_DEV_T devno_cached = 0 ;
595 static int found ;
597 euser_id = geteuid();
599 if ( sys_stat(path,&sbuf) == -1 )
600 return(False) ;
602 devno = sbuf.st_dev ;
603 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,(unsigned int)devno));
604 if ( devno != devno_cached ) {
605 devno_cached = devno ;
606 #if defined(SUNOS5)
607 if ((fd = sys_fopen(MNTTAB, "r")) == NULL)
608 return(False) ;
610 found = False ;
611 slprintf(devopt, sizeof(devopt) - 1, "dev=%x", (unsigned int)devno);
612 while (getmntent(fd, &mnt) == 0) {
613 if( !hasmntopt(&mnt, devopt) )
614 continue;
616 DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt));
618 /* quotas are only on vxfs, UFS or NFS */
619 if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
620 strcmp( mnt.mnt_fstype, "nfs" ) == 0 ||
621 strcmp( mnt.mnt_fstype, "vxfs" ) == 0 ) {
622 found = True ;
623 break;
627 pstrcpy(name,mnt.mnt_mountp) ;
628 pstrcat(name,"/quotas") ;
629 fclose(fd) ;
630 #else /* SunOS4 */
631 if ((fd = setmntent(MOUNTED, "r")) == NULL)
632 return(False) ;
634 found = False ;
635 while ((mnt = getmntent(fd)) != NULL) {
636 if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
637 continue ;
638 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt->mnt_dir,(unsigned int)sbuf.st_dev));
639 if (sbuf.st_dev == devno) {
640 found = True ;
641 break;
645 pstrcpy(name,mnt->mnt_fsname) ;
646 endmntent(fd) ;
647 #endif
650 if ( ! found )
651 return(False) ;
653 save_re_uid();
654 set_effective_uid(0);
656 #if defined(SUNOS5)
657 if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) {
658 BOOL retval;
659 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special));
660 retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize);
661 restore_re_uid();
662 return retval;
665 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
666 if((file=sys_open(name, O_RDONLY,0))<0) {
667 restore_re_uid();
668 return(False);
670 command.op = Q_GETQUOTA;
671 command.uid = euser_id;
672 command.addr = (caddr_t) &D;
673 ret = ioctl(file, Q_QUOTACTL, &command);
674 close(file);
675 #else
676 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
677 ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
678 #endif
680 restore_re_uid();
682 if (ret < 0) {
683 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) ));
685 #if defined(SUNOS5) && defined(VXFS_QUOTA)
686 /* If normal quotactl() fails, try vxfs private calls */
687 set_effective_uid(euser_id);
688 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
689 if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
690 BOOL retval;
691 retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize);
692 return(retval);
694 #else
695 return(False);
696 #endif
699 /* If softlimit is zero, set it equal to hardlimit.
702 if (D.dqb_bsoftlimit==0)
703 D.dqb_bsoftlimit = D.dqb_bhardlimit;
705 /* Use softlimit to determine disk space. A user exceeding the quota is told
706 * that there's no space left. Writes might actually work for a bit if the
707 * hardlimit is set higher than softlimit. Effectively the disk becomes
708 * made of rubber latex and begins to expand to accommodate the user :-)
711 if (D.dqb_bsoftlimit==0)
712 return(False);
713 *bsize = DEV_BSIZE;
714 *dsize = D.dqb_bsoftlimit;
716 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
717 *dfree = 0;
718 *dsize = D.dqb_curblocks;
719 } else
720 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
722 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
723 path,(double)*bsize,(double)*dfree,(double)*dsize));
725 return(True);
729 #elif defined(OSF1)
730 #include <ufs/quota.h>
732 /****************************************************************************
733 try to get the disk space from disk quotas - OSF1 version
734 ****************************************************************************/
736 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
738 int r, save_errno;
739 struct dqblk D;
740 SMB_STRUCT_STAT S;
741 uid_t euser_id;
744 * This code presumes that OSF1 will only
745 * give out quota info when the real uid
746 * matches the effective uid. JRA.
748 euser_id = geteuid();
749 save_re_uid();
750 if (set_re_uid() != 0) return False;
752 r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D);
753 if (r) {
754 save_errno = errno;
757 restore_re_uid();
759 *bsize = DEV_BSIZE;
761 if (r)
763 if (save_errno == EDQUOT) /* disk quota exceeded */
765 *dfree = 0;
766 *dsize = D.dqb_curblocks;
767 return (True);
769 else
770 return (False);
773 /* If softlimit is zero, set it equal to hardlimit.
776 if (D.dqb_bsoftlimit==0)
777 D.dqb_bsoftlimit = D.dqb_bhardlimit;
779 /* Use softlimit to determine disk space, except when it has been exceeded */
781 if (D.dqb_bsoftlimit==0)
782 return(False);
784 if ((D.dqb_curblocks>D.dqb_bsoftlimit)) {
785 *dfree = 0;
786 *dsize = D.dqb_curblocks;
787 } else {
788 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
789 *dsize = D.dqb_bsoftlimit;
791 return (True);
794 #elif defined (IRIX6)
795 /****************************************************************************
796 try to get the disk space from disk quotas (IRIX 6.2 version)
797 ****************************************************************************/
799 #include <sys/quota.h>
800 #include <mntent.h>
802 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
804 uid_t euser_id;
805 int r;
806 struct dqblk D;
807 struct fs_disk_quota F;
808 SMB_STRUCT_STAT S;
809 FILE *fp;
810 struct mntent *mnt;
811 SMB_DEV_T devno;
812 int found;
814 /* find the block device file */
816 if ( sys_stat(path, &S) == -1 ) {
817 return(False) ;
820 devno = S.st_dev ;
822 fp = setmntent(MOUNTED,"r");
823 found = False ;
825 while ((mnt = getmntent(fp))) {
826 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
827 continue ;
828 if (S.st_dev == devno) {
829 found = True ;
830 break ;
833 endmntent(fp) ;
835 if (!found) {
836 return(False);
839 euser_id=geteuid();
840 save_re_uid();
841 set_effective_uid(0);
843 /* Use softlimit to determine disk space, except when it has been exceeded */
845 *bsize = 512;
847 if ( 0 == strcmp ( mnt->mnt_type, "efs" ))
849 r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);
851 restore_re_uid();
853 if (r==-1)
854 return(False);
856 /* Use softlimit to determine disk space, except when it has been exceeded */
857 if (
858 (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
859 (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
860 (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) ||
861 (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit)
864 *dfree = 0;
865 *dsize = D.dqb_curblocks;
867 else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
869 return(False);
871 else
873 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
874 *dsize = D.dqb_bsoftlimit;
878 else if ( 0 == strcmp ( mnt->mnt_type, "xfs" ))
880 r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);
882 restore_re_uid();
884 if (r==-1)
885 return(False);
887 /* Use softlimit to determine disk space, except when it has been exceeded */
888 if (
889 (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) ||
890 (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) ||
891 (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) ||
892 (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit)
895 *dfree = 0;
896 *dsize = F.d_bcount;
898 else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0)
900 return(False);
902 else
904 *dfree = (F.d_blk_softlimit - F.d_bcount);
905 *dsize = F.d_blk_softlimit;
909 else
911 restore_re_uid();
912 return(False);
915 return (True);
919 #else
921 #if defined(__FreeBSD__) || defined(__OpenBSD__)
922 #include <ufs/ufs/quota.h>
923 #include <machine/param.h>
924 #elif AIX
925 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
926 #include <jfs/quota.h>
927 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
928 #define dqb_curfiles dqb_curinodes
929 #define dqb_fhardlimit dqb_ihardlimit
930 #define dqb_fsoftlimit dqb_isoftlimit
931 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
932 #include <sys/quota.h>
933 #include <devnm.h>
934 #endif
936 #if defined(__FreeBSD__)
938 #include <rpc/rpc.h>
939 #include <rpc/types.h>
940 #include <rpcsvc/rquota.h>
941 #include <rpc/nettype.h>
942 #include <rpc/xdr.h>
944 static int quotastat;
946 static int my_xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
948 if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
949 return(0);
950 if (!xdr_int(xdrsp, &args->gqa_uid))
951 return(0);
952 return (1);
955 static int my_xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
957 if (!xdr_int(xdrsp, &quotastat)) {
958 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
959 return 0;
961 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
962 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
963 return 0;
965 if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
966 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
967 return 0;
969 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
970 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
971 return 0;
973 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
974 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
975 return 0;
977 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
978 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
979 return 0;
981 return (1);
984 /* Works on FreeBSD, too. :-) */
985 static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
987 uid_t uid = euser_id;
988 struct dqblk D;
989 char *mnttype = nfspath;
990 CLIENT *clnt;
991 struct getquota_rslt gqr;
992 struct getquota_args args;
993 char *cutstr, *pathname, *host, *testpath;
994 int len;
995 static struct timeval timeout = {2,0};
996 enum clnt_stat clnt_stat;
997 BOOL ret = True;
999 *bsize = *dfree = *dsize = (SMB_BIG_UINT)0;
1001 len=strcspn(mnttype, ":");
1002 pathname=strstr(mnttype, ":");
1003 cutstr = (char *) malloc(len+1);
1004 if (!cutstr)
1005 return False;
1007 memset(cutstr, '\0', len+1);
1008 host = strncat(cutstr,mnttype, sizeof(char) * len );
1009 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
1010 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
1011 testpath=strchr_m(mnttype, ':');
1012 args.gqa_pathp = testpath+1;
1013 args.gqa_uid = uid;
1015 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
1017 if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
1018 ret = False;
1019 goto out;
1022 clnt->cl_auth = authunix_create_default();
1023 DEBUG(9,("nfs_quotas: auth_success\n"));
1025 clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, (const xdrproc_t) my_xdr_getquota_args, (caddr_t)&args, (const xdrproc_t) my_xdr_getquota_rslt, (caddr_t)&gqr, timeout);
1027 if (clnt_stat != RPC_SUCCESS) {
1028 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
1029 ret = False;
1030 goto out;
1034 * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
1035 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
1036 * something sensible.
1039 switch ( quotastat ) {
1040 case 0:
1041 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat ));
1042 ret = False;
1043 goto out;
1045 case 1:
1046 DEBUG(9,("nfs_quotas: Good quota data\n"));
1047 D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
1048 D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
1049 D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
1050 break;
1052 case 2:
1053 case 3:
1054 D.dqb_bsoftlimit = 1;
1055 D.dqb_curblocks = 1;
1056 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat ));
1057 break;
1059 default:
1060 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", quotastat ));
1061 break;
1064 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",
1065 quotastat,
1066 gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
1067 gqr.getquota_rslt_u.gqr_rquota.rq_active,
1068 gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
1069 gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
1070 gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
1072 if (D.dqb_bsoftlimit == 0)
1073 D.dqb_bsoftlimit = D.dqb_bhardlimit;
1074 if (D.dqb_bsoftlimit == 0)
1075 return False;
1077 *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
1078 *dsize = D.dqb_bsoftlimit;
1080 if (D.dqb_curblocks == D.dqb_curblocks == 1)
1081 *bsize = DEV_BSIZE;
1083 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
1084 *dfree = 0;
1085 *dsize = D.dqb_curblocks;
1086 } else
1087 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
1089 out:
1091 if (clnt) {
1092 if (clnt->cl_auth)
1093 auth_destroy(clnt->cl_auth);
1094 clnt_destroy(clnt);
1097 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
1099 SAFE_FREE(cutstr);
1100 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
1101 return ret;
1104 #endif
1106 /****************************************************************************
1107 try to get the disk space from disk quotas - default version
1108 ****************************************************************************/
1110 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
1112 int r;
1113 struct dqblk D;
1114 uid_t euser_id;
1115 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__)
1116 char dev_disk[256];
1117 SMB_STRUCT_STAT S;
1119 /* find the block device file */
1121 #ifdef HPUX
1122 /* Need to set the cache flag to 1 for HPUX. Seems
1123 * to have a significant performance boost when
1124 * lstat calls on /dev access this function.
1126 if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0))
1127 #else
1128 if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0))
1129 return (False);
1130 #endif /* ifdef HPUX */
1132 #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */
1134 euser_id = geteuid();
1136 #ifdef HPUX
1137 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
1138 save_re_uid();
1139 if (set_re_uid() != 0) return False;
1141 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
1143 restore_re_uid();
1144 #else
1145 #if defined(__FreeBSD__) || defined(__OpenBSD__)
1147 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
1148 gid_t egrp_id;
1149 #if defined(__FreeBSD__)
1150 SMB_DEV_T devno;
1151 struct statfs *mnts;
1152 SMB_STRUCT_STAT st;
1153 int mntsize, i;
1155 if (sys_stat(path,&st) < 0)
1156 return False;
1157 devno = st.st_dev;
1159 mntsize = getmntinfo(&mnts,MNT_NOWAIT);
1160 if (mntsize <= 0)
1161 return False;
1163 for (i = 0; i < mntsize; i++) {
1164 if (sys_stat(mnts[i].f_mntonname,&st) < 0)
1165 return False;
1166 if (st.st_dev == devno)
1167 break;
1169 if (i == mntsize)
1170 return False;
1171 #endif
1173 save_re_uid();
1174 set_effective_uid(0);
1176 #if defined(__FreeBSD__)
1177 if (strcmp(mnts[i].f_fstypename,"nfs") == 0) {
1178 BOOL retval;
1179 retval = nfs_quotas(mnts[i].f_mntfromname,euser_id,bsize,dfree,dsize);
1180 restore_re_uid();
1181 return retval;
1183 #endif
1185 egrp_id = getegid();
1186 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
1188 /* As FreeBSD has group quotas, if getting the user
1189 quota fails, try getting the group instead. */
1190 if (r) {
1191 r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
1194 restore_re_uid();
1196 #elif defined(AIX)
1197 /* AIX has both USER and GROUP quotas:
1198 Get the USER quota (ohnielse@fysik.dtu.dk) */
1199 save_re_uid();
1200 if (set_re_uid() != 0)
1201 return False;
1202 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
1203 restore_re_uid();
1204 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
1205 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
1206 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
1207 #endif /* HPUX */
1209 /* Use softlimit to determine disk space, except when it has been exceeded */
1210 #if defined(__FreeBSD__) || defined(__OpenBSD__)
1211 *bsize = DEV_BSIZE;
1212 #else /* !__FreeBSD__ && !__OpenBSD__ */
1213 *bsize = 1024;
1214 #endif /*!__FreeBSD__ && !__OpenBSD__ */
1216 if (r)
1218 if (errno == EDQUOT)
1220 *dfree =0;
1221 *dsize =D.dqb_curblocks;
1222 return (True);
1224 else return(False);
1227 /* If softlimit is zero, set it equal to hardlimit.
1230 if (D.dqb_bsoftlimit==0)
1231 D.dqb_bsoftlimit = D.dqb_bhardlimit;
1233 if (D.dqb_bsoftlimit==0)
1234 return(False);
1235 /* Use softlimit to determine disk space, except when it has been exceeded */
1236 if ((D.dqb_curblocks>D.dqb_bsoftlimit)
1237 #if !defined(__FreeBSD__) && !defined(__OpenBSD__)
1238 ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
1239 #endif
1241 *dfree = 0;
1242 *dsize = D.dqb_curblocks;
1244 else {
1245 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
1246 *dsize = D.dqb_bsoftlimit;
1248 return (True);
1251 #endif
1253 #if defined(VXFS_QUOTA)
1255 /****************************************************************************
1256 Try to get the disk space from Veritas disk quotas.
1257 David Lee <T.D.Lee@durham.ac.uk> August 1999.
1259 Background assumptions:
1260 Potentially under many Operating Systems. Initially Solaris 2.
1262 My guess is that Veritas is largely, though not entirely,
1263 independent of OS. So I have separated it out.
1265 There may be some details. For example, OS-specific "include" files.
1267 It is understood that HPUX 10 somehow gets Veritas quotas without
1268 any special effort; if so, this routine need not be compiled in.
1269 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
1271 Warning:
1272 It is understood that Veritas do not publicly support this ioctl interface.
1273 Rather their preference would be for the user (us) to call the native
1274 OS and then for the OS itself to call through to the VxFS filesystem.
1275 Presumably HPUX 10, see above, does this.
1277 Hints for porting:
1278 Add your OS to "IFLIST" below.
1279 Get it to compile successfully:
1280 Almost certainly "include"s require attention: see SUNOS5.
1281 In the main code above, arrange for it to be called: see SUNOS5.
1282 Test!
1284 ****************************************************************************/
1286 /* "IFLIST"
1287 * This "if" is a list of ports:
1288 * if defined(OS1) || defined(OS2) || ...
1290 #if defined(SUNOS5)
1292 #if defined(SUNOS5)
1293 #include <sys/fs/vx_solaris.h>
1294 #endif
1295 #include <sys/fs/vx_machdep.h>
1296 #include <sys/fs/vx_layout.h>
1297 #include <sys/fs/vx_quota.h>
1298 #include <sys/fs/vx_aioctl.h>
1299 #include <sys/fs/vx_ioctl.h>
1301 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
1303 uid_t user_id, euser_id;
1304 int ret;
1305 struct vx_dqblk D;
1306 struct vx_quotctl quotabuf;
1307 struct vx_genioctl genbuf;
1308 pstring qfname;
1309 int file;
1312 * "name" may or may not include a trailing "/quotas".
1313 * Arranging consistency of calling here in "quotas.c" may not be easy and
1314 * it might be easier to examine and adjust it here.
1315 * Fortunately, VxFS seems not to mind at present.
1317 pstrcpy(qfname, name) ;
1318 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
1320 euser_id = geteuid();
1321 set_effective_uid(0);
1323 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
1324 if((file=sys_open(qfname, O_RDONLY,0))<0) {
1325 set_effective_uid(euser_id);
1326 return(False);
1328 genbuf.ioc_cmd = VX_QUOTACTL;
1329 genbuf.ioc_up = (void *) &quotabuf;
1331 quotabuf.cmd = VX_GETQUOTA;
1332 quotabuf.uid = euser_id;
1333 quotabuf.addr = (caddr_t) &D;
1334 ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
1335 close(file);
1337 set_effective_uid(euser_id);
1339 if (ret < 0) {
1340 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
1341 return(False);
1344 /* If softlimit is zero, set it equal to hardlimit.
1347 if (D.dqb_bsoftlimit==0)
1348 D.dqb_bsoftlimit = D.dqb_bhardlimit;
1350 /* Use softlimit to determine disk space. A user exceeding the quota is told
1351 * that there's no space left. Writes might actually work for a bit if the
1352 * hardlimit is set higher than softlimit. Effectively the disk becomes
1353 * made of rubber latex and begins to expand to accommodate the user :-)
1355 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
1356 path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
1357 D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));
1359 if (D.dqb_bsoftlimit==0)
1360 return(False);
1361 *bsize = DEV_BSIZE;
1362 *dsize = D.dqb_bsoftlimit;
1364 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
1365 *dfree = 0;
1366 *dsize = D.dqb_curblocks;
1367 } else
1368 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
1370 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
1371 path,(double)*bsize,(double)*dfree,(double)*dsize));
1373 return(True);
1376 #endif /* SUNOS5 || ... */
1378 #endif /* VXFS_QUOTA */
1380 #else /* WITH_QUOTAS */
1382 BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
1384 (*bsize) = 512; /* This value should be ignored */
1386 /* And just to be sure we set some values that hopefully */
1387 /* will be larger that any possible real-world value */
1388 (*dfree) = (SMB_BIG_UINT)-1;
1389 (*dsize) = (SMB_BIG_UINT)-1;
1391 /* As we have select not to use quotas, allways fail */
1392 return False;
1394 #endif /* WITH_QUOTAS */
1396 #else /* HAVE_SYS_QUOTAS */
1397 /* wrapper to the new sys_quota interface
1398 this file should be removed later
1400 BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
1402 int r;
1403 SMB_DISK_QUOTA D;
1404 unid_t id;
1406 id.uid = geteuid();
1408 ZERO_STRUCT(D);
1409 r=sys_get_quota(path, SMB_USER_QUOTA_TYPE, id, &D);
1411 /* Use softlimit to determine disk space, except when it has been exceeded */
1412 *bsize = D.bsize;
1413 if (r == -1) {
1414 if (errno == EDQUOT) {
1415 *dfree =0;
1416 *dsize =D.curblocks;
1417 return (True);
1418 } else {
1419 goto try_group_quota;
1423 /* Use softlimit to determine disk space, except when it has been exceeded */
1424 if (
1425 (D.softlimit && D.curblocks >= D.softlimit) ||
1426 (D.hardlimit && D.curblocks >= D.hardlimit) ||
1427 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
1428 (D.ihardlimit && D.curinodes>=D.ihardlimit)
1430 *dfree = 0;
1431 *dsize = D.curblocks;
1432 } else if (D.softlimit==0 && D.hardlimit==0) {
1433 goto try_group_quota;
1434 } else {
1435 if (D.softlimit == 0)
1436 D.softlimit = D.hardlimit;
1437 *dfree = D.softlimit - D.curblocks;
1438 *dsize = D.softlimit;
1441 return True;
1443 try_group_quota:
1444 id.gid = getegid();
1446 ZERO_STRUCT(D);
1447 r=sys_get_quota(path, SMB_GROUP_QUOTA_TYPE, id, &D);
1449 /* Use softlimit to determine disk space, except when it has been exceeded */
1450 *bsize = D.bsize;
1451 if (r == -1) {
1452 if (errno == EDQUOT) {
1453 *dfree =0;
1454 *dsize =D.curblocks;
1455 return (True);
1456 } else {
1457 return False;
1461 /* Use softlimit to determine disk space, except when it has been exceeded */
1462 if (
1463 (D.softlimit && D.curblocks >= D.softlimit) ||
1464 (D.hardlimit && D.curblocks >= D.hardlimit) ||
1465 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
1466 (D.ihardlimit && D.curinodes>=D.ihardlimit)
1468 *dfree = 0;
1469 *dsize = D.curblocks;
1470 } else if (D.softlimit==0 && D.hardlimit==0) {
1471 return False;
1472 } else {
1473 if (D.softlimit == 0)
1474 D.softlimit = D.hardlimit;
1475 *dfree = D.softlimit - D.curblocks;
1476 *dsize = D.softlimit;
1479 return (True);
1481 #endif /* HAVE_SYS_QUOTAS */