summaryrefslogtreecommitdiffstats
path: root/debugfs/quota.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--debugfs/quota.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/debugfs/quota.c b/debugfs/quota.c
new file mode 100644
index 0000000..1da1e03
--- /dev/null
+++ b/debugfs/quota.c
@@ -0,0 +1,172 @@
+/*
+ * quota.c --- debugfs quota commands
+ *
+ * Copyright (C) 2014 Theodore Ts'o. This file may be redistributed
+ * under the terms of the GNU Public License.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <sys/types.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern int optind;
+extern char *optarg;
+#endif
+
+#include "debugfs.h"
+
+const char *quota_type[] = { "user", "group", "project", NULL };
+
+static int load_quota_ctx(char *progname)
+{
+ errcode_t retval;
+
+ if (check_fs_open(progname))
+ return 1;
+
+ if (!ext2fs_has_feature_quota(current_fs->super)) {
+ com_err(progname, 0, "quota feature not enabled");
+ return 1;
+ }
+
+ if (current_qctx)
+ return 0;
+
+ retval = quota_init_context(&current_qctx, current_fs, 0);
+ if (retval) {
+ com_err(current_fs->device_name, retval,
+ "while trying to load quota information");
+ return 1;
+ }
+ return 0;
+}
+
+static int parse_quota_type(const char *cmdname, const char *str)
+{
+ errcode_t retval;
+ char *t;
+ int flags = 0;
+ int i;
+
+ for (i = 0; i < MAXQUOTAS; i++) {
+ if (strcasecmp(str, quota_type[i]) == 0)
+ break;
+ }
+ if (i >= MAXQUOTAS) {
+ i = strtol(str, &t, 0);
+ if (*t)
+ i = -1;
+ }
+ if (i < 0 || i >= MAXQUOTAS) {
+ com_err(0, 0, "Invalid quota type: %s", str);
+ printf("Valid quota types are: ");
+ for (i = 0; i < MAXQUOTAS; i++)
+ printf("%s ", quota_type[i]);
+ printf("\n");
+ return -1;
+ }
+
+ if (current_fs->flags & EXT2_FLAG_RW)
+ flags |= EXT2_FILE_WRITE;
+
+ retval = quota_file_open(current_qctx, NULL, 0, i, -1, flags);
+ if (retval) {
+ com_err(cmdname, retval,
+ "while opening quota inode (type %d)", i);
+ return -1;
+ }
+ return i;
+}
+
+
+static int list_quota_callback(struct dquot *dq,
+ void *cb_data EXT2FS_ATTR((unused)))
+{
+ printf("%10u %8lld %8lld %8lld %8lld %8lld %8lld\n",
+ dq->dq_id, (long long)dq->dq_dqb.dqb_curspace,
+ (long long)dq->dq_dqb.dqb_bsoftlimit,
+ (long long)dq->dq_dqb.dqb_bhardlimit,
+ (long long)dq->dq_dqb.dqb_curinodes,
+ (long long)dq->dq_dqb.dqb_isoftlimit,
+ (long long)dq->dq_dqb.dqb_ihardlimit);
+ return 0;
+}
+
+void do_list_quota(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
+ void *infop EXT2FS_ATTR((unused)))
+{
+ errcode_t retval;
+ int type;
+ struct quota_handle *qh;
+
+ if (load_quota_ctx(argv[0]))
+ return;
+
+ if (argc != 2) {
+ com_err(0, 0, "Usage: list_quota <quota_type>\n");
+ return;
+ }
+
+ type = parse_quota_type(argv[0], argv[1]);
+ if (type < 0)
+ return;
+
+ printf("%7s %2s %8s %8s %8s %8s %8s %8s\n",
+ quota_type[type], "id",
+ "space", "quota", "limit", "inodes", "quota", "limit");
+ qh = current_qctx->quota_file[type];
+ retval = qh->qh_ops->scan_dquots(qh, list_quota_callback, NULL);
+ if (retval) {
+ com_err(argv[0], retval, "while scanning dquots");
+ return;
+ }
+}
+
+void do_get_quota(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
+ void *infop EXT2FS_ATTR((unused)))
+{
+ int err, type;
+ struct quota_handle *qh;
+ struct dquot *dq;
+ qid_t id;
+
+ if (load_quota_ctx(argv[0]))
+ return;
+
+ if (argc != 3) {
+ com_err(0, 0, "Usage: get_quota <quota_type> <id>\n");
+ return;
+ }
+
+ type = parse_quota_type(argv[0], argv[1]);
+ if (type < 0)
+ return;
+
+ id = parse_ulong(argv[2], argv[0], "id", &err);
+ if (err)
+ return;
+
+ printf("%7s %2s %8s %8s %8s %8s %8s %8s\n",
+ quota_type[type], "id",
+ "space", "quota", "limit", "inodes", "quota", "limit");
+
+ qh = current_qctx->quota_file[type];
+
+ dq = qh->qh_ops->read_dquot(qh, id);
+ if (dq) {
+ list_quota_callback(dq, NULL);
+ ext2fs_free_mem(&dq);
+ } else {
+ com_err(argv[0], 0, "couldn't read quota record");
+ }
+}