105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* getdelim.c --- Implementation of replacement getdelim function. 205436638acc7c010349a69c3395f1a57c642dc62Ying Wang Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2012 Free Software 305436638acc7c010349a69c3395f1a57c642dc62Ying Wang Foundation, Inc. 405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 505436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is free software; you can redistribute it and/or 605436638acc7c010349a69c3395f1a57c642dc62Ying Wang modify it under the terms of the GNU General Public License as 705436638acc7c010349a69c3395f1a57c642dc62Ying Wang published by the Free Software Foundation; either version 3, or (at 805436638acc7c010349a69c3395f1a57c642dc62Ying Wang your option) any later version. 905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is distributed in the hope that it will be useful, but 1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang WITHOUT ANY WARRANTY; without even the implied warranty of 1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang General Public License for more details. 1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang You should have received a copy of the GNU General Public License 1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang along with this program; if not, see <http://www.gnu.org/licenses/>. */ 1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Ported from glibc by Simon Josefsson. */ 1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <config.h> 2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc 2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang optimizes away the lineptr == NULL || n == NULL || fp == NULL tests below. */ 2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define _GL_ARG_NONNULL(params) 2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdio.h> 2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <limits.h> 2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdint.h> 3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdlib.h> 3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <errno.h> 3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef SSIZE_MAX 3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) 3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if USE_UNLOCKED_IO 3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "unlocked-io.h" 3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define getc_maybe_unlocked(fp) getc(fp) 4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED 4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# undef flockfile 4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# undef funlockfile 4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define flockfile(x) ((void) 0) 4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define funlockfile(x) ((void) 0) 4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define getc_maybe_unlocked(fp) getc(fp) 4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else 4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define getc_maybe_unlocked(fp) getc_unlocked(fp) 4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and 5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang NUL-terminate it). *LINEPTR is a pointer returned from malloc (or 5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang NULL), pointing to *N characters of space. It is realloc'ed as 5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang necessary. Returns the number of characters read (not including 5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang the null terminator), or -1 on error or EOF. */ 5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 5605436638acc7c010349a69c3395f1a57c642dc62Ying Wangssize_t 5705436638acc7c010349a69c3395f1a57c642dc62Ying Wanggetdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) 5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang ssize_t result; 6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t cur_len = 0; 6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lineptr == NULL || n == NULL || fp == NULL) 6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = EINVAL; 6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return -1; 6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang flockfile (fp); 6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*lineptr == NULL || *n == 0) 7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang char *new_lineptr; 7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang *n = 120; 7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang new_lineptr = (char *) realloc (*lineptr, *n); 7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (new_lineptr == NULL) 7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = -1; 7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto unlock_return; 7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang *lineptr = new_lineptr; 8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (;;) 8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang int i; 8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang i = getc_maybe_unlocked (fp); 8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (i == EOF) 8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = -1; 9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Make enough space for len+1 (for final NUL) bytes. */ 9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (cur_len + 1 >= *n) 9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t needed_max = 9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; 9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang size_t needed = 2 * *n + 1; /* Be generous. */ 10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang char *new_lineptr; 10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (needed_max < needed) 10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang needed = needed_max; 10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (cur_len + 1 >= needed) 10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = -1; 10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = EOVERFLOW; 10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto unlock_return; 10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang new_lineptr = (char *) realloc (*lineptr, needed); 11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (new_lineptr == NULL) 11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = -1; 11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang goto unlock_return; 11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang *lineptr = new_lineptr; 11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang *n = needed; 12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang (*lineptr)[cur_len] = i; 12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang cur_len++; 12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (i == delimiter) 12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang (*lineptr)[cur_len] = '\0'; 12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = cur_len ? cur_len : result; 13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang unlock_return: 13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang funlockfile (fp); /* doesn't set errno */ 13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return result; 13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 136