"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/core-parse-opts.c" (15 Mar 2019, 6988 Bytes) of package /linux/privat/stress-ng-0.09.56.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "core-parse-opts.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) 2013-2019 Canonical, Ltd.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (at your option) any later version.
    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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   17  *
   18  * This code is a complete clean re-write of the stress tool by
   19  * Colin Ian King <colin.king@canonical.com> and attempts to be
   20  * backwardly compatible with the stress tool by Amos Waterland
   21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   22  * functionality.
   23  *
   24  */
   25 #include "stress-ng.h"
   26 
   27 /*
   28  *  check_value()
   29  *  sanity check number of workers
   30  */
   31 void check_value(
   32     const char *const msg,
   33     const int val)
   34 {
   35     if ((val < 0) || (val > STRESS_PROCS_MAX)) {
   36         (void)fprintf(stderr, "Number of %s workers must be between "
   37             "0 and %d\n", msg, STRESS_PROCS_MAX);
   38         longjmp(g_error_env, 1);
   39     }
   40 }
   41 
   42 
   43 /*
   44  *  check_range()
   45  *  Sanity check val against a lo - hi range
   46  */
   47 void check_range(
   48     const char *const opt,
   49     const uint64_t val,
   50     const uint64_t lo,
   51     const uint64_t hi)
   52 {
   53     if ((val < lo) || (val > hi)) {
   54         (void)fprintf(stderr, "Value %" PRId64 " is out of range for %s,"
   55             " allowed: %" PRId64 " .. %" PRId64 "\n",
   56             val, opt, lo, hi);
   57         longjmp(g_error_env, 1);
   58     }
   59 }
   60 
   61 /*
   62  *  check_range()
   63  *  Sanity check val against a lo - hi range
   64  */
   65 void check_range_bytes(
   66     const char *const opt,
   67     const uint64_t val,
   68     const uint64_t lo,
   69     const uint64_t hi)
   70 {
   71     if ((val < lo) || (val > hi)) {
   72         char strval[32], strlo[32], strhi[32];
   73 
   74         (void)fprintf(stderr, "Value %sB is out of range for %s,"
   75             " allowed: %sB .. %sB\n",
   76             stress_uint64_to_str(strval, sizeof(strval), val),
   77             opt,
   78             stress_uint64_to_str(strlo, sizeof(strlo), lo),
   79             stress_uint64_to_str(strhi, sizeof(strhi), hi));
   80         longjmp(g_error_env, 1);
   81     }
   82 }
   83 
   84 
   85 /*
   86  *  ensure_positive()
   87  *  ensure string contains just a +ve value
   88  */
   89 static void ensure_positive(const char *const str)
   90 {
   91     const char *ptr;
   92     bool negative = false;
   93 
   94     for (ptr = str; *ptr; ptr++) {
   95         if (*ptr == '-') {
   96             negative = true;
   97             continue;
   98         }
   99 
  100         if (isdigit((int)*ptr)) {
  101             if (!negative)
  102                 return;
  103 
  104             (void)fprintf(stderr, "Invalid negative number %s\n", str);
  105             longjmp(g_error_env, 1);
  106         }
  107     }
  108 }
  109 
  110 /*
  111  *  get_uint32()
  112  *  string to uint32_t
  113  */
  114 uint32_t get_uint32(const char *const str)
  115 {
  116     uint32_t val;
  117 
  118     ensure_positive(str);
  119     if (sscanf(str, "%12" SCNu32, &val) != 1) {
  120         (void)fprintf(stderr, "Invalid number %s\n", str);
  121         longjmp(g_error_env, 1);
  122     }
  123     return val;
  124 }
  125 
  126 /*
  127  *  get_int32()
  128  *  string to int32_t
  129  */
  130 int32_t get_int32(const char *const str)
  131 {
  132     int32_t val;
  133 
  134     if (sscanf(str, "%12" SCNd32, &val) != 1) {
  135         (void)fprintf(stderr, "Invalid number %s\n", str);
  136         longjmp(g_error_env, 1);
  137     }
  138     return val;
  139 }
  140 
  141 /*
  142  *  get_uint64()
  143  *  string to uint64_t
  144  */
  145 uint64_t get_uint64(const char *const str)
  146 {
  147     uint64_t val;
  148 
  149     ensure_positive(str);
  150     if (sscanf(str, "%" SCNu64, &val) != 1) {
  151         (void)fprintf(stderr, "Invalid number %s\n", str);
  152         longjmp(g_error_env, 1);
  153     }
  154     return val;
  155 }
  156 
  157 /*
  158  *  get_uint64_scale()
  159  *  get a value and scale it by the given scale factor
  160  */
  161 uint64_t get_uint64_scale(
  162     const char *const str,
  163     const scale_t scales[],
  164     const char *const msg)
  165 {
  166     uint64_t val;
  167     size_t len = strlen(str);
  168     int ch;
  169     int i;
  170 
  171     val = get_uint64(str);
  172     if (!len)  {
  173         (void)fprintf(stderr, "Value %s is an invalid size\n", str);
  174         longjmp(g_error_env, 1);
  175     }
  176     len--;
  177     ch = str[len];
  178 
  179     if (isdigit(ch))
  180         return val;
  181 
  182     ch = tolower(ch);
  183     for (i = 0; scales[i].ch; i++) {
  184         if (ch == scales[i].ch)
  185             return val * scales[i].scale;
  186     }
  187 
  188     (void)fprintf(stderr, "Illegal %s specifier %c\n", msg, str[len]);
  189     _exit(EXIT_FAILURE);
  190 }
  191 
  192 /*
  193  *  get_uint64_byte()
  194  *  size in bytes, K bytes, M bytes or G bytes
  195  */
  196 uint64_t get_uint64_byte(const char *const str)
  197 {
  198     static const scale_t scales[] = {
  199         { 'b',  1ULL },     /* bytes */
  200         { 'k',  1ULL << 10 },   /* kilobytes */
  201         { 'm',  1ULL << 20 },   /* megabytes */
  202         { 'g',  1ULL << 30 },   /* gigabytes */
  203         { 't',  1ULL << 40 },   /* terabytes */
  204         { 'p',  1ULL << 50 },   /* petabytes */
  205         { 'e',  1ULL << 60 },   /* exabytes */
  206         { 0,    0 },
  207     };
  208 
  209     return get_uint64_scale(str, scales, "length");
  210 }
  211 
  212 /*
  213  *  get_uint64_percent()
  214  *  get a value by whole number or by percentage
  215  */
  216 uint64_t get_uint64_percent(
  217     const char *const str,
  218     const uint32_t instances,
  219     const uint64_t max,
  220     const char *const errmsg)
  221 {
  222     size_t len = strlen(str);
  223 
  224     /* Convert to % over N instances */
  225     if ((len > 1) && (str[len - 1] == '%')) {
  226         double val;
  227 
  228         /* Avoid division by zero */
  229         if (max == 0) {
  230             (void)fprintf(stderr, "%s\n", errmsg);
  231             longjmp(g_error_env, 1);
  232         }
  233 
  234         /* Should NEVER happen */
  235         if (instances < 1) {
  236             (void)fprintf(stderr, "Invalid number of instances\n");
  237             longjmp(g_error_env, 1);
  238         }
  239         if (sscanf(str, "%lf", &val) != 1) {
  240             (void)fprintf(stderr, "Invalid percentage %s\n", str);
  241             longjmp(g_error_env, 1);
  242         }
  243         if (val < 0.0) {
  244             (void)fprintf(stderr, "Invalid percentage %s\n", str);
  245             longjmp(g_error_env, 1);
  246         }
  247         return (uint64_t)((double)(max * val) / (100.0 * instances));
  248         }
  249     return get_uint64_byte(str);
  250 }
  251 
  252 /*
  253  *  get_uint64_byte_memory()
  254  *  get memory size from string. If it contains %
  255  *  at the end, then covert it into the available
  256  *  physical memory scaled by that percentage divided
  257  *  by the number of stressor instances
  258  */
  259 uint64_t get_uint64_byte_memory(
  260     const char *const str,
  261     const uint32_t instances)
  262 {
  263     uint64_t phys_mem = stress_get_phys_mem_size();
  264 
  265     return get_uint64_percent(str, instances, phys_mem,
  266         "Cannot determine physical memory size");
  267 }
  268 
  269 /*
  270  *  get_uint64_byte_filesystem()
  271  *  get file size from string. If it contains %
  272  *  at the end, then covert it into the available
  273  *  file system space scaled by that percentage divided
  274  *  by the number of stressor instances
  275  */
  276 uint64_t get_uint64_byte_filesystem(
  277     const char *const str,
  278     const uint32_t instances)
  279 {
  280     uint64_t bytes = stress_get_filesystem_size();
  281 
  282     return get_uint64_percent(str, instances, bytes,
  283         "Cannot determine available space on file system");
  284 }
  285 
  286 /*
  287  *  get_uint64_time()
  288  *  time in seconds, minutes, hours, days or years
  289  */
  290 uint64_t get_uint64_time(const char *const str)
  291 {
  292     static const scale_t scales[] = {
  293         { 's',  1ULL },         /* seconds */
  294         { 'm',  60ULL },        /* minutes */
  295         { 'h',  3600ULL },      /* hours */
  296         { 'd',  24ULL * 3600 },     /* days */
  297         { 'w',  24ULL * 3600 * 7 }, /* weeks */
  298         { 'y',  31556926ULL },      /* years (equinoctial) */
  299     };
  300 
  301     return get_uint64_scale(str, scales, "time");
  302 }