diff options
author | Kirk McKusick <mckusick@FreeBSD.org> | 2009-12-28 22:44:19 +0000 |
---|---|---|
committer | Kirk McKusick <mckusick@FreeBSD.org> | 2009-12-28 22:44:19 +0000 |
commit | aee785babde44bcfef1d711653a85896dde7324b (patch) | |
tree | 5ca170e00b6c594a0844a3f2d064848cb0cd762b /lib/libutil/quotafile.c | |
parent | 3af26d4abba3ad1858920eedf0710663499167f1 (diff) | |
download | src-aee785babde44bcfef1d711653a85896dde7324b.tar.gz src-aee785babde44bcfef1d711653a85896dde7324b.zip |
Add and document the quota_convert function which converts between the
old 32-bit and the new 64-bit formats.
Notes
Notes:
svn path=/projects/quota64/; revision=201144
Diffstat (limited to 'lib/libutil/quotafile.c')
-rw-r--r-- | lib/libutil/quotafile.c | 99 |
1 files changed, 97 insertions, 2 deletions
diff --git a/lib/libutil/quotafile.c b/lib/libutil/quotafile.c index 652d95a290fc..ab57d662bdc7 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); +} |