2 Unix SMB/CIFS implementation.
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.
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
30 #ifndef HAVE_SYS_QUOTAS
34 #if defined(VXFS_QUOTA)
37 * In addition to their native filesystems, some systems have Veritas VxFS.
38 * Declare here, define at end: reduces likely "include" interaction problems.
39 * David Lee <T.D.Lee@durham.ac.uk>
41 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
43 #endif /* VXFS_QUOTA */
47 #include <sys/types.h>
48 #include <asm/types.h>
51 * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
52 * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk
53 * rather than the struct dqblk defined in /usr/include/sys/quota.h.
54 * This means we must include linux/quota.h to have a hope of working on
55 * RH7.1 systems. And it also means this breaks if the kernel is upgraded
56 * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until
57 * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA.
60 #include <linux/quota.h>
61 #ifdef HAVE_LINUX_XQM_H
62 #include <linux/xqm.h>
66 #define HAVE_LINUX_XQM_H
71 #include <linux/unistd.h>
74 #define LINUX_QUOTAS_2
76 typedef struct _LINUX_SMB_DISK_QUOTA {
78 SMB_BIG_UINT hardlimit; /* In bsize units. */
79 SMB_BIG_UINT softlimit; /* In bsize units. */
80 SMB_BIG_UINT curblocks; /* In bsize units. */
81 SMB_BIG_UINT ihardlimit; /* inode hard limit. */
82 SMB_BIG_UINT isoftlimit; /* inode soft limit. */
83 SMB_BIG_UINT curinodes; /* Current used inodes. */
84 } LINUX_SMB_DISK_QUOTA;
86 /****************************************************************************
87 Abstract out the XFS Quota Manager quota get call.
88 ****************************************************************************/
90 static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
93 #ifdef HAVE_LINUX_XQM_H
94 struct fs_disk_quota D;
97 if ((ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D)))
100 dp->bsize = (SMB_BIG_UINT)512;
101 dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
102 dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
103 dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
104 dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
105 dp->curinodes = (SMB_BIG_UINT)D.d_icount;
106 dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
111 /****************************************************************************
112 Abstract out the old and new Linux quota get calls.
113 ****************************************************************************/
115 static int get_smb_linux_vfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
118 #ifdef LINUX_QUOTAS_1
121 dp->bsize = (SMB_BIG_UINT)1024;
122 #else /* LINUX_QUOTAS_2 */
125 #ifndef QUOTABLOCK_SIZE
126 #define QUOTABLOCK_SIZE 1024
128 dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
131 if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D)))
134 dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
135 dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
136 dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
137 dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
138 dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
140 #ifdef LINUX_QUOTAS_1
141 dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
142 #else /* LINUX_QUOTAS_2 */
143 dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace)/ dp->bsize;
149 /****************************************************************************
150 try to get the disk space from disk quotas (LINUX version)
151 ****************************************************************************/
153 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
158 LINUX_SMB_DISK_QUOTA D;
164 euser_id = geteuid();
166 /* find the block device file */
168 if ( sys_stat(path, &S) == -1 )
173 fp = setmntent(MOUNTED,"r");
176 while ((mnt = getmntent(fp))) {
177 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
180 if (S.st_dev == devno) {
192 set_effective_uid(0);
193 if (strcmp(mnt->mnt_type, "xfs") == 0)
194 r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, &D);
196 r=get_smb_linux_vfs_quota(mnt->mnt_fsname, euser_id, &D);
199 /* Use softlimit to determine disk space, except when it has been exceeded */
202 if (errno == EDQUOT) {
211 /* Use softlimit to determine disk space, except when it has been exceeded */
213 (D.softlimit && D.curblocks >= D.softlimit) ||
214 (D.hardlimit && D.curblocks >= D.hardlimit) ||
215 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
216 (D.ihardlimit && D.curinodes>=D.ihardlimit)
219 *dsize = D.curblocks;
220 } else if (D.softlimit==0 && D.hardlimit==0) {
223 if (D.softlimit == 0)
224 D.softlimit = D.hardlimit;
225 *dfree = D.softlimit - D.curblocks;
226 *dsize = D.softlimit;
234 #include <sys/quota.h>
237 /****************************************************************************
238 try to get the disk space from disk quotas (CRAY VERSION)
239 ****************************************************************************/
241 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
245 SMB_STRUCT_STAT sbuf;
247 static SMB_DEV_T devno_cached = 0 ;
249 struct q_request request ;
250 struct qf_header header ;
251 static int quota_default = 0 ;
254 if ( sys_stat(path,&sbuf) == -1 )
257 devno = sbuf.st_dev ;
259 if ( devno != devno_cached ) {
261 devno_cached = devno ;
263 if ((fd = setmntent(KMTAB)) == NULL)
268 while ((mnt = getmntent(fd)) != NULL) {
270 if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
273 if (sbuf.st_dev == devno) {
282 pstrcpy(name,mnt->mnt_dir) ;
289 request.qf_magic = QF_MAGIC ;
290 request.qf_entry.id = geteuid() ;
292 if (quotactl(name, Q_GETQUOTA, &request) == -1)
295 if ( ! request.user )
298 if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
300 if ( ! quota_default ) {
302 if ( quotactl(name, Q_GETHEADER, &header) == -1 )
305 quota_default = header.user_h.def_fq ;
308 *dfree = quota_default ;
310 }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
316 *dfree = request.qf_entry.user_q.f_quota ;
320 *dsize = request.qf_entry.user_q.f_use ;
322 if ( *dfree < *dsize )
327 *bsize = 4096 ; /* Cray blocksize */
334 #elif defined(SUNOS5) || defined(SUNOS4)
337 #include <sys/param.h>
339 #include <sys/fs/ufs_quota.h>
340 #include <sys/mnttab.h>
341 #include <sys/mntent.h>
342 #else /* defined(SUNOS4) */
343 #include <ufs/quota.h>
349 /****************************************************************************
350 Allows querying of remote hosts for quotas on NFS mounted shares.
351 Supports normal NFS and AMD mounts.
352 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
353 ****************************************************************************/
356 #include <rpc/types.h>
357 #include <rpcsvc/rquota.h>
358 #include <rpc/nettype.h>
361 static int quotastat;
363 static int xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
365 if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
367 if (!xdr_int(xdrsp, &args->gqa_uid))
372 static int xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
374 if (!xdr_int(xdrsp, "astat)) {
375 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
378 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
379 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
382 if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
383 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
386 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
387 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
390 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
391 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
394 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
395 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
401 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
402 static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
404 uid_t uid = euser_id;
406 char *mnttype = nfspath;
408 struct getquota_rslt gqr;
409 struct getquota_args args;
410 char *cutstr, *pathname, *host, *testpath;
412 static struct timeval timeout = {2,0};
413 enum clnt_stat clnt_stat;
416 *bsize = *dfree = *dsize = (SMB_BIG_UINT)0;
418 len=strcspn(mnttype, ":");
419 pathname=strstr(mnttype, ":");
420 cutstr = (char *) malloc(len+1);
424 memset(cutstr, '\0', len+1);
425 host = strncat(cutstr,mnttype, sizeof(char) * len );
426 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
427 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
428 testpath=strchr_m(mnttype, ':');
429 args.gqa_pathp = testpath+1;
432 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
434 if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
439 clnt->cl_auth = authunix_create_default();
440 DEBUG(9,("nfs_quotas: auth_success\n"));
442 clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, xdr_getquota_args, (caddr_t)&args, xdr_getquota_rslt, (caddr_t)&gqr, timeout);
444 if (clnt_stat != RPC_SUCCESS) {
445 DEBUG(9,("nfs_quotas: clnt_call fail\n"));
451 * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
452 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
453 * something sensible.
456 switch ( quotastat ) {
458 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat ));
463 DEBUG(9,("nfs_quotas: Good quota data\n"));
464 D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
465 D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
466 D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
471 D.dqb_bsoftlimit = 1;
473 DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat ));
477 DEBUG(9,("nfs_quotas: Remote Quotas Questionable! Error \"%i\" \n", quotastat ));
481 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",
483 gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
484 gqr.getquota_rslt_u.gqr_rquota.rq_active,
485 gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
486 gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
487 gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
489 *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
490 *dsize = D.dqb_bsoftlimit;
492 if (D.dqb_curblocks == D.dqb_curblocks == 1)
495 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
497 *dsize = D.dqb_curblocks;
499 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
505 auth_destroy(clnt->cl_auth);
509 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
512 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
517 /****************************************************************************
518 try to get the disk space from disk quotas (SunOS & Solaris2 version)
519 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
520 ****************************************************************************/
522 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
528 struct quotctl command;
530 static struct mnttab mnt;
538 SMB_STRUCT_STAT sbuf;
540 static SMB_DEV_T devno_cached = 0 ;
543 euser_id = geteuid();
545 if ( sys_stat(path,&sbuf) == -1 )
548 devno = sbuf.st_dev ;
549 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,(unsigned int)devno));
550 if ( devno != devno_cached ) {
551 devno_cached = devno ;
553 if ((fd = sys_fopen(MNTTAB, "r")) == NULL)
557 slprintf(devopt, sizeof(devopt) - 1, "dev=%x", (unsigned int)devno);
558 while (getmntent(fd, &mnt) == 0) {
559 if( !hasmntopt(&mnt, devopt) )
562 DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt));
564 /* quotas are only on vxfs, UFS or NFS */
565 if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
566 strcmp( mnt.mnt_fstype, "nfs" ) == 0 ||
567 strcmp( mnt.mnt_fstype, "vxfs" ) == 0 ) {
573 pstrcpy(name,mnt.mnt_mountp) ;
574 pstrcat(name,"/quotas") ;
577 if ((fd = setmntent(MOUNTED, "r")) == NULL)
581 while ((mnt = getmntent(fd)) != NULL) {
582 if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
584 DEBUG(5,("disk_quotas: testing \"%s\" devno=%x\n", mnt->mnt_dir,(unsigned int)sbuf.st_dev));
585 if (sbuf.st_dev == devno) {
591 pstrcpy(name,mnt->mnt_fsname) ;
600 set_effective_uid(0);
603 if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) {
605 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special));
606 retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize);
611 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
612 if((file=sys_open(name, O_RDONLY,0))<0) {
616 command.op = Q_GETQUOTA;
617 command.uid = euser_id;
618 command.addr = (caddr_t) &D;
619 ret = ioctl(file, Q_QUOTACTL, &command);
622 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
623 ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
629 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) ));
631 #if defined(SUNOS5) && defined(VXFS_QUOTA)
632 /* If normal quotactl() fails, try vxfs private calls */
633 set_effective_uid(euser_id);
634 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
635 if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
637 retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize);
645 /* If softlimit is zero, set it equal to hardlimit.
648 if (D.dqb_bsoftlimit==0)
649 D.dqb_bsoftlimit = D.dqb_bhardlimit;
651 /* Use softlimit to determine disk space. A user exceeding the quota is told
652 * that there's no space left. Writes might actually work for a bit if the
653 * hardlimit is set higher than softlimit. Effectively the disk becomes
654 * made of rubber latex and begins to expand to accommodate the user :-)
657 if (D.dqb_bsoftlimit==0)
660 *dsize = D.dqb_bsoftlimit;
662 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
664 *dsize = D.dqb_curblocks;
666 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
668 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
669 path,(double)*bsize,(double)*dfree,(double)*dsize));
676 #include <ufs/quota.h>
678 /****************************************************************************
679 try to get the disk space from disk quotas - OSF1 version
680 ****************************************************************************/
682 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
690 * This code presumes that OSF1 will only
691 * give out quota info when the real uid
692 * matches the effective uid. JRA.
694 euser_id = geteuid();
696 if (set_re_uid() != 0) return False;
698 r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D);
709 if (save_errno == EDQUOT) /* disk quota exceeded */
712 *dsize = D.dqb_curblocks;
719 /* If softlimit is zero, set it equal to hardlimit.
722 if (D.dqb_bsoftlimit==0)
723 D.dqb_bsoftlimit = D.dqb_bhardlimit;
725 /* Use softlimit to determine disk space, except when it has been exceeded */
727 if (D.dqb_bsoftlimit==0)
730 if ((D.dqb_curblocks>D.dqb_bsoftlimit)) {
732 *dsize = D.dqb_curblocks;
734 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
735 *dsize = D.dqb_bsoftlimit;
740 #elif defined (IRIX6)
741 /****************************************************************************
742 try to get the disk space from disk quotas (IRIX 6.2 version)
743 ****************************************************************************/
745 #include <sys/quota.h>
748 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
753 struct fs_disk_quota F;
760 /* find the block device file */
762 if ( sys_stat(path, &S) == -1 ) {
768 fp = setmntent(MOUNTED,"r");
771 while ((mnt = getmntent(fp))) {
772 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
774 if (S.st_dev == devno) {
787 set_effective_uid(0);
789 /* Use softlimit to determine disk space, except when it has been exceeded */
793 if ( 0 == strcmp ( mnt->mnt_type, "efs" ))
795 r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);
802 /* Use softlimit to determine disk space, except when it has been exceeded */
804 (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
805 (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
806 (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) ||
807 (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit)
811 *dsize = D.dqb_curblocks;
813 else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
819 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
820 *dsize = D.dqb_bsoftlimit;
824 else if ( 0 == strcmp ( mnt->mnt_type, "xfs" ))
826 r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);
833 /* Use softlimit to determine disk space, except when it has been exceeded */
835 (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) ||
836 (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) ||
837 (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) ||
838 (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit)
844 else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0)
850 *dfree = (F.d_blk_softlimit - F.d_bcount);
851 *dsize = F.d_blk_softlimit;
867 #if defined(__FreeBSD__) || defined(__OpenBSD__)
868 #include <ufs/ufs/quota.h>
869 #include <machine/param.h>
871 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
872 #include <jfs/quota.h>
873 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
874 #define dqb_curfiles dqb_curinodes
875 #define dqb_fhardlimit dqb_ihardlimit
876 #define dqb_fsoftlimit dqb_isoftlimit
877 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
878 #include <sys/quota.h>
882 /****************************************************************************
883 try to get the disk space from disk quotas - default version
884 ****************************************************************************/
886 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
891 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__)
895 /* find the block device file */
898 /* Need to set the cache flag to 1 for HPUX. Seems
899 * to have a significant performance boost when
900 * lstat calls on /dev access this function.
902 if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0))
904 if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0))
905 #endif /* ifdef HPUX */
908 #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */
910 euser_id = geteuid();
913 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
915 if (set_re_uid() != 0) return False;
917 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
921 #if defined(__FreeBSD__) || defined(__OpenBSD__)
923 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
927 set_effective_uid(0);
930 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
932 /* As FreeBSD has group quotas, if getting the user
933 quota fails, try getting the group instead. */
935 r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
941 /* AIX has both USER and GROUP quotas:
942 Get the USER quota (ohnielse@fysik.dtu.dk) */
943 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
944 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
945 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
946 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
949 /* Use softlimit to determine disk space, except when it has been exceeded */
950 #if defined(__FreeBSD__) || defined(__OpenBSD__)
952 #else /* !__FreeBSD__ && !__OpenBSD__ */
954 #endif /*!__FreeBSD__ && !__OpenBSD__ */
961 *dsize =D.dqb_curblocks;
967 /* If softlimit is zero, set it equal to hardlimit.
970 if (D.dqb_bsoftlimit==0)
971 D.dqb_bsoftlimit = D.dqb_bhardlimit;
973 if (D.dqb_bsoftlimit==0)
975 /* Use softlimit to determine disk space, except when it has been exceeded */
976 if ((D.dqb_curblocks>D.dqb_bsoftlimit)
977 #if !defined(__FreeBSD__) && !defined(__OpenBSD__)
978 ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
982 *dsize = D.dqb_curblocks;
985 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
986 *dsize = D.dqb_bsoftlimit;
993 #if defined(VXFS_QUOTA)
995 /****************************************************************************
996 Try to get the disk space from Veritas disk quotas.
997 David Lee <T.D.Lee@durham.ac.uk> August 1999.
999 Background assumptions:
1000 Potentially under many Operating Systems. Initially Solaris 2.
1002 My guess is that Veritas is largely, though not entirely,
1003 independent of OS. So I have separated it out.
1005 There may be some details. For example, OS-specific "include" files.
1007 It is understood that HPUX 10 somehow gets Veritas quotas without
1008 any special effort; if so, this routine need not be compiled in.
1009 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
1012 It is understood that Veritas do not publicly support this ioctl interface.
1013 Rather their preference would be for the user (us) to call the native
1014 OS and then for the OS itself to call through to the VxFS filesystem.
1015 Presumably HPUX 10, see above, does this.
1018 Add your OS to "IFLIST" below.
1019 Get it to compile successfully:
1020 Almost certainly "include"s require attention: see SUNOS5.
1021 In the main code above, arrange for it to be called: see SUNOS5.
1024 ****************************************************************************/
1027 * This "if" is a list of ports:
1028 * if defined(OS1) || defined(OS2) || ...
1033 #include <sys/fs/vx_solaris.h>
1035 #include <sys/fs/vx_machdep.h>
1036 #include <sys/fs/vx_layout.h>
1037 #include <sys/fs/vx_quota.h>
1038 #include <sys/fs/vx_aioctl.h>
1039 #include <sys/fs/vx_ioctl.h>
1041 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
1043 uid_t user_id, euser_id;
1046 struct vx_quotctl quotabuf;
1047 struct vx_genioctl genbuf;
1052 * "name" may or may not include a trailing "/quotas".
1053 * Arranging consistency of calling here in "quotas.c" may not be easy and
1054 * it might be easier to examine and adjust it here.
1055 * Fortunately, VxFS seems not to mind at present.
1057 pstrcpy(qfname, name) ;
1058 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
1060 euser_id = geteuid();
1061 set_effective_uid(0);
1063 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
1064 if((file=sys_open(qfname, O_RDONLY,0))<0) {
1065 set_effective_uid(euser_id);
1068 genbuf.ioc_cmd = VX_QUOTACTL;
1069 genbuf.ioc_up = (void *) "abuf;
1071 quotabuf.cmd = VX_GETQUOTA;
1072 quotabuf.uid = euser_id;
1073 quotabuf.addr = (caddr_t) &D;
1074 ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
1077 set_effective_uid(euser_id);
1080 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
1084 /* If softlimit is zero, set it equal to hardlimit.
1087 if (D.dqb_bsoftlimit==0)
1088 D.dqb_bsoftlimit = D.dqb_bhardlimit;
1090 /* Use softlimit to determine disk space. A user exceeding the quota is told
1091 * that there's no space left. Writes might actually work for a bit if the
1092 * hardlimit is set higher than softlimit. Effectively the disk becomes
1093 * made of rubber latex and begins to expand to accommodate the user :-)
1095 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
1096 path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
1097 D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));
1099 if (D.dqb_bsoftlimit==0)
1102 *dsize = D.dqb_bsoftlimit;
1104 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
1106 *dsize = D.dqb_curblocks;
1108 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
1110 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
1111 path,(double)*bsize,(double)*dfree,(double)*dsize));
1116 #endif /* SUNOS5 || ... */
1118 #endif /* VXFS_QUOTA */
1120 #else /* WITH_QUOTAS */
1122 BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
1124 (*bsize) = 512; /* This value should be ignored */
1126 /* And just to be sure we set some values that hopefully */
1127 /* will be larger that any possible real-world value */
1128 (*dfree) = (SMB_BIG_UINT)-1;
1129 (*dsize) = (SMB_BIG_UINT)-1;
1131 /* As we have select not to use quotas, allways fail */
1134 #endif /* WITH_QUOTAS */
1136 #else /* HAVE_SYS_QUOTAS */
1137 /* wrapper to the new sys_quota interface
1138 this file should be removed later
1140 BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize)
1148 r=sys_get_quota(path, SMB_USER_QUOTA_TYPE, id, &D);
1150 /* Use softlimit to determine disk space, except when it has been exceeded */
1153 if (errno == EDQUOT) {
1155 *dsize =D.curblocks;
1158 goto try_group_quota;
1162 /* Use softlimit to determine disk space, except when it has been exceeded */
1164 (D.softlimit && D.curblocks >= D.softlimit) ||
1165 (D.hardlimit && D.curblocks >= D.hardlimit) ||
1166 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
1167 (D.ihardlimit && D.curinodes>=D.ihardlimit)
1170 *dsize = D.curblocks;
1171 } else if (D.softlimit==0 && D.hardlimit==0) {
1172 goto try_group_quota;
1174 if (D.softlimit == 0)
1175 D.softlimit = D.hardlimit;
1176 *dfree = D.softlimit - D.curblocks;
1177 *dsize = D.softlimit;
1183 #ifdef HAVE_GROUP_QUOTA
1186 r=sys_get_quota(path, SMB_GROUP_QUOTA_TYPE, id, &D);
1188 /* Use softlimit to determine disk space, except when it has been exceeded */
1191 if (errno == EDQUOT) {
1193 *dsize =D.curblocks;
1200 /* Use softlimit to determine disk space, except when it has been exceeded */
1202 (D.softlimit && D.curblocks >= D.softlimit) ||
1203 (D.hardlimit && D.curblocks >= D.hardlimit) ||
1204 (D.isoftlimit && D.curinodes >= D.isoftlimit) ||
1205 (D.ihardlimit && D.curinodes>=D.ihardlimit)
1208 *dsize = D.curblocks;
1209 } else if (D.softlimit==0 && D.hardlimit==0) {
1212 if (D.softlimit == 0)
1213 D.softlimit = D.hardlimit;
1214 *dfree = D.softlimit - D.curblocks;
1215 *dsize = D.softlimit;
1219 #else /* HAVE_GROUP_QUOTA */
1221 #endif /* HAVE_GROUP_QUOTA */
1223 #endif /* HAVE_SYS_QUOTAS */