mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
Further extend the quotafile API.
This commit is contained in:
parent
4085a92bc9
commit
5666aadb3d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/quota64/; revision=197532
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 ,
|
||||||
|
|
|
@ -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));
|
||||||
|
|
Loading…
Reference in a new issue