]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - quota/quota.c
xfsprogs: Don't translate command name
[thirdparty/xfsprogs-dev.git] / quota / quota.c
1 /*
2 * Copyright (c) 2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <xfs/command.h>
20 #include <ctype.h>
21 #include <pwd.h>
22 #include <grp.h>
23 #include "init.h"
24 #include "quota.h"
25
26 static cmdinfo_t quota_cmd;
27
28 static void
29 quota_help(void)
30 {
31 printf(_(
32 "\n"
33 " display usage and quota information\n"
34 "\n"
35 " -g -- display group quota information\n"
36 " -p -- display project quota information\n"
37 " -u -- display user quota information\n"
38 " -b -- display number of blocks used\n"
39 " -i -- display number of inodes used\n"
40 " -r -- display number of realtime blocks used\n"
41 " -h -- report in a human-readable format\n"
42 " -n -- skip identifier-to-name translations, just report IDs\n"
43 " -N -- suppress the initial header\n"
44 " -v -- increase verbosity in reporting (also dumps zero values)\n"
45 " -f -- send output to a file\n"
46 " The (optional) user/group/project can be specified either by name or by\n"
47 " number (i.e. uid/gid/projid).\n"
48 "\n"));
49 }
50
51 static int
52 quota_mount(
53 FILE *fp,
54 __uint32_t id,
55 char *name,
56 uint form,
57 uint type,
58 fs_path_t *mount,
59 uint flags)
60 {
61 fs_disk_quota_t d;
62 char *dev = mount->fs_name;
63 char c[8], h[8], s[8];
64 uint qflags;
65 int count;
66
67 xfsquotactl(XFS_QSYNC, dev, type, 0, NULL);
68 if (xfsquotactl(XFS_GETQUOTA, dev, type, id, (void *)&d) < 0)
69 return 0;
70
71 if (!(flags & VERBOSE_FLAG)) {
72 count = 0;
73 if ((form & XFS_BLOCK_QUOTA) && d.d_bcount)
74 count++;
75 if ((form & XFS_INODE_QUOTA) && d.d_icount)
76 count++;
77 if ((form & XFS_RTBLOCK_QUOTA) && d.d_rtbcount)
78 count++;
79 if (!count)
80 return 0;
81 }
82
83 if (!(flags & NO_HEADER_FLAG)) {
84 fprintf(fp,
85 _("Disk quotas for %s %s (%u)\nFilesystem%s"),
86 type_to_string(type), name, id,
87 (flags & HUMAN_FLAG) ? " " : " ");
88 if (form & XFS_BLOCK_QUOTA)
89 fprintf(fp, (flags & HUMAN_FLAG) ?
90 _(" Blocks Quota Limit Warn/Time ") :
91 _(" Blocks Quota Limit Warn/Time "));
92 if (form & XFS_INODE_QUOTA)
93 fprintf(fp, (flags & HUMAN_FLAG) ?
94 _(" Files Quota Limit Warn/Time ") :
95 _(" Files Quota Limit Warn/Time "));
96 if (form & XFS_RTBLOCK_QUOTA)
97 fprintf(fp, (flags & HUMAN_FLAG) ?
98 _("Realtime Quota Limit Warn/Time ") :
99 _(" Realtime Quota Limit Warn/Time "));
100 fputs("Mounted on\n", fp);
101 }
102
103 if (flags & HUMAN_FLAG) {
104 count = fprintf(fp, "%-12s", dev);
105 if (count > 13)
106 fprintf(fp, "\n%12s", " ");
107 } else {
108 count = fprintf(fp, "%-19s", dev);
109 if (count > 20)
110 fprintf(fp, "\n%19s", " ");
111 }
112
113 if (form & XFS_BLOCK_QUOTA) {
114 qflags = (flags & HUMAN_FLAG);
115 if (d.d_blk_hardlimit && d.d_bcount > d.d_blk_hardlimit)
116 qflags |= LIMIT_FLAG;
117 if (d.d_blk_softlimit && d.d_bcount > d.d_blk_softlimit)
118 qflags |= QUOTA_FLAG;
119 if (flags & HUMAN_FLAG)
120 fprintf(fp, " %6s %6s %6s %02d %8s ",
121 bbs_to_string(d.d_bcount, c, sizeof(c)),
122 bbs_to_string(d.d_blk_softlimit, s, sizeof(s)),
123 bbs_to_string(d.d_blk_hardlimit, h, sizeof(h)),
124 d.d_bwarns,
125 time_to_string(d.d_btimer, qflags));
126 else
127 fprintf(fp, " %10llu %10llu %10llu %02d %9s ",
128 (unsigned long long)d.d_bcount >> 1,
129 (unsigned long long)d.d_blk_softlimit >> 1,
130 (unsigned long long)d.d_blk_hardlimit >> 1,
131 d.d_bwarns,
132 time_to_string(d.d_btimer, qflags));
133 }
134 if (form & XFS_INODE_QUOTA) {
135 qflags = (flags & HUMAN_FLAG);
136 if (d.d_ino_hardlimit && d.d_icount > d.d_ino_hardlimit)
137 qflags |= LIMIT_FLAG;
138 if (d.d_ino_softlimit && d.d_icount > d.d_ino_softlimit)
139 qflags |= QUOTA_FLAG;
140 if (flags & HUMAN_FLAG)
141 fprintf(fp, " %6s %6s %6s %02d %8s ",
142 num_to_string(d.d_icount, c, sizeof(c)),
143 num_to_string(d.d_ino_softlimit, s, sizeof(s)),
144 num_to_string(d.d_ino_hardlimit, h, sizeof(h)),
145 d.d_iwarns,
146 time_to_string(d.d_itimer, qflags));
147 else
148 fprintf(fp, " %10llu %10llu %10llu %02d %9s ",
149 (unsigned long long)d.d_icount,
150 (unsigned long long)d.d_ino_softlimit,
151 (unsigned long long)d.d_ino_hardlimit,
152 d.d_iwarns,
153 time_to_string(d.d_itimer, qflags));
154 }
155 if (form & XFS_RTBLOCK_QUOTA) {
156 qflags = (flags & HUMAN_FLAG);
157 if (d.d_rtb_hardlimit && d.d_rtbcount > d.d_rtb_hardlimit)
158 qflags |= LIMIT_FLAG;
159 if (d.d_rtb_softlimit && d.d_rtbcount > d.d_rtb_softlimit)
160 qflags |= QUOTA_FLAG;
161 if (flags & HUMAN_FLAG)
162 fprintf(fp, " %6s %6s %6s %02d %8s ",
163 bbs_to_string(d.d_rtbcount, c, sizeof(c)),
164 bbs_to_string(d.d_rtb_softlimit, s, sizeof(s)),
165 bbs_to_string(d.d_rtb_hardlimit, h, sizeof(h)),
166 d.d_rtbwarns,
167 time_to_string(d.d_rtbtimer, qflags));
168 else
169 fprintf(fp, " %10llu %10llu %10llu %02d %9s ",
170 (unsigned long long)d.d_rtbcount >> 1,
171 (unsigned long long)d.d_rtb_softlimit >> 1,
172 (unsigned long long)d.d_rtb_hardlimit >> 1,
173 d.d_rtbwarns,
174 time_to_string(d.d_rtbtimer, qflags));
175 }
176 fprintf(fp, "%s\n", mount->fs_dir);
177 return 1;
178 }
179
180 static void
181 quota(
182 FILE *fp,
183 __uint32_t id,
184 char *name,
185 uint form,
186 uint type,
187 uint flags)
188 {
189 fs_cursor_t cursor;
190 fs_path_t *path;
191
192 fs_cursor_initialise(NULL, FS_MOUNT_POINT, &cursor);
193 while ((path = fs_cursor_next_entry(&cursor))) {
194 if (quota_mount(fp, id, name, form, type, path, flags))
195 flags |= NO_HEADER_FLAG;
196 }
197 }
198
199 static char *
200 getusername(
201 uid_t uid,
202 int numeric)
203 {
204 static char buffer[32];
205
206 if (!numeric) {
207 struct passwd *u = getpwuid(uid);
208 if (u)
209 return u->pw_name;
210 }
211 snprintf(buffer, sizeof(buffer), "#%u", uid);
212 return &buffer[0];
213 }
214
215 static void
216 quota_user_type(
217 FILE *fp,
218 char *name,
219 uint form,
220 uint type,
221 uint flags)
222 {
223 struct passwd *u;
224 uid_t id;
225
226 if (name) {
227 if (isdigit(name[0])) {
228 id = atoi(name);
229 name = getusername(id, flags & NO_LOOKUP_FLAG);
230 } else if ((u = getpwnam(name))) {
231 id = u->pw_uid;
232 name = u->pw_name;
233 } else {
234 exitcode = 1;
235 fprintf(stderr, _("%s: cannot find user %s\n"),
236 progname, name);
237 return;
238 }
239 } else {
240 id = getuid();
241 name = getusername(id, flags & NO_LOOKUP_FLAG);
242 }
243
244 quota(fp, id, name, form, type, flags);
245 }
246
247 static char *
248 getgroupname(
249 gid_t gid,
250 int numeric)
251 {
252 static char buffer[32];
253
254 if (!numeric) {
255 struct group *g = getgrgid(gid);
256 if (g)
257 return g->gr_name;
258 }
259 snprintf(buffer, sizeof(buffer), "#%u", gid);
260 return &buffer[0];
261 }
262
263 static void
264 quota_group_type(
265 FILE *fp,
266 char *name,
267 uint form,
268 uint type,
269 uint flags)
270 {
271 struct group *g;
272 gid_t gid, *gids = NULL;
273 int i, ngroups, dofree = 0;
274
275 if (name) {
276 if (isdigit(name[0])) {
277 gid = atoi(name);
278 name = getgroupname(gid, flags & NO_LOOKUP_FLAG);
279 } else {
280 if ((g = getgrnam(name))) {
281 gid = g->gr_gid;
282 name = g->gr_name;
283 } else {
284 exitcode = 1;
285 fprintf(stderr, _("%s: cannot find group %s\n"),
286 progname, name);
287 return;
288 }
289 }
290 gids = &gid;
291 ngroups = 1;
292 } else if ( ((ngroups = sysconf(_SC_NGROUPS_MAX)) < 0) ||
293 ((gids = malloc(ngroups * sizeof(gid_t))) == NULL) ||
294 ((ngroups = getgroups(ngroups, gids)) < 0)) {
295 dofree = (gids != NULL);
296 gid = getgid();
297 gids = &gid;
298 ngroups = 1;
299 } else {
300 dofree = (gids != NULL);
301 }
302
303 for (i = 0; i < ngroups; i++, name = NULL) {
304 if (!name)
305 name = getgroupname(gids[i], flags & NO_LOOKUP_FLAG);
306 quota(fp, gids[i], name, form, type, flags);
307 }
308
309 if (dofree)
310 free(gids);
311 }
312
313 static char *
314 getprojectname(
315 prid_t prid,
316 int numeric)
317 {
318 static char buffer[32];
319
320 if (!numeric) {
321 fs_project_t *p = getprprid(prid);
322 if (p)
323 return p->pr_name;
324 }
325 snprintf(buffer, sizeof(buffer), "#%u", (unsigned int)prid);
326 return &buffer[0];
327 }
328
329 static void
330 quota_proj_type(
331 FILE *fp,
332 char *name,
333 uint form,
334 uint type,
335 uint flags)
336 {
337 fs_project_t *p;
338 prid_t id;
339
340 if (!name) {
341 exitcode = 1;
342 fprintf(stderr, _("%s: must specify a project name/ID\n"),
343 progname);
344 return;
345 }
346
347 if (isdigit(name[0])) {
348 id = atoi(name);
349 name = getprojectname(id, flags & NO_LOOKUP_FLAG);
350 } else if ((p = getprnam(name))) {
351 id = p->pr_prid;
352 name = p->pr_name;
353 } else {
354 exitcode = 1;
355 fprintf(stderr, _("%s: cannot find project %s\n"),
356 progname, name);
357 return;
358 }
359
360 quota(fp, id, name, form, type, flags);
361 }
362
363 static void
364 quota_any_type(
365 FILE *fp,
366 char *name,
367 uint form,
368 uint type,
369 uint flags)
370 {
371 switch (type) {
372 case XFS_USER_QUOTA:
373 quota_user_type(fp, name, form, type, flags);
374 break;
375 case XFS_GROUP_QUOTA:
376 quota_group_type(fp, name, form, type, flags);
377 break;
378 case XFS_PROJ_QUOTA:
379 quota_proj_type(fp, name, form, type, flags);
380 break;
381 }
382 }
383
384 static int
385 quota_f(
386 int argc,
387 char **argv)
388 {
389 FILE *fp = NULL;
390 char *fname = NULL;
391 int c, flags = 0, type = 0, form = 0;
392
393 while ((c = getopt(argc, argv, "bf:ghnNipruv")) != EOF) {
394 switch (c) {
395 case 'f':
396 fname = optarg;
397 break;
398 case 'b':
399 form |= XFS_BLOCK_QUOTA;
400 break;
401 case 'i':
402 form |= XFS_INODE_QUOTA;
403 break;
404 case 'r':
405 form |= XFS_RTBLOCK_QUOTA;
406 break;
407 case 'g':
408 type = XFS_GROUP_QUOTA;
409 break;
410 case 'p':
411 type = XFS_PROJ_QUOTA;
412 break;
413 case 'u':
414 type = XFS_USER_QUOTA;
415 break;
416 case 'h':
417 flags |= HUMAN_FLAG;
418 break;
419 case 'n':
420 flags |= NO_LOOKUP_FLAG;
421 break;
422 case 'N':
423 flags |= NO_HEADER_FLAG;
424 break;
425 case 'v':
426 flags |= VERBOSE_FLAG;
427 break;
428 default:
429 return command_usage(&quota_cmd);
430 }
431 }
432
433 if (!form)
434 form = XFS_BLOCK_QUOTA;
435
436 if (!type)
437 type = XFS_USER_QUOTA;
438
439 if ((fp = fopen_write_secure(fname)) == NULL)
440 return 0;
441
442 if (argc == optind)
443 quota_any_type(fp, NULL, form, type, flags);
444 else while (argc > optind)
445 quota_any_type(fp, argv[optind++], form, type, flags);
446
447 if (fname)
448 fclose(fp);
449 return 0;
450 }
451
452 void
453 quota_init(void)
454 {
455 quota_cmd.name = "quota";
456 quota_cmd.altname = "l";
457 quota_cmd.cfunc = quota_f;
458 quota_cmd.argmin = 0;
459 quota_cmd.argmax = -1;
460 quota_cmd.args = _("[-bir] [-gpu] [-hnNv] [-f file] [id|name]...");
461 quota_cmd.oneline = _("show usage and limits");
462 quota_cmd.help = quota_help;
463
464 add_command(&quota_cmd);
465 }