Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 26 Sep 2009 23:16:06 +0000 (UTC)
From:      Dag-Erling Smorgrav <des@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r197532 - projects/quota64/lib/libutil
Message-ID:  <200909262316.n8QNG6CH073496@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: des
Date: Sat Sep 26 23:16:06 2009
New Revision: 197532
URL: http://svn.freebsd.org/changeset/base/197532

Log:
  Further extend the quotafile API.

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

Modified: projects/quota64/lib/libutil/Makefile
==============================================================================
--- projects/quota64/lib/libutil/Makefile	Sat Sep 26 23:05:01 2009	(r197531)
+++ projects/quota64/lib/libutil/Makefile	Sat Sep 26 23:16:06 2009	(r197532)
@@ -60,8 +60,12 @@ MLINKS+=pidfile.3 pidfile_open.3 \
 	pidfile.3 pidfile_close.3 \
 	pidfile.3 pidfile_remove.3
 MLINKS+=quotafile.3 quota_open.3 \
+	quotafile.3 quota_fsname.3 \
+	quotafile.3 quota_qfname.3 \
+	quotafile.3 quota_statfs.3 \
 	quotafile.3 quota_read.3 \
-	quotafile.3 quota_write.3 \
+	quotafile.3 quota_write_limits.3 \
+	quotafile.3 quota_write_usage.3 \
 	quotafile.3 quota_close.3
 
 .include <bsd.lib.mk>

Modified: projects/quota64/lib/libutil/libutil.h
==============================================================================
--- projects/quota64/lib/libutil/libutil.h	Sat Sep 26 23:05:01 2009	(r197531)
+++ projects/quota64/lib/libutil/libutil.h	Sat Sep 26 23:16:06 2009	(r197532)
@@ -144,10 +144,13 @@ int pidfile_remove(struct pidfh *pfh);
 struct quotafile;
 struct fstab;
 struct quotafile *quota_open(struct fstab *, int, int);
-void quota_close(struct quotafile *);
+const char *quota_fsname(const struct quotafile *);
+const char *quota_qfname(const struct quotafile *);
+int quota_check_path(const struct quotafile *, const char *path);
 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);
+void quota_close(struct quotafile *);
 #endif
 
 __END_DECLS

Modified: projects/quota64/lib/libutil/quotafile.3
==============================================================================
--- projects/quota64/lib/libutil/quotafile.3	Sat Sep 26 23:05:01 2009	(r197531)
+++ projects/quota64/lib/libutil/quotafile.3	Sat Sep 26 23:16:06 2009	(r197532)
@@ -25,11 +25,14 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 14, 2009
+.Dd September 26, 2009
 .Dt QUOTAFILE 3
 .Os
 .Sh NAME
 .Nm quota_open
+.Nm quota_fsname
+.Nm quota_qfname
+.Nm quota_check_path
 .Nm quota_read
 .Nm quota_write_limits
 .Nm quota_write_usage
@@ -38,11 +41,19 @@
 .Sh LIBRARY
 .Lb libutil
 .Sh SYNOPSIS
+.In sys/param.h
+.In sys/mount.h
 .In ufs/ufs/quota.h
 .In libutil.h
 .In fstab.h
 .Ft "struct quotafile *"
 .Fn quota_open "struct fstab *fs" "int quotatype" "int openflags"
+.Ft "const char *"
+.Fn quota_fsname "const struct quotafile *qf"
+.Ft "const char *"
+.Fn quota_qfname "const struct quotafile *qf"
+.Ft int
+.Fn quota_check_path "const struct quotafile *qf" "const char *path"
 .Ft int
 .Fn quota_read "struct quotafile *qf" "struct dqblk *dqb" "int id"
 .Ft int
@@ -84,12 +95,42 @@ if the quotas are just to be read, or
 if the quotas are to be updated.
 The
 .Dv O_CREAT
