Further extend the quotafile API.

This commit is contained in:
Dag-Erling Smørgrav 2009-09-26 23:16:06 +00:00
parent 4085a92bc9
commit 5666aadb3d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/quota64/; revision=197532
4 changed files with 137 additions and 42 deletions

View file

@ -60,8 +60,12 @@ MLINKS+=pidfile.3 pidfile_open.3 \
pidfile.3 pidfile_close.3 \ pidfile.3 pidfile_close.3 \
pidfile.3 pidfile_remove.3 pidfile.3 pidfile_remove.3
MLINKS+=quotafile.3 quota_open.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_read.3 \
quotafile.3 quota_write.3 \ quotafile.3 quota_write_limits.3 \
quotafile.3 quota_write_usage.3 \
quotafile.3 quota_close.3 quotafile.3 quota_close.3
.include <bsd.lib.mk> .include <bsd.lib.mk>

View file

@ -144,10 +144,13 @@ int pidfile_remove(struct pidfh *pfh);
struct quotafile; struct quotafile;
struct fstab; struct fstab;
struct quotafile *quota_open(struct fstab *, int, int); 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_read(struct quotafile *, struct dqblk *, int);
int quota_write_limits(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_write_usage(struct quotafile *, struct dqblk *, int);
void quota_close(struct quotafile *);
#endif #endif
__END_DECLS __END_DECLS

View file

@ -25,11 +25,14 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd February 14, 2009 .Dd September 26, 2009
.Dt QUOTAFILE 3 .Dt QUOTAFILE 3
.Os .Os
.Sh NAME .Sh NAME
.Nm quota_open .Nm quota_open
.Nm quota_fsname
.Nm quota_qfname
.Nm quota_check_path
.Nm quota_read .Nm quota_read
.Nm quota_write_limits .Nm quota_write_limits
.Nm quota_write_usage .Nm quota_write_usage
@ -38,11 +41,19 @@
.Sh LIBRARY .Sh LIBRARY
.Lb libutil .Lb libutil
.Sh SYNOPSIS .Sh SYNOPSIS
.In sys/param.h
.In sys/mount.h
.In ufs/ufs/quota.h .In ufs/ufs/quota.h
.In libutil.h .In libutil.h
.In fstab.h .In fstab.h
.Ft "struct quotafile *" .Ft "struct quotafile *"
.Fn quota_open "struct fstab *fs" "int quotatype" "int openflags" .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 .Ft int
.Fn quota_read "struct quotafile *qf" "struct dqblk *dqb" "int id" .Fn quota_read "struct quotafile *qf" "struct dqblk *dqb" "int id"
.Ft int .Ft int
@ -84,12 +95,42 @@ if the quotas are just to be read, or
if the quotas are to be updated. if the quotas are to be updated.
The The
.Dv O_CREAT .Dv O_CREAT
flag should be specified if a new quota file of the requested type should flag should be specified if a new quota file of the requested type
be created if it does not already exist. 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 .Pp
The The
.Fn quota_read .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 .Va qf
for the user (or group) specified by for the user (or group) specified by
.Va id .Va id
@ -127,6 +168,9 @@ The
function closes any open file descriptors and frees any storage function closes any open file descriptors and frees any storage
associated with the filesystem and quota type referenced by associated with the filesystem and quota type referenced by
.Va qf . .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 .Sh RETURN VALUES
If the filesystem has quotas associated with it, If the filesystem has quotas associated with it,
.Fn quota_open .Fn quota_open
@ -137,7 +181,15 @@ If the filesystem has no quotas, or access permission is denied
.Dv NULL .Dv NULL
is returned and is returned and
.Va errno .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 .Pp
The The
.Fn quota_read , .Fn quota_read ,
@ -146,11 +198,10 @@ The
and and
.Fn quota_close .Fn quota_close
functions return zero on success. functions return zero on success.
On error they return On error they return\~-1
.Dv -1
and set and set
.Va errno .Va errno
to indicate the cause of failure. to indicate the error.
.Sh SEE ALSO .Sh SEE ALSO
.Xr quotactl 2 , .Xr quotactl 2 ,
.Xr quota.user 5 , .Xr quota.user 5 ,

View file

@ -49,8 +49,10 @@
struct quotafile { struct quotafile {
int fd; /* -1 means using quotactl for access */ int fd; /* -1 means using quotactl for access */
int accmode; /* access mode */
int wordsize; /* 32-bit or 64-bit limits */ int wordsize; /* 32-bit or 64-bit limits */
int quotatype; /* USRQUOTA or GRPQUOTA */ int quotatype; /* USRQUOTA or GRPQUOTA */
dev_t dev; /* device */
char fsname[MAXPATHLEN + 1]; /* mount point of filesystem */ char fsname[MAXPATHLEN + 1]; /* mount point of filesystem */
char qfname[MAXPATHLEN + 1]; /* quota file if not using quotactl */ 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. * Check to see if a particular quota is to be enabled.
* XXX merge into quota_open
*/ */
static int static int
hasquota(struct fstab *fs, int type, char *qfnamep, int qfbufsize) 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]; char buf[BUFSIZ];
static char initname, usrname[100], grpname[100]; static char initname, usrname[100], grpname[100];
/*
* XXX
* 1) we only need one of these
* 2) fstab may specify a different filename
*/
if (!initname) { if (!initname) {
(void)snprintf(usrname, sizeof(usrname), "%s%s", (void)snprintf(usrname, sizeof(usrname), "%s%s",
qfextension[USRQUOTA], QUOTAFILENAME); qfextension[USRQUOTA], QUOTAFILENAME);
@ -109,12 +117,17 @@ quota_open(struct fstab *fs, int quotatype, int openflags)
struct quotafile *qf; struct quotafile *qf;
struct dqhdr64 dqh; struct dqhdr64 dqh;
struct group *grp; struct group *grp;
struct stat st;
int qcmd, serrno; int qcmd, serrno;
if ((qf = calloc(1, sizeof(*qf))) == NULL) if ((qf = calloc(1, sizeof(*qf))) == NULL)
return (NULL); return (NULL);
qf->fd = -1;
qf->quotatype = quotatype; qf->quotatype = quotatype;
strncpy(qf->fsname, fs->fs_file, sizeof(qf->fsname)); 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); qcmd = QCMD(Q_GETQUOTA, quotatype);
if (quotactl(fs->fs_file, qcmd, 0, &dqh) == 0) { if (quotactl(fs->fs_file, qcmd, 0, &dqh) == 0) {
qf->wordsize = 64; qf->wordsize = 64;
@ -122,27 +135,19 @@ quota_open(struct fstab *fs, int quotatype, int openflags)
return (qf); return (qf);
} }
if (!hasquota(fs, quotatype, qf->qfname, sizeof(qf->qfname))) { if (!hasquota(fs, quotatype, qf->qfname, sizeof(qf->qfname))) {
free(qf);
errno = EOPNOTSUPP; errno = EOPNOTSUPP;
return (NULL); goto error;
}
if ((qf->fd = open(qf->qfname, openflags & O_ACCMODE)) < 0 &&
(openflags & O_CREAT) == 0) {
serrno = errno;
free(qf);
errno = serrno;
return (NULL);
} }
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 */ /* File open worked, so process it */
if (qf->fd != -1) { if (qf->fd != -1) {
qf->wordsize = 32; qf->wordsize = 32;
switch (read(qf->fd, &dqh, sizeof(dqh))) { switch (read(qf->fd, &dqh, sizeof(dqh))) {
case -1: case -1:
serrno = errno; goto error;
close(qf->fd);
free(qf);
errno = serrno;
return (NULL);
case sizeof(dqh): case sizeof(dqh):
if (strcmp(dqh.dqh_magic, Q_DQHDR64_MAGIC) != 0) { if (strcmp(dqh.dqh_magic, Q_DQHDR64_MAGIC) != 0) {
/* no magic, assume 32 bits */ /* 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_hdrlen) != sizeof(struct dqhdr64) ||
be32toh(dqh.dqh_reclen) != sizeof(struct dqblk64)) { be32toh(dqh.dqh_reclen) != sizeof(struct dqblk64)) {
/* correct magic, wrong version / lengths */ /* correct magic, wrong version / lengths */
close(qf->fd);
free(qf);
errno = EINVAL; errno = EINVAL;
return (NULL); goto error;
} }
qf->wordsize = 64; qf->wordsize = 64;
return (qf); return (qf);
@ -166,31 +169,33 @@ quota_open(struct fstab *fs, int quotatype, int openflags)
} }
/* not reached */ /* not reached */
} }
/* Open failed above, but O_CREAT specified, so create a new file */ /* 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) { if ((qf->fd = open(qf->qfname, O_RDWR|O_CREAT|O_TRUNC, 0)) < 0)
serrno = errno; goto error;
free(qf);
errno = serrno;
return (NULL);
}
qf->wordsize = 64; qf->wordsize = 64;
memset(&dqh, 0, sizeof(dqh)); memset(&dqh, 0, sizeof(dqh));
memcpy(dqh.dqh_magic, Q_DQHDR64_MAGIC, sizeof(dqh.dqh_magic)); memcpy(dqh.dqh_magic, Q_DQHDR64_MAGIC, sizeof(dqh.dqh_magic));
dqh.dqh_version = htobe32(Q_DQHDR64_VERSION); dqh.dqh_version = htobe32(Q_DQHDR64_VERSION);
dqh.dqh_hdrlen = htobe32(sizeof(struct dqhdr64)); dqh.dqh_hdrlen = htobe32(sizeof(struct dqhdr64));
dqh.dqh_reclen = htobe32(sizeof(struct dqblk64)); dqh.dqh_reclen = htobe32(sizeof(struct dqblk64));
if (write(qf->fd, &dqh, sizeof(dqh)) != sizeof(dqh)) { if (write(qf->fd, &dqh, sizeof(dqh)) != sizeof(dqh))
serrno = errno; goto error;
unlink(qf->qfname);
close(qf->fd);
free(qf);
errno = serrno;
return (NULL);
}
grp = getgrnam(QUOTAGROUP); grp = getgrnam(QUOTAGROUP);
fchown(qf->fd, 0, grp ? grp->gr_gid : 0); fchown(qf->fd, 0, grp ? grp->gr_gid : 0);
fchmod(qf->fd, 0640); fchmod(qf->fd, 0640);
return (qf); 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 void
@ -202,6 +207,30 @@ quota_close(struct quotafile *qf)
free(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 static int
quota_read32(struct quotafile *qf, struct dqblk *dqb, int id) 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; struct dqblk dqbuf;
int qcmd; int qcmd;
if ((qf->accmode & O_RDWR) != O_RDWR) {
errno = EBADF;
return (-1);
}
if (qf->fd == -1) { if (qf->fd == -1) {
qcmd = QCMD(Q_SETUSE, qf->quotatype); qcmd = QCMD(Q_SETUSE, qf->quotatype);
return (quotactl(qf->fsname, qcmd, id, dqb)); 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; struct dqblk dqbuf;
int qcmd; int qcmd;
if ((qf->accmode & O_RDWR) != O_RDWR) {
errno = EBADF;
return (-1);
}
if (qf->fd == -1) { if (qf->fd == -1) {
qcmd = QCMD(Q_SETQUOTA, qf->quotatype); qcmd = QCMD(Q_SETQUOTA, qf->quotatype);
return (quotactl(qf->fsname, qcmd, id, dqb)); return (quotactl(qf->fsname, qcmd, id, dqb));