Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 28 Dec 2009 22:44:20 +0000 (UTC)
From:      Kirk McKusick <mckusick@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r201144 - projects/quota64/lib/libutil
Message-ID:  <200912282244.nBSMiKxY003431@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mckusick
Date: Mon Dec 28 22:44:19 2009
New Revision: 201144
URL: http://svn.freebsd.org/changeset/base/201144

Log:
  Add and document the quota_convert function which converts between the
  old 32-bit and the new 64-bit formats.

Modified:
  projects/quota64/lib/libutil/libutil.h
  projects/quota64/lib/libutil/quotafile.3
  projects/quota64/lib/libutil/quotafile.c

Modified: projects/quota64/lib/libutil/libutil.h
==============================================================================
--- projects/quota64/lib/libutil/libutil.h	Mon Dec 28 22:15:11 2009	(r201143)
+++ projects/quota64/lib/libutil/libutil.h	Mon Dec 28 22:44:19 2009	(r201144)
@@ -154,6 +154,7 @@ int quota_check_path(const struct quotaf
 int quota_read(struct quotafile *, struct dqblk *, int);
 int quota_write_limits(struct quotafile *, struct dqblk *, int);
 int quota_write_usage(struct quotafile *, struct dqblk *, int);
+int quota_convert(struct quotafile *, int);
 #endif
 
 __END_DECLS

Modified: projects/quota64/lib/libutil/quotafile.3
==============================================================================
--- projects/quota64/lib/libutil/quotafile.3	Mon Dec 28 22:15:11 2009	(r201143)
+++ projects/quota64/lib/libutil/quotafile.3	Mon Dec 28 22:44:19 2009	(r201144)
@@ -1,6 +1,6 @@
 .\"-
-.\" Copyright (c) 2008 Dag-Erling Coïdan Smørgrav
-.\" All rights reserved.
+.\" Copyright (c) 2009 Dag-Erling Coïdan Smørgrav and
+.\" Marshall Kirk McKusick. All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd September 26, 2009
+.Dd December 28, 2009
 .Dt QUOTAFILE 3
 .Os
 .Sh NAME
@@ -40,6 +40,7 @@
 .Nm quota_qfname
 .Nm quota_maxid
 .Nm quota_check_path
+.Nm quota_convert
 .Nd "Manipulate quotas"
 .Sh LIBRARY
 .Lb libutil
@@ -72,6 +73,8 @@
 .Fn quota_maxid "const struct quotafile *qf"
 .Ft int
 .Fn quota_check_path "const struct quotafile *qf" "const char *path"
+.Ft int
+.Fn quota_convert "struct quotafile *qf" "int wordsize"
 .Sh DESCRIPTION
 These functions are designed to simplify access to filesystem quotas.
 If quotas are active on a filesystem,
@@ -219,9 +222,23 @@ If the
 argument refers to a symbolic link,
 .Fn quota_check_path
 will follow it.
+.Pp
+The
+.Fn quota_convert
+function converts the quota file associated with its
+.Va qf
+argument to the data size specified by its
+.Va wordsize
+argument.
+The supported wordsize arguments are 32 for the old 32-bit
+quota file format and 64 for the new 64-bit quota file format.
+The
+.Fn quota_convert
+function may only be called to operate on quota files that
+are not currently active.
 .Sh IMPLEMENTATION NOTES
-If the underlying quota file is in the old 32-bit format, limit and
-usage values written to the quota file will be clipped to 32 bits.
+If the underlying quota file is in or converted to the old 32-bit format,
+limit and usage values written to the quota file will be clipped to 32 bits.
 .Sh RETURN VALUES
 If the filesystem has quotas associated with it,
 .Fn quota_open
@@ -246,6 +263,7 @@ The
 .Fn quota_read ,
 .Fn quota_write_limits ,
 .Fn quota_write_usage ,
+.Fn quota_convert ,
 and
 .Fn quota_close
 functions return zero on success.
@@ -259,13 +277,13 @@ to indicate the error.
 .Xr quota.group 5
 .Sh HISTORY
 The
-.Nm
+.Nm quotafile
 functions first appeared in
-.Fx 8.0 .
+.Fx 8.1 .
 .Sh AUTHORS
 .An -nosplit
 The
-.Nm
+.Nm quotafile
 functions and this manual page were written by
 .An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org 
 and

Modified: projects/quota64/lib/libutil/quotafile.c
==============================================================================
--- projects/quota64/lib/libutil/quotafile.c	Mon Dec 28 22:15:11 2009	(r201143)
+++ projects/quota64/lib/libutil/quotafile.c	Mon Dec 28 22:44:19 2009	(r201144)
@@ -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,
 	}
 	/* 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);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200912282244.nBSMiKxY003431>