-flag should be specified if a new quota file of the requested type should
-be created if it does not already exist.
+flag should be specified if a new quota file of the requested type
+should be created if it does not already exist.
+.Pp
+The
+.Fn quota_fsname
+function returns a pointer to a buffer containing the path to the root
+of the file system that corresponds to its
+.Va qf
+argument, as listed in
+.Pa /etc/fstab .
+Note that this may be a symbolic link to the actual directory.
+.Pp
+The
+.Fn quota_qfname
+function returns a pointer to a buffer containing the name of the
+quota file that corresponds to its
+.Va qf
+argument.
+Note that this may be a symbolic link to the actual file.
+.Pp
+The
+.Fn quota_check_path
+function checks if the specified path is within the filesystem that
+corresponds to its
+.Va qf
+argument.
+If the
+.Va path
+argument refers to a symbolic link,
+.Fn quota_check_path
+will follow it.
 .Pp
 The
 .Fn quota_read
-function reads the quota from the filesystem and quota type referenced by
+function reads the quota from the filesystem and quota type referenced
+by
 .Va qf
 for the user (or group) specified by
 .Va id
@@ -127,6 +168,9 @@ The
 function closes any open file descriptors and frees any storage
 associated with the filesystem and quota type referenced by
 .Va qf .
+.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.
 .Sh RETURN VALUES
 If the filesystem has quotas associated with it,
 .Fn quota_open
@@ -137,7 +181,15 @@ If the filesystem has no quotas, or acce
 .Dv NULL
 is returned and
 .Va errno
-is set to indicate the cause of failure.
+is set to indicate the error.
+.Pp
+The
+.Fn quota_check_path
+function returns\~1 for a positive result and\~0 for a negative
+result.
+If an error occurs, it returns\~-1 and sets
+.Va errno
+to indicate the error.
 .Pp
 The
 .Fn quota_read ,
@@ -146,11 +198,10 @@ The
 and
 .Fn quota_close
 functions return zero on success.
-On error they return
-.Dv -1
+On error they return\~-1
 and set
 .Va errno
-to indicate the cause of failure.
+to indicate the error.
 .Sh SEE ALSO
 .Xr quotactl 2 ,
 .Xr quota.user 5 ,

Modified: projects/quota64/lib/libutil/quotafile.c
==============================================================================
--- projects/quota64/lib/libutil/quotafile.c	Sat Sep 26 23:05:01 2009	(r197531)
+++ projects/quota64/lib/libutil/quotafile.c	Sat Sep 26 23:16:06 2009	(r197532)
@@ -49,8 +49,10 @@
 
 struct quotafile {
 	int fd;				/* -1 means using quotactl for access */
+	int accmode;			/* access mode */
 	int wordsize;			/* 32-bit or 64-bit limits */
 	int quotatype;			/* USRQUOTA or GRPQUOTA */
+	dev_t dev;			/* device */
 	char fsname[MAXPATHLEN + 1];	/* mount point of filesystem */
 	char qfname[MAXPATHLEN + 1];	/* quota file if not using quotactl */
 };
@@ -59,6 +61,7 @@ static const char *qfextension[] = INITQ
 
 /*
  * Check to see if a particular quota is to be enabled.
+ * XXX merge into quota_open
  */
 static int
 hasquota(struct fstab *fs, int type, char *qfnamep, int qfbufsize)
