(root)/
tar-1.35/
gnu/
xstrtol.c
       1  /* A more useful interface to strtol.
       2  
       3     Copyright (C) 1995-1996, 1998-2001, 2003-2007, 2009-2023 Free Software
       4     Foundation, Inc.
       5  
       6     This program is free software: you can redistribute it and/or modify
       7     it under the terms of the GNU General Public License as published by
       8     the Free Software Foundation, either version 3 of the License, or
       9     (at your option) any later version.
      10  
      11     This program is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14     GNU General Public License for more details.
      15  
      16     You should have received a copy of the GNU General Public License
      17     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      18  
      19  /* Written by Jim Meyering. */
      20  
      21  #ifndef __strtol
      22  # define __strtol strtol
      23  # define __strtol_t long int
      24  # define __xstrtol xstrtol
      25  # define STRTOL_T_MINIMUM LONG_MIN
      26  # define STRTOL_T_MAXIMUM LONG_MAX
      27  #endif
      28  
      29  #include <config.h>
      30  
      31  #include "xstrtol.h"
      32  
      33  /* Some pre-ANSI implementations (e.g. SunOS 4)
      34     need stderr defined if assertion checking is enabled.  */
      35  #include <stdio.h>
      36  
      37  #include <ctype.h>
      38  #include <errno.h>
      39  #include <limits.h>
      40  #include <stdckdint.h>
      41  #include <stdlib.h>
      42  #include <string.h>
      43  
      44  #if XSTRTOL_INCLUDE_INTTYPES_H
      45  # include <inttypes.h>
      46  #endif
      47  
      48  #include "assure.h"
      49  #include "intprops.h"
      50  
      51  static strtol_error
      52  bkm_scale (__strtol_t *x, int scale_factor)
      53  {
      54    __strtol_t scaled;
      55    if (ckd_mul (&scaled, *x, scale_factor))
      56      {
      57        *x = *x < 0 ? TYPE_MINIMUM (__strtol_t) : TYPE_MAXIMUM (__strtol_t);
      58        return LONGINT_OVERFLOW;
      59      }
      60  
      61    *x = scaled;
      62  
      63    return LONGINT_OK;
      64  }
      65  
      66  static strtol_error
      67  bkm_scale_by_power (__strtol_t *x, int base, int power)
      68  {
      69    strtol_error err = LONGINT_OK;
      70    while (power--)
      71      err |= bkm_scale (x, base);
      72    return err;
      73  }
      74  
      75  /* FIXME: comment.  */
      76  
      77  strtol_error
      78  __xstrtol (const char *s, char **ptr, int strtol_base,
      79             __strtol_t *val, const char *valid_suffixes)
      80  {
      81    char *t_ptr;
      82    char **p;
      83    __strtol_t tmp;
      84    strtol_error err = LONGINT_OK;
      85  
      86    assure (0 <= strtol_base && strtol_base <= 36);
      87  
      88    p = (ptr ? ptr : &t_ptr);
      89  
      90    errno = 0;
      91  
      92    if (! TYPE_SIGNED (__strtol_t))
      93      {
      94        const char *q = s;
      95        unsigned char ch = *q;
      96        while (isspace (ch))
      97          ch = *++q;
      98        if (ch == '-')
      99          return LONGINT_INVALID;
     100      }
     101  
     102    tmp = __strtol (s, p, strtol_base);
     103  
     104    if (*p == s)
     105      {
     106        /* If there is no number but there is a valid suffix, assume the
     107           number is 1.  The string is invalid otherwise.  */
     108        if (valid_suffixes && **p && strchr (valid_suffixes, **p))
     109          tmp = 1;
     110        else
     111          return LONGINT_INVALID;
     112      }
     113    else if (errno != 0)
     114      {
     115        if (errno != ERANGE)
     116          return LONGINT_INVALID;
     117        err = LONGINT_OVERFLOW;
     118      }
     119  
     120    /* Let valid_suffixes == NULL mean "allow any suffix".  */
     121    /* FIXME: update all callers except the ones that allow suffixes
     122       after the number, changing last parameter NULL to "".  */
     123    if (!valid_suffixes)
     124      {
     125        *val = tmp;
     126        return err;
     127      }
     128  
     129    if (**p != '\0')
     130      {
     131        int base = 1024;
     132        int suffixes = 1;
     133        strtol_error overflow;
     134  
     135        if (!strchr (valid_suffixes, **p))
     136          {
     137            *val = tmp;
     138            return err | LONGINT_INVALID_SUFFIX_CHAR;
     139          }
     140  
     141        switch (**p)
     142          {
     143          case 'E': case 'G': case 'g': case 'k': case 'K': case 'M': case 'm':
     144          case 'P': case 'Q': case 'R': case 'T': case 't': case 'Y': case 'Z':
     145  
     146            /* The "valid suffix" '0' is a special flag meaning that
     147               an optional second suffix is allowed, which can change
     148               the base.  A suffix "B" (e.g. "100MB") stands for a power
     149               of 1000, whereas a suffix "iB" (e.g. "100MiB") stands for
     150               a power of 1024.  If no suffix (e.g. "100M"), assume
     151               power-of-1024.  */
     152  
     153            if (strchr (valid_suffixes, '0'))
     154              switch (p[0][1])
     155                {
     156                case 'i':
     157                  if (p[0][2] == 'B')
     158                    suffixes += 2;
     159                  break;
     160  
     161                case 'B':
     162                case 'D': /* 'D' is obsolescent */
     163                  base = 1000;
     164                  suffixes++;
     165                  break;
     166                }
     167          }
     168  
     169        switch (**p)
     170          {
     171          case 'b':
     172            overflow = bkm_scale (&tmp, 512);
     173            break;
     174  
     175          case 'B':
     176            /* This obsolescent first suffix is distinct from the 'B'
     177               second suffix above.  E.g., 'tar -L 1000B' means change
     178               the tape after writing 1000 KiB of data.  */
     179            overflow = bkm_scale (&tmp, 1024);
     180            break;
     181  
     182          case 'c':
     183            overflow = LONGINT_OK;
     184            break;
     185  
     186          case 'E': /* exa or exbi */
     187            overflow = bkm_scale_by_power (&tmp, base, 6);
     188            break;
     189  
     190          case 'G': /* giga or gibi */
     191          case 'g': /* 'g' is undocumented; for compatibility only */
     192            overflow = bkm_scale_by_power (&tmp, base, 3);
     193            break;
     194  
     195          case 'k': /* kilo */
     196          case 'K': /* kibi */
     197            overflow = bkm_scale_by_power (&tmp, base, 1);
     198            break;
     199  
     200          case 'M': /* mega or mebi */
     201          case 'm': /* 'm' is undocumented; for compatibility only */
     202            overflow = bkm_scale_by_power (&tmp, base, 2);
     203            break;
     204  
     205          case 'P': /* peta or pebi */
     206            overflow = bkm_scale_by_power (&tmp, base, 5);
     207            break;
     208  
     209          case 'Q': /* quetta or 2**100 */
     210            overflow = bkm_scale_by_power (&tmp, base, 10);
     211            break;
     212  
     213          case 'R': /* ronna or 2**90 */
     214            overflow = bkm_scale_by_power (&tmp, base, 9);
     215            break;
     216  
     217          case 'T': /* tera or tebi */
     218          case 't': /* 't' is undocumented; for compatibility only */
     219            overflow = bkm_scale_by_power (&tmp, base, 4);
     220            break;
     221  
     222          case 'w':
     223            overflow = bkm_scale (&tmp, 2);
     224            break;
     225  
     226          case 'Y': /* yotta or 2**80 */
     227            overflow = bkm_scale_by_power (&tmp, base, 8);
     228            break;
     229  
     230          case 'Z': /* zetta or 2**70 */
     231            overflow = bkm_scale_by_power (&tmp, base, 7);
     232            break;
     233  
     234          default:
     235            *val = tmp;
     236            return err | LONGINT_INVALID_SUFFIX_CHAR;
     237          }
     238  
     239        err |= overflow;
     240        *p += suffixes;
     241        if (**p)
     242          err |= LONGINT_INVALID_SUFFIX_CHAR;
     243      }
     244  
     245    *val = tmp;
     246    return err;
     247  }