Fix getdelim(3).

This commit is contained in:
Jonas 'Sortie' Termansen 2015-05-11 15:49:54 +02:00
parent 86c5bc52b3
commit f3e4be0d83
8 changed files with 48 additions and 39 deletions

View File

@ -53,7 +53,10 @@ char* read_single_line(FILE* fp)
size_t ret_size = 0;
ssize_t ret_length = getline(&ret, &ret_size, fp);
if ( ret_length < 0 )
{
free(ret);
return NULL;
}
if ( ret_length && ret[ret_length-1] == '\n' )
ret[--ret_length] = '\0';
return ret;

View File

@ -1,6 +1,6 @@
/*******************************************************************************
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014.
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014, 2015.
This file is part of the Sortix C Library.
@ -22,58 +22,55 @@
*******************************************************************************/
#include <sys/types.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
static const size_t DEFAULT_BUFSIZE = 32UL;
extern "C" ssize_t getdelim(char** lineptr, size_t* n, int delim, FILE* fp)
{
if ( !lineptr || (*lineptr && !n) || !fp )
return errno = EINVAL, -1;
const size_t DEFAULT_BUFSIZE = 32UL;
bool malloced = !*lineptr;
if ( malloced )
*lineptr = (char*) malloc(DEFAULT_BUFSIZE);
if ( !*lineptr )
return -1;
size_t bufsize = malloced ? DEFAULT_BUFSIZE : *n;
if ( n )
*n = bufsize;
ssize_t written = 0;
int c;
int err = EINVAL;
flockfile(fp);
if ( !lineptr || !n )
{
failure:
fp->flags |= _FILE_STATUS_ERROR;
funlockfile(fp);
return errno = err, -1;
}
err = ENOMEM;
if ( !*lineptr )
*n = 0;
size_t written = 0;
int c;
do
{
if ( (c = getc_unlocked(fp)) == EOF )
if ( written == (size_t) SSIZE_MAX )
goto failure;
if ( *n <= (size_t) written + 1UL )
{
if ( written )
break;
else
goto cleanup;
}
if ( bufsize <= (size_t) written + 1UL )
{
size_t newbufsize = 2UL * bufsize;
size_t newbufsize = *n ? 2UL * *n : DEFAULT_BUFSIZE;
char* newbuf = (char*) realloc(*lineptr, newbufsize);
if ( !newbuf )
goto cleanup;
bufsize = newbufsize;
if ( n )
*n = bufsize;
goto failure;
*lineptr = newbuf;
*n = newbufsize;
}
if ( (c = getc_unlocked(fp)) == EOF )
{
if ( !written || feof_unlocked(fp) )
{
funlockfile(fp);
return -1;
}
}
(*lineptr)[written++] = c;
} while ( c != delim );
funlockfile(fp);
(*lineptr)[written] = 0;
return written;
cleanup:
funlockfile(fp);
if ( malloced )
{
free(*lineptr);
*lineptr = NULL;
}
return -1;
return (ssize_t) written;
}

View File

@ -270,6 +270,7 @@ void string_array_append_file(string_array_t* sa, FILE* fp)
entry[entry_length-1] = '\0';
string_array_append(sa, entry);
}
free(entry);
}
bool string_array_append_file_path(string_array_t* sa, const char* path)
@ -355,6 +356,7 @@ void dictionary_append_file(string_array_t* sa, FILE* fp)
continue;
string_array_append(sa, entry);
}
free(entry);
}
bool dictionary_append_file_path(string_array_t* sa, const char* path)
@ -384,7 +386,10 @@ char* read_single_line(FILE* fp)
size_t ret_size = 0;
ssize_t ret_len = getline(&ret, &ret_size, fp);
if ( ret_len < 0 )
{
free(ret);
return NULL;
}
if ( ret_len && ret[ret_len-1] == '\n' )
ret[ret_len-1] = '\0';
return ret;

View File

@ -26,6 +26,7 @@
#include <errno.h>
#include <error.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@ -96,6 +97,7 @@ int main(int /*argc*/, char* argv[])
fflush(stdout);
mode = next_mode;
}
free(line);
int status;
waitpid(child_pid, &status, 0);
return WEXITSTATUS(status);

View File

@ -100,10 +100,9 @@ bool append_lines_from_file(FILE* fp,
ssize_t string_length = getline(&string, &string_size, fp);
if ( string_length < 0 )
{
free(string);
if ( feof(stdin) )
return true;
// TODO: HACK: Unfortunately feof(stdin) isn't always true in the
// normal EOF case due to a getline/getdelim bug.
if ( errno == 0 )
return true;
error(0, errno, "getline: `%s'", fpname);

View File

@ -102,6 +102,7 @@ char* read_line(FILE* fp, const char* fpname, int delim)
ssize_t amount = getdelim(&line, &line_size, delim, fp);
if ( amount < 0 )
{
free(line);
if ( ferror(fp) )
error(0, errno, "read: `%s'", fpname);
return NULL;

View File

@ -67,6 +67,7 @@ bool processfp(const char* inputname, FILE* fp)
ssize_t linelen = getline(&line, &linesize, fp);
if ( linelen < 0 )
{
free(line);
if ( feof(fp) ) { break; }
error(1, errno, "error reading line: %s", inputname);
}

View File

@ -38,6 +38,7 @@ char* read_line(FILE* fp, const char* fpname, int delim)
ssize_t amount = getdelim(&line, &line_size, delim, fp);
if ( amount < 0 )
{
free(line);
if ( ferror(fp) )
error(0, errno, "read: `%s'", fpname);
return NULL;