@@ -69,6 +72,11 @@ hasquota(struct fstab *fs, int type, cha
 	char buf[BUFSIZ];
 	static char initname, usrname[100], grpname[100];
 
+	/*
+	 * XXX
+	 * 1) we only need one of these
+	 * 2) fstab may specify a different filename
+	 */
 	if (!initname) {
 		(void)snprintf(usrname, sizeof(usrname), "%s%s",
 		    qfextension[USRQUOTA], QUOTAFILENAME);
@@ -109,12 +117,17 @@ quota_open(struct fstab *fs, int quotaty
 	struct quotafile *qf;
 	struct dqhdr64 dqh;
 	struct group *grp;
+	struct stat st;
 	int qcmd, serrno;
 
 	if ((qf = calloc(1, sizeof(*qf))) == NULL)
 		return (NULL);
+	qf->fd = -1;
 	qf->quotatype = quotatype;
 	strncpy(qf->fsname, fs->fs_file, sizeof(qf->fsname));
+	if (stat(qf->fsname, &st) != 0)
+		goto error;
+	qf->dev = st.st_dev;
 	qcmd = QCMD(Q_GETQUOTA, quotatype);
 	if (quotactl(fs->fs_file, qcmd, 0, &dqh) == 0) {
 		qf->wordsize = 64;
@@ -122,27 +135,19 @@ quota_open(struct fstab *fs, int quotaty
 		return (qf);
 	}
 	if (!hasquota(fs, quotatype, qf->qfname, sizeof(qf->qfname))) {
-		free(qf);
 		errno = EOPNOTSUPP;
-		return (NULL);
-	}
-	if ((qf->fd = open(qf->qfname, openflags & O_ACCMODE)) < 0 &&
-	    (openflags & O_CREAT) == 0) {
-		serrno = errno;
-		free(qf);
-		errno = serrno;
-		return (NULL);
+		goto error;
 	}
+	qf->accmode = openflags & O_ACCMODE;
+	if ((qf->fd = open(qf->qfname, qf->accmode)) < 0 &&
+	    (openflags & O_CREAT) != O_CREAT)
+		goto error;
 	/* File open worked, so process it */
 	if (qf->fd != -1) {
 		qf->wordsize = 32;
 		switch (read(qf->fd, &dqh, sizeof(dqh))) {
 		case -1:
-			serrno = errno;
-			close(qf->fd);
-			free(qf);
-			errno = serrno;
-			return (NULL);
+			goto error;
 		case sizeof(dqh):
 			if (strcmp(dqh.dqh_magic, Q_DQHDR64_MAGIC) != 0) {
 				/* no magic, assume 32 bits */
@@ -153,10 +158,8 @@ quota_open(struct fstab *fs, int quotaty
 			    be32toh(dqh.dqh_hdrlen) != sizeof(struct dqhdr64) ||
 			    be32toh(dqh.dqh_reclen) != sizeof(struct dqblk64)) {
 				/* correct magic, wrong version / lengths */
-				close(qf->fd);
-				free(qf);
 				errno = EINVAL;
-				return (NULL);
+				goto error;
 			}
 			qf->wordsize = 64;
 			return (qf);
@@ -166,31 +169,33 @@ quota_open(struct fstab *fs, int quotaty
 		}
 		/* not reached */
 	}
-	/* Open failed above, but O_CREAT specified, so create a new file */
-	if ((qf->fd = open(qf->qfname, O_RDWR|O_CREAT|O_TRUNC, 0)) < 0) {
-		serrno = errno;
-		free(qf);
-		errno = serrno;
-		return (NULL);
-	}
+	/* open failed, but O_CREAT was specified, so create a new file */
+	if ((qf->fd = open(qf->qfname, O_RDWR|O_CREAT|O_TRUNC, 0)) < 0)
+		goto error;
 	qf->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(qf->fd, &dqh, sizeof(dqh)) != sizeof(dqh)) {
-		serrno = errno;
-		unlink(qf->qfname);
-		close(qf->fd);
-		free(qf);
-		errno = serrno;
-		return (NULL);
-	}
+	if (write(qf->fd, &dqh, sizeof(dqh)) != sizeof(dqh))
+		goto error;
 	grp = getgrnam(QUOTAGROUP);
 	fchown(qf->fd, 0, grp ? grp->gr_gid : 0);
 	fchmod(qf->fd, 0640);
 	return (qf);
+error:
+	serrno = errno;
+	/* did we have an open file? */
+	if (qf->fd != -1) {
+		/* was it one we created ourselves? */
+		if ((openflags & O_CREAT) == O_CREAT)
+			unlink(qf->qfname);
+		close(qf->fd);
+	}
+	free(qf);
+	errno = serrno;
+	return (NULL);
 }
 
 void
@@ -202,6 +207,30 @@ quota_close(struct quotafile *qf)
 	free(qf);
 }
 
+const char *
+quota_fsname(const struct quotafile *qf)
+{
+
+	return (qf->fsname);
+}
+
+const char *
+quota_qfname(const struct quotafile *qf)
+{
+
+	return (qf->qfname);
+}
+
+int
+quota_check_path(const struct quotafile *qf, const char *path)
+{
+	struct stat st;
+
+	if (stat(path, &st) == -1)
+		return (-1);
+	return (st.st_dev == qf->dev);
+}
+
 static int
 quota_read32(struct quotafile *qf, struct dqblk *dqb, int id)
 {
@@ -333,6 +362,10 @@ quota_write_usage(struct quotafile *qf, 
 	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));
@@ -377,6 +410,10 @@ quota_write_limits(struct quotafile *qf,
 	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));



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