2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1992-1998
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.
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.
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.
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
31 extern int DEBUGLEVEL;
33 #if defined(VXFS_QUOTA)
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>
40 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
42 #endif /* VXFS_QUOTA */
46 #include <sys/types.h>
47 #include <asm/types.h>
48 #include <sys/quota.h>
51 #include <linux/unistd.h>
53 _syscall4(int, quotactl, int, cmd, const char *, special, int, id, caddr_t, addr);
55 /****************************************************************************
56 try to get the disk space from disk quotas (LINUX version)
57 ****************************************************************************/
59 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
72 /* find the block device file */
74 if ( sys_stat(path, &S) == -1 ) {
80 fp = setmntent(MOUNTED,"r");
83 while ((mnt = getmntent(fp))) {
84 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
86 if (S.st_dev == devno) {
99 r=quotactl(QCMD(Q_GETQUOTA,USRQUOTA), mnt->mnt_fsname, euser_id, (caddr_t)&D);
102 /* Use softlimit to determine disk space, except when it has been exceeded */
109 *dsize =D.dqb_curblocks;
114 /* Use softlimit to determine disk space, except when it has been exceeded */
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)
123 *dsize = D.dqb_curblocks;
125 else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
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;
140 #include <sys/quota.h>
143 /****************************************************************************
144 try to get the disk space from disk quotas (CRAY VERSION)
145 ****************************************************************************/
147 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
151 SMB_STRUCT_STAT sbuf;
153 static SMB_DEV_T devno_cached = 0 ;
155 struct q_request request ;
156 struct qf_header header ;
157 static int quota_default = 0 ;
160 if ( sys_stat(path,&sbuf) == -1 )
163 devno = sbuf.st_dev ;
165 if ( devno != devno_cached ) {
167 devno_cached = devno ;
169 if ((fd = setmntent(KMTAB)) == NULL)
174 while ((mnt = getmntent(fd)) != NULL) {
176 if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
179 if (sbuf.st_dev == devno) {
188 pstrcpy(name,mnt->mnt_dir) ;
195 request.qf_magic = QF_MAGIC ;
196 request.qf_entry.id = geteuid() ;
198 if (quotactl(name, Q_GETQUOTA, &request) == -1)
201 if ( ! request.user )
204 if ( request.qf_entry.user_q.f_quota == QFV_DEFAULT ) {
206 if ( ! quota_default ) {
208 if ( quotactl(name, Q_GETHEADER, &header) == -1 )
211 quota_default = header.user_h.def_fq ;
214 *dfree = quota_default ;
216 }else if ( request.qf_entry.user_q.f_quota == QFV_PREVENT ) {
222 *dfree = request.qf_entry.user_q.f_quota ;
226 *dsize = request.qf_entry.user_q.f_use ;
228 if ( *dfree < *dsize )
233 *bsize = 4096 ; /* Cray blocksize */
240 #elif defined(SUNOS5) || defined(SUNOS4)
243 #include <sys/param.h>
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>
255 /****************************************************************************
256 Allows querying of remote hosts for quotas on NFS mounted shares.
257 Supports normal NFS and AMD mounts.
258 Alan Romeril <a.romeril@ic.ac.uk> July 2K.
259 ****************************************************************************/
262 #include <rpc/types.h>
263 #include <rpcsvc/rquota.h>
264 #include <rpc/nettype.h>
267 static int quotastat;
269 static int xdr_getquota_args(XDR *xdrsp, struct getquota_args *args)
271 if (!xdr_string(xdrsp, &args->gqa_pathp, RQ_PATHLEN ))
273 if (!xdr_int(xdrsp, &args->gqa_uid))
278 static int xdr_getquota_rslt(XDR *xdrsp, struct getquota_rslt *gqr)
285 if (!xdr_int(xdrsp, "astat)) {
286 DEBUG(6,("nfs_quotas: Status bad or zero\n"));
289 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsize)) {
290 DEBUG(6,("nfs_quotas: Block size bad or zero\n"));
293 if (!xdr_bool(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_active)) {
294 DEBUG(6,("nfs_quotas: Active bad or zero\n"));
297 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bhardlimit)) {
298 DEBUG(6,("nfs_quotas: Hardlimit bad or zero\n"));
301 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_bsoftlimit)) {
302 DEBUG(6,("nfs_quotas: Softlimit bad or zero\n"));
305 if (!xdr_int(xdrsp, &gqr->getquota_rslt_u.gqr_rquota.rq_curblocks)) {
306 DEBUG(6,("nfs_quotas: Currentblocks bad or zero\n"));
312 /* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */
313 static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
315 uid_t uid = euser_id;
317 char *mnttype = nfspath;
319 struct getquota_rslt gqr;
320 struct getquota_args args;
321 char *cutstr, *pathname, *host, *testpath;
323 static struct timeval timeout = {2,0};
324 enum clnt_stat clnt_stat;
326 len=strcspn(mnttype, ":");
327 pathname=strstr(mnttype, ":");
328 cutstr = (char *) malloc(sizeof(char) * len );
332 host = strncat(cutstr,mnttype, sizeof(char) * len );
333 DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
334 DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
335 testpath=strchr(mnttype, ':');
336 args.gqa_pathp = testpath+1;
339 DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));
341 if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) != NULL) {
342 clnt->cl_auth = authunix_create_default();
343 DEBUG(9,("nfs_quotas: auth_success\n"));
345 clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, xdr_getquota_args, (caddr_t)&args, xdr_getquota_rslt, (caddr_t)&gqr, timeout);
346 if (clnt_stat == RPC_SUCCESS)
347 DEBUG(9,("nfs_quotas: rpccall_success\n"));
352 * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
353 * no quota set, and 3 if no permission to get the quota. If 0 or 3 return
354 * something sensible.
357 if (quotastat == 1) {
358 DEBUG(9,("nfs_quotas: Good quota data\n"));
359 D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
360 D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
361 D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
364 if (quotastat == 0 || quotastat == 3) {
365 D.dqb_bsoftlimit = 1;
367 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat ));
370 if (quotastat == 2) {
371 DEBUG(9,("nfs_quotas: Remote Quotas Failed! Error \"%i\" \n", quotastat ));
372 auth_destroy(clnt->cl_auth);
378 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",
380 gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
381 gqr.getquota_rslt_u.gqr_rquota.rq_active,
382 gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
383 gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
384 gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));
386 *bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
387 *dsize = D.dqb_bsoftlimit;
389 if (D.dqb_curblocks == D.dqb_curblocks == 1)
392 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
394 *dsize = D.dqb_curblocks;
396 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
398 auth_destroy(clnt->cl_auth);
401 DEBUG(5,("nfs_quotas: For path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));
404 DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
409 /****************************************************************************
410 try to get the disk space from disk quotas (SunOS & Solaris2 version)
411 Quota code by Peter Urbanec (amiga@cse.unsw.edu.au).
412 ****************************************************************************/
414 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
420 struct quotctl command;
422 static struct mnttab mnt;
430 SMB_STRUCT_STAT sbuf;
432 static SMB_DEV_T devno_cached = 0 ;
435 euser_id = geteuid();
437 if ( sys_stat(path,&sbuf) == -1 )
440 devno = sbuf.st_dev ;
441 DEBUG(5,("disk_quotas: looking for path \"%s\" devno=%x\n", path,devno));
442 if ( devno != devno_cached ) {
443 devno_cached = devno ;
445 if ((fd = sys_fopen(MNTTAB, "r")) == NULL)
449 slprintf(devopt, sizeof(devopt) - 1, "dev=%x", devno);
450 while (getmntent(fd, &mnt) == 0) {
451 if( !hasmntopt(&mnt, devopt) )
454 DEBUG(5,("disk_quotas: testing \"%s\" %s\n", mnt.mnt_mountp,devopt));
456 /* quotas are only on vxfs, UFS or NFS */
457 if ( strcmp( mnt.mnt_fstype, MNTTYPE_UFS ) == 0 ||
458 strcmp( mnt.mnt_fstype, "nfs" ) == 0 ||
459 strcmp( mnt.mnt_fstype, "vxfs" ) == 0 ) {
465 pstrcpy(name,mnt.mnt_mountp) ;
466 pstrcat(name,"/quotas") ;
469 if ((fd = setmntent(MOUNTED, "r")) == NULL)
473 while ((mnt = getmntent(fd)) != NULL) {
474 if ( sys_stat(mnt->mnt_dir,&sbuf) == -1 )
476 DEBUG(5,("disk_quotas: testing \"%s\" devno=%o\n", mnt->mnt_dir,sbuf.st_dev));
477 if (sbuf.st_dev == devno) {
483 pstrcpy(name,mnt->mnt_fsname) ;
492 set_effective_uid(0);
495 if ( strcmp( mnt.mnt_fstype, "nfs" ) == 0) {
497 DEBUG(5,("disk_quotas: looking for mountpath (NFS) \"%s\"\n", mnt.mnt_special));
498 retval = nfs_quotas(mnt.mnt_special, euser_id, bsize, dfree, dsize);
503 DEBUG(5,("disk_quotas: looking for quotas file \"%s\"\n", name));
504 if((file=sys_open(name, O_RDONLY,0))<0) {
508 command.op = Q_GETQUOTA;
509 command.uid = euser_id;
510 command.addr = (caddr_t) &D;
511 ret = ioctl(file, Q_QUOTACTL, &command);
514 DEBUG(5,("disk_quotas: trying quotactl on device \"%s\"\n", name));
515 ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
521 DEBUG(5,("disk_quotas ioctl (Solaris) failed. Error = %s\n", strerror(errno) ));
523 #if defined(SUNOS5) && defined(VXFS_QUOTA)
524 /* If normal quotactl() fails, try vxfs private calls */
525 set_effective_uid(euser_id);
526 DEBUG(5,("disk_quotas: mount type \"%s\"\n", mnt.mnt_fstype));
527 if ( 0 == strcmp ( mnt.mnt_fstype, "vxfs" )) {
529 retval = disk_quotas_vxfs(name, path, bsize, dfree, dsize);
537 /* If softlimit is zero, set it equal to hardlimit.
540 if (D.dqb_bsoftlimit==0)
541 D.dqb_bsoftlimit = D.dqb_bhardlimit;
543 /* Use softlimit to determine disk space. A user exceeding the quota is told
544 * that there's no space left. Writes might actually work for a bit if the
545 * hardlimit is set higher than softlimit. Effectively the disk becomes
546 * made of rubber latex and begins to expand to accommodate the user :-)
549 if (D.dqb_bsoftlimit==0)
552 *dsize = D.dqb_bsoftlimit;
554 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
556 *dsize = D.dqb_curblocks;
558 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
560 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
561 path,(double)*bsize,(double)*dfree,(double)*dsize));
568 #include <ufs/quota.h>
570 /****************************************************************************
571 try to get the disk space from disk quotas - OSF1 version
572 ****************************************************************************/
574 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
582 * This code presumes that OSF1 will only
583 * give out quota info when the real uid
584 * matches the effective uid. JRA.
586 euser_id = geteuid();
588 if (set_re_uid() != 0) return False;
590 r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D);
601 if (save_errno == EDQUOT) /* disk quota exceeded */
604 *dsize = D.dqb_curblocks;
611 /* If softlimit is zero, set it equal to hardlimit.
614 if (D.dqb_bsoftlimit==0)
615 D.dqb_bsoftlimit = D.dqb_bhardlimit;
617 /* Use softlimit to determine disk space, except when it has been exceeded */
619 if (D.dqb_bsoftlimit==0)
622 if ((D.dqb_curblocks>D.dqb_bsoftlimit)) {
624 *dsize = D.dqb_curblocks;
626 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
627 *dsize = D.dqb_bsoftlimit;
632 #elif defined (IRIX6)
633 /****************************************************************************
634 try to get the disk space from disk quotas (IRIX 6.2 version)
635 ****************************************************************************/
637 #include <sys/quota.h>
640 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
645 struct fs_disk_quota F;
652 /* find the block device file */
654 if ( sys_stat(path, &S) == -1 ) {
660 fp = setmntent(MOUNTED,"r");
663 while ((mnt = getmntent(fp))) {
664 if ( sys_stat(mnt->mnt_dir,&S) == -1 )
666 if (S.st_dev == devno) {
679 set_effective_uid(0);
681 /* Use softlimit to determine disk space, except when it has been exceeded */
685 if ( 0 == strcmp ( mnt->mnt_type, "efs" ))
687 r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);
694 /* Use softlimit to determine disk space, except when it has been exceeded */
696 (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
697 (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
698 (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) ||
699 (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit)
703 *dsize = D.dqb_curblocks;
705 else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
711 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
712 *dsize = D.dqb_bsoftlimit;
716 else if ( 0 == strcmp ( mnt->mnt_type, "xfs" ))
718 r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);
725 /* Use softlimit to determine disk space, except when it has been exceeded */
727 (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) ||
728 (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) ||
729 (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) ||
730 (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit)
736 else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0)
742 *dfree = (F.d_blk_softlimit - F.d_bcount);
743 *dsize = F.d_blk_softlimit;
759 #if defined(__FreeBSD__) || defined(__OpenBSD__)
760 #include <ufs/ufs/quota.h>
761 #include <machine/param.h>
763 /* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
764 #include <jfs/quota.h>
765 /* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
766 #define dqb_curfiles dqb_curinodes
767 #define dqb_fhardlimit dqb_ihardlimit
768 #define dqb_fsoftlimit dqb_isoftlimit
769 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
770 #include <sys/quota.h>
774 /****************************************************************************
775 try to get the disk space from disk quotas - default version
776 ****************************************************************************/
778 BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
783 #if !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__)
786 /* find the block device file */
787 if ((sys_stat(path, &S)<0) ||
788 (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False);
791 euser_id = geteuid();
794 /* for HPUX, real uid must be same as euid to execute quotactl for euid */
796 if (set_re_uid() != 0) return False;
798 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
802 #if defined(__FreeBSD__) || defined(__OpenBSD__)
804 /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
808 set_effective_uid(0);
811 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
813 /* As FreeBSD has group quotas, if getting the user
814 quota fails, try getting the group instead. */
816 r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
822 /* AIX has both USER and GROUP quotas:
823 Get the USER quota (ohnielse@fysik.dtu.dk) */
824 r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
825 #else /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
826 r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
827 #endif /* !__FreeBSD__ && !AIX && !__OpenBSD__ */
830 /* Use softlimit to determine disk space, except when it has been exceeded */
831 #if defined(__FreeBSD__) || defined(__OpenBSD__)
833 #else /* !__FreeBSD__ && !__OpenBSD__ */
835 #endif /*!__FreeBSD__ && !__OpenBSD__ */
842 *dsize =D.dqb_curblocks;
848 /* If softlimit is zero, set it equal to hardlimit.
851 if (D.dqb_bsoftlimit==0)
852 D.dqb_bsoftlimit = D.dqb_bhardlimit;
854 if (D.dqb_bsoftlimit==0)
856 /* Use softlimit to determine disk space, except when it has been exceeded */
857 if ((D.dqb_curblocks>D.dqb_bsoftlimit)
858 #if !defined(__FreeBSD__) && !defined(__OpenBSD__)
859 ||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
863 *dsize = D.dqb_curblocks;
866 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
867 *dsize = D.dqb_bsoftlimit;
874 #if defined(VXFS_QUOTA)
876 /****************************************************************************
877 Try to get the disk space from Veritas disk quotas.
878 David Lee <T.D.Lee@durham.ac.uk> August 1999.
880 Background assumptions:
881 Potentially under many Operating Systems. Initially Solaris 2.
883 My guess is that Veritas is largely, though not entirely,
884 independent of OS. So I have separated it out.
886 There may be some details. For example, OS-specific "include" files.
888 It is understood that HPUX 10 somehow gets Veritas quotas without
889 any special effort; if so, this routine need not be compiled in.
890 Dirk De Wachter <Dirk.DeWachter@rug.ac.be>
893 It is understood that Veritas do not publicly support this ioctl interface.
894 Rather their preference would be for the user (us) to call the native
895 OS and then for the OS itself to call through to the VxFS filesystem.
896 Presumably HPUX 10, see above, does this.
899 Add your OS to "IFLIST" below.
900 Get it to compile successfully:
901 Almost certainly "include"s require attention: see SUNOS5.
902 In the main code above, arrange for it to be called: see SUNOS5.
905 ****************************************************************************/
908 * This "if" is a list of ports:
909 * if defined(OS1) || defined(OS2) || ...
914 #include <sys/fs/vx_solaris.h>
916 #include <sys/fs/vx_machdep.h>
917 #include <sys/fs/vx_layout.h>
918 #include <sys/fs/vx_quota.h>
919 #include <sys/fs/vx_aioctl.h>
920 #include <sys/fs/vx_ioctl.h>
922 BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
924 uid_t user_id, euser_id;
927 struct vx_quotctl quotabuf;
928 struct vx_genioctl genbuf;
933 * "name" may or may not include a trailing "/quotas".
934 * Arranging consistency of calling here in "quotas.c" may not be easy and
935 * it might be easier to examine and adjust it here.
936 * Fortunately, VxFS seems not to mind at present.
938 pstrcpy(qfname, name) ;
939 /* pstrcat(qfname, "/quotas") ; */ /* possibly examine and adjust "name" */
941 euser_id = geteuid();
942 set_effective_uid(0);
944 DEBUG(5,("disk_quotas: looking for VxFS quotas file \"%s\"\n", qfname));
945 if((file=sys_open(qfname, O_RDONLY,0))<0) {
946 set_effective_uid(euser_id);
949 genbuf.ioc_cmd = VX_QUOTACTL;
950 genbuf.ioc_up = (void *) "abuf;
952 quotabuf.cmd = VX_GETQUOTA;
953 quotabuf.uid = euser_id;
954 quotabuf.addr = (caddr_t) &D;
955 ret = ioctl(file, VX_ADMIN_IOCTL, &genbuf);
958 set_effective_uid(euser_id);
961 DEBUG(5,("disk_quotas ioctl (VxFS) failed. Error = %s\n", strerror(errno) ));
965 /* If softlimit is zero, set it equal to hardlimit.
968 if (D.dqb_bsoftlimit==0)
969 D.dqb_bsoftlimit = D.dqb_bhardlimit;
971 /* Use softlimit to determine disk space. A user exceeding the quota is told
972 * that there's no space left. Writes might actually work for a bit if the
973 * hardlimit is set higher than softlimit. Effectively the disk becomes
974 * made of rubber latex and begins to expand to accommodate the user :-)
976 DEBUG(5,("disk_quotas for path \"%s\" block c/s/h %ld/%ld/%ld; file c/s/h %ld/%ld/%ld\n",
977 path, D.dqb_curblocks, D.dqb_bsoftlimit, D.dqb_bhardlimit,
978 D.dqb_curfiles, D.dqb_fsoftlimit, D.dqb_fhardlimit));
980 if (D.dqb_bsoftlimit==0)
983 *dsize = D.dqb_bsoftlimit;
985 if (D.dqb_curblocks > D.dqb_bsoftlimit) {
987 *dsize = D.dqb_curblocks;
989 *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
991 DEBUG(5,("disk_quotas for path \"%s\" returning bsize %.0f, dfree %.0f, dsize %.0f\n",
992 path,(double)*bsize,(double)*dfree,(double)*dsize));
997 #endif /* SUNOS5 || ... */
999 #endif /* VXFS_QUOTA */