#ifdef LINUX
-#ifdef __KERNEL__
-# undef __KERNEL__
-# include <sys/quota.h>
-# define __KERNEL__
-#else
-# include <sys/quota.h>
-#endif
+#include <sys/types.h>
+#include <asm/types.h>
+#include <sys/quota.h>
#include <mntent.h>
+#include <linux/unistd.h>
+
+_syscall4(int, quotactl, int, cmd, const char *, special, int, id, caddr_t, addr);
/****************************************************************************
try to get the disk space from disk quotas (LINUX version)
****************************************************************************/
-/*
-If you didn't make the symlink to the quota package, too bad :(
-*/
-#include "quota/quotactl.c"
-#include "quota/hasquota.c"
+
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
{
uid_t euser_id;
+ int r;
struct dqblk D;
struct stat S;
- dev_t devno ;
- struct mntent *mnt;
FILE *fp;
- int found ;
- int qcmd, fd ;
- char *qfpathname;
+ struct mntent *mnt;
+ int devno;
+ int found;
/* find the block device file */
- if ( stat(path, &S) == -1 )
+ if ( stat(path, &S) == -1 ) {
return(False) ;
+ }
devno = S.st_dev ;
fp = setmntent(MOUNTED,"r");
found = False ;
- while ((mnt = getmntent(fp)) != (struct mntent *) 0) {
+ while ((mnt = getmntent(fp))) {
if ( stat(mnt->mnt_dir,&S) == -1 )
continue ;
if (S.st_dev == devno) {
}
endmntent(fp) ;
- if ( ! found )
- return(False) ;
-
- qcmd = QCMD(Q_GETQUOTA, USRQUOTA);
-
- if (hasmntopt(mnt, MNTOPT_NOAUTO) || hasmntopt(mnt, MNTOPT_NOQUOTA))
- return(False) ;
-
- if (!hasquota(mnt, USRQUOTA, &qfpathname))
- return(False) ;
-
- euser_id = geteuid();
- seteuid(0);
-
- if (quotactl(qcmd, mnt->mnt_fsname, euser_id, (caddr_t)&D) != 0) {
- if ((fd = open(qfpathname, O_RDONLY)) < 0) {
- seteuid(euser_id);
+ if (!found) {
return(False);
}
- lseek(fd, (long) dqoff(euser_id), L_SET);
- switch (read(fd, &D, sizeof(struct dqblk))) {
- case 0:/* EOF */
- memset((caddr_t)&D, 0, sizeof(struct dqblk));
- break;
- case sizeof(struct dqblk): /* OK */
- break;
- default: /* ERROR */
- close(fd);
+
+ euser_id=geteuid();
+ seteuid(0);
+ r=quotactl(QCMD(Q_GETQUOTA,USRQUOTA), mnt->mnt_fsname, euser_id, (caddr_t)&D);
seteuid(euser_id);
- return(False);
+
+ /* Use softlimit to determine disk space, except when it has been exceeded */
+ *bsize = 1024;
+ if (r)
+ {
+ if (errno == EDQUOT)
+ {
+ *dfree =0;
+ *dsize =D.dqb_curblocks;
+ return (True);
}
+ else return(False);
}
- seteuid(euser_id);
- *bsize=1024;
-
- if (D.dqb_bsoftlimit==0)
- return(False);
- if ((D.dqb_curblocks>D.dqb_bsoftlimit)||(D.dqb_curinodes>D.dqb_isoftlimit))
+ /* Use softlimit to determine disk space, except when it has been exceeded */
+ if (
+ (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
+ (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
+ (D.dqb_isoftlimit && D.dqb_curinodes>=D.dqb_isoftlimit) ||
+ (D.dqb_ihardlimit && D.dqb_curinodes>=D.dqb_ihardlimit)
+ )
{
*dfree = 0;
*dsize = D.dqb_curblocks;
}
+ else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
+ {
+ return(False);
+ }
else {
*dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
*dsize = D.dqb_bsoftlimit;
ret = quotactl(Q_GETQUOTA, name, euser_id, &D);
#endif
- setuid(user_id); /* Restore the original UID status */
+ setuid(user_id); /* Restore the original uid status. */
seteuid(euser_id);
if (ret < 0) {
return(True);
}
+
+#elif defined(OSF1)
+#include <ufs/quota.h>
+
+/****************************************************************************
+try to get the disk space from disk quotas - OFS1 version
+****************************************************************************/
+BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
+{
+ uid_t user_id, euser_id;
+ int r, save_errno;
+ struct dqblk D;
+ struct stat S;
+
+ euser_id = geteuid();
+ user_id = getuid();
+
+ setreuid(euser_id, -1);
+ r= quotactl(path,QCMD(Q_GETQUOTA, USRQUOTA),euser_id,(char *) &D);
+ if (r)
+ save_errno = errno;
+
+ if (setreuid(user_id, -1) == -1)
+ DEBUG(5,("Unable to reset uid to %d\n", user_id));
+
+ *bsize = DEV_BSIZE;
+
+ if (r)
+ {
+ if (save_errno == EDQUOT) // disk quota exceeded
+ {
+ *dfree = 0;
+ *dsize = D.dqb_curblocks;
+ return (True);
+ }
+ else
+ return (False);
+ }
+
+ /* Use softlimit to determine disk space, except when it has been exceeded */
+
+ if (D.dqb_bsoftlimit==0)
+ return(False);
+
+ if ((D.dqb_curblocks>D.dqb_bsoftlimit)) {
+ *dfree = 0;
+ *dsize = D.dqb_curblocks;
+ } else {
+ *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
+ *dsize = D.dqb_bsoftlimit;
+ }
+ return (True);
+}
+
+#elif defined (SGI6)
+/****************************************************************************
+try to get the disk space from disk quotas (IRIX 6.2 version)
+****************************************************************************/
+
+#include <sys/quota.h>
+#include <mntent.h>
+
+BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
+{
+ uid_t euser_id;
+ int r;
+ struct dqblk D;
+ struct fs_disk_quota F;
+ struct stat S;
+ FILE *fp;
+ struct mntent *mnt;
+ int devno;
+ int found;
+
+ /* find the block device file */
+
+ if ( stat(path, &S) == -1 ) {
+ return(False) ;
+ }
+
+ devno = S.st_dev ;
+
+ fp = setmntent(MOUNTED,"r");
+ found = False ;
+
+ while ((mnt = getmntent(fp))) {
+ if ( stat(mnt->mnt_dir,&S) == -1 )
+ continue ;
+ if (S.st_dev == devno) {
+ found = True ;
+ break ;
+ }
+ }
+ endmntent(fp) ;
+
+ if (!found) {
+ return(False);
+ }
+
+ euser_id=geteuid();
+ seteuid(0);
+
+ /* Use softlimit to determine disk space, except when it has been exceeded */
+
+ *bsize = 512;
+
+ if ( 0 == strcmp ( mnt->mnt_type, "efs" ))
+ {
+ r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);
+
+ if (r==-1)
+ return(False);
+
+ /* Use softlimit to determine disk space, except when it has been exceeded */
+ if (
+ (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
+ (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
+ (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) ||
+ (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit)
+ )
+ {
+ *dfree = 0;
+ *dsize = D.dqb_curblocks;
+ }
+ else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
+ {
+ return(False);
+ }
+ else
+ {
+ *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
+ *dsize = D.dqb_bsoftlimit;
+ }
+
+ }
+ else if ( 0 == strcmp ( mnt->mnt_type, "xfs" ))
+ {
+ r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);
+
+ if (r==-1)
+ return(False);
+
+ /* Use softlimit to determine disk space, except when it has been exceeded */
+ if (
+ (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) ||
+ (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) ||
+ (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) ||
+ (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit)
+ )
+ {
+ /*
+ * Fixme!: these are __uint64_t, this may truncate values
+ */
+ *dfree = 0;
+ *dsize = (int) F.d_bcount;
+ }
+ else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0)
+ {
+ return(False);
+ }
+ else
+ {
+ *dfree = (int)(F.d_blk_softlimit - F.d_bcount);
+ *dsize = (int)F.d_blk_softlimit;
+ }
+
+ }
+ else
+ return(False);
+
+ return (True);
+
+}
+
#else
#ifdef __FreeBSD__
#include <ufs/ufs/quota.h>
-#else
+#include <machine/param.h>
+#elif AIX
+/* AIX quota patch from Ole Holm Nielsen <ohnielse@fysik.dtu.dk> */
+#include <jfs/quota.h>
+/* AIX 4.X: Rename members of the dqblk structure (ohnielse@fysik.dtu.dk) */
+#define dqb_curfiles dqb_curinodes
+#define dqb_fhardlimit dqb_ihardlimit
+#define dqb_fsoftlimit dqb_isoftlimit
+#else /* !__FreeBSD__ && !AIX */
#include <sys/quota.h>
#include <devnm.h>
#endif
****************************************************************************/
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
{
- uid_t user_id, euser_id;
+ uid_t euser_id;
int r;
- char dev_disk[256];
struct dqblk D;
+#if !defined(__FreeBSD__) && !defined(AIX)
+ char dev_disk[256];
struct stat S;
-#ifndef __FreeBSD__
/* find the block device file */
if ((stat(path, &S)<0) ||
(devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) return (False);
euser_id = geteuid();
#ifdef USE_SETRES
- /* for HPUX, real uid must be same as euid to execute quotactl for euid */
- user_id = getuid();
- setresuid(euser_id,-1,-1);
- r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
- if (setresuid(user_id,-1,-1))
- DEBUG(5,("Unable to reset uid to %d\n", user_id));
-#else
+ {
+ uid_t user_id;
+
+ /* for HPUX, real uid must be same as euid to execute quotactl for euid */
+ user_id = getuid();
+ setresuid(euser_id,-1,-1);
+ r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
+ if (setresuid(user_id,-1,-1))
+ DEBUG(5,("Unable to reset uid to %d\n", user_id));
+ }
+#else /* USE_SETRES */
#if defined(__FreeBSD__)
- r= quotactl(path,Q_GETQUOTA,euser_id,(char *) &D);
-#else
+ {
+ /* FreeBSD patches from Marty Moll <martym@arbor.edu> */
+ uid_t user_id;
+ gid_t egrp_id;
+
+ /* Need to be root to get quotas in FreeBSD */
+ user_id = getuid();
+ egrp_id = getegid();
+ setuid(0);
+ seteuid(0);
+ r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
+
+ /* As FreeBSD has group quotas, if getting the user
+ quota fails, try getting the group instead. */
+ if (r)
+ r= quotactl(path,QCMD(Q_GETQUOTA,GRPQUOTA),egrp_id,(char *) &D);
+ setuid(user_id);
+ seteuid(euser_id);
+ }
+#elif defined(AIX)
+ /* AIX has both USER and GROUP quotas:
+ Get the USER quota (ohnielse@fysik.dtu.dk) */
+ r= quotactl(path,QCMD(Q_GETQUOTA,USRQUOTA),euser_id,(char *) &D);
+#else /* !__FreeBSD__ && !AIX */
r=quotactl(Q_GETQUOTA, dev_disk, euser_id, &D);
-#endif
-#endif
+#endif /* !__FreeBSD__ && !AIX */
+#endif /* USE_SETRES */
/* Use softlimit to determine disk space, except when it has been exceeded */
+#if defined(__FreeBSD__)
+ *bsize = DEV_BSIZE;
+#else /* !__FreeBSD__ */
*bsize = 1024;
+#endif /*!__FreeBSD__ */
+
if (r)
{
if (errno == EDQUOT)
/* Use softlimit to determine disk space, except when it has been exceeded */
if ((D.dqb_curblocks>D.dqb_bsoftlimit)
#if !defined(__FreeBSD__)
-||(D.dqb_curfiles>D.dqb_fsoftlimit)
+||((D.dqb_curfiles>D.dqb_fsoftlimit) && (D.dqb_fsoftlimit != 0))
#endif
) {
*dfree = 0;