summaryrefslogtreecommitdiffstats
path: root/debugfs/quota.c
blob: 7d8e82f660f679d1e1013c6b8820666885c7a744 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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, ss_argv_t 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, ss_argv_t 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");
	}
}