#include <sys/param.h>
#include <sys/attr.h>
#include <sys/quota.h>
#include <sys/vnode.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "quotacheck.h"
#define QQ_COMMON (ATTR_CMN_OWNERID)
struct quota_query {
u_long qq_len;
uid_t qq_uid;
};
#define QA_COMMON (ATTR_CMN_OBJTYPE | ATTR_CMN_OWNERID | ATTR_CMN_GRPID)
#define QA_FILE (ATTR_FILE_ALLOCSIZE)
#define QA_DIR (0)
struct quota_attr {
unsigned long qa_attrlen;
fsobj_type_t qa_type;
uid_t qa_uid;
gid_t qa_gid;
off_t qa_bytes;
};
#define ITEMS_PER_SEARCH 2500
void collectdata(const char*, struct quotaname *);
int
chkquota_hfs(fsname, mntpt, qnp)
char *fsname, *mntpt;
register struct quotaname *qnp;
{
int errs = 0;
sync();
collectdata(mntpt, qnp);
if (qnp->flags & HASUSR)
errs = update(mntpt, qnp->usrqfname, USRQUOTA);
if (qnp->flags & HASGRP)
errs = update(mntpt, qnp->grpqfname, GRPQUOTA);
return (errs);
}
void
collectdata(const char* path, struct quotaname *qnp)
{
struct fssearchblock searchblk = {0};
struct attrlist attrlist = {0};
struct searchstate state;
struct quota_attr *qap;
struct quota_query query;
u_long nummatches;
u_long options;
int i;
int result;
int vntype;
off_t filebytes;
register struct fileusage *fup;
qap = malloc(ITEMS_PER_SEARCH * sizeof(struct quota_attr));
if (qap == NULL)
err(1, "%s", strerror(errno));
options = SRCHFS_START |SRCHFS_MATCHDIRS | SRCHFS_MATCHFILES;
query.qq_len = sizeof(struct quota_query);
query.qq_uid = 0;
options |= SRCHFS_NEGATEPARAMS;
searchblk.searchattrs.bitmapcount = ATTR_BIT_MAP_COUNT;
searchblk.searchattrs.commonattr = QQ_COMMON;
searchblk.searchparams1 = &query;
searchblk.searchparams2 = &query;
searchblk.sizeofsearchparams1 = sizeof(query);
searchblk.sizeofsearchparams2 = sizeof(query);
searchblk.returnattrs = &attrlist;
attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
attrlist.commonattr = QA_COMMON;
attrlist.dirattr = QA_DIR;
attrlist.fileattr = QA_FILE;
searchblk.returnbuffer = qap;
searchblk.returnbuffersize = ITEMS_PER_SEARCH * sizeof(struct quota_attr);
searchblk.maxmatches = ITEMS_PER_SEARCH;
for (;;) {
nummatches = 0;
result = searchfs(path, &searchblk, &nummatches, 0, options, &state);
if (result && errno != EAGAIN && errno != EBUSY) {
fprintf(stderr, "%d \n", errno);
err(1, "searchfs %s", strerror(errno));
}
if (result == 0 && nummatches == 0)
break;
options &= ~SRCHFS_START;
for (i = 0; i < nummatches; ++i) {
vntype = qap[i].qa_type;
filebytes = (vntype == VDIR) ? 0 :qap[i].qa_bytes;
if (qnp->flags & HASGRP) {
fup = addid(qap[i].qa_gid, GRPQUOTA);
fup->fu_curinodes++;
if (vntype == VREG || vntype == VDIR || vntype == VLNK)
fup->fu_curbytes += filebytes;
}
if (qnp->flags & HASUSR) {
fup = addid(qap[i].qa_uid, USRQUOTA);
fup->fu_curinodes++;
if (vntype == VREG || vntype == VDIR || vntype == VLNK)
fup->fu_curbytes += filebytes;
}
}
}
free(qap);
}