]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - quota/edit.c
2 * Copyright (c) 2005 Silicon Graphics, Inc.
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.
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.
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
27 static cmdinfo_t limit_cmd
;
28 static cmdinfo_t restore_cmd
;
29 static cmdinfo_t timer_cmd
;
30 static cmdinfo_t warn_cmd
;
37 " modify quota limits for the specified user\n"
40 " 'limit bsoft=100m bhard=110m tanya\n"
42 " Changes the soft and/or hard block limits, inode limits and/or realtime\n"
43 " block limits that are currently being used for the specified user, group,\n"
44 " or project. The filesystem identified by the current path is modified.\n"
45 " -d -- set the default values, used the first time a file is created\n"
46 " -g -- modify group quota limits\n"
47 " -p -- modify project quota limits\n"
48 " -u -- modify user quota limits\n"
49 " The block limit values can be specified with a units suffix - accepted\n"
50 " units are: k (kilobytes), m (megabytes), g (gigabytes), and t (terabytes).\n"
51 " The user/group/project can be specified either by name or by number.\n"
60 " modify quota enforcement timeout for the current filesystem\n"
64 " (soft inode limit timer is changed to 3 days)\n"
66 " Changes the timeout value associated with the block limits, inode limits\n"
67 " and/or realtime block limits for all users, groups, or projects on the\n"
68 " current filesystem.\n"
69 " As soon as a user consumes the amount of space or number of inodes set as\n"
70 " the soft limit, a timer is started. If the timer expires and the user is\n"
71 " still over the soft limit, the soft limit is enforced as the hard limit.\n"
72 " The default timeout is 7 days.\n"
73 " -d -- set the default values, used the first time a file is created\n"
74 " -g -- modify group quota timer\n"
75 " -p -- modify project quota timer\n"
76 " -u -- modify user quota timer\n"
77 " -b -- modify the blocks-used timer\n"
78 " -i -- modify the inodes-used timer\n"
79 " -r -- modify the blocks-used timer for the (optional) realtime subvolume\n"
80 " The timeout value is specified as a number of seconds, by default.\n"
81 " However, a suffix may be used to alternatively specify minutes (m),\n"
82 " hours (h), days (d), or weeks (w) - either the full word or the first\n"
83 " letter of the word can be used.\n"
92 " modify the number of quota warnings sent to the specified user\n"
96 " (tell the quota system that two warnings have been sent to user jimmy)\n"
98 " Changes the warning count associated with the block limits, inode limits\n"
99 " and/or realtime block limits for the specified user, group, or project.\n"
100 " When a user has been warned the maximum number of times allowed, the soft\n"
101 " limit is enforced as the hard limit. It is intended as an alternative to\n"
102 " the timeout system, where the system administrator updates a count of the\n"
103 " number of warnings issued to people, and they are penalised if the warnings\n"
105 " -d -- set maximum warning count, which triggers soft limit enforcement\n"
106 " -g -- set group quota warning count\n"
107 " -p -- set project quota warning count\n"
108 " -u -- set user quota warning count\n"
109 " -b -- set the blocks-used warning count\n"
110 " -i -- set the inodes-used warning count\n"
111 " -r -- set the blocks-used warn count for the (optional) realtime subvolume\n"
112 " The user/group/project can be specified either by name or by number.\n"
131 memset(&d
, 0, sizeof(d
));
132 d
.d_version
= FS_DQUOT_VERSION
;
135 d
.d_fieldmask
= mask
;
136 d
.d_blk_hardlimit
= *bhard
;
137 d
.d_blk_softlimit
= *bsoft
;
138 d
.d_ino_hardlimit
= *ihard
;
139 d
.d_ino_softlimit
= *isoft
;
140 d
.d_rtb_hardlimit
= *rtbhard
;
141 d
.d_rtb_softlimit
= *rtbsoft
;
143 if (xfsquotactl(XFS_SETQLIM
, dev
, type
, id
, (void *)&d
) < 0) {
145 fprintf(stderr
, _("%s: cannot set limits: %s\n"),
146 progname
, strerror(errno
));
162 uid_t uid
= uid_from_string(name
);
166 fprintf(stderr
, _("%s: invalid user name: %s\n"),
169 set_limits(uid
, type
, mask
, fs_path
->fs_name
,
170 bsoft
, bhard
, isoft
, ihard
, rtbsoft
, rtbhard
);
185 gid_t gid
= gid_from_string(name
);
189 fprintf(stderr
, _("%s: invalid group name: %s\n"),
192 set_limits(gid
, type
, mask
, fs_path
->fs_name
,
193 bsoft
, bhard
, isoft
, ihard
, rtbsoft
, rtbhard
);
208 prid_t prid
= prid_from_string(name
);
212 fprintf(stderr
, _("%s: invalid project name: %s\n"),
215 set_limits(prid
, type
, mask
, fs_path
->fs_name
,
216 bsoft
, bhard
, isoft
, ihard
, rtbsoft
, rtbhard
);
219 /* extract number of blocks from an ascii string */
232 if (strncmp(string
, prefix
, length
) == 0) {
233 s
= string
+ length
+ 1;
234 v
= cvtnum(blocksize
, sectorsize
, s
);
237 _("%s: Error: could not parse size %s.\n"),
241 *value
= (uint64_t)v
>> 9; /* syscalls use basic blocks */
242 if (v
> 0 && *value
== 0)
243 fprintf(stderr
, _("%s: Warning: `%s' in quota blocks is 0 (unlimited).\n"), progname
, s
);
249 /* extract number of inodes from an ascii string */
257 char *sp
, *s
= string
;
259 if (strncmp(string
, prefix
, length
) == 0) {
260 s
= string
+ length
+ 1;
261 *value
= strtoll(s
, &sp
, 0);
273 uint64_t bsoft
, bhard
, isoft
, ihard
, rtbsoft
, rtbhard
;
274 int c
, type
= 0, mask
= 0, flags
= 0;
275 uint bsize
, ssize
, endoptions
;
277 init_cvtnum(&bsize
, &ssize
);
278 bsoft
= bhard
= isoft
= ihard
= rtbsoft
= rtbhard
= 0;
279 while ((c
= getopt(argc
, argv
, "dgpu")) != EOF
) {
282 flags
|= DEFAULTS_FLAG
;
285 type
|= XFS_GROUP_QUOTA
;
288 type
|= XFS_PROJ_QUOTA
;
291 type
|= XFS_USER_QUOTA
;
294 return command_usage(&limit_cmd
);
299 * In the usual case, we need at least 2 more arguments -
300 * one (or more) limits and a user name/id.
301 * For setting defaults (-d) we don't want a user name/id.
303 if (flags
& DEFAULTS_FLAG
) {
304 if (argc
< optind
+ 1)
305 return command_usage(&limit_cmd
);
307 } else if (argc
< optind
+ 2) {
308 return command_usage(&limit_cmd
);
314 * Extract limit values from remaining optional arguments.
316 while (argc
> optind
+ endoptions
- 1) {
317 char *s
= argv
[optind
++];
318 if (extractb(s
, "bsoft=", 5, bsize
, ssize
, &bsoft
))
320 else if (extractb(s
, "bhard=", 5, bsize
, ssize
, &bhard
))
322 else if (extracti(s
, "isoft=", 5, &isoft
))
324 else if (extracti(s
, "ihard=", 5, &ihard
))
326 else if (extractb(s
, "rtbsoft=", 7, bsize
, ssize
, &rtbsoft
))
327 mask
|= FS_DQ_RTBSOFT
;
328 else if (extractb(s
, "rtbhard=", 7, bsize
, ssize
, &rtbhard
))
329 mask
|= FS_DQ_RTBHARD
;
332 fprintf(stderr
, _("%s: unrecognised argument %s\n"),
339 fprintf(stderr
, _("%s: cannot find any valid arguments\n"),
344 name
= (flags
& DEFAULTS_FLAG
) ? "0" : argv
[optind
++];
347 type
= XFS_USER_QUOTA
;
348 } else if (type
!= XFS_GROUP_QUOTA
&&
349 type
!= XFS_PROJ_QUOTA
&&
350 type
!= XFS_USER_QUOTA
) {
351 return command_usage(&limit_cmd
);
356 set_user_limits(name
, type
, mask
,
357 &bsoft
, &bhard
, &isoft
, &ihard
, &rtbsoft
, &rtbhard
);
359 case XFS_GROUP_QUOTA
:
360 set_group_limits(name
, type
, mask
,
361 &bsoft
, &bhard
, &isoft
, &ihard
, &rtbsoft
, &rtbhard
);
364 set_project_limits(name
, type
, mask
,
365 &bsoft
, &bhard
, &isoft
, &ihard
, &rtbsoft
, &rtbhard
);
372 * Iterate through input file, restoring the limits.
373 * File format is as follows:
375 * <numeric id> bsoft bhard isoft ihard [rtbsoft rtbhard]
388 uint64_t bsoft
, bhard
, isoft
, ihard
, rtbsoft
, rtbhard
;
390 while (fgets(buffer
, sizeof(buffer
), fp
) != NULL
) {
391 if (strncmp("fs = ", buffer
, 5) == 0) {
392 dev
= strncpy(devbuffer
, buffer
+5, sizeof(devbuffer
));
393 dev
[strlen(dev
) - 1] = '\0';
396 rtbsoft
= rtbhard
= 0;
397 cnt
= sscanf(buffer
, "%u %llu %llu %llu %llu %llu %llu\n",
399 (unsigned long long *)&bsoft
,
400 (unsigned long long *)&bhard
,
401 (unsigned long long *)&isoft
,
402 (unsigned long long *)&ihard
,
403 (unsigned long long *)&rtbsoft
,
404 (unsigned long long *)&rtbhard
);
405 if (cnt
== 5 || cnt
== 7) {
406 mask
= FS_DQ_ISOFT
|FS_DQ_IHARD
|FS_DQ_BSOFT
|FS_DQ_BHARD
;
408 mask
|= FS_DQ_RTBSOFT
|FS_DQ_RTBHARD
;
409 set_limits(id
, type
, mask
, dev
, &bsoft
, &bhard
,
410 &isoft
, &ihard
, &rtbsoft
, &rtbhard
);
424 while ((c
= getopt(argc
, argv
, "f:gpu")) != EOF
) {
430 type
|= XFS_GROUP_QUOTA
;
433 type
|= XFS_PROJ_QUOTA
;
436 type
|= XFS_USER_QUOTA
;
439 return command_usage(&restore_cmd
);
444 return command_usage(&restore_cmd
);
447 type
= XFS_USER_QUOTA
;
448 } else if (type
!= XFS_GROUP_QUOTA
&&
449 type
!= XFS_PROJ_QUOTA
&&
450 type
!= XFS_USER_QUOTA
) {
451 return command_usage(&restore_cmd
);
455 if ((fp
= fopen(fname
, "r")) == NULL
) {
457 fprintf(stderr
, _("%s: fopen on %s failed: %s\n"),
458 progname
, fname
, strerror(errno
));
463 restore_file(fp
, type
);
479 memset(&d
, 0, sizeof(d
));
480 d
.d_version
= FS_DQUOT_VERSION
;
482 d
.d_fieldmask
= mask
;
485 d
.d_rtbtimer
= value
;
487 if (xfsquotactl(XFS_SETQLIM
, dev
, type
, 0, (void *)&d
) < 0) {
489 fprintf(stderr
, _("%s: cannot set timer: %s\n"),
490 progname
, strerror(errno
));
500 int c
, type
= 0, mask
= 0;
502 while ((c
= getopt(argc
, argv
, "bgipru")) != EOF
) {
505 mask
|= FS_DQ_BTIMER
;
508 mask
|= FS_DQ_ITIMER
;
511 mask
|= FS_DQ_RTBTIMER
;
514 type
|= XFS_GROUP_QUOTA
;
517 type
|= XFS_PROJ_QUOTA
;
520 type
|= XFS_USER_QUOTA
;
523 return command_usage(&timer_cmd
);
527 if (argc
!= optind
+ 1)
528 return command_usage(&timer_cmd
);
530 value
= cvttime(argv
[optind
++]);
533 mask
= FS_DQ_TIMER_MASK
;
536 type
= XFS_USER_QUOTA
;
537 } else if (type
!= XFS_GROUP_QUOTA
&&
538 type
!= XFS_PROJ_QUOTA
&&
539 type
!= XFS_USER_QUOTA
) {
540 return command_usage(&timer_cmd
);
543 set_timer(type
, mask
, fs_path
->fs_name
, value
);
557 memset(&d
, 0, sizeof(d
));
558 d
.d_version
= FS_DQUOT_VERSION
;
561 d
.d_fieldmask
= mask
;
564 d
.d_rtbwarns
= value
;
566 if (xfsquotactl(XFS_SETQLIM
, dev
, type
, id
, (void *)&d
) < 0) {
568 fprintf(stderr
, _("%s: cannot set warnings: %s\n"),
569 progname
, strerror(errno
));
580 uid_t uid
= uid_from_string(name
);
584 fprintf(stderr
, _("%s: invalid user name: %s\n"),
587 set_warnings(uid
, type
, mask
, fs_path
->fs_name
, value
);
597 gid_t gid
= gid_from_string(name
);
601 fprintf(stderr
, _("%s: invalid group name: %s\n"),
604 set_warnings(gid
, type
, mask
, fs_path
->fs_name
, value
);
608 set_project_warnings(
614 prid_t prid
= prid_from_string(name
);
618 fprintf(stderr
, _("%s: invalid project name: %s\n"),
621 set_warnings(prid
, type
, mask
, fs_path
->fs_name
, value
);
631 int c
, flags
= 0, type
= 0, mask
= 0;
633 while ((c
= getopt(argc
, argv
, "bdgipru")) != EOF
) {
636 flags
|= DEFAULTS_FLAG
;
639 mask
|= FS_DQ_BWARNS
;
642 mask
|= FS_DQ_IWARNS
;
645 mask
|= FS_DQ_RTBWARNS
;
648 type
|= XFS_GROUP_QUOTA
;
651 type
|= XFS_PROJ_QUOTA
;
654 type
|= XFS_USER_QUOTA
;
657 return command_usage(&warn_cmd
);
662 * In the usual case, we need at least 2 more arguments -
663 * one (or more) value and a user name/id.
664 * For setting defaults (-d) we don't want a user name/id.
666 if (flags
& DEFAULTS_FLAG
) {
667 if (argc
!= optind
+ 1)
668 return command_usage(&warn_cmd
);
669 } else if (argc
!= optind
+ 2) {
670 return command_usage(&warn_cmd
);
673 value
= atoi(argv
[optind
++]);
674 name
= (flags
& DEFAULTS_FLAG
) ? "0" : argv
[optind
++];
677 mask
= FS_DQ_WARNS_MASK
;
680 type
= XFS_USER_QUOTA
;
681 } else if (type
!= XFS_GROUP_QUOTA
&&
682 type
!= XFS_PROJ_QUOTA
&&
683 type
!= XFS_USER_QUOTA
) {
684 return command_usage(&warn_cmd
);
689 set_user_warnings(name
, type
, mask
, value
);
691 case XFS_GROUP_QUOTA
:
692 set_group_warnings(name
, type
, mask
, value
);
695 set_project_warnings(name
, type
, mask
, value
);
704 limit_cmd
.name
= "limit";
705 limit_cmd
.cfunc
= limit_f
;
706 limit_cmd
.argmin
= 2;
707 limit_cmd
.argmax
= -1;
709 _("[-g|-p|-u] bsoft|bhard|isoft|ihard|rtbsoft|rtbhard=N -d|id|name");
710 limit_cmd
.oneline
= _("modify quota limits");
711 limit_cmd
.help
= limit_help
;
712 limit_cmd
.flags
= CMD_FLAG_FOREIGN_OK
;
714 restore_cmd
.name
= "restore";
715 restore_cmd
.cfunc
= restore_f
;
716 restore_cmd
.argmin
= 0;
717 restore_cmd
.argmax
= -1;
718 restore_cmd
.args
= _("[-g|-p|-u] [-f file]");
719 restore_cmd
.oneline
= _("restore quota limits from a backup file");
720 restore_cmd
.flags
= CMD_FLAG_FOREIGN_OK
;
722 timer_cmd
.name
= "timer";
723 timer_cmd
.cfunc
= timer_f
;
724 timer_cmd
.argmin
= 2;
725 timer_cmd
.argmax
= -1;
726 timer_cmd
.args
= _("[-bir] [-g|-p|-u] value");
727 timer_cmd
.oneline
= _("set quota enforcement timeouts");
728 timer_cmd
.help
= timer_help
;
729 timer_cmd
.flags
= CMD_FLAG_FOREIGN_OK
;
731 warn_cmd
.name
= "warn";
732 warn_cmd
.cfunc
= warn_f
;
734 warn_cmd
.argmax
= -1;
735 warn_cmd
.args
= _("[-bir] [-g|-p|-u] value -d|id|name");
736 warn_cmd
.oneline
= _("get/set enforcement warning counter");
737 warn_cmd
.help
= warn_help
;
740 add_command(&limit_cmd
);
741 add_command(&restore_cmd
);
742 add_command(&timer_cmd
);
743 add_command(&warn_cmd
);