summaryrefslogtreecommitdiffstats
path: root/diskdev_cmds/quotacheck.tproj/hfs_quotacheck.c
diff options
context:
space:
mode:
Diffstat (limited to 'diskdev_cmds/quotacheck.tproj/hfs_quotacheck.c')
-rw-r--r--diskdev_cmds/quotacheck.tproj/hfs_quotacheck.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/diskdev_cmds/quotacheck.tproj/hfs_quotacheck.c b/diskdev_cmds/quotacheck.tproj/hfs_quotacheck.c
new file mode 100644
index 0000000..31bb0f5
--- /dev/null
+++ b/diskdev_cmds/quotacheck.tproj/hfs_quotacheck.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#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"
+
+
+/*
+ * Query is based on uid
+ */
+#define QQ_COMMON (ATTR_CMN_OWNERID)
+
+struct quota_query {
+ u_int32_t qq_len;
+ uid_t qq_uid;
+};
+
+/*
+ * Desired atttributes for quota checking
+ */
+#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 {
+ u_int32_t 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 *);
+
+
+/*
+ * Scan an HFS filesystem to check quota(s) present on it.
+ */
+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_int 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;
+
+ /* Search for items with uid != 0 */
+ query.qq_len = sizeof(struct quota_query);
+ query.qq_uid = 0;
+ options |= SRCHFS_NEGATEPARAMS | SRCHFS_SKIPLINKS;
+ 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);
+
+ /* Ask for type, uid, gid and file bytes */
+ searchblk.returnattrs = &attrlist;
+ attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
+ attrlist.commonattr = QA_COMMON;
+ attrlist.dirattr = QA_DIR;
+ attrlist.fileattr = QA_FILE;
+
+ /* Collect 2,500 items at a time (~60K) */
+ 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; /* all done */
+ 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);
+}