]>
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 NS |
193 | static void |
194 | state_quotafile_mount( | |
bb92709f ES |
195 | FILE *fp, |
196 | uint type, | |
197 | struct fs_path *mount, | |
198 | uint flags) | |
5aead01d | 199 | { |
bb92709f ES |
200 | struct fs_quota_stat s; |
201 | struct fs_quota_statv sv; | |
202 | char *dev = mount->fs_name; | |
203 | ||
204 | sv.qs_version = FS_QSTATV_VERSION1; | |
205 | ||
206 | if (xfsquotactl(XFS_GETQSTATV, dev, type, 0, (void *)&sv) < 0) { | |
207 | if (xfsquotactl(XFS_GETQSTAT, dev, type, 0, (void *)&s) < 0) { | |
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 | } | |
214 | state_stat_to_statv(&s, &sv); | |
5aead01d NS |
215 | } |
216 | ||
217 | if (type & XFS_USER_QUOTA) | |
bb92709f ES |
218 | state_qfilestat(fp, mount, XFS_USER_QUOTA, &sv.qs_uquota, |
219 | sv.qs_flags & XFS_QUOTA_UDQ_ACCT, | |
220 | sv.qs_flags & XFS_QUOTA_UDQ_ENFD); | |
5aead01d | 221 | if (type & XFS_GROUP_QUOTA) |
bb92709f ES |
222 | state_qfilestat(fp, mount, XFS_GROUP_QUOTA, &sv.qs_gquota, |
223 | sv.qs_flags & XFS_QUOTA_GDQ_ACCT, | |
224 | sv.qs_flags & XFS_QUOTA_GDQ_ENFD); | |
5aead01d | 225 | if (type & XFS_PROJ_QUOTA) |
bb92709f ES |
226 | state_qfilestat(fp, mount, XFS_PROJ_QUOTA, &sv.qs_pquota, |
227 | sv.qs_flags & XFS_QUOTA_PDQ_ACCT, | |
228 | sv.qs_flags & XFS_QUOTA_PDQ_ENFD); | |
5aead01d | 229 | |
bb92709f | 230 | state_timelimit(fp, XFS_BLOCK_QUOTA, sv.qs_btimelimit); |
387a96e1 DW |
231 | state_warnlimit(fp, XFS_BLOCK_QUOTA, sv.qs_bwarnlimit); |
232 | ||
bb92709f | 233 | state_timelimit(fp, XFS_INODE_QUOTA, sv.qs_itimelimit); |
387a96e1 DW |
234 | state_warnlimit(fp, XFS_INODE_QUOTA, sv.qs_iwarnlimit); |
235 | ||
bb92709f | 236 | state_timelimit(fp, XFS_RTBLOCK_QUOTA, sv.qs_rtbtimelimit); |
5aead01d NS |
237 | } |
238 | ||
239 | static void | |
240 | state_quotafile( | |
241 | FILE *fp, | |
242 | uint type, | |
243 | char *dir, | |
244 | uint flags) | |
245 | { | |
246 | fs_cursor_t cursor; | |
247 | fs_path_t *mount; | |
248 | ||
249 | fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor); | |
250 | while ((mount = fs_cursor_next_entry(&cursor))) | |
251 | state_quotafile_mount(fp, type, mount, flags); | |
252 | } | |
253 | ||
254 | static int | |
255 | state_f( | |
256 | int argc, | |
257 | char **argv) | |
258 | { | |
259 | FILE *fp = NULL; | |
260 | char *fname = NULL; | |
261 | int c, flags = 0, type = 0; | |
262 | ||
263 | while ((c = getopt(argc, argv, "af:gpuv")) != EOF) { | |
264 | switch (c) { | |
265 | case 'a': | |
266 | flags |= ALL_MOUNTS_FLAG; | |
267 | break; | |
268 | case 'f': | |
269 | fname = optarg; | |
270 | break; | |
271 | case 'g': | |
272 | type |= XFS_GROUP_QUOTA; | |
273 | break; | |
274 | case 'p': | |
275 | type |= XFS_PROJ_QUOTA; | |
276 | break; | |
277 | case 'u': | |
278 | type |= XFS_USER_QUOTA; | |
279 | break; | |
280 | case 'v': | |
281 | flags |= VERBOSE_FLAG; | |
282 | break; | |
283 | default: | |
284 | return command_usage(&state_cmd); | |
285 | } | |
286 | } | |
287 | ||
288 | if (argc != optind) | |
289 | return command_usage(&state_cmd); | |
290 | ||
291 | if ((fp = fopen_write_secure(fname)) == NULL) | |
292 | return 0; | |
293 | ||
294 | if (!type) | |
295 | type = XFS_USER_QUOTA | XFS_GROUP_QUOTA | XFS_PROJ_QUOTA; | |
296 | ||
fa13a00f NS |
297 | if (flags & ALL_MOUNTS_FLAG) |
298 | state_quotafile(fp, type, NULL, flags); | |
04418c59 | 299 | else if (fs_path && fs_path->fs_flags & FS_MOUNT_POINT) |
fa13a00f | 300 | state_quotafile(fp, type, fs_path->fs_dir, flags); |
5aead01d NS |
301 | |
302 | if (fname) | |
303 | fclose(fp); | |
304 | return 0; | |
305 | } | |
306 | ||
307 | static void | |
308 | enable_enforcement( | |
309 | char *dir, | |
310 | uint type, | |
311 | uint qflags, | |
312 | uint flags) | |
313 | { | |
314 | fs_path_t *mount; | |
5aead01d NS |
315 | |
316 | mount = fs_table_lookup(dir, FS_MOUNT_POINT); | |
317 | if (!mount) { | |
e3210fd8 | 318 | exitcode = 1; |
5aead01d NS |
319 | fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); |
320 | return; | |
321 | } | |
322 | dir = mount->fs_name; | |
ca42fa70 BD |
323 | if (xfsquotactl(XFS_QUOTAON, dir, type, 0, (void *)&qflags) < 0) { |
324 | if (errno == EEXIST) | |
325 | fprintf(stderr, | |
326 | _("Quota enforcement already enabled.\n")); | |
327 | else if (errno == EINVAL || errno == ENOSYS) | |
328 | fprintf(stderr, | |
329 | _("Can't enable enforcement when quota off.\n")); | |
330 | else | |
331 | perror("XFS_QUOTAON"); | |
332 | } | |
5aead01d NS |
333 | else if (flags & VERBOSE_FLAG) |
334 | state_quotafile_mount(stdout, type, mount, flags); | |
335 | } | |
336 | ||
337 | static void | |
338 | disable_enforcement( | |
339 | char *dir, | |
340 | uint type, | |
341 | uint qflags, | |
342 | uint flags) | |
343 | { | |
344 | fs_path_t *mount; | |
5aead01d NS |
345 | |
346 | mount = fs_table_lookup(dir, FS_MOUNT_POINT); | |
347 | if (!mount) { | |
e3210fd8 | 348 | exitcode = 1; |
5aead01d NS |
349 | fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); |
350 | return; | |
351 | } | |
352 | dir = mount->fs_name; | |
ca42fa70 BD |
353 | if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) { |
354 | if (errno == EEXIST) | |
355 | fprintf(stderr, | |
356 | _("Quota enforcement already disabled.\n")); | |
357 | else if (errno == EINVAL || errno == ENOSYS) | |
358 | fprintf(stderr, | |
359 | _("Can't disable enforcement when quota off.\n")); | |
360 | else | |
361 | perror("XFS_QUOTAOFF"); | |
362 | } | |
5aead01d NS |
363 | else if (flags & VERBOSE_FLAG) |
364 | state_quotafile_mount(stdout, type, mount, flags); | |
365 | } | |
366 | ||
367 | static void | |
368 | quotaoff( | |
369 | char *dir, | |
370 | uint type, | |
371 | uint qflags, | |
372 | uint flags) | |
373 | { | |
374 | fs_path_t *mount; | |
5aead01d NS |
375 | |
376 | mount = fs_table_lookup(dir, FS_MOUNT_POINT); | |
377 | if (!mount) { | |
e3210fd8 | 378 | exitcode = 1; |
5aead01d NS |
379 | fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); |
380 | return; | |
381 | } | |
382 | dir = mount->fs_name; | |
ca42fa70 BD |
383 | if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) { |
384 | if (errno == EEXIST || errno == ENOSYS) | |
385 | fprintf(stderr, _("Quota already off.\n")); | |
386 | else | |
387 | perror("XFS_QUOTAOFF"); | |
388 | } | |
5aead01d NS |
389 | else if (flags & VERBOSE_FLAG) |
390 | state_quotafile_mount(stdout, type, mount, flags); | |
391 | } | |
392 | ||
79ac1ae4 DD |
393 | static int |
394 | remove_qtype_extents( | |
395 | char *dir, | |
396 | uint type) | |
397 | { | |
398 | int error = 0; | |
399 | ||
400 | if ((error = xfsquotactl(XFS_QUOTARM, dir, type, 0, (void *)&type)) < 0) | |
401 | perror("XFS_QUOTARM"); | |
402 | return error; | |
403 | } | |
404 | ||
5aead01d NS |
405 | static void |
406 | remove_extents( | |
407 | char *dir, | |
408 | uint type, | |
5aead01d NS |
409 | uint flags) |
410 | { | |
411 | fs_path_t *mount; | |
5aead01d NS |
412 | |
413 | mount = fs_table_lookup(dir, FS_MOUNT_POINT); | |
414 | if (!mount) { | |
e3210fd8 | 415 | exitcode = 1; |
5aead01d NS |
416 | fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); |
417 | return; | |
418 | } | |
419 | dir = mount->fs_name; | |
79ac1ae4 | 420 | if (type & XFS_USER_QUOTA) { |
f8149110 | 421 | if (remove_qtype_extents(dir, XFS_USER_QUOTA) < 0) |
79ac1ae4 DD |
422 | return; |
423 | } | |
424 | if (type & XFS_GROUP_QUOTA) { | |
f8149110 | 425 | if (remove_qtype_extents(dir, XFS_GROUP_QUOTA) < 0) |
79ac1ae4 DD |
426 | return; |
427 | } else if (type & XFS_PROJ_QUOTA) { | |
f8149110 | 428 | if (remove_qtype_extents(dir, XFS_PROJ_QUOTA) < 0) |
79ac1ae4 DD |
429 | return; |
430 | } | |
431 | if (flags & VERBOSE_FLAG) | |
5aead01d NS |
432 | state_quotafile_mount(stdout, type, mount, flags); |
433 | } | |
434 | ||
435 | static int | |
436 | enable_f( | |
437 | int argc, | |
438 | char **argv) | |
439 | { | |
440 | int c, flags = 0, qflags = 0, type = 0; | |
441 | ||
442 | while ((c = getopt(argc, argv, "gpuv")) != EOF) { | |
443 | switch (c) { | |
444 | case 'g': | |
445 | type |= XFS_GROUP_QUOTA; | |
446 | qflags |= XFS_QUOTA_GDQ_ACCT | XFS_QUOTA_GDQ_ENFD; | |
447 | break; | |
448 | case 'p': | |
449 | type |= XFS_PROJ_QUOTA; | |
450 | qflags |= XFS_QUOTA_PDQ_ACCT | XFS_QUOTA_PDQ_ENFD; | |
451 | break; | |
452 | case 'u': | |
453 | type |= XFS_USER_QUOTA; | |
454 | qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; | |
455 | break; | |
456 | case 'v': | |
457 | flags |= VERBOSE_FLAG; | |
458 | break; | |
459 | default: | |
460 | return command_usage(&enable_cmd); | |
461 | } | |
462 | } | |
463 | ||
464 | if (argc != optind) | |
465 | return command_usage(&enable_cmd); | |
466 | ||
79ac1ae4 | 467 | if (!type) { |
5aead01d NS |
468 | type |= XFS_USER_QUOTA; |
469 | qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; | |
470 | } | |
471 | ||
fa13a00f NS |
472 | if (fs_path->fs_flags & FS_MOUNT_POINT) |
473 | enable_enforcement(fs_path->fs_dir, type, qflags, flags); | |
5aead01d NS |
474 | return 0; |
475 | } | |
476 | ||
477 | static int | |
478 | disable_f( | |
479 | int argc, | |
480 | char **argv) | |
481 | { | |
482 | int c, flags = 0, qflags = 0, type = 0; | |
483 | ||
484 | while ((c = getopt(argc, argv, "gpuv")) != EOF) { | |
485 | switch (c) { | |
486 | case 'g': | |
487 | type |= XFS_GROUP_QUOTA; | |
79ac1ae4 | 488 | qflags |= XFS_QUOTA_GDQ_ENFD; |
5aead01d NS |
489 | break; |
490 | case 'p': | |
491 | type |= XFS_PROJ_QUOTA; | |
79ac1ae4 | 492 | qflags |= XFS_QUOTA_PDQ_ENFD; |
5aead01d NS |
493 | break; |
494 | case 'u': | |
495 | type |= XFS_USER_QUOTA; | |
79ac1ae4 | 496 | qflags |= XFS_QUOTA_UDQ_ENFD; |
5aead01d NS |
497 | break; |
498 | case 'v': | |
499 | flags |= VERBOSE_FLAG; | |
500 | break; | |
501 | default: | |
502 | return command_usage(&disable_cmd); | |
503 | } | |
504 | } | |
505 | ||
506 | if (argc != optind) | |
507 | return command_usage(&disable_cmd); | |
508 | ||
79ac1ae4 | 509 | if (!type) { |
5aead01d | 510 | type |= XFS_USER_QUOTA; |
79ac1ae4 | 511 | qflags |= XFS_QUOTA_UDQ_ENFD; |
5aead01d NS |
512 | } |
513 | ||
fa13a00f NS |
514 | if (fs_path->fs_flags & FS_MOUNT_POINT) |
515 | disable_enforcement(fs_path->fs_dir, type, qflags, flags); | |
5aead01d NS |
516 | return 0; |
517 | } | |
518 | ||
519 | static int | |
520 | off_f( | |
521 | int argc, | |
522 | char **argv) | |
523 | { | |
524 | int c, flags = 0, qflags = 0, type = 0; | |
525 | ||
526 | while ((c = getopt(argc, argv, "gpuv")) != EOF) { | |
527 | switch (c) { | |
528 | case 'g': | |
529 | type |= XFS_GROUP_QUOTA; | |
530 | qflags |= XFS_QUOTA_GDQ_ACCT | XFS_QUOTA_GDQ_ENFD; | |
531 | break; | |
532 | case 'p': | |
533 | type |= XFS_PROJ_QUOTA; | |
534 | qflags |= XFS_QUOTA_PDQ_ACCT | XFS_QUOTA_PDQ_ENFD; | |
535 | break; | |
536 | case 'u': | |
537 | type |= XFS_USER_QUOTA; | |
538 | qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; | |
539 | break; | |
540 | case 'v': | |
541 | flags |= VERBOSE_FLAG; | |
542 | break; | |
543 | default: | |
544 | return command_usage(&off_cmd); | |
545 | } | |
546 | } | |
547 | ||
548 | if (argc != optind) | |
549 | return command_usage(&off_cmd); | |
550 | ||
79ac1ae4 | 551 | if (!type) { |
5aead01d NS |
552 | type |= XFS_USER_QUOTA; |
553 | qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; | |
554 | } | |
555 | ||
fa13a00f NS |
556 | if (fs_path->fs_flags & FS_MOUNT_POINT) |
557 | quotaoff(fs_path->fs_dir, type, qflags, flags); | |
5aead01d NS |
558 | return 0; |
559 | } | |
560 | ||
561 | static int | |
562 | remove_f( | |
563 | int argc, | |
564 | char **argv) | |
565 | { | |
79ac1ae4 | 566 | int c, flags = 0, type = 0; |
5aead01d NS |
567 | |
568 | while ((c = getopt(argc, argv, "gpuv")) != EOF) { | |
569 | switch (c) { | |
570 | case 'g': | |
571 | type |= XFS_GROUP_QUOTA; | |
5aead01d NS |
572 | break; |
573 | case 'p': | |
574 | type |= XFS_PROJ_QUOTA; | |
5aead01d NS |
575 | break; |
576 | case 'u': | |
577 | type |= XFS_USER_QUOTA; | |
5aead01d NS |
578 | break; |
579 | case 'v': | |
580 | flags |= VERBOSE_FLAG; | |
581 | break; | |
582 | default: | |
583 | return command_usage(&remove_cmd); | |
584 | } | |
585 | } | |
586 | ||
587 | if (argc != optind) | |
588 | return command_usage(&remove_cmd); | |
589 | ||
79ac1ae4 | 590 | if (!type) { |
5aead01d | 591 | type |= XFS_USER_QUOTA; |
5aead01d NS |
592 | } |
593 | ||
fa13a00f | 594 | if (fs_path->fs_flags & FS_MOUNT_POINT) |
79ac1ae4 | 595 | remove_extents(fs_path->fs_dir, type, flags); |
5aead01d NS |
596 | return 0; |
597 | } | |
598 | ||
599 | void | |
600 | state_init(void) | |
601 | { | |
ad765595 | 602 | off_cmd.name = "off"; |
5aead01d NS |
603 | off_cmd.cfunc = off_f; |
604 | off_cmd.argmin = 0; | |
605 | off_cmd.argmax = -1; | |
606 | off_cmd.args = _("[-gpu] [-v]"); | |
607 | off_cmd.oneline = _("permanently switch quota off for a path"); | |
608 | off_cmd.help = off_help; | |
609 | ||
ad765595 | 610 | state_cmd.name = "state"; |
5aead01d NS |
611 | state_cmd.cfunc = state_f; |
612 | state_cmd.argmin = 0; | |
613 | state_cmd.argmax = -1; | |
62790d19 | 614 | state_cmd.args = _("[-gpu] [-a] [-v] [-f file]"); |
5aead01d NS |
615 | state_cmd.oneline = _("get overall quota state information"); |
616 | state_cmd.help = state_help; | |
29647c8d | 617 | state_cmd.flags = CMD_FLAG_FOREIGN_OK; |
5aead01d | 618 | |
ad765595 | 619 | enable_cmd.name = "enable"; |
5aead01d NS |
620 | enable_cmd.cfunc = enable_f; |
621 | enable_cmd.argmin = 0; | |
622 | enable_cmd.argmax = -1; | |
623 | enable_cmd.args = _("[-gpu] [-v]"); | |
624 | enable_cmd.oneline = _("enable quota enforcement"); | |
625 | enable_cmd.help = enable_help; | |
626 | ||
ad765595 | 627 | disable_cmd.name = "disable"; |
5aead01d NS |
628 | disable_cmd.cfunc = disable_f; |
629 | disable_cmd.argmin = 0; | |
630 | disable_cmd.argmax = -1; | |
631 | disable_cmd.args = _("[-gpu] [-v]"); | |
632 | disable_cmd.oneline = _("disable quota enforcement"); | |
633 | disable_cmd.help = disable_help; | |
634 | ||
ad765595 | 635 | remove_cmd.name = "remove"; |
5aead01d NS |
636 | remove_cmd.cfunc = remove_f; |
637 | remove_cmd.argmin = 0; | |
638 | remove_cmd.argmax = -1; | |
639 | remove_cmd.args = _("[-gpu] [-v]"); | |
640 | remove_cmd.oneline = _("remove quota extents from a filesystem"); | |
641 | remove_cmd.help = remove_help; | |
642 | ||
643 | if (expert) { | |
644 | add_command(&off_cmd); | |
645 | add_command(&state_cmd); | |
646 | add_command(&enable_cmd); | |
647 | add_command(&disable_cmd); | |
648 | add_command(&remove_cmd); | |
649 | } | |
650 | } |