]>
Commit | Line | Data |
---|---|---|
959ef981 | 1 | // SPDX-License-Identifier: GPL-2.0 |
5aead01d | 2 | /* |
da23017d NS |
3 | * Copyright (c) 2005 Silicon Graphics, Inc. |
4 | * All Rights Reserved. | |
5aead01d | 5 | */ |
29647c8d | 6 | #include <stdbool.h> |
6b803e5a | 7 | #include "command.h" |
5aead01d NS |
8 | #include "init.h" |
9 | #include "quota.h" | |
10 | ||
11 | static cmdinfo_t off_cmd; | |
12 | static cmdinfo_t state_cmd; | |
13 | static cmdinfo_t enable_cmd; | |
14 | static cmdinfo_t disable_cmd; | |
15 | static cmdinfo_t remove_cmd; | |
16 | ||
17 | static void | |
18 | off_help(void) | |
19 | { | |
20 | printf(_( | |
21 | "\n" | |
22 | " turn filesystem quota off, both accounting and enforcement\n" | |
23 | "\n" | |
24 | " Example:\n" | |
25 | " 'off -uv' (switch off user quota on the current filesystem)\n" | |
26 | " This command is the equivalent of the traditional quotaoff command,\n" | |
27 | " which disables quota completely on a mounted filesystem.\n" | |
28 | " Note that there is no 'on' command - for XFS filesystems (with the\n" | |
29 | " exception of the root filesystem on IRIX) quota can only be enabled\n" | |
30 | " at mount time, through the use of one of the quota mount options.\n" | |
31 | "\n" | |
32 | " The state command is useful for displaying the current state. Using\n" | |
33 | " the -v (verbose) option with the 'off' command will display the quota\n" | |
34 | " state for the affected filesystem once the operation is complete.\n" | |
35 | " The affected quota type is -g (groups), -p (projects) or -u (users)\n" | |
36 | " and defaults to user quota (multiple types can be specified).\n" | |
37 | "\n")); | |
38 | } | |
39 | ||
40 | static void | |
41 | state_help(void) | |
42 | { | |
43 | printf(_( | |
44 | "\n" | |
45 | " query the state of quota on the current filesystem\n" | |
46 | "\n" | |
47 | " This is a verbose status command, reporting whether or not accounting\n" | |
48 | " and/or enforcement are enabled for a filesystem, which inodes are in\n" | |
49 | " use as the quota state inodes, and how many extents and blocks are\n" | |
50 | " presently being used to hold that information.\n" | |
51 | " The quota type is specified via -g (groups), -p (projects) or -u (users)\n" | |
52 | " and defaults to user quota (multiple types can be specified).\n" | |
53 | "\n")); | |
54 | } | |
55 | ||
56 | static void | |
57 | enable_help(void) | |
58 | { | |
59 | printf(_( | |
60 | "\n" | |
61 | " enable quota enforcement on a filesystem\n" | |
62 | "\n" | |
63 | " If a filesystem is mounted and has quota accounting enabled, but not\n" | |
64 | " quota enforcement, enforcement can be enabled with this command.\n" | |
65 | " With the -v (verbose) option, the status of the filesystem will be\n" | |
66 | " reported after the operation is complete.\n" | |
67 | " The affected quota type is -g (groups), -p (projects) or -u (users)\n" | |
68 | " and defaults to user quota (multiple types can be specified).\n" | |
69 | "\n")); | |
70 | } | |
71 | ||
72 | static void | |
73 | disable_help(void) | |
74 | { | |
75 | printf(_( | |
76 | "\n" | |
77 | " disable quota enforcement on a filesystem\n" | |
78 | "\n" | |
79 | " If a filesystem is mounted and is currently enforcing quota, this\n" | |
80 | " provides a mechanism to switch off the enforcement, but continue to\n" | |
81 | " perform used space (and used inodes) accounting.\n" | |
82 | " The affected quota type is -g (groups), -p (projects) or -u (users).\n" | |
83 | "\n")); | |
84 | } | |
85 | ||
86 | static void | |
87 | remove_help(void) | |
88 | { | |
89 | printf(_( | |
90 | "\n" | |
91 | " remove any space being used by the quota subsystem\n" | |
92 | "\n" | |
93 | " Once quota has been switched 'off' on a filesystem, the space that\n" | |
94 | " was allocated to holding quota metadata can be freed via this command.\n" | |
95 | " The affected quota type is -g (groups), -p (projects) or -u (users)\n" | |
96 | " and defaults to user quota (multiple types can be specified).\n" | |
97 | "\n")); | |
98 | } | |
99 | ||
100 | static void | |
101 | state_qfilestat( | |
bb92709f ES |
102 | FILE *fp, |
103 | struct fs_path *mount, | |
104 | uint type, | |
105 | struct fs_qfilestatv *qfs, | |
106 | int accounting, | |
107 | int enforcing) | |
5aead01d NS |
108 | { |
109 | fprintf(fp, _("%s quota state on %s (%s)\n"), type_to_string(type), | |
110 | mount->fs_dir, mount->fs_name); | |
111 | fprintf(fp, _(" Accounting: %s\n"), accounting ? _("ON") : _("OFF")); | |
112 | fprintf(fp, _(" Enforcement: %s\n"), enforcing ? _("ON") : _("OFF")); | |
06065b12 AE |
113 | if (qfs->qfs_ino != (__u64) -1) |
114 | fprintf(fp, _(" Inode: #%llu (%llu blocks, %lu extents)\n"), | |
115 | (unsigned long long)qfs->qfs_ino, | |
116 | (unsigned long long)qfs->qfs_nblks, | |
117 | (unsigned long)qfs->qfs_nextents); | |
118 | else | |
119 | fprintf(fp, _(" Inode: N/A\n")); | |
5aead01d NS |
120 | } |
121 | ||
122 | static void | |
123 | state_timelimit( | |
124 | FILE *fp, | |
125 | uint form, | |
14f8b681 | 126 | uint32_t timelimit) |
5aead01d NS |
127 | { |
128 | fprintf(fp, _("%s grace time: %s\n"), | |
129 | form_to_string(form), | |
130 | time_to_string(timelimit, VERBOSE_FLAG | ABSOLUTE_FLAG)); | |
131 | } | |
132 | ||
387a96e1 DW |
133 | static void |
134 | state_warnlimit( | |
135 | FILE *fp, | |
136 | uint form, | |
137 | uint16_t warnlimit) | |
138 | { | |
139 | fprintf(fp, _("%s max warnings: %u\n"), | |
140 | form_to_string(form), warnlimit); | |
141 | } | |
142 | ||
bb92709f ES |
143 | /* |
144 | * fs_quota_stat holds a subset of fs_quota_statv; this copies | |
145 | * the smaller into the larger, leaving any not-present fields | |
146 | * empty. This is so the same reporting function can be used | |
147 | * for both XFS_GETQSTAT and XFS_GETQSTATV results. | |
148 | */ | |
149 | static void | |
150 | state_stat_to_statv( | |
151 | struct fs_quota_stat *s, | |
152 | struct fs_quota_statv *sv) | |
153 | { | |
154 | memset(sv, 0, sizeof(struct fs_quota_statv)); | |
155 | ||
156 | /* shared information */ | |
157 | sv->qs_version = s->qs_version; | |
158 | sv->qs_flags = s->qs_flags; | |
159 | sv->qs_incoredqs = s->qs_incoredqs; | |
160 | sv->qs_btimelimit = s->qs_btimelimit; | |
161 | sv->qs_itimelimit = s->qs_itimelimit; | |
162 | sv->qs_rtbtimelimit = s->qs_rtbtimelimit; | |
163 | sv->qs_bwarnlimit = s->qs_bwarnlimit; | |
164 | sv->qs_iwarnlimit = s->qs_iwarnlimit; | |
165 | ||
166 | /* Always room for uquota */ | |
167 | sv->qs_uquota.qfs_ino = s->qs_uquota.qfs_ino; | |
168 | sv->qs_uquota.qfs_nblks = s->qs_uquota.qfs_nblks; | |
169 | sv->qs_uquota.qfs_nextents = s->qs_uquota.qfs_nextents; | |
170 | ||
171 | /* | |
172 | * If we are here, XFS_GETQSTATV failed and XFS_GETQSTAT passed; | |
173 | * that is a very strong hint that we're on a kernel which predates | |
174 | * the on-disk pquota inode; both were added in v3.12. So, we do | |
175 | * some tricksy determination here. | |
176 | * gs_gquota may hold either group quota inode info, or project | |
177 | * quota if that is used instead; which one it actually holds depends | |
178 | * on the quota flags. (If neither is set, neither is used) | |
179 | */ | |
180 | if (s->qs_flags & XFS_QUOTA_GDQ_ACCT) { | |
181 | /* gs_gquota holds group quota info */ | |
182 | sv->qs_gquota.qfs_ino = s->qs_gquota.qfs_ino; | |
183 | sv->qs_gquota.qfs_nblks = s->qs_gquota.qfs_nblks; | |
184 | sv->qs_gquota.qfs_nextents = s->qs_gquota.qfs_nextents; | |
185 | } else if (s->qs_flags & XFS_QUOTA_PDQ_ACCT) { | |
186 | /* gs_gquota actually holds project quota info */ | |
187 | sv->qs_pquota.qfs_ino = s->qs_gquota.qfs_ino; | |
188 | sv->qs_pquota.qfs_nblks = s->qs_gquota.qfs_nblks; | |
189 | sv->qs_pquota.qfs_nextents = s->qs_gquota.qfs_nextents; | |
190 | } | |
191 | } | |
192 | ||
5aead01d | 193 | static void |
d8a94546 | 194 | state_quotafile_stat( |
bb92709f ES |
195 | FILE *fp, |
196 | uint type, | |
d8a94546 BD |
197 | struct fs_path *mount, |
198 | struct fs_quota_statv *sv, | |
199 | struct fs_quota_stat *s, | |
bb92709f | 200 | uint flags) |
5aead01d | 201 | { |
d8a94546 BD |
202 | bool accounting, enforcing; |
203 | struct fs_qfilestatv *qsv; | |
bb92709f ES |
204 | char *dev = mount->fs_name; |
205 | ||
d8a94546 BD |
206 | if (xfsquotactl(XFS_GETQSTATV, dev, type, 0, (void *)sv) < 0) { |
207 | if (xfsquotactl(XFS_GETQSTAT, dev, type, 0, (void *)s) < 0) { | |
bb92709f ES |
208 | if (flags & VERBOSE_FLAG) |
209 | fprintf(fp, | |
210 | _("%s quota are not enabled on %s\n"), | |
211 | type_to_string(type), dev); | |
212 | return; | |
213 | } | |
d8a94546 BD |
214 | state_stat_to_statv(s, sv); |
215 | } | |
216 | ||
217 | switch(type) { | |
218 | case XFS_USER_QUOTA: | |
219 | qsv = &sv->qs_uquota; | |
220 | accounting = sv->qs_flags & XFS_QUOTA_UDQ_ACCT; | |
221 | enforcing = sv->qs_flags & XFS_QUOTA_UDQ_ENFD; | |
222 | break; | |
223 | case XFS_GROUP_QUOTA: | |
224 | qsv = &sv->qs_gquota; | |
225 | accounting = sv->qs_flags & XFS_QUOTA_GDQ_ACCT; | |
226 | enforcing = sv->qs_flags & XFS_QUOTA_GDQ_ENFD; | |
227 | break; | |
228 | case XFS_PROJ_QUOTA: | |
229 | qsv = &sv->qs_pquota; | |
230 | accounting = sv->qs_flags & XFS_QUOTA_PDQ_ACCT; | |
231 | enforcing = sv->qs_flags & XFS_QUOTA_PDQ_ENFD; | |
232 | break; | |
233 | default: | |
234 | return; | |
235 | } | |
236 | ||
237 | ||
238 | state_qfilestat(fp, mount, type, qsv, accounting, enforcing); | |
239 | ||
240 | state_timelimit(fp, XFS_BLOCK_QUOTA, sv->qs_btimelimit); | |
241 | state_warnlimit(fp, XFS_BLOCK_QUOTA, sv->qs_bwarnlimit); | |
242 | ||
243 | state_timelimit(fp, XFS_INODE_QUOTA, sv->qs_itimelimit); | |
244 | state_warnlimit(fp, XFS_INODE_QUOTA, sv->qs_iwarnlimit); | |
245 | ||
246 | state_timelimit(fp, XFS_RTBLOCK_QUOTA, sv->qs_rtbtimelimit); | |
247 | } | |
248 | ||
249 | static void | |
250 | state_quotafile_mount( | |
251 | FILE *fp, | |
252 | uint type, | |
253 | struct fs_path *mount, | |
254 | uint flags) | |
255 | { | |
256 | struct fs_quota_stat s; | |
257 | struct fs_quota_statv sv; | |
258 | ||
259 | sv.qs_version = FS_QSTATV_VERSION1; | |
260 | ||
261 | if (type & XFS_USER_QUOTA) { | |
262 | state_quotafile_stat(fp, XFS_USER_QUOTA, mount, | |
263 | &sv, &s, flags); | |
264 | } | |
265 | ||
266 | if (type & XFS_GROUP_QUOTA) { | |
267 | state_quotafile_stat(fp, XFS_GROUP_QUOTA, mount, | |
268 | &sv, &s, flags); | |
5aead01d NS |
269 | } |
270 | ||
d8a94546 BD |
271 | if (type & XFS_PROJ_QUOTA) { |
272 | state_quotafile_stat(fp, XFS_PROJ_QUOTA, mount, | |
273 | &sv, &s, flags); | |
274 | } | |
5aead01d NS |
275 | } |
276 | ||
277 | static void | |
278 | state_quotafile( | |
279 | FILE *fp, | |
280 | uint type, | |
281 | char *dir, | |
282 | uint flags) | |
283 | { | |
284 | fs_cursor_t cursor; | |
285 | fs_path_t *mount; | |
286 | ||
287 | fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor); | |
288 | while ((mount = fs_cursor_next_entry(&cursor))) | |
289 | state_quotafile_mount(fp, type, mount, flags); | |
290 | } | |
291 | ||
292 | static int | |
293 | state_f( | |
294 | int argc, | |
295 | char **argv) | |
296 | { | |
297 | FILE *fp = NULL; | |
298 | char *fname = NULL; | |
299 | int c, flags = 0, type = 0; | |
300 | ||
301 | while ((c = getopt(argc, argv, "af:gpuv")) != EOF) { | |
302 | switch (c) { | |
303 | case 'a': | |
304 | flags |= ALL_MOUNTS_FLAG; | |
305 | break; | |
306 | case 'f': | |
307 | fname = optarg; | |
308 | break; | |
309 | case 'g': | |
310 | type |= XFS_GROUP_QUOTA; | |
311 | break; | |
312 | case 'p': | |
313 | type |= XFS_PROJ_QUOTA; | |
314 | break; | |
315 | case 'u': | |
316 | type |= XFS_USER_QUOTA; | |
317 | break; | |
318 | case 'v': | |
319 | flags |= VERBOSE_FLAG; | |
320 | break; | |
321 | default: | |
322 | return command_usage(&state_cmd); | |
323 | } | |
324 | } | |
325 | ||
326 | if (argc != optind) | |
327 | return command_usage(&state_cmd); | |
328 | ||
329 | if ((fp = fopen_write_secure(fname)) == NULL) | |
330 | return 0; | |
331 | ||
332 | if (!type) | |
333 | type = XFS_USER_QUOTA | XFS_GROUP_QUOTA | XFS_PROJ_QUOTA; | |
334 | ||
fa13a00f NS |
335 | if (flags & ALL_MOUNTS_FLAG) |
336 | state_quotafile(fp, type, NULL, flags); | |
04418c59 | 337 | else if (fs_path && fs_path->fs_flags & FS_MOUNT_POINT) |
fa13a00f | 338 | state_quotafile(fp, type, fs_path->fs_dir, flags); |
5aead01d NS |
339 | |
340 | if (fname) | |
341 | fclose(fp); | |
342 | return 0; | |
343 | } | |
344 | ||
345 | static void | |
346 | enable_enforcement( | |
347 | char *dir, | |
348 | uint type, | |
349 | uint qflags, | |
350 | uint flags) | |
351 | { | |
352 | fs_path_t *mount; | |
5aead01d NS |
353 | |
354 | mount = fs_table_lookup(dir, FS_MOUNT_POINT); | |
355 | if (!mount) { | |
e3210fd8 | 356 | exitcode = 1; |
5aead01d NS |
357 | fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); |
358 | return; | |
359 | } | |
360 | dir = mount->fs_name; | |
ca42fa70 BD |
361 | if (xfsquotactl(XFS_QUOTAON, dir, type, 0, (void *)&qflags) < 0) { |
362 | if (errno == EEXIST) | |
363 | fprintf(stderr, | |
364 | _("Quota enforcement already enabled.\n")); | |
365 | else if (errno == EINVAL || errno == ENOSYS) | |
366 | fprintf(stderr, | |
367 | _("Can't enable enforcement when quota off.\n")); | |
368 | else | |
369 | perror("XFS_QUOTAON"); | |
370 | } | |
5aead01d NS |
371 | else if (flags & VERBOSE_FLAG) |
372 | state_quotafile_mount(stdout, type, mount, flags); | |
373 | } | |
374 | ||
375 | static void | |
376 | disable_enforcement( | |
377 | char *dir, | |
378 | uint type, | |
379 | uint qflags, | |
380 | uint flags) | |
381 | { | |
382 | fs_path_t *mount; | |
5aead01d NS |
383 | |
384 | mount = fs_table_lookup(dir, FS_MOUNT_POINT); | |
385 | if (!mount) { | |
e3210fd8 | 386 | exitcode = 1; |
5aead01d NS |
387 | fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); |
388 | return; | |
389 | } | |
390 | dir = mount->fs_name; | |
ca42fa70 BD |
391 | if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) { |
392 | if (errno == EEXIST) | |
393 | fprintf(stderr, | |
394 | _("Quota enforcement already disabled.\n")); | |
395 | else if (errno == EINVAL || errno == ENOSYS) | |
396 | fprintf(stderr, | |
397 | _("Can't disable enforcement when quota off.\n")); | |
398 | else | |
399 | perror("XFS_QUOTAOFF"); | |
400 | } | |
5aead01d NS |
401 | else if (flags & VERBOSE_FLAG) |
402 | state_quotafile_mount(stdout, type, mount, flags); | |
403 | } | |
404 | ||
405 | static void | |
406 | quotaoff( | |
407 | char *dir, | |
408 | uint type, | |
409 | uint qflags, | |
410 | uint flags) | |
411 | { | |
412 | fs_path_t *mount; | |
5aead01d NS |
413 | |
414 | mount = fs_table_lookup(dir, FS_MOUNT_POINT); | |
415 | if (!mount) { | |
e3210fd8 | 416 | exitcode = 1; |
5aead01d NS |
417 | fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); |
418 | return; | |
419 | } | |
420 | dir = mount->fs_name; | |
ca42fa70 BD |
421 | if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) { |
422 | if (errno == EEXIST || errno == ENOSYS) | |
423 | fprintf(stderr, _("Quota already off.\n")); | |
424 | else | |
425 | perror("XFS_QUOTAOFF"); | |
426 | } | |
5aead01d NS |
427 | else if (flags & VERBOSE_FLAG) |
428 | state_quotafile_mount(stdout, type, mount, flags); | |
429 | } | |
430 | ||
79ac1ae4 DD |
431 | static int |
432 | remove_qtype_extents( | |
433 | char *dir, | |
434 | uint type) | |
435 | { | |
436 | int error = 0; | |
437 | ||
438 | if ((error = xfsquotactl(XFS_QUOTARM, dir, type, 0, (void *)&type)) < 0) | |
439 | perror("XFS_QUOTARM"); | |
440 | return error; | |
441 | } | |
442 | ||
5aead01d NS |
443 | static void |
444 | remove_extents( | |
445 | char *dir, | |
446 | uint type, | |
5aead01d NS |
447 | uint flags) |
448 | { | |
449 | fs_path_t *mount; | |
5aead01d NS |
450 | |
451 | mount = fs_table_lookup(dir, FS_MOUNT_POINT); | |
452 | if (!mount) { | |
e3210fd8 | 453 | exitcode = 1; |
5aead01d NS |
454 | fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); |
455 | return; | |
456 | } | |
457 | dir = mount->fs_name; | |
79ac1ae4 | 458 | if (type & XFS_USER_QUOTA) { |
f8149110 | 459 | if (remove_qtype_extents(dir, XFS_USER_QUOTA) < 0) |
79ac1ae4 DD |
460 | return; |
461 | } | |
462 | if (type & XFS_GROUP_QUOTA) { | |
f8149110 | 463 | if (remove_qtype_extents(dir, XFS_GROUP_QUOTA) < 0) |
79ac1ae4 | 464 | return; |
610ec295 DW |
465 | } |
466 | if (type & XFS_PROJ_QUOTA) { | |
f8149110 | 467 | if (remove_qtype_extents(dir, XFS_PROJ_QUOTA) < 0) |
79ac1ae4 DD |
468 | return; |
469 | } | |
470 | if (flags & VERBOSE_FLAG) | |
5aead01d NS |
471 | state_quotafile_mount(stdout, type, mount, flags); |
472 | } | |
473 | ||
474 | static int | |
475 | enable_f( | |
476 | int argc, | |
477 | char **argv) | |
478 | { | |
479 | int c, flags = 0, qflags = 0, type = 0; | |
480 | ||
481 | while ((c = getopt(argc, argv, "gpuv")) != EOF) { | |
482 | switch (c) { | |
483 | case 'g': | |
484 | type |= XFS_GROUP_QUOTA; | |
485 | qflags |= XFS_QUOTA_GDQ_ACCT | XFS_QUOTA_GDQ_ENFD; | |
486 | break; | |
487 | case 'p': | |
488 | type |= XFS_PROJ_QUOTA; | |
489 | qflags |= XFS_QUOTA_PDQ_ACCT | XFS_QUOTA_PDQ_ENFD; | |
490 | break; | |
491 | case 'u': | |
492 | type |= XFS_USER_QUOTA; | |
493 | qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; | |
494 | break; | |
495 | case 'v': | |
496 | flags |= VERBOSE_FLAG; | |
497 | break; | |
498 | default: | |
499 | return command_usage(&enable_cmd); | |
500 | } | |
501 | } | |
502 | ||
503 | if (argc != optind) | |
504 | return command_usage(&enable_cmd); | |
505 | ||
79ac1ae4 | 506 | if (!type) { |
5aead01d NS |
507 | type |= XFS_USER_QUOTA; |
508 | qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; | |
509 | } | |
510 | ||
fa13a00f NS |
511 | if (fs_path->fs_flags & FS_MOUNT_POINT) |
512 | enable_enforcement(fs_path->fs_dir, type, qflags, flags); | |
5aead01d NS |
513 | return 0; |
514 | } | |
515 | ||
516 | static int | |
517 | disable_f( | |
518 | int argc, | |
519 | char **argv) | |
520 | { | |
521 | int c, flags = 0, qflags = 0, type = 0; | |
522 | ||
523 | while ((c = getopt(argc, argv, "gpuv")) != EOF) { | |
524 | switch (c) { | |
525 | case 'g': | |
526 | type |= XFS_GROUP_QUOTA; | |
79ac1ae4 | 527 | qflags |= XFS_QUOTA_GDQ_ENFD; |
5aead01d NS |
528 | break; |
529 | case 'p': | |
530 | type |= XFS_PROJ_QUOTA; | |
79ac1ae4 | 531 | qflags |= XFS_QUOTA_PDQ_ENFD; |
5aead01d NS |
532 | break; |
533 | case 'u': | |
534 | type |= XFS_USER_QUOTA; | |
79ac1ae4 | 535 | qflags |= XFS_QUOTA_UDQ_ENFD; |
5aead01d NS |
536 | break; |
537 | case 'v': | |
538 | flags |= VERBOSE_FLAG; | |
539 | break; | |
540 | default: | |
541 | return command_usage(&disable_cmd); | |
542 | } | |
543 | } | |
544 | ||
545 | if (argc != optind) | |
546 | return command_usage(&disable_cmd); | |
547 | ||
79ac1ae4 | 548 | if (!type) { |
5aead01d | 549 | type |= XFS_USER_QUOTA; |
79ac1ae4 | 550 | qflags |= XFS_QUOTA_UDQ_ENFD; |
5aead01d NS |
551 | } |
552 | ||
fa13a00f NS |
553 | if (fs_path->fs_flags & FS_MOUNT_POINT) |
554 | disable_enforcement(fs_path->fs_dir, type, qflags, flags); | |
5aead01d NS |
555 | return 0; |
556 | } | |
557 | ||
558 | static int | |
559 | off_f( | |
560 | int argc, | |
561 | char **argv) | |
562 | { | |
563 | int c, flags = 0, qflags = 0, type = 0; | |
564 | ||
565 | while ((c = getopt(argc, argv, "gpuv")) != EOF) { | |
566 | switch (c) { | |
567 | case 'g': | |
568 | type |= XFS_GROUP_QUOTA; | |
569 | qflags |= XFS_QUOTA_GDQ_ACCT | XFS_QUOTA_GDQ_ENFD; | |
570 | break; | |
571 | case 'p': | |
572 | type |= XFS_PROJ_QUOTA; | |
573 | qflags |= XFS_QUOTA_PDQ_ACCT | XFS_QUOTA_PDQ_ENFD; | |
574 | break; | |
575 | case 'u': | |
576 | type |= XFS_USER_QUOTA; | |
577 | qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; | |
578 | break; | |
579 | case 'v': | |
580 | flags |= VERBOSE_FLAG; | |
581 | break; | |
582 | default: | |
583 | return command_usage(&off_cmd); | |
584 | } | |
585 | } | |
586 | ||
587 | if (argc != optind) | |
588 | return command_usage(&off_cmd); | |
589 | ||
79ac1ae4 | 590 | if (!type) { |
5aead01d NS |
591 | type |= XFS_USER_QUOTA; |
592 | qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; | |
593 | } | |
594 | ||
fa13a00f NS |
595 | if (fs_path->fs_flags & FS_MOUNT_POINT) |
596 | quotaoff(fs_path->fs_dir, type, qflags, flags); | |
5aead01d NS |
597 | return 0; |
598 | } | |
599 | ||
600 | static int | |
601 | remove_f( | |
602 | int argc, | |
603 | char **argv) | |
604 | { | |
79ac1ae4 | 605 | int c, flags = 0, type = 0; |
5aead01d NS |
606 | |
607 | while ((c = getopt(argc, argv, "gpuv")) != EOF) { | |
608 | switch (c) { | |
609 | case 'g': | |
610 | type |= XFS_GROUP_QUOTA; | |
5aead01d NS |
611 | break; |
612 | case 'p': | |
613 | type |= XFS_PROJ_QUOTA; | |
5aead01d NS |
614 | break; |
615 | case 'u': | |
616 | type |= XFS_USER_QUOTA; | |
5aead01d NS |
617 | break; |
618 | case 'v': | |
619 | flags |= VERBOSE_FLAG; | |
620 | break; | |
621 | default: | |
622 | return command_usage(&remove_cmd); | |
623 | } | |
624 | } | |
625 | ||
626 | if (argc != optind) | |
627 | return command_usage(&remove_cmd); | |
628 | ||
79ac1ae4 | 629 | if (!type) { |
5aead01d | 630 | type |= XFS_USER_QUOTA; |
5aead01d NS |
631 | } |
632 | ||
fa13a00f | 633 | if (fs_path->fs_flags & FS_MOUNT_POINT) |
79ac1ae4 | 634 | remove_extents(fs_path->fs_dir, type, flags); |
5aead01d NS |
635 | return 0; |
636 | } | |
637 | ||
638 | void | |
639 | state_init(void) | |
640 | { | |
ad765595 | 641 | off_cmd.name = "off"; |
5aead01d NS |
642 | off_cmd.cfunc = off_f; |
643 | off_cmd.argmin = 0; | |
644 | off_cmd.argmax = -1; | |
645 | off_cmd.args = _("[-gpu] [-v]"); | |
646 | off_cmd.oneline = _("permanently switch quota off for a path"); | |
647 | off_cmd.help = off_help; | |
648 | ||
ad765595 | 649 | state_cmd.name = "state"; |
5aead01d NS |
650 | state_cmd.cfunc = state_f; |
651 | state_cmd.argmin = 0; | |
652 | state_cmd.argmax = -1; | |
62790d19 | 653 | state_cmd.args = _("[-gpu] [-a] [-v] [-f file]"); |
5aead01d NS |
654 | state_cmd.oneline = _("get overall quota state information"); |
655 | state_cmd.help = state_help; | |
29647c8d | 656 | state_cmd.flags = CMD_FLAG_FOREIGN_OK; |
5aead01d | 657 | |
ad765595 | 658 | enable_cmd.name = "enable"; |
5aead01d NS |
659 | enable_cmd.cfunc = enable_f; |
660 | enable_cmd.argmin = 0; | |
661 | enable_cmd.argmax = -1; | |
662 | enable_cmd.args = _("[-gpu] [-v]"); | |
663 | enable_cmd.oneline = _("enable quota enforcement"); | |
664 | enable_cmd.help = enable_help; | |
665 | ||
ad765595 | 666 | disable_cmd.name = "disable"; |
5aead01d NS |
667 | disable_cmd.cfunc = disable_f; |
668 | disable_cmd.argmin = 0; | |
669 | disable_cmd.argmax = -1; | |
670 | disable_cmd.args = _("[-gpu] [-v]"); | |
671 | disable_cmd.oneline = _("disable quota enforcement"); | |
672 | disable_cmd.help = disable_help; | |
673 | ||
ad765595 | 674 | remove_cmd.name = "remove"; |
5aead01d NS |
675 | remove_cmd.cfunc = remove_f; |
676 | remove_cmd.argmin = 0; | |
677 | remove_cmd.argmax = -1; | |
678 | remove_cmd.args = _("[-gpu] [-v]"); | |
679 | remove_cmd.oneline = _("remove quota extents from a filesystem"); | |
680 | remove_cmd.help = remove_help; | |
681 | ||
682 | if (expert) { | |
683 | add_command(&off_cmd); | |
684 | add_command(&state_cmd); | |
685 | add_command(&enable_cmd); | |
686 | add_command(&disable_cmd); | |
687 | add_command(&remove_cmd); | |
688 | } | |
689 | } |