(root)/
sed-4.9/
lib/
getdelim.c
       1  /* getdelim.c --- Implementation of replacement getdelim function.
       2     Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2022 Free Software
       3     Foundation, Inc.
       4  
       5     This file is free software: you can redistribute it and/or modify
       6     it under the terms of the GNU Lesser General Public License as
       7     published by the Free Software Foundation; either version 2.1 of the
       8     License, or (at your option) any later version.
       9  
      10     This file is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13     GNU Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public License
      16     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      17  
      18  /* Ported from glibc by Simon Josefsson. */
      19  
      20  /* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
      21     optimizes away the lineptr == NULL || n == NULL || fp == NULL tests below.  */
      22  #define _GL_ARG_NONNULL(params)
      23  
      24  #include <config.h>
      25  
      26  #include <stdio.h>
      27  
      28  #include <limits.h>
      29  #include <stdint.h>
      30  #include <stdlib.h>
      31  #include <errno.h>
      32  
      33  #ifndef SSIZE_MAX
      34  # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
      35  #endif
      36  
      37  #if USE_UNLOCKED_IO
      38  # include "unlocked-io.h"
      39  # define getc_maybe_unlocked(fp)        getc(fp)
      40  #elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED
      41  # undef flockfile
      42  # undef funlockfile
      43  # define flockfile(x) ((void) 0)
      44  # define funlockfile(x) ((void) 0)
      45  # define getc_maybe_unlocked(fp)        getc(fp)
      46  #else
      47  # define getc_maybe_unlocked(fp)        getc_unlocked(fp)
      48  #endif
      49  
      50  static void
      51  alloc_failed (void)
      52  {
      53  #if defined _WIN32 && ! defined __CYGWIN__
      54    /* Avoid errno problem without using the realloc module; see:
      55       https://lists.gnu.org/r/bug-gnulib/2016-08/msg00025.html  */
      56    errno = ENOMEM;
      57  #endif
      58  }
      59  
      60  /* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
      61     NUL-terminate it).  *LINEPTR is a pointer returned from malloc (or
      62     NULL), pointing to *N characters of space.  It is realloc'ed as
      63     necessary.  Returns the number of characters read (not including
      64     the null terminator), or -1 on error or EOF.  */
      65  
      66  ssize_t
      67  getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
      68  {
      69    ssize_t result;
      70    size_t cur_len = 0;
      71  
      72    if (lineptr == NULL || n == NULL || fp == NULL)
      73      {
      74        errno = EINVAL;
      75        return -1;
      76      }
      77  
      78    flockfile (fp);
      79  
      80    if (*lineptr == NULL || *n == 0)
      81      {
      82        char *new_lineptr;
      83        *n = 120;
      84        new_lineptr = (char *) realloc (*lineptr, *n);
      85        if (new_lineptr == NULL)
      86          {
      87            alloc_failed ();
      88            result = -1;
      89            goto unlock_return;
      90          }
      91        *lineptr = new_lineptr;
      92      }
      93  
      94    for (;;)
      95      {
      96        int i;
      97  
      98        i = getc_maybe_unlocked (fp);
      99        if (i == EOF)
     100          {
     101            result = -1;
     102            break;
     103          }
     104  
     105        /* Make enough space for len+1 (for final NUL) bytes.  */
     106        if (cur_len + 1 >= *n)
     107          {
     108            size_t needed_max =
     109              SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
     110            size_t needed = 2 * *n + 1;   /* Be generous. */
     111            char *new_lineptr;
     112  
     113            if (needed_max < needed)
     114              needed = needed_max;
     115            if (cur_len + 1 >= needed)
     116              {
     117                result = -1;
     118                errno = EOVERFLOW;
     119                goto unlock_return;
     120              }
     121  
     122            new_lineptr = (char *) realloc (*lineptr, needed);
     123            if (new_lineptr == NULL)
     124              {
     125                alloc_failed ();
     126                result = -1;
     127                goto unlock_return;
     128              }
     129  
     130            *lineptr = new_lineptr;
     131            *n = needed;
     132          }
     133  
     134        (*lineptr)[cur_len] = i;
     135        cur_len++;
     136  
     137        if (i == delimiter)
     138          break;
     139      }
     140    (*lineptr)[cur_len] = '\0';
     141    result = cur_len ? cur_len : result;
     142  
     143   unlock_return:
     144    funlockfile (fp); /* doesn't set errno */
     145  
     146    return result;
     147  }