vshost-util-vserver

Build script and sources for util-vserver.
git clone https://ccx.te2000.cz/git/vshost-util-vserver
Log | Files | Refs

vdlimit.c (8240B)


      1 // $Id$    --*- c -*--
      2 
      3 // Copyright (C) 2005 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
      4 //  
      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.
      8 //  
      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.
     13 //  
     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.
     17 
     18 
     19 #ifdef HAVE_CONFIG_H
     20 #  include <config.h>
     21 #endif
     22 
     23 #include "util.h"
     24 #include <lib/internal.h>
     25 
     26 #include <vserver.h>
     27 
     28 #include <getopt.h>
     29 #include <libgen.h>
     30 #include <errno.h>
     31 #include <signal.h>
     32 #include <sched.h>
     33 
     34 #define ENSC_WRAPPERS_PREFIX	"vdlimit: "
     35 #define ENSC_WRAPPERS_UNISTD	1
     36 #define ENSC_WRAPPERS_VSERVER	1
     37 #include <wrappers.h>
     38 
     39 #define CMD_HELP		0x1000
     40 #define CMD_VERSION		0x1001
     41 
     42 int		wrapper_exit_code  =  1;
     43 
     44 struct option const
     45 CMDLINE_OPTIONS[] = {
     46   { "help",       no_argument,       0, CMD_HELP },
     47   { "version",    no_argument,       0, CMD_VERSION },
     48   { "xid",        required_argument, 0, 'x' },
     49   { "set",        required_argument, 0, 's' },
     50   { "remove",     no_argument,       0, 'd' },
     51   { "flags",      required_argument, 0, 'f' },
     52   {0,0,0,0}
     53 };
     54 
     55 static void
     56 showHelp(int fd, char const *cmd)
     57 {
     58   WRITE_MSG(fd, "Usage: ");
     59   WRITE_STR(fd, cmd);
     60   WRITE_MSG(fd,
     61 	    " --xid <xid> [--flags <flags>] (--set <limit>=<value>|--remove) <mount point>\n"
     62 	    "\n"
     63 	    "    --set|-s <limit>=<value>  ...  set <limit> to <value>, where limit is \n"
     64 	    "                           one of: space_used, space_total, inodes_used,\n"
     65 	    "                           inodes_total, reserved\n"
     66 	    "    --remove|-d       ...  removes the disk limit for <xid> from <mount point>\n"
     67 	    "\n"
     68 	    "Please report bugs to " PACKAGE_BUGREPORT "\n");
     69 
     70   exit(0);
     71 }
     72 
     73 static void
     74 showVersion()
     75 {
     76   WRITE_MSG(1,
     77 	    "vdlimit " VERSION " -- manages disk limits\n"
     78 	    "This program is part of " PACKAGE_STRING "\n\n"
     79 	    "Copyright (C) 2005 Enrico Scholz\n"
     80 	    VERSION_COPYRIGHT_DISCLAIMER);
     81   exit(0);
     82 }
     83 
     84 static void
     85 setDlimit(char const *filename, xid_t xid, uint32_t flags, struct vc_ctx_dlimit const *limit)
     86 {
     87   bool		was_added = false;
     88 
     89   if (vc_get_dlimit(filename, xid, flags, 0) == -1) {
     90     if (vc_add_dlimit(filename, xid, flags) == -1) {
     91       perror(ENSC_WRAPPERS_PREFIX "vc_add_dlimit()");
     92       exit(wrapper_exit_code);
     93     }
     94 
     95     was_added = true;
     96   }
     97 
     98   if (vc_set_dlimit(filename, xid, flags, limit) == -1) {
     99     perror(ENSC_WRAPPERS_PREFIX "vc_set_dlimit()");
    100 
    101     if (was_added &&
    102 	vc_rem_dlimit(filename, xid, flags)==-1)
    103       perror(ENSC_WRAPPERS_PREFIX "vc_rem_dlimit()");
    104 
    105     exit(wrapper_exit_code);
    106   }
    107 }
    108 
    109 static void
    110 remDlimit(char const *filename, xid_t xid, uint32_t flags)
    111 {
    112   if (vc_rem_dlimit(filename, xid, flags) == -1) {
    113     perror(ENSC_WRAPPERS_PREFIX "vc_rem_dlimit()");
    114     exit(wrapper_exit_code);
    115   }
    116 }
    117 
    118 static void
    119 writeInt(int fd, char const *prefix, unsigned int val)
    120 {
    121   char		buf[sizeof(val)*3 + 2];
    122   size_t	len = utilvserver_fmt_uint(buf, val);
    123 
    124   if (prefix)
    125     WRITE_STR(fd, prefix);
    126   if (val == VC_CDLIM_INFINITY)
    127     WRITE_STR(fd, "-1");
    128   else
    129     Vwrite(fd, buf, len);
    130 }
    131 
    132 static void
    133 printDlimit(char const *filename, xid_t xid, uint32_t flags, bool formatted)
    134 {
    135   struct vc_ctx_dlimit		limit;
    136   
    137   if (vc_get_dlimit(filename, xid, flags, &limit) == -1) {
    138     perror(ENSC_WRAPPERS_PREFIX "vc_get_dlimit()");
    139     exit(wrapper_exit_code);
    140   }
    141 
    142   if (formatted) {
    143     writeInt (1, 0, xid);
    144     WRITE_MSG(1, " ");
    145     WRITE_STR(1, filename);
    146     writeInt (1, "\nspace_used=",   limit.space_used);
    147     writeInt (1, "\nspace_total=",  limit.space_total);
    148     writeInt (1, "\ninodes_used=",  limit.inodes_used);
    149     writeInt (1, "\ninodes_total=", limit.inodes_total);
    150     writeInt (1, "\nreserved=",     limit.reserved);
    151     WRITE_MSG(1, "\n");
    152   }
    153   else {
    154     writeInt (1, 0,   xid);
    155     writeInt (1, " ", limit.space_used);
    156     writeInt (1, " ", limit.space_total);
    157     writeInt (1, " ", limit.inodes_used);
    158     writeInt (1, " ", limit.inodes_total);
    159     writeInt (1, " ", limit.reserved);
    160     WRITE_MSG(1, " ");
    161     WRITE_STR(1, filename);
    162     WRITE_MSG(1, "\n");
    163   }
    164 }
    165 
    166 
    167 static bool
    168 setDLimitField(struct vc_ctx_dlimit *dst, char const *opt)
    169 {
    170   uint_least32_t	*ptr;
    171   char const * const	orig_opt = opt;
    172 
    173 #define GET_VAL_PTR(CMP, VAL)						\
    174   (strncmp(opt, CMP "=", sizeof(CMP))==0) ?				\
    175   (opt+=sizeof(CMP), &VAL) : 0
    176   
    177   if      ((ptr=GET_VAL_PTR("space_used",   dst->space_used))!=0)   {}
    178   else if ((ptr=GET_VAL_PTR("space_total",  dst->space_total))!=0)  {}
    179   else if ((ptr=GET_VAL_PTR("inodes_used",  dst->inodes_used))!=0)  {}
    180   else if ((ptr=GET_VAL_PTR("inodes_total", dst->inodes_total))!=0) {}
    181   else if ((ptr=GET_VAL_PTR("reserved",     dst->reserved))!=0)     {}
    182   else      ptr=0;
    183 
    184 #undef  GET_VAL_PTR  
    185 
    186   if (ptr!=0 && *ptr==VC_CDLIM_KEEP) {
    187     char	*endptr;
    188     long	val = strtol(opt, &endptr, 0);
    189 
    190     if (*opt==0 || *endptr!='\0') {
    191       WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "can not parse number in '");
    192       WRITE_STR(2, orig_opt);
    193       WRITE_MSG(2, "'\n");
    194       return false;
    195     }
    196 
    197     *ptr = val;
    198   }
    199   else if (ptr!=0) {
    200     WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "value already set in '");
    201     WRITE_STR(2, orig_opt);
    202     WRITE_MSG(2, "'\n");
    203     return false;
    204   }
    205   else {
    206     WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "unknown limit in '");
    207     WRITE_STR(2, orig_opt);
    208     WRITE_MSG(2, "'\n");
    209     return false;
    210   }
    211 
    212   return true;
    213 }
    214 
    215 bool
    216 isHigherLimit(uint_least32_t lhs, uint_least32_t rhs)
    217 {
    218   if (lhs==VC_CDLIM_KEEP || rhs==VC_CDLIM_KEEP) return false;
    219 
    220   return lhs > rhs;
    221 }
    222 
    223 int main(int argc, char *argv[])
    224 {
    225   bool		do_set       = false;
    226   bool		do_remove    = false;
    227   xid_t		xid          = VC_NOCTX;
    228   uint32_t	flags        = 0;
    229   char		*endptr;
    230   int		sum          = 0;
    231 
    232   struct vc_ctx_dlimit		limit = {
    233     .space_used   = VC_CDLIM_KEEP,
    234     .space_total  = VC_CDLIM_KEEP,
    235     .inodes_used  = VC_CDLIM_KEEP,
    236     .inodes_total = VC_CDLIM_KEEP,
    237     .reserved     = VC_CDLIM_KEEP
    238   };
    239   
    240   while (1) {
    241     int		c = getopt_long(argc, argv, "+x:s:df:", CMDLINE_OPTIONS, 0);
    242     if (c==-1) break;
    243 
    244     switch (c) {
    245       case CMD_HELP	:  showHelp(1, argv[0]);
    246       case CMD_VERSION	:  showVersion();
    247       case 'x'		:  xid = Evc_xidopt2xid(optarg, true); break;
    248       case 's'		:
    249 	if (!setDLimitField(&limit, optarg))
    250 	  return EXIT_FAILURE;
    251 	else
    252 	  do_set = true;
    253 	break;
    254       case 'd'		:  do_remove = true; break;
    255       case 'f'		:
    256 	{
    257 	  flags = strtol(optarg, &endptr, 0);
    258 	  if ((flags == 0 && errno != 0) || *endptr != '\0') {
    259 	    WRITE_MSG(2, "Invalid flags argument: '");
    260 	    WRITE_STR(2, optarg);
    261 	    WRITE_MSG(2, "'; try '--help' for more information\n");
    262 	    return EXIT_FAILURE;
    263 	  }
    264 	}
    265 	break;
    266 
    267       default		:
    268 	WRITE_MSG(2, "Try '");
    269 	WRITE_STR(2, argv[0]);
    270 	WRITE_MSG(2, " --help' for more information.\n");
    271 	return EXIT_FAILURE;
    272 	break;
    273     }
    274   }
    275 
    276   sum = ((do_set ? 1 : 0) + (do_remove ? 1 : 0));
    277   
    278   if (sum>1)
    279     WRITE_MSG(2, "Can not specify multiple operations; try '--help' for more information\n");
    280   else if (optind==argc)
    281     WRITE_MSG(2, "No mount point specified; try '--help' for more information\n");
    282   else if (xid==VC_NOCTX)
    283     WRITE_MSG(2, "No xid specified; try '--help' for more information\n");
    284   else if (isHigherLimit(limit.space_used, limit.space_total))
    285     WRITE_MSG(2, "invalid parameters: 'space_used' is larger than 'space_total'\n");
    286   else if (isHigherLimit(limit.inodes_used, limit.inodes_total))
    287     WRITE_MSG(2, "invalid parameters: 'inodes_used' is larger than 'inodes_total'\n");
    288   else {
    289     for (; optind < argc; ++optind) {
    290       if      (do_set)     setDlimit(argv[optind], xid, flags, &limit);
    291       else if (do_remove)  remDlimit(argv[optind], xid, flags);
    292       else                 printDlimit(argv[optind], xid, flags, true);
    293     }
    294 
    295     return EXIT_SUCCESS;
    296   }
    297 
    298   return EXIT_FAILURE;
    299 }