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