diff options
-rw-r--r-- | lib/libc/sys/quotactl.2 | 22 | ||||
-rw-r--r-- | lib/libutil/quotafile.c | 34 | ||||
-rw-r--r-- | sys/ufs/ufs/quota.h | 2 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_quota.c | 39 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_vfsops.c | 4 | ||||
-rw-r--r-- | usr.bin/quota/Makefile | 1 | ||||
-rw-r--r-- | usr.sbin/repquota/repquota.c | 2 |
7 files changed, 80 insertions, 24 deletions
diff --git a/lib/libc/sys/quotactl.2 b/lib/libc/sys/quotactl.2 index 4b4dca5..ff3cb4b 100644 --- a/lib/libc/sys/quotactl.2 +++ b/lib/libc/sys/quotactl.2 @@ -84,7 +84,7 @@ and group identifiers (GRPQUOTA). The .Dq ufs specific commands are: -.Bl -tag -width Q_QUOTAOFFxx +.Bl -tag -width Q_GETQUOTASIZEx .It Dv Q_QUOTAON Enable disk quotas for the file system specified by .Fa path . @@ -110,6 +110,17 @@ and .Fa id arguments are unused. Only the super-user may turn quotas off. +.It Dv Q_GETQUOTASIZE +Get the wordsize used to represent the quotas for the user or group +(as determined by the command type). +Possible values are 32 for the old-style quota file +and 64 for the new-style quota file. +The +.Fa addr +argument is a pointer to an integer into which the size is stored. +The identifier +.Fa id +is not used. .It Dv Q_GETQUOTA Get disk quota limits and current usage for the user or group (as determined by the command type) with identifier @@ -177,9 +188,11 @@ The argument or the command type is invalid. In -.Dv Q_GETQUOTA -and +.Dv Q_GETQUOTASIZE , +.Dv Q_GETQUOTA , .Dv Q_SETQUOTA , +and +.Dv Q_SETUSE , quotas are not currently enabled for this file system. .Pp The @@ -208,7 +221,8 @@ Too many symbolic links were encountered in translating a pathname. .It Bq Er EROFS In .Dv Q_QUOTAON , -the quota file resides on a read-only file system. +either the file system on which quotas are to be enabled is mounted read-only +or the quota file resides on a read-only file system. .It Bq Er EIO An .Tn I/O diff --git a/lib/libutil/quotafile.c b/lib/libutil/quotafile.c index ab57d66..0fda5f6 100644 --- a/lib/libutil/quotafile.c +++ b/lib/libutil/quotafile.c @@ -129,11 +129,9 @@ quota_open(struct fstab *fs, int quotatype, int openflags) goto error; qf->dev = st.st_dev; serrno = hasquota(fs, quotatype, qf->qfname, sizeof(qf->qfname)); - qcmd = QCMD(Q_GETQUOTA, quotatype); - if (quotactl(fs->fs_file, qcmd, 0, &dqh) == 0) { - qf->wordsize = 64; + qcmd = QCMD(Q_GETQUOTASIZE, quotatype); + if (quotactl(qf->fsname, qcmd, 0, &qf->wordsize) == 0) return (qf); - } if (serrno == 0) { errno = EOPNOTSUPP; goto error; @@ -250,18 +248,22 @@ int quota_maxid(struct quotafile *qf) { struct stat st; + int maxid; if (stat(qf->qfname, &st) < 0) return (0); switch (qf->wordsize) { case 32: - return (st.st_size / sizeof(struct dqblk32) - 1); + maxid = st.st_size / sizeof(struct dqblk32) - 1; + break; case 64: - return (st.st_size / sizeof(struct dqblk64) - 2); + maxid = st.st_size / sizeof(struct dqblk64) - 2; + break; default: - return (0); + maxid = 0; + break; } - /* not reached */ + return (maxid > 0 ? maxid : 0); } static int @@ -395,10 +397,6 @@ quota_write_usage(struct quotafile *qf, struct dqblk *dqb, int id) struct dqblk dqbuf; int qcmd; - if ((qf->accmode & O_RDWR) != O_RDWR) { - errno = EBADF; - return (-1); - } if (qf->fd == -1) { qcmd = QCMD(Q_SETUSE, qf->quotatype); return (quotactl(qf->fsname, qcmd, id, dqb)); @@ -406,6 +404,10 @@ quota_write_usage(struct quotafile *qf, struct dqblk *dqb, int id) /* * Have to do read-modify-write of quota in file. */ + if ((qf->accmode & O_RDWR) != O_RDWR) { + errno = EBADF; + return (-1); + } if (quota_read(qf, &dqbuf, id) != 0) return (-1); /* @@ -443,10 +445,6 @@ quota_write_limits(struct quotafile *qf, struct dqblk *dqb, int id) struct dqblk dqbuf; int qcmd; - if ((qf->accmode & O_RDWR) != O_RDWR) { - errno = EBADF; - return (-1); - } if (qf->fd == -1) { qcmd = QCMD(Q_SETQUOTA, qf->quotatype); return (quotactl(qf->fsname, qcmd, id, dqb)); @@ -454,6 +452,10 @@ quota_write_limits(struct quotafile *qf, struct dqblk *dqb, int id) /* * Have to do read-modify-write of quota in file. */ + if ((qf->accmode & O_RDWR) != O_RDWR) { + errno = EBADF; + return (-1); + } if (quota_read(qf, &dqbuf, id) != 0) return (-1); /* diff --git a/sys/ufs/ufs/quota.h b/sys/ufs/ufs/quota.h index 82b0170..ca0dcce 100644 --- a/sys/ufs/ufs/quota.h +++ b/sys/ufs/ufs/quota.h @@ -88,6 +88,7 @@ #define Q_GETQUOTA 0x0700 /* get limits and usage (64-bit version) */ #define Q_SETQUOTA 0x0800 /* set limits and usage (64-bit version) */ #define Q_SETUSE 0x0900 /* set usage (64-bit version) */ +#define Q_GETQUOTASIZE 0x0A00 /* get bit-size of quota file fields */ /* * The following structure defines the format of the disk quota file @@ -235,6 +236,7 @@ int setuse32(struct thread *, struct mount *, u_long, int, void *); int getquota(struct thread *, struct mount *, u_long, int, void *); int setquota(struct thread *, struct mount *, u_long, int, void *); int setuse(struct thread *, struct mount *, u_long, int, void *); +int getquotasize(struct thread *, struct mount *, u_long, int, void *); vfs_quotactl_t ufs_quotactl; #else /* !_KERNEL */ diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index 5b1da50..c516189 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -508,6 +508,9 @@ quotaon(struct thread *td, struct mount *mp, int type, void *fname) if (error) return (error); + if (mp->mnt_flag & MNT_RDONLY) + return (EROFS); + ump = VFSTOUFS(mp); dq = NODQUOT; @@ -534,7 +537,9 @@ quotaon(struct thread *td, struct mount *mp, int type, void *fname) return (EALREADY); } ump->um_qflags[type] |= QTF_OPENING|QTF_CLOSING; + UFS_UNLOCK(ump); if ((error = dqopen(vp, ump, type)) != 0) { + UFS_LOCK(ump); ump->um_qflags[type] &= ~(QTF_OPENING|QTF_CLOSING); UFS_UNLOCK(ump); (void) vn_close(vp, FREAD|FWRITE, td->td_ucred, td); @@ -544,7 +549,6 @@ quotaon(struct thread *td, struct mount *mp, int type, void *fname) MNT_ILOCK(mp); mp->mnt_flag |= MNT_QUOTA; MNT_IUNLOCK(mp); - UFS_UNLOCK(ump); vpp = &ump->um_quotas[type]; if (*vpp != vp) @@ -989,6 +993,30 @@ setuse(struct thread *td, struct mount *mp, u_long id, int type, void *addr) } /* + * Q_GETQUOTASIZE - get bit-size of quota file fields + */ +int +getquotasize(struct thread *td, struct mount *mp, u_long id, int type, + void *sizep) +{ + struct ufsmount *ump = VFSTOUFS(mp); + int bitsize; + + UFS_LOCK(ump); + if (ump->um_quotas[type] == NULLVP || + (ump->um_qflags[type] & QTF_CLOSING)) { + UFS_UNLOCK(ump); + return (EINVAL); + } + if ((ump->um_qflags[type] & QTF_64BIT) != 0) + bitsize = 64; + else + bitsize = 32; + UFS_UNLOCK(ump); + return (copyout(&bitsize, sizep, sizeof(int))); +} + +/* * Q_SYNC - sync quota files to disk. */ int @@ -1163,12 +1191,17 @@ dqopen(struct vnode *vp, struct ufsmount *ump, int type) return (0); } + UFS_LOCK(ump); if (strcmp(dqh.dqh_magic, Q_DQHDR64_MAGIC) == 0 && be32toh(dqh.dqh_version) == Q_DQHDR64_VERSION && be32toh(dqh.dqh_hdrlen) == (uint32_t)sizeof(struct dqhdr64) && - be32toh(dqh.dqh_reclen) == (uint32_t)sizeof(struct dqblk64)) + be32toh(dqh.dqh_reclen) == (uint32_t)sizeof(struct dqblk64)) { + /* XXX: what if the magic matches, but the sizes are wrong? */ ump->um_qflags[type] |= QTF_64BIT; - /* XXX: what if the magic matches, but the sizes are wrong? */ + } else { + ump->um_qflags[type] &= ~QTF_64BIT; + } + UFS_UNLOCK(ump); return (0); } diff --git a/sys/ufs/ufs/ufs_vfsops.c b/sys/ufs/ufs/ufs_vfsops.c index 3abd5eb..0eeb14f 100644 --- a/sys/ufs/ufs/ufs_vfsops.c +++ b/sys/ufs/ufs/ufs_vfsops.c @@ -151,6 +151,10 @@ ufs_quotactl(mp, cmds, id, arg) error = getquota(td, mp, id, type, arg); break; + case Q_GETQUOTASIZE: + error = getquotasize(td, mp, id, type, arg); + break; + case Q_SYNC: error = qsync(mp); break; diff --git a/usr.bin/quota/Makefile b/usr.bin/quota/Makefile index a479402..26585ae 100644 --- a/usr.bin/quota/Makefile +++ b/usr.bin/quota/Makefile @@ -3,6 +3,7 @@ PROG= quota BINOWN= root +BINMODE=4555 DPADD= ${LIBRPCSVC} ${LIBUTIL} LDADD= -lrpcsvc -lutil diff --git a/usr.sbin/repquota/repquota.c b/usr.sbin/repquota/repquota.c index f90269f..8fdea20 100644 --- a/usr.sbin/repquota/repquota.c +++ b/usr.sbin/repquota/repquota.c @@ -224,7 +224,7 @@ repquota(struct fstab *fs, int type) printf("User%*s used soft hard grace used soft hard grace\n", max(MAXLOGNAME - 1, 10), " "); maxid = quota_maxid(qf); - for (id = 0; id < maxid; id++) { + for (id = 0; id <= maxid; id++) { if (quota_read(qf, &dqbuf, id) != 0) break; if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0) |