summaryrefslogtreecommitdiffstats
path: root/usr.sbin/edquota
diff options
context:
space:
mode:
authormpp <mpp@FreeBSD.org>2007-02-04 01:41:32 +0000
committermpp <mpp@FreeBSD.org>2007-02-04 01:41:32 +0000
commitb1367bfe2c1e060d7d0e30a02898e30ee01f8fff (patch)
treefba8b44466e0b7959e9be6d9ed4aaffbcc808ca2 /usr.sbin/edquota
parentd7099516c9d7ff9d65156d16226e0a40afa9dbf2 (diff)
downloadFreeBSD-src-b1367bfe2c1e060d7d0e30a02898e30ee01f8fff.zip
FreeBSD-src-b1367bfe2c1e060d7d0e30a02898e30ee01f8fff.tar.gz
If quotas are not currently enabled for a file system, edquota -p
will operate directly on the quota file. It will incorrectly write the prototype user's usage information for each new quota it sets. Fixed to read in the current quota information and update the file correctly. If quotas are enabled the kernel handles this case fine. PR: bin/15410
Diffstat (limited to 'usr.sbin/edquota')
-rw-r--r--usr.sbin/edquota/edquota.c71
1 files changed, 63 insertions, 8 deletions
diff --git a/usr.sbin/edquota/edquota.c b/usr.sbin/edquota/edquota.c
index 1edca4a..a333314 100644
--- a/usr.sbin/edquota/edquota.c
+++ b/usr.sbin/edquota/edquota.c
@@ -375,7 +375,13 @@ getprivs(id, quotatype, fspath)
getentry(quotagroup, GRPQUOTA));
(void) fchmod(fd, 0640);
}
- lseek(fd, (long)(id * sizeof(struct dqblk)), L_SET);
+ if (lseek(fd, (off_t)id * sizeof(struct dqblk),
+ L_SET) < 0) {
+ warn("seek error on %s", qfpathname);
+ close(fd);
+ free(qup);
+ continue;
+ }
switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) {
case 0: /* EOF */
/*
@@ -421,21 +427,70 @@ putprivs(id, quotatype, quplist)
{
register struct quotause *qup;
int qcmd, fd;
+ struct dqblk dqbuf;
qcmd = QCMD(Q_SETQUOTA, quotatype);
for (qup = quplist; qup; qup = qup->next) {
if (quotactl(qup->fsname, qcmd, id, &qup->dqblk) == 0)
continue;
- if ((fd = open(qup->qfname, O_WRONLY)) < 0) {
+ if ((fd = open(qup->qfname, O_RDWR)) < 0) {
warn("%s", qup->qfname);
- } else {
- lseek(fd, (long)id * (long)sizeof (struct dqblk), 0);
- if (write(fd, &qup->dqblk, sizeof (struct dqblk)) !=
- sizeof (struct dqblk)) {
- warn("%s", qup->qfname);
- }
+ continue;
+ }
+ if (lseek(fd, (off_t)id * sizeof(struct dqblk), L_SET) < 0) {
+ warn("seek error on %s", qup->qfname);
+ close(fd);
+ continue;
+ }
+ switch (read(fd, &dqbuf, sizeof(struct dqblk))) {
+ case 0: /* EOF */
+ /*
+ * Convert implicit 0 quota (EOF)
+ * into an explicit one (zero'ed dqblk)
+ */
+ bzero(&dqbuf, sizeof(struct dqblk));
+ break;
+
+ case sizeof(struct dqblk): /* OK */
+ break;
+
+ default: /* ERROR */
+ warn("read error in %s", qup->qfname);
close(fd);
+ continue;
}
+ /*
+ * Reset time limit if have a soft limit and were
+ * previously under it, but are now over it
+ * or if there previously was no soft limit, but
+ * now have one and are over it.
+ */
+ if (dqbuf.dqb_bsoftlimit && id != 0 &&
+ dqbuf.dqb_curblocks < dqbuf.dqb_bsoftlimit &&
+ dqbuf.dqb_curblocks >= qup->dqblk.dqb_bsoftlimit)
+ qup->dqblk.dqb_btime = 0;
+ if (dqbuf.dqb_bsoftlimit == 0 && id != 0 &&
+ dqbuf.dqb_curblocks >= qup->dqblk.dqb_bsoftlimit)
+ qup->dqblk.dqb_btime = 0;
+ if (dqbuf.dqb_isoftlimit && id != 0 &&
+ dqbuf.dqb_curinodes < dqbuf.dqb_isoftlimit &&
+ dqbuf.dqb_curinodes >= qup->dqblk.dqb_isoftlimit)
+ qup->dqblk.dqb_itime = 0;
+ if (dqbuf.dqb_isoftlimit == 0 && id !=0 &&
+ dqbuf.dqb_curinodes >= qup->dqblk.dqb_isoftlimit)
+ qup->dqblk.dqb_itime = 0;
+ qup->dqblk.dqb_curinodes = dqbuf.dqb_curinodes;
+ qup->dqblk.dqb_curblocks = dqbuf.dqb_curblocks;
+ if (lseek(fd, (off_t)id * sizeof(struct dqblk), L_SET) < 0) {
+ warn("seek error on %s", qup->qfname);
+ close(fd);
+ continue;
+ }
+ if (write(fd, &qup->dqblk, sizeof (struct dqblk)) !=
+ sizeof (struct dqblk)) {
+ warn("%s", qup->qfname);
+ }
+ close(fd);
}
}
OpenPOWER on IntegriCloud