summaryrefslogtreecommitdiffstats
path: root/lib/libutil/quotafile.c
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2009-12-28 22:44:19 +0000
committermckusick <mckusick@FreeBSD.org>2009-12-28 22:44:19 +0000
commit5a28062dc24966ea01e64681efb62463ef077ce7 (patch)
tree5ca170e00b6c594a0844a3f2d064848cb0cd762b /lib/libutil/quotafile.c
parenta5fbf7886647ae0b1d2e8138236283d1128132f3 (diff)
downloadFreeBSD-src-5a28062dc24966ea01e64681efb62463ef077ce7.zip
FreeBSD-src-5a28062dc24966ea01e64681efb62463ef077ce7.tar.gz
Add and document the quota_convert function which converts between the
old 32-bit and the new 64-bit formats.
Diffstat (limited to 'lib/libutil/quotafile.c')
-rw-r--r--lib/libutil/quotafile.c99
1 files changed, 97 insertions, 2 deletions
diff --git a/lib/libutil/quotafile.c b/lib/libutil/quotafile.c
index 652d95a..ab57d66 100644
--- a/lib/libutil/quotafile.c
+++ b/lib/libutil/quotafile.c
@@ -255,9 +255,9 @@ quota_maxid(struct quotafile *qf)
return (0);
switch (qf->wordsize) {
case 32:
- return (st.st_size / sizeof(struct dqblk32));
+ return (st.st_size / sizeof(struct dqblk32) - 1);
case 64:
- return (st.st_size / sizeof(struct dqblk64) - 1);
+ return (st.st_size / sizeof(struct dqblk64) - 2);
default:
return (0);
}
@@ -494,3 +494,98 @@ quota_write_limits(struct quotafile *qf, struct dqblk *dqb, int id)
}
/* not reached */
}
+
+/*
+ * Convert a quota file from one format to another.
+ */
+int
+quota_convert(struct quotafile *qf, int wordsize)
+{
+ struct quotafile *newqf;
+ struct dqhdr64 dqh;
+ struct dqblk dqblk;
+ struct group *grp;
+ int serrno, maxid, id, fd;
+
+ /*
+ * Quotas must not be active and quotafile must be open
+ * for reading and writing.
+ */
+ if ((qf->accmode & O_RDWR) != O_RDWR || qf->fd == -1) {
+ errno = EBADF;
+ return (-1);
+ }
+ if ((wordsize != 32 && wordsize != 64) ||
+ wordsize == qf->wordsize) {
+ errno = EINVAL;
+ return (-1);
+ }
+ maxid = quota_maxid(qf);
+ if ((newqf = calloc(1, sizeof(*qf))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ *newqf = *qf;
+ snprintf(newqf->qfname, MAXPATHLEN + 1, "%s_%d.orig", qf->qfname,
+ qf->wordsize);
+ if (rename(qf->qfname, newqf->qfname) < 0) {
+ free(newqf);
+ return (-1);
+ }
+ if ((newqf->fd = open(qf->qfname, O_RDWR|O_CREAT|O_TRUNC, 0)) < 0) {
+ serrno = errno;
+ goto error;
+ }
+ newqf->wordsize = wordsize;
+ if (wordsize == 64) {
+ memset(&dqh, 0, sizeof(dqh));
+ memcpy(dqh.dqh_magic, Q_DQHDR64_MAGIC, sizeof(dqh.dqh_magic));
+ dqh.dqh_version = htobe32(Q_DQHDR64_VERSION);
+ dqh.dqh_hdrlen = htobe32(sizeof(struct dqhdr64));
+ dqh.dqh_reclen = htobe32(sizeof(struct dqblk64));
+ if (write(newqf->fd, &dqh, sizeof(dqh)) != sizeof(dqh)) {
+ serrno = errno;
+ goto error;
+ }
+ }
+ grp = getgrnam(QUOTAGROUP);
+ fchown(newqf->fd, 0, grp ? grp->gr_gid : 0);
+ fchmod(newqf->fd, 0640);
+ for (id = 0; id <= maxid; id++) {
+ if ((quota_read(qf, &dqblk, id)) < 0)
+ break;
+ switch (newqf->wordsize) {
+ case 32:
+ if ((quota_write32(newqf, &dqblk, id)) < 0)
+ break;
+ continue;
+ case 64:
+ if ((quota_write64(newqf, &dqblk, id)) < 0)
+ break;
+ continue;
+ default:
+ errno = EINVAL;
+ break;
+ }
+ }
+ if (id < maxid) {
+ serrno = errno;
+ goto error;
+ }
+ /*
+ * Update the passed in quotafile to reference the new file
+ * of the converted format size.
+ */
+ fd = qf->fd;
+ qf->fd = newqf->fd;
+ newqf->fd = fd;
+ qf->wordsize = newqf->wordsize;
+ quota_close(newqf);
+ return (0);
+error:
+ /* put back the original file */
+ (void) rename(newqf->qfname, qf->qfname);
+ quota_close(newqf);
+ errno = serrno;
+ return (-1);
+}
OpenPOWER on IntegriCloud