/* * 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", "blocks", "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", "blocks", "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"); } }