(root)/
glibc-2.38/
gshadow/
fgetsgent.c
       1  /* Copyright (C) 2009-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library 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 GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <libc-lock.h>
      20  #include <gshadow.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <set-freeres.h>
      24  
      25  
      26  /* A reasonable size for a buffer to start with.  */
      27  #define BUFLEN_SPWD 1024
      28  
      29  /* We need to protect the dynamic buffer handling.  */
      30  __libc_lock_define_initialized (static, lock);
      31  
      32  static char *buffer;
      33  
      34  /* Read one shadow entry from the given stream.  */
      35  struct sgrp *
      36  fgetsgent (FILE *stream)
      37  {
      38    static size_t buffer_size;
      39    static struct sgrp resbuf;
      40    fpos_t pos;
      41    struct sgrp *result;
      42    int save;
      43  
      44    if (fgetpos (stream, &pos) != 0)
      45      return NULL;
      46  
      47    /* Get lock.  */
      48    __libc_lock_lock (lock);
      49  
      50    /* Allocate buffer if not yet available.  */
      51    if (buffer == NULL)
      52      {
      53        buffer_size = BUFLEN_SPWD;
      54        buffer = malloc (buffer_size);
      55      }
      56  
      57    while (buffer != NULL
      58  	 && (__fgetsgent_r (stream, &resbuf, buffer, buffer_size, &result)
      59  	     == ERANGE))
      60      {
      61        char *new_buf;
      62        buffer_size += BUFLEN_SPWD;
      63        new_buf = realloc (buffer, buffer_size);
      64        if (new_buf == NULL)
      65  	{
      66  	  /* We are out of memory.  Free the current buffer so that the
      67  	     process gets a chance for a normal termination.  */
      68  	  save = errno;
      69  	  free (buffer);
      70  	  __set_errno (save);
      71  	}
      72        buffer = new_buf;
      73  
      74        /* Reset the stream.  */
      75        if (fsetpos (stream, &pos) != 0)
      76  	buffer = NULL;
      77      }
      78  
      79    if (buffer == NULL)
      80      result = NULL;
      81  
      82    /* Release lock.  Preserve error value.  */
      83    save = errno;
      84    __libc_lock_unlock (lock);
      85    __set_errno (save);
      86  
      87    return result;
      88  }
      89  
      90  weak_alias (buffer, __libc_fgetsgent_freeres_ptr);