diff options
Diffstat (limited to 'debugfs/quota.c')
-rw-r--r-- | debugfs/quota.c | 172 |
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(¤t_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"); + } +} |