summaryrefslogtreecommitdiffstats
path: root/lib/libutil
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2009-09-26 23:16:06 +0000
committerdes <des@FreeBSD.org>2009-09-26 23:16:06 +0000
commita45436ee4714833a11bf829d86620ac727a0d501 (patch)
tree0816e10ab8fbd7ed1c706af2ca3a7f07ca804880 /lib/libutil
parent99096894824ebaad6bc1c96245f72c97bfc37564 (diff)
downloadFreeBSD-src-a45436ee4714833a11bf829d86620ac727a0d501.zip
FreeBSD-src-a45436ee4714833a11bf829d86620ac727a0d501.tar.gz
Further extend the quotafile API.
Diffstat (limited to 'lib/libutil')
-rw-r--r--lib/libutil/Makefile6
-rw-r--r--lib/libutil/libutil.h5
-rw-r--r--lib/libutil/quotafile.367
-rw-r--r--lib/libutil/quotafile.c101
4 files changed, 137 insertions, 42 deletions
diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile
index d7bd6dc..6b489d3 100644
--- a/lib/libutil/Makefile
+++ b/lib/libutil/Makefile
@@ -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>
diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h
index afd5db6..2190a53 100644
--- a/lib/libutil/libutil.h
+++ b/lib/libutil/libutil.h
@@ -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
diff --git a/lib/libutil/quotafile.3 b/lib/libutil/quotafile.3
index 07a08a2..4762bf9 100644
--- a/lib/libutil/quotafile.3
+++ b/lib/libutil/quotafile.3
@@ -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 access permission is denied
.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 ,
diff --git a/lib/libutil/quotafile.c b/lib/libutil/quotafile.c
index 98f6f7c..6dcb697 100644
--- a/lib/libutil/quotafile.c
+++ b/lib/libutil/quotafile.c
@@ -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[] = INITQFNAMES;
/*
* 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, char *qfnamep, int qfbufsize)
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 quotatype, int openflags)
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 quotatype, int openflags)
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 quotatype, int openflags)
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 quotatype, int openflags)
}
/* 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 *dqb, int id)
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 *dqb, int id)
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));
OpenPOWER on IntegriCloud