]>
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 | ||
bb92709f ES |
133 | /* |
134 | * fs_quota_stat holds a subset of fs_quota_statv; this copies | |
135 | * the smaller into the larger, leaving any not-present fields | |
136 | * empty. This is so the same reporting function can be used | |
137 | * for both XFS_GETQSTAT and XFS_GETQSTATV results. | |
138 | */ | |
139 | static void | |
140 | state_stat_to_statv( | |
141 | struct fs_quota_stat *s, | |
142 | struct fs_quota_statv *sv) | |
143 | { | |
144 | memset(sv, 0, sizeof(struct fs_quota_statv)); | |
145 | ||
146 | /* shared information */ | |
147 | sv->qs_version = s->qs_version; | |
148 | sv->qs_flags = s->qs_flags; | |
149 | sv->qs_incoredqs = s->qs_incoredqs; | |
150 | sv->qs_btimelimit = s->qs_btimelimit; | |
151 | sv->qs_itimelimit = s->qs_itimelimit; | |
152 | sv->qs_rtbtimelimit = s->qs_rtbtimelimit; | |
153 | sv->qs_bwarnlimit = s->qs_bwarnlimit; | |
154 | sv->qs_iwarnlimit = s->qs_iwarnlimit; | |
155 | ||
156 | /* Always room for uquota */ | |
157 | sv->qs_uquota.qfs_ino = s->qs_uquota.qfs_ino; | |
158 | sv->qs_uquota.qfs_nblks = s->qs_uquota.qfs_nblks; | |
159 | sv->qs_uquota.qfs_nextents = s->qs_uquota.qfs_nextents; | |
160 | ||
161 | /* | |
162 | * If we are here, XFS_GETQSTATV failed and XFS_GETQSTAT passed; | |
163 | * that is a very strong hint that we're on a kernel which predates | |
164 | * the on-disk pquota inode; both were added in v3.12. So, we do | |
165 | * some tricksy determination here. | |
166 | * gs_gquota may hold either group quota inode info, or project | |
167 | * quota if that is used instead; which one it actually holds depends | |
168 | * on the quota flags. (If neither is set, neither is used) | |
169 | */ | |
170 | if (s->qs_flags & XFS_QUOTA_GDQ_ACCT) { | |
171 | /* gs_gquota holds group quota info */ | |
172 | sv->qs_gquota.qfs_ino = s->qs_gquota.qfs_ino; | |
173 | sv->qs_gquota.qfs_nblks = s->qs_gquota.qfs_nblks; | |
174 | sv->qs_gquota.qfs_nextents = s->qs_gquota.qfs_nextents; | |
175 | } else if (s->qs_flags & XFS_QUOTA_PDQ_ACCT) { | |
176 | /* gs_gquota actually holds project quota info */ | |
177 | sv->qs_pquota.qfs_ino = s->qs_gquota.qfs_ino; | |
178 | sv->qs_pquota.qfs_nblks = s->qs_gquota.qfs_nblks; | |
179 | sv->qs_pquota.qfs_nextents = s->qs_gquota.qfs_nextents; | |
180 | } | |
181 | } | |
182 | ||
5aead01d NS |
183 | static void |
184 | state_quotafile_mount( | |
bb92709f ES |
185 | FILE *fp, |
186 | uint type, | |
187 | struct fs_path *mount, | |
188 | uint flags) | |
5aead01d | 189 | { |
bb92709f ES |
190 | struct fs_quota_stat s; |
191 | struct fs_quota_statv sv; | |
192 | char *dev = mount->fs_name; | |
193 | ||
194 | sv.qs_version = FS_QSTATV_VERSION1; | |
195 | ||
196 | if (xfsquotactl(XFS_GETQSTATV, dev, type, 0, (void *)&sv) < 0) { | |
197 | if (xfsquotactl(XFS_GETQSTAT, dev, type, 0, (void *)&s) < 0) { | |
198 | if (flags & VERBOSE_FLAG) | |
199 | fprintf(fp, | |
200 | _("%s quota are not enabled on %s\n"), | |
201 | type_to_string(type), dev); | |
202 | return; | |
203 | } | |
204 | state_stat_to_statv(&s, &sv); | |
5aead01d NS |
205 | } |
206 | ||
207 | if (type & XFS_USER_QUOTA) | |
bb92709f ES |
208 | state_qfilestat(fp, mount, XFS_USER_QUOTA, &sv.qs_uquota, |
209 | sv.qs_flags & XFS_QUOTA_UDQ_ACCT, | |
210 | sv.qs_flags & XFS_QUOTA_UDQ_ENFD); | |
5aead01d | 211 | if (type & XFS_GROUP_QUOTA) |
bb92709f ES |
212 | state_qfilestat(fp, mount, XFS_GROUP_QUOTA, &sv.qs_gquota, |
213 | sv.qs_flags & XFS_QUOTA_GDQ_ACCT, | |
214 | sv.qs_flags & XFS_QUOTA_GDQ_ENFD); | |
5aead01d | 215 | if (type & XFS_PROJ_QUOTA) |
bb92709f ES |
216 | state_qfilestat(fp, mount, XFS_PROJ_QUOTA, &sv.qs_pquota, |
217 | sv.qs_flags & XFS_QUOTA_PDQ_ACCT, | |
218 | sv.qs_flags & XFS_QUOTA_PDQ_ENFD); | |
5aead01d | 219 | |
bb92709f ES |
220 | state_timelimit(fp, XFS_BLOCK_QUOTA, sv.qs_btimelimit); |
221 | state_timelimit(fp, XFS_INODE_QUOTA, sv.qs_itimelimit); | |
222 | state_timelimit(fp, XFS_RTBLOCK_QUOTA, sv.qs_rtbtimelimit); | |
5aead01d NS |
223 | } |
224 | ||
225 | static void | |
226 | state_quotafile( | |
227 | FILE *fp, | |
228 | uint type, | |
229 | char *dir, | |
230 | uint flags) | |
231 | { | |
232 | fs_cursor_t cursor; | |
233 | fs_path_t *mount; | |
234 | ||
235 | fs_cursor_initialise(dir, FS_MOUNT_POINT, &cursor); | |
236 | while ((mount = fs_cursor_next_entry(&cursor))) | |
237 | state_quotafile_mount(fp, type, mount, flags); | |
238 | } | |
239 | ||
240 | static int | |
241 | state_f( | |
242 | int argc, | |
243 | char **argv) | |
244 | { | |
245 | FILE *fp = NULL; | |
246 | char *fname = NULL; | |
247 | int c, flags = 0, type = 0; | |
248 | ||
249 | while ((c = getopt(argc, argv, "af:gpuv")) != EOF) { | |
250 | switch (c) { | |
251 | case 'a': | |
252 | flags |= ALL_MOUNTS_FLAG; | |
253 | break; | |
254 | case 'f': | |
255 | fname = optarg; | |
256 | break; | |
257 | case 'g': | |
258 | type |= XFS_GROUP_QUOTA; | |
259 | break; | |
260 | case 'p': | |
261 | type |= XFS_PROJ_QUOTA; | |
262 | break; | |
263 | case 'u': | |
264 | type |= XFS_USER_QUOTA; | |
265 | break; | |
266 | case 'v': | |
267 | flags |= VERBOSE_FLAG; | |
268 | break; | |
269 | default: | |
270 | return command_usage(&state_cmd); | |
271 | } | |
272 | } | |
273 | ||
274 | if (argc != optind) | |
275 | return command_usage(&state_cmd); | |
276 | ||
277 | if ((fp = fopen_write_secure(fname)) == NULL) | |
278 | return 0; | |
279 | ||
280 | if (!type) | |
281 | type = XFS_USER_QUOTA | XFS_GROUP_QUOTA | XFS_PROJ_QUOTA; | |
282 | ||
fa13a00f NS |
283 | if (flags & ALL_MOUNTS_FLAG) |
284 | state_quotafile(fp, type, NULL, flags); | |
04418c59 | 285 | else if (fs_path && fs_path->fs_flags & FS_MOUNT_POINT) |
fa13a00f | 286 | state_quotafile(fp, type, fs_path->fs_dir, flags); |
5aead01d NS |
287 | |
288 | if (fname) | |
289 | fclose(fp); | |
290 | return 0; | |
291 | } | |
292 | ||
293 | static void | |
294 | enable_enforcement( | |
295 | char *dir, | |
296 | uint type, | |
297 | uint qflags, | |
298 | uint flags) | |
299 | { | |
300 | fs_path_t *mount; | |
5aead01d NS |
301 | |
302 | mount = fs_table_lookup(dir, FS_MOUNT_POINT); | |
303 | if (!mount) { | |
e3210fd8 | 304 | exitcode = 1; |
5aead01d NS |
305 | fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); |
306 | return; | |
307 | } | |
308 | dir = mount->fs_name; | |
ca42fa70 BD |
309 | if (xfsquotactl(XFS_QUOTAON, dir, type, 0, (void *)&qflags) < 0) { |
310 | if (errno == EEXIST) | |
311 | fprintf(stderr, | |
312 | _("Quota enforcement already enabled.\n")); | |
313 | else if (errno == EINVAL || errno == ENOSYS) | |
314 | fprintf(stderr, | |
315 | _("Can't enable enforcement when quota off.\n")); | |
316 | else | |
317 | perror("XFS_QUOTAON"); | |
318 | } | |
5aead01d NS |
319 | else if (flags & VERBOSE_FLAG) |
320 | state_quotafile_mount(stdout, type, mount, flags); | |
321 | } | |
322 | ||
323 | static void | |
324 | disable_enforcement( | |
325 | char *dir, | |
326 | uint type, | |
327 | uint qflags, | |
328 | uint flags) | |
329 | { | |
330 | fs_path_t *mount; | |
5aead01d NS |
331 | |
332 | mount = fs_table_lookup(dir, FS_MOUNT_POINT); | |
333 | if (!mount) { | |
e3210fd8 | 334 | exitcode = 1; |
5aead01d NS |
335 | fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); |
336 | return; | |
337 | } | |
338 | dir = mount->fs_name; | |
ca42fa70 BD |
339 | if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) { |
340 | if (errno == EEXIST) | |
341 | fprintf(stderr, | |
342 | _("Quota enforcement already disabled.\n")); | |
343 | else if (errno == EINVAL || errno == ENOSYS) | |
344 | fprintf(stderr, | |
345 | _("Can't disable enforcement when quota off.\n")); | |
346 | else | |
347 | perror("XFS_QUOTAOFF"); | |
348 | } | |
5aead01d NS |
349 | else if (flags & VERBOSE_FLAG) |
350 | state_quotafile_mount(stdout, type, mount, flags); | |
351 | } | |
352 | ||
353 | static void | |
354 | quotaoff( | |
355 | char *dir, | |
356 | uint type, | |
357 | uint qflags, | |
358 | uint flags) | |
359 | { | |
360 | fs_path_t *mount; | |
5aead01d NS |
361 | |
362 | mount = fs_table_lookup(dir, FS_MOUNT_POINT); | |
363 | if (!mount) { | |
e3210fd8 | 364 | exitcode = 1; |
5aead01d NS |
365 | fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); |
366 | return; | |
367 | } | |
368 | dir = mount->fs_name; | |
ca42fa70 BD |
369 | if (xfsquotactl(XFS_QUOTAOFF, dir, type, 0, (void *)&qflags) < 0) { |
370 | if (errno == EEXIST || errno == ENOSYS) | |
371 | fprintf(stderr, _("Quota already off.\n")); | |
372 | else | |
373 | perror("XFS_QUOTAOFF"); | |
374 | } | |
5aead01d NS |
375 | else if (flags & VERBOSE_FLAG) |
376 | state_quotafile_mount(stdout, type, mount, flags); | |
377 | } | |
378 | ||
79ac1ae4 DD |
379 | static int |
380 | remove_qtype_extents( | |
381 | char *dir, | |
382 | uint type) | |
383 | { | |
384 | int error = 0; | |
385 | ||
386 | if ((error = xfsquotactl(XFS_QUOTARM, dir, type, 0, (void *)&type)) < 0) | |
387 | perror("XFS_QUOTARM"); | |
388 | return error; | |
389 | } | |
390 | ||
5aead01d NS |
391 | static void |
392 | remove_extents( | |
393 | char *dir, | |
394 | uint type, | |
5aead01d NS |
395 | uint flags) |
396 | { | |
397 | fs_path_t *mount; | |
5aead01d NS |
398 | |
399 | mount = fs_table_lookup(dir, FS_MOUNT_POINT); | |
400 | if (!mount) { | |
e3210fd8 | 401 | exitcode = 1; |
5aead01d NS |
402 | fprintf(stderr, "%s: unknown mount point %s\n", progname, dir); |
403 | return; | |
404 | } | |
405 | dir = mount->fs_name; | |
79ac1ae4 | 406 | if (type & XFS_USER_QUOTA) { |
f8149110 | 407 | if (remove_qtype_extents(dir, XFS_USER_QUOTA) < 0) |
79ac1ae4 DD |
408 | return; |
409 | } | |
410 | if (type & XFS_GROUP_QUOTA) { | |
f8149110 | 411 | if (remove_qtype_extents(dir, XFS_GROUP_QUOTA) < 0) |
79ac1ae4 DD |
412 | return; |
413 | } else if (type & XFS_PROJ_QUOTA) { | |
f8149110 | 414 | if (remove_qtype_extents(dir, XFS_PROJ_QUOTA) < 0) |
79ac1ae4 DD |
415 | return; |
416 | } | |
417 | if (flags & VERBOSE_FLAG) | |
5aead01d NS |
418 | state_quotafile_mount(stdout, type, mount, flags); |
419 | } | |
420 | ||
421 | static int | |
422 | enable_f( | |
423 | int argc, | |
424 | char **argv) | |
425 | { | |
426 | int c, flags = 0, qflags = 0, type = 0; | |
427 | ||
428 | while ((c = getopt(argc, argv, "gpuv")) != EOF) { | |
429 | switch (c) { | |
430 | case 'g': | |
431 | type |= XFS_GROUP_QUOTA; | |
432 | qflags |= XFS_QUOTA_GDQ_ACCT | XFS_QUOTA_GDQ_ENFD; | |
433 | break; | |
434 | case 'p': | |
435 | type |= XFS_PROJ_QUOTA; | |
436 | qflags |= XFS_QUOTA_PDQ_ACCT | XFS_QUOTA_PDQ_ENFD; | |
437 | break; | |
438 | case 'u': | |
439 | type |= XFS_USER_QUOTA; | |
440 | qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; | |
441 | break; | |
442 | case 'v': | |
443 | flags |= VERBOSE_FLAG; | |
444 | break; | |
445 | default: | |
446 | return command_usage(&enable_cmd); | |
447 | } | |
448 | } | |
449 | ||
450 | if (argc != optind) | |
451 | return command_usage(&enable_cmd); | |
452 | ||
79ac1ae4 | 453 | if (!type) { |
5aead01d NS |
454 | type |= XFS_USER_QUOTA; |
455 | qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; | |
456 | } | |
457 | ||
fa13a00f NS |
458 | if (fs_path->fs_flags & FS_MOUNT_POINT) |
459 | enable_enforcement(fs_path->fs_dir, type, qflags, flags); | |
5aead01d NS |
460 | return 0; |
461 | } | |
462 | ||
463 | static int | |
464 | disable_f( | |
465 | int argc, | |
466 | char **argv) | |
467 | { | |
468 | int c, flags = 0, qflags = 0, type = 0; | |
469 | ||
470 | while ((c = getopt(argc, argv, "gpuv")) != EOF) { | |
471 | switch (c) { | |
472 | case 'g': | |
473 | type |= XFS_GROUP_QUOTA; | |
79ac1ae4 | 474 | qflags |= XFS_QUOTA_GDQ_ENFD; |
5aead01d NS |
475 | break; |
476 | case 'p': | |
477 | type |= XFS_PROJ_QUOTA; | |
79ac1ae4 | 478 | qflags |= XFS_QUOTA_PDQ_ENFD; |
5aead01d NS |
479 | break; |
480 | case 'u': | |
481 | type |= XFS_USER_QUOTA; | |
79ac1ae4 | 482 | qflags |= XFS_QUOTA_UDQ_ENFD; |
5aead01d NS |
483 | break; |
484 | case 'v': | |
485 | flags |= VERBOSE_FLAG; | |
486 | break; | |
487 | default: | |
488 | return command_usage(&disable_cmd); | |
489 | } | |
490 | } | |
491 | ||
492 | if (argc != optind) | |
493 | return command_usage(&disable_cmd); | |
494 | ||
79ac1ae4 | 495 | if (!type) { |
5aead01d | 496 | type |= XFS_USER_QUOTA; |
79ac1ae4 | 497 | qflags |= XFS_QUOTA_UDQ_ENFD; |
5aead01d NS |
498 | } |
499 | ||
fa13a00f NS |
500 | if (fs_path->fs_flags & FS_MOUNT_POINT) |
501 | disable_enforcement(fs_path->fs_dir, type, qflags, flags); | |
5aead01d NS |
502 | return 0; |
503 | } | |
504 | ||
505 | static int | |
506 | off_f( | |
507 | int argc, | |
508 | char **argv) | |
509 | { | |
510 | int c, flags = 0, qflags = 0, type = 0; | |
511 | ||
512 | while ((c = getopt(argc, argv, "gpuv")) != EOF) { | |
513 | switch (c) { | |
514 | case 'g': | |
515 | type |= XFS_GROUP_QUOTA; | |
516 | qflags |= XFS_QUOTA_GDQ_ACCT | XFS_QUOTA_GDQ_ENFD; | |
517 | break; | |
518 | case 'p': | |
519 | type |= XFS_PROJ_QUOTA; | |
520 | qflags |= XFS_QUOTA_PDQ_ACCT | XFS_QUOTA_PDQ_ENFD; | |
521 | break; | |
522 | case 'u': | |
523 | type |= XFS_USER_QUOTA; | |
524 | qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; | |
525 | break; | |
526 | case 'v': | |
527 | flags |= VERBOSE_FLAG; | |
528 | break; | |
529 | default: | |
530 | return command_usage(&off_cmd); | |
531 | } | |
532 | } | |
533 | ||
534 | if (argc != optind) | |
535 | return command_usage(&off_cmd); | |
536 | ||
79ac1ae4 | 537 | if (!type) { |
5aead01d NS |
538 | type |= XFS_USER_QUOTA; |
539 | qflags |= XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD; | |
540 | } | |
541 | ||
fa13a00f NS |
542 | if (fs_path->fs_flags & FS_MOUNT_POINT) |
543 | quotaoff(fs_path->fs_dir, type, qflags, flags); | |
5aead01d NS |
544 | return 0; |
545 | } | |
546 | ||
547 | static int | |
548 | remove_f( | |
549 | int argc, | |
550 | char **argv) | |
551 | { | |
79ac1ae4 | 552 | int c, flags = 0, type = 0; |
5aead01d NS |
553 | |
554 | while ((c = getopt(argc, argv, "gpuv")) != EOF) { | |
555 | switch (c) { | |
556 | case 'g': | |
557 | type |= XFS_GROUP_QUOTA; | |
5aead01d NS |
558 | break; |
559 | case 'p': | |
560 | type |= XFS_PROJ_QUOTA; | |
5aead01d NS |
561 | break; |
562 | case 'u': | |
563 | type |= XFS_USER_QUOTA; | |
5aead01d NS |
564 | break; |
565 | case 'v': | |
566 | flags |= VERBOSE_FLAG; | |
567 | break; | |
568 | default: | |
569 | return command_usage(&remove_cmd); | |
570 | } | |
571 | } | |
572 | ||
573 | if (argc != optind) | |
574 | return command_usage(&remove_cmd); | |
575 | ||
79ac1ae4 | 576 | if (!type) { |
5aead01d | 577 | type |= XFS_USER_QUOTA; |
5aead01d NS |
578 | } |
579 | ||
fa13a00f | 580 | if (fs_path->fs_flags & FS_MOUNT_POINT) |
79ac1ae4 | 581 | remove_extents(fs_path->fs_dir, type, flags); |
5aead01d NS |
582 | return 0; |
583 | } | |
584 | ||
585 | void | |
586 | state_init(void) | |
587 | { | |
ad765595 | 588 | off_cmd.name = "off"; |
5aead01d NS |
589 | off_cmd.cfunc = off_f; |
590 | off_cmd.argmin = 0; | |
591 | off_cmd.argmax = -1; | |
592 | off_cmd.args = _("[-gpu] [-v]"); | |
593 | off_cmd.oneline = _("permanently switch quota off for a path"); | |
594 | off_cmd.help = off_help; | |
595 | ||
ad765595 | 596 | state_cmd.name = "state"; |
5aead01d NS |
597 | state_cmd.cfunc = state_f; |
598 | state_cmd.argmin = 0; | |
599 | state_cmd.argmax = -1; | |
62790d19 | 600 | state_cmd.args = _("[-gpu] [-a] [-v] [-f file]"); |
5aead01d NS |
601 | state_cmd.oneline = _("get overall quota state information"); |
602 | state_cmd.help = state_help; | |
29647c8d | 603 | state_cmd.flags = CMD_FLAG_FOREIGN_OK; |
5aead01d | 604 | |
ad765595 | 605 | enable_cmd.name = "enable"; |
5aead01d NS |
606 | enable_cmd.cfunc = enable_f; |
607 | enable_cmd.argmin = 0; | |
608 | enable_cmd.argmax = -1; | |
609 | enable_cmd.args = _("[-gpu] [-v]"); | |
610 | enable_cmd.oneline = _("enable quota enforcement"); | |
611 | enable_cmd.help = enable_help; | |
612 | ||
ad765595 | 613 | disable_cmd.name = "disable"; |
5aead01d NS |
614 | disable_cmd.cfunc = disable_f; |
615 | disable_cmd.argmin = 0; | |
616 | disable_cmd.argmax = -1; | |
617 | disable_cmd.args = _("[-gpu] [-v]"); | |
618 | disable_cmd.oneline = _("disable quota enforcement"); | |
619 | disable_cmd.help = disable_help; | |
620 | ||
ad765595 | 621 | remove_cmd.name = "remove"; |
5aead01d NS |
622 | remove_cmd.cfunc = remove_f; |
623 | remove_cmd.argmin = 0; | |
624 | remove_cmd.argmax = -1; | |
625 | remove_cmd.args = _("[-gpu] [-v]"); | |
626 | remove_cmd.oneline = _("remove quota extents from a filesystem"); | |
627 | remove_cmd.help = remove_help; | |
628 | ||
629 | if (expert) { | |
630 | add_command(&off_cmd); | |
631 | add_command(&state_cmd); | |
632 | add_command(&enable_cmd); | |
633 | add_command(&disable_cmd); | |
634 | add_command(&remove_cmd); | |
635 | } | |
636 | } |