X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=src%2Fvdlimit.c;h=3df67ba44bcb6baf0ec2690978fb18c7dad13d06;hb=5f167675beabb9f55df5fe8a579f87763764cb08;hp=beea0c5846ea08f9ad2bac08f054233323228075;hpb=903ac95d92d316979e0b2e5073d4252ac3af63b5;p=util-vserver.git diff --git a/src/vdlimit.c b/src/vdlimit.c index beea0c5..3df67ba 100644 --- a/src/vdlimit.c +++ b/src/vdlimit.c @@ -1,174 +1,296 @@ +// $Id: vdlimit.c,v 1.5 2007/06/28 15:20:30 dhozac Exp $ --*- c -*-- + +// Copyright (C) 2005 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -/* -** (c) 2004 Herbert Poetzl -** -** V0.01 ioctls so far -** -*/ #ifdef HAVE_CONFIG_H # include #endif -#include "compat.h" -#include -#include +#include "util.h" +#include + +#include + +#include +#include #include -#include -#include -#include -#include -#include -#include -#include - -#include "vserver.h" -#include "vserver-internal.h" -#include "dlimit.h" - -#ifdef O_LARGEFILE -#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) -#else -#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) -#endif +#include +#include + +#define ENSC_WRAPPERS_PREFIX "vdlimit: " +#define ENSC_WRAPPERS_UNISTD 1 +#define ENSC_WRAPPERS_VSERVER 1 +#include + +#define CMD_HELP 0x1000 +#define CMD_VERSION 0x1001 + +int wrapper_exit_code = 1; + +struct option const +CMDLINE_OPTIONS[] = { + { "help", no_argument, 0, CMD_HELP }, + { "version", no_argument, 0, CMD_VERSION }, + { "xid", required_argument, 0, 'x' }, + { "set", required_argument, 0, 's' }, + { "remove", no_argument, 0, 'd' }, + { "flags", required_argument, 0, 'f' }, + {0,0,0,0} +}; + +static void +showHelp(int fd, char const *cmd) +{ + WRITE_MSG(fd, "Usage: "); + WRITE_STR(fd, cmd); + WRITE_MSG(fd, + " --xid [--flags ] (--set =|--remove) \n" + "\n" + " --set|-s = ... set to , where limit is \n" + " one of: space_used, space_total, inodes_used,\n" + " inodes_total, reserved\n" + " --remove|-d ... removes the disk limit for from \n" + "\n" + "Please report bugs to " PACKAGE_BUGREPORT "\n"); + + exit(0); +} -static char err_flag = 0; +static void +showVersion() +{ + WRITE_MSG(1, + "vdlimit " VERSION " -- manages disk limits\n" + "This program is part of " PACKAGE_STRING "\n\n" + "Copyright (C) 2005 Enrico Scholz\n" + VERSION_COPYRIGHT_DISCLAIMER); + exit(0); +} + +static void +setDlimit(char const *filename, xid_t xid, uint32_t flags, struct vc_ctx_dlimit const *limit) +{ + bool was_added = false; + + if (vc_get_dlimit(filename, xid, flags, 0) == -1) { + if (vc_add_dlimit(filename, xid, flags) == -1) { + perror(ENSC_WRAPPERS_PREFIX "vc_add_dlimit()"); + exit(wrapper_exit_code); + } -static char opt_xid = 0; -static char opt_flag = 0; -static char opt_vers = 0; -static char opt_add = 0; -static char opt_rem = 0; -static char opt_set = 0; + was_added = true; + } -static char * cmd_name = NULL; -static char * set_arg = NULL; + if (vc_set_dlimit(filename, xid, flags, limit) == -1) { + perror(ENSC_WRAPPERS_PREFIX "vc_set_dlimit()"); -static int num_xid = 0; -static int num_flag = 0; + if (was_added && + vc_rem_dlimit(filename, xid, flags)==-1) + perror(ENSC_WRAPPERS_PREFIX "vc_rem_dlimit()"); + exit(wrapper_exit_code); + } +} +static void +remDlimit(char const *filename, xid_t xid, uint32_t flags) +{ + if (vc_rem_dlimit(filename, xid, flags) == -1) { + perror(ENSC_WRAPPERS_PREFIX "vc_rem_dlimit()"); + exit(wrapper_exit_code); + } +} +static void +writeInt(int fd, char const *prefix, int val) +{ + char buf[sizeof(val)*3 + 2]; + size_t len = utilvserver_fmt_int(buf, val); -#define OPTIONS "+hadf:x:S:V" + if (prefix) + WRITE_STR(fd, prefix); + Vwrite(fd, buf, len); +} -int main(int argc, char *argv[]) +static void +printDlimit(char const *filename, xid_t xid, uint32_t flags, bool formatted) { - extern int optind; - extern char *optarg; - char c, errflg = 0; - int r; - - - cmd_name = argv[0]; - while ((c = getopt(argc, argv, OPTIONS)) != EOF) { - switch (c) { - case 'h': - fprintf(stderr, - "This is %s " VERSION "\n" - "options are:\n" - "-h print this help message\n" - "-a add dlimit entry\n" - "-d delete dlimit entry\n" - "-f flag value in decimal\n" - "-x context id\n" - "-S current/limit values\n" - "-V verify interface version\n" - "-- end of options\n" - ,cmd_name); - exit(0); - break; - case 'a': - opt_add = 1; - break; - case 'd': - opt_rem = 1; - break; - case 'f': - num_flag = atol(optarg); - opt_flag = 1; - break; - case 'x': - num_xid = atol(optarg); - opt_xid = 1; - break; - case 'S': - set_arg = optarg; - opt_set = 1; - break; - case 'V': - opt_vers = 1; - break; - case '?': - default: - errflg++; - break; - } - } - if (errflg) { - fprintf(stderr, - "Usage: %s -[" OPTIONS "] ...\n" - "%s -h for help.\n", - cmd_name, cmd_name); - exit(2); - } - - if (opt_vers) { - r = vc_get_version(); - if (r<0) - perror("vc_get_version"); - else - printf("version: %04x:%04x\n", - (r>>16)&0xFFFF, r&0xFFFF); - } + struct vc_ctx_dlimit limit; + + if (vc_get_dlimit(filename, xid, flags, &limit) == -1) { + perror(ENSC_WRAPPERS_PREFIX "vc_get_dlimit()"); + exit(wrapper_exit_code); + } - for (; optind < argc; optind++) { - struct vcmd_ctx_dlimit_base_v0 init; - struct vcmd_ctx_dlimit_v0 data; - - init.name = argv[optind]; - init.flags = num_flag; - - if (opt_rem) { - r = vserver(VCMD_rem_dlimit, num_xid, &init); - if (r<0) - perror("vc_rem_dlimit"); - } - if (opt_add) { - r = vserver(VCMD_add_dlimit, num_xid, &init); - if (r<0) - perror("vc_add_dlimit"); - } - - memset(&data, 0, sizeof(data)); - data.name = argv[optind]; - data.flags = num_flag; - - if (opt_set) { - sscanf(set_arg, "%u,%u,%u,%u,%u", - &data.space_used, &data.space_total, - &data.inodes_used, &data.inodes_total, - &data.reserved); - - r = vserver(VCMD_set_dlimit, num_xid, &data); - if (r<0) - perror("vc_set_dlimit"); - } - - memset(&data, 0, sizeof(data)); - data.name = argv[optind]; - data.flags = num_flag; - - r = vserver(VCMD_get_dlimit, num_xid, &data); - if (r<0) - perror("vc_get_dlimit"); - - printf("%s: %u,%u,%u,%u,%u\n", argv[optind], - data.space_used, data.space_total, - data.inodes_used, data.inodes_total, - data.reserved); - } - - exit((err_flag)?1:0); + if (formatted) { + writeInt (1, 0, xid); + WRITE_MSG(1, " "); + WRITE_STR(1, filename); + writeInt (1, "\nspace_used=", limit.space_used); + writeInt (1, "\nspace_total=", limit.space_total); + writeInt (1, "\ninodes_used=", limit.inodes_used); + writeInt (1, "\ninodes_total=", limit.inodes_total); + writeInt (1, "\nreserved=", limit.reserved); + WRITE_MSG(1, "\n"); + } + else { + writeInt (1, 0, xid); + writeInt (1, " ", limit.space_used); + writeInt (1, " ", limit.space_total); + writeInt (1, " ", limit.inodes_used); + writeInt (1, " ", limit.inodes_total); + writeInt (1, " ", limit.reserved); + WRITE_MSG(1, " "); + WRITE_STR(1, filename); + WRITE_MSG(1, "\n"); + } } + +static bool +setDLimitField(struct vc_ctx_dlimit *dst, char const *opt) +{ + uint_least32_t *ptr; + char const * const orig_opt = opt; + +#define GET_VAL_PTR(CMP, VAL) \ + (strncmp(opt, CMP "=", sizeof(CMP))==0) ? \ + (opt+=sizeof(CMP), &VAL) : 0 + + if ((ptr=GET_VAL_PTR("space_used", dst->space_used))!=0) {} + else if ((ptr=GET_VAL_PTR("space_total", dst->space_total))!=0) {} + else if ((ptr=GET_VAL_PTR("inodes_used", dst->inodes_used))!=0) {} + else if ((ptr=GET_VAL_PTR("inodes_total", dst->inodes_total))!=0) {} + else if ((ptr=GET_VAL_PTR("reserved", dst->reserved))!=0) {} + else ptr=0; + +#undef GET_VAL_PTR + + if (ptr!=0 && *ptr==VC_CDLIM_KEEP) { + char *endptr; + long val = strtol(opt, &endptr, 0); + + if (*opt==0 || *endptr!='\0') { + WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "can not parse number in '"); + WRITE_STR(2, orig_opt); + WRITE_MSG(2, "'\n"); + return false; + } + + *ptr = val; + } + else if (ptr!=0) { + WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "value already set in '"); + WRITE_STR(2, orig_opt); + WRITE_MSG(2, "'\n"); + return false; + } + else { + WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "unknown limit in '"); + WRITE_STR(2, orig_opt); + WRITE_MSG(2, "'\n"); + return false; + } + + return true; +} + +bool +isHigherLimit(uint_least32_t lhs, uint_least32_t rhs) +{ + if (lhs==VC_CDLIM_KEEP || rhs==VC_CDLIM_KEEP) return false; + + return lhs > rhs; +} + +int main(int argc, char *argv[]) +{ + bool do_set = false; + bool do_remove = false; + xid_t xid = VC_NOCTX; + uint32_t flags = 0; + char *endptr; + int sum = 0; + + struct vc_ctx_dlimit limit = { + .space_used = VC_CDLIM_KEEP, + .space_total = VC_CDLIM_KEEP, + .inodes_used = VC_CDLIM_KEEP, + .inodes_total = VC_CDLIM_KEEP, + .reserved = VC_CDLIM_KEEP + }; + + while (1) { + int c = getopt_long(argc, argv, "+x:s:df:", CMDLINE_OPTIONS, 0); + if (c==-1) break; + + switch (c) { + case CMD_HELP : showHelp(1, argv[0]); + case CMD_VERSION : showVersion(); + case 'x' : xid = Evc_xidopt2xid(optarg, true); break; + case 's' : + if (!setDLimitField(&limit, optarg)) + return EXIT_FAILURE; + else + do_set = true; + break; + case 'd' : do_remove = true; break; + case 'f' : + { + flags = strtol(optarg, &endptr, 0); + if ((flags == 0 && errno != 0) || *endptr != '\0') { + WRITE_MSG(2, "Invalid flags argument: '"); + WRITE_STR(2, optarg); + WRITE_MSG(2, "'; try '--help' for more information\n"); + return EXIT_FAILURE; + } + } + break; + + default : + WRITE_MSG(2, "Try '"); + WRITE_STR(2, argv[0]); + WRITE_MSG(2, " --help' for more information.\n"); + return EXIT_FAILURE; + break; + } + } + + sum = ((do_set ? 1 : 0) + (do_remove ? 1 : 0)); + + if (sum>1) + WRITE_MSG(2, "Can not specify multiple operations; try '--help' for more information\n"); + else if (optind==argc) + WRITE_MSG(2, "No mount point specified; try '--help' for more information\n"); + else if (xid==VC_NOCTX) + WRITE_MSG(2, "No xid specified; try '--help' for more information\n"); + else if (isHigherLimit(limit.space_used, limit.space_total)) + WRITE_MSG(2, "invalid parameters: 'space_used' is larger than 'space_total'\n"); + else if (isHigherLimit(limit.inodes_used, limit.inodes_total)) + WRITE_MSG(2, "invalid parameters: 'inodes_used' is larger than 'inodes_total'\n"); + else { + for (; optind < argc; ++optind) { + if (do_set) setDlimit(argv[optind], xid, flags, &limit); + else if (do_remove) remDlimit(argv[optind], xid, flags); + else printDlimit(argv[optind], xid, flags, true); + } + + return EXIT_SUCCESS; + } + + return EXIT_FAILURE; +}