3 // Copyright (C) 2005 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
9 // This program is distributed in the hope that it will 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 to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include <lib_internal/sys_clone.h>
25 #include <lib/internal.h>
35 #define ENSC_WRAPPERS_PREFIX "vdlimit: "
36 #define ENSC_WRAPPERS_UNISTD 1
37 #define ENSC_WRAPPERS_VSERVER 1
40 #define CMD_HELP 0x1000
41 #define CMD_VERSION 0x1001
43 int wrapper_exit_code = 1;
47 { "help", no_argument, 0, CMD_HELP },
48 { "version", no_argument, 0, CMD_VERSION },
49 { "xid", required_argument, 0, 'x' },
50 { "set", required_argument, 0, 's' },
51 { "remove", no_argument, 0, 'd' },
52 { "flags", required_argument, 0, 'f' },
57 showHelp(int fd, char const *cmd)
59 WRITE_MSG(fd, "Usage: ");
62 " --xid <xid> [--flags <flags>] (--set <limit>=<value>|--remove) <mount point>\n"
64 " --set|-s <limit>=<value> ... set <limit> to <value>, where limit is \n"
65 " one of: space_used, space_total, inodes_used,\n"
66 " inodes_total, reserved\n"
67 " --remove|-d ... removes the disk limit for <xid> from <mount point>\n"
69 "Please report bugs to " PACKAGE_BUGREPORT "\n");
78 "vdlimit " VERSION " -- manages disk limits\n"
79 "This program is part of " PACKAGE_STRING "\n\n"
80 "Copyright (C) 2005 Enrico Scholz\n"
81 VERSION_COPYRIGHT_DISCLAIMER);
86 setDlimit(char const *filename, xid_t xid, uint32_t flags, struct vc_ctx_dlimit const *limit)
88 bool was_added = false;
90 if (vc_get_dlimit(filename, xid, flags, 0) == -1) {
91 if (vc_add_dlimit(filename, xid, flags) == -1) {
92 perror(ENSC_WRAPPERS_PREFIX "vc_add_dlimit()");
93 exit(wrapper_exit_code);
99 if (vc_set_dlimit(filename, xid, flags, limit) == -1) {
100 perror(ENSC_WRAPPERS_PREFIX "vc_set_dlimit()");
103 vc_rem_dlimit(filename, xid, flags)==-1)
104 perror(ENSC_WRAPPERS_PREFIX "vc_rem_dlimit()");
106 exit(wrapper_exit_code);
111 remDlimit(char const *filename, xid_t xid, uint32_t flags)
113 if (vc_rem_dlimit(filename, xid, flags) == -1) {
114 perror(ENSC_WRAPPERS_PREFIX "vc_rem_dlimit()");
115 exit(wrapper_exit_code);
120 writeInt(int fd, char const *prefix, int val)
122 char buf[sizeof(val)*3 + 2];
123 size_t len = utilvserver_fmt_int(buf, val);
126 WRITE_STR(fd, prefix);
127 Vwrite(fd, buf, len);
131 printDlimit(char const *filename, xid_t xid, uint32_t flags, bool formatted)
133 struct vc_ctx_dlimit limit;
135 if (vc_get_dlimit(filename, xid, flags, &limit) == -1) {
136 perror(ENSC_WRAPPERS_PREFIX "vc_get_dlimit()");
137 exit(wrapper_exit_code);
141 writeInt (1, 0, xid);
143 WRITE_STR(1, filename);
144 writeInt (1, "\nspace_used=", limit.space_used);
145 writeInt (1, "\nspace_total=", limit.space_total);
146 writeInt (1, "\ninodes_used=", limit.inodes_used);
147 writeInt (1, "\ninodes_total=", limit.inodes_total);
148 writeInt (1, "\nreserved=", limit.reserved);
152 writeInt (1, 0, xid);
153 writeInt (1, " ", limit.space_used);
154 writeInt (1, " ", limit.space_total);
155 writeInt (1, " ", limit.inodes_used);
156 writeInt (1, " ", limit.inodes_total);
157 writeInt (1, " ", limit.reserved);
159 WRITE_STR(1, filename);
166 setDLimitField(struct vc_ctx_dlimit *dst, char const *opt)
169 char const * const orig_opt = opt;
171 #define GET_VAL_PTR(CMP, VAL) \
172 (strncmp(opt, CMP "=", sizeof(CMP))==0) ? \
173 (opt+=sizeof(CMP), &VAL) : 0
175 if ((ptr=GET_VAL_PTR("space_used", dst->space_used))!=0) {}
176 else if ((ptr=GET_VAL_PTR("space_total", dst->space_total))!=0) {}
177 else if ((ptr=GET_VAL_PTR("inodes_used", dst->inodes_used))!=0) {}
178 else if ((ptr=GET_VAL_PTR("inodes_total", dst->inodes_total))!=0) {}
179 else if ((ptr=GET_VAL_PTR("reserved", dst->reserved))!=0) {}
184 if (ptr!=0 && *ptr==VC_CDLIM_KEEP) {
186 long val = strtol(opt, &endptr, 0);
188 if (*opt==0 || *endptr!='\0') {
189 WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "can not parse number in '");
190 WRITE_STR(2, orig_opt);
198 WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "value already set in '");
199 WRITE_STR(2, orig_opt);
204 WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "unknown limit in '");
205 WRITE_STR(2, orig_opt);
214 isHigherLimit(uint_least32_t lhs, uint_least32_t rhs)
216 if (lhs==VC_CDLIM_KEEP || rhs==VC_CDLIM_KEEP) return false;
221 int main(int argc, char *argv[])
224 bool do_remove = false;
225 xid_t xid = VC_NOCTX;
230 struct vc_ctx_dlimit limit = {
231 .space_used = VC_CDLIM_KEEP,
232 .space_total = VC_CDLIM_KEEP,
233 .inodes_used = VC_CDLIM_KEEP,
234 .inodes_total = VC_CDLIM_KEEP,
235 .reserved = VC_CDLIM_KEEP
239 int c = getopt_long(argc, argv, "+x:s:df:", CMDLINE_OPTIONS, 0);
243 case CMD_HELP : showHelp(1, argv[0]);
244 case CMD_VERSION : showVersion();
245 case 'x' : xid = Evc_xidopt2xid(optarg, true); break;
247 if (!setDLimitField(&limit, optarg))
252 case 'd' : do_remove = true; break;
255 flags = strtol(optarg, &endptr, 0);
256 if ((flags == 0 && errno != 0) || *endptr != '\0') {
257 WRITE_MSG(2, "Invalid flags argument: '");
258 WRITE_STR(2, optarg);
259 WRITE_MSG(2, "'; try '--help' for more information\n");
266 WRITE_MSG(2, "Try '");
267 WRITE_STR(2, argv[0]);
268 WRITE_MSG(2, " --help' for more information.\n");
274 sum = ((do_set ? 1 : 0) + (do_remove ? 1 : 0));
277 WRITE_MSG(2, "Can not specify multiple operations; try '--help' for more information\n");
278 else if (optind==argc)
279 WRITE_MSG(2, "No mount point specified; try '--help' for more information\n");
280 else if (xid==VC_NOCTX)
281 WRITE_MSG(2, "No xid specified; try '--help' for more information\n");
282 else if (isHigherLimit(limit.space_used, limit.space_total))
283 WRITE_MSG(2, "invalid parameters: 'space_used' is larger than 'space_total'\n");
284 else if (isHigherLimit(limit.inodes_used, limit.inodes_total))
285 WRITE_MSG(2, "invalid parameters: 'inodes_used' is larger than 'inodes_total'\n");
287 for (; optind < argc; ++optind) {
288 if (do_set) setDlimit(argv[optind], xid, flags, &limit);
289 else if (do_remove) remDlimit(argv[optind], xid, flags);
290 else printDlimit(argv[optind], xid, flags, true);