From: neilbrown Date: Wed, 21 Dec 2005 04:01:08 +0000 (+0000) Subject: Handle new-style quotactl. X-Git-Tag: nfs-utils-1-0-8~41 X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=commitdiff_plain;h=a021f1f459d8fd471123848c8f83a73a5fc1629e Handle new-style quotactl. --- diff --git a/ChangeLog b/ChangeLog index 6440b4d..916ba0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2005-12-21 NeilBrown + utils/rquotad/rquota_server.c: Detect and handle both old-style + (2.4) and new-style(2.6) quotactl. + 2005-12-20 Kevin Coffman NeilBrown Substantial Makefile/configure rewrite. Run 'autogen.sh' to create "Makefile.in" etc. diff --git a/utils/rquotad/rquota_server.c b/utils/rquotad/rquota_server.c index 32e5cba..109c94e 100644 --- a/utils/rquotad/rquota_server.c +++ b/utils/rquotad/rquota_server.c @@ -22,14 +22,20 @@ #ifdef HAVE_CONFIG_H #include #endif -#define _LINUX_QUOTA_VERSION 1 #include #include "rquota.h" #include #include #include +/* Unfortunately we cannot trust sys/quota.h to have + * what we need, either the old interface could be missing + * (SLES9) or the new (SLES8 and others). + * So we will just put it explicitly below + */ +#if 0 #include +#endif #include #include #include @@ -50,6 +56,47 @@ #define BLOCK_SIZE 1024 #endif +#define MAXQUOTAS 2 +#define USRQUOTA 0 /* element used for user quotas */ +#define GRPQUOTA 1 /* element used for group quotas */ + +struct dqblk { + u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ + u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */ + u_int32_t dqb_curblocks; /* current block count */ + u_int32_t dqb_ihardlimit; /* maximum # allocated inodes */ + u_int32_t dqb_isoftlimit; /* preferred inode limit */ + u_int32_t dqb_curinodes; /* current # allocated inodes */ + time_t dqb_btime; /* time limit for excessive disk use */ + time_t dqb_itime; /* time limit for excessive files */ +}; + +struct if_dqblk { + u_int64_t dqb_bhardlimit; + u_int64_t dqb_bsoftlimit; + u_int64_t dqb_curspace; + u_int64_t dqb_ihardlimit; + u_int64_t dqb_isoftlimit; + u_int64_t dqb_curinodes; + u_int64_t dqb_btime; + u_int64_t dqb_itime; + u_int32_t dqb_valid; +}; + +#define SUBCMDMASK 0x00ff +#define SUBCMDSHIFT 8 +#define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK)) + +#define Q_GETQUOTA 0x0300 /* get limits and usage */ +#define Q_SETQUOTA 0x0400 /* set limits and usage */ + +#define Q_GETFMT 0x800004 /* get quota format used on given filesystem */ +#define Q_GETQUOTA_NEW 0x800007 /* get user quota structure */ +#define Q_SETQUOTA_NEW 0x800008 /* set user quota structure */ +#define dqoff(UID) ((loff_t)((UID) * sizeof (struct dqblk))) + +extern int quotactl (int __cmd, const char *__special, int __id, + caddr_t __addr) __THROW; /* * Global unix authentication credentials. */ @@ -75,12 +122,12 @@ getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp) ext_getquota_args *ext_args; } arguments; FILE *fp; - struct dqblk dq_dqb; struct mntent *mnt; char *pathname, *qfpathname; int fd, err, id, type; struct stat stm, stn; struct rquota *rquota; + struct if_dqblk dqb; /* * First check authentication. @@ -134,32 +181,53 @@ getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp) result.getquota_rslt_u.gqr_rquota.rq_bsize = BLOCK_SIZE; if (hasquota(mnt, type, &qfpathname)) { - if ((err = quotactl(QCMD(Q_GETQUOTA, type), mnt->mnt_fsname, - id, (caddr_t)&dq_dqb)) == -1 - && !(flags & ACTIVE)) { - if ((fd = open(qfpathname, O_RDONLY)) < 0) - { - free(qfpathname); - continue; - } - free(qfpathname); - lseek(fd, (long) dqoff(id), L_SET); - switch (read(fd, &dq_dqb, sizeof(struct dqblk))) { - case 0:/* EOF */ - /* - * Convert implicit 0 quota (EOF) into an - * explicit one (zero'ed dqblk) - */ - memset((caddr_t)&dq_dqb, 0, sizeof(struct dqblk)); - break; - case sizeof(struct dqblk): /* OK */ - break; - default: /* ERROR */ - close(fd); - continue; - } - close(fd); - } + int fmt; + if (quotactl(QCMD(Q_GETFMT, type), mnt->mnt_fsname, 0, (caddr_t)&fmt)==0) { + /* new style interface + * Don't bother trying to read from the file + */ + err = quotactl(QCMD(Q_GETQUOTA_NEW, type), + mnt->mnt_fsname, id, (caddr_t)&dqb); + if (err) memset(&dqb, 0, sizeof(dqb)); + } else { + /* old style */ + struct dqblk dq_dqb; + + if ((err = quotactl(QCMD(Q_GETQUOTA, type), mnt->mnt_fsname, + id, (caddr_t)&dq_dqb)) == -1 + && !(flags & ACTIVE)) { + if ((fd = open(qfpathname, O_RDONLY)) < 0) + { + free(qfpathname); + continue; + } + free(qfpathname); + lseek(fd, (long) dqoff(id), L_SET); + switch (read(fd, &dq_dqb, sizeof(struct dqblk))) { + case 0:/* EOF */ + /* + * Convert implicit 0 quota (EOF) into an + * explicit one (zero'ed dqblk) + */ + memset((caddr_t)&dq_dqb, 0, sizeof(struct dqblk)); + break; + case sizeof(struct dqblk): /* OK */ + break; + default: /* ERROR */ + close(fd); + continue; + } + close(fd); + } + dqb.dqb_bhardlimit = dq_dqb.dqb_bhardlimit; + dqb.dqb_bsoftlimit = dq_dqb.dqb_bsoftlimit; + dqb.dqb_curspace = dq_dqb.dqb_curblocks * 1024; + dqb.dqb_ihardlimit = dq_dqb.dqb_ihardlimit; + dqb.dqb_isoftlimit = dq_dqb.dqb_isoftlimit; + dqb.dqb_curinodes = dq_dqb.dqb_curinodes; + dqb.dqb_btime = dq_dqb.dqb_btime; + dqb.dqb_itime = dq_dqb.dqb_itime; + } endmntent(fp); if (err && (flags & ACTIVE)) { @@ -175,14 +243,14 @@ getquota_rslt *getquotainfo(int flags, caddr_t *argp, struct svc_req *rqstp) */ rquota = &result.getquota_rslt_u.gqr_rquota; - rquota->rq_bhardlimit = dq_dqb.dqb_bhardlimit; - rquota->rq_bsoftlimit = dq_dqb.dqb_bsoftlimit;; - rquota->rq_curblocks = dq_dqb.dqb_curblocks; - rquota->rq_fhardlimit = dq_dqb.dqb_ihardlimit; - rquota->rq_fsoftlimit = dq_dqb.dqb_isoftlimit; - rquota->rq_curfiles = dq_dqb.dqb_curinodes; - rquota->rq_btimeleft = dq_dqb.dqb_btime; - rquota->rq_ftimeleft = dq_dqb.dqb_itime; + rquota->rq_bhardlimit = dqb.dqb_bhardlimit; + rquota->rq_bsoftlimit = dqb.dqb_bsoftlimit;; + rquota->rq_curblocks = dqb.dqb_curspace/1024; + rquota->rq_fhardlimit = dqb.dqb_ihardlimit; + rquota->rq_fsoftlimit = dqb.dqb_isoftlimit; + rquota->rq_curfiles = dqb.dqb_curinodes; + rquota->rq_btimeleft = dqb.dqb_btime; + rquota->rq_ftimeleft = dqb.dqb_itime; return(&result); }