Fix getdelim(3).
This commit is contained in:
parent
86c5bc52b3
commit
f3e4be0d83
|
@ -53,7 +53,10 @@ char* read_single_line(FILE* fp)
|
||||||
size_t ret_size = 0;
|
size_t ret_size = 0;
|
||||||
ssize_t ret_length = getline(&ret, &ret_size, fp);
|
ssize_t ret_length = getline(&ret, &ret_size, fp);
|
||||||
if ( ret_length < 0 )
|
if ( ret_length < 0 )
|
||||||
|
{
|
||||||
|
free(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
if ( ret_length && ret[ret_length-1] == '\n' )
|
if ( ret_length && ret[ret_length-1] == '\n' )
|
||||||
ret[--ret_length] = '\0';
|
ret[--ret_length] = '\0';
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -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.
|
This file is part of the Sortix C Library.
|
||||||
|
|
||||||
|
@ -22,58 +22,55 @@
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.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)
|
extern "C" ssize_t getdelim(char** lineptr, size_t* n, int delim, FILE* fp)
|
||||||
{
|
{
|
||||||
if ( !lineptr || (*lineptr && !n) || !fp )
|
int err = EINVAL;
|
||||||
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;
|
|
||||||
flockfile(fp);
|
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
|
do
|
||||||
{
|
{
|
||||||
if ( (c = getc_unlocked(fp)) == EOF )
|
if ( written == (size_t) SSIZE_MAX )
|
||||||
|
goto failure;
|
||||||
|
if ( *n <= (size_t) written + 1UL )
|
||||||
{
|
{
|
||||||
if ( written )
|
size_t newbufsize = *n ? 2UL * *n : DEFAULT_BUFSIZE;
|
||||||
break;
|
|
||||||
else
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if ( bufsize <= (size_t) written + 1UL )
|
|
||||||
{
|
|
||||||
size_t newbufsize = 2UL * bufsize;
|
|
||||||
char* newbuf = (char*) realloc(*lineptr, newbufsize);
|
char* newbuf = (char*) realloc(*lineptr, newbufsize);
|
||||||
if ( !newbuf )
|
if ( !newbuf )
|
||||||
goto cleanup;
|
goto failure;
|
||||||
bufsize = newbufsize;
|
|
||||||
if ( n )
|
|
||||||
*n = bufsize;
|
|
||||||
*lineptr = newbuf;
|
*lineptr = newbuf;
|
||||||
|
*n = newbufsize;
|
||||||
|
}
|
||||||
|
if ( (c = getc_unlocked(fp)) == EOF )
|
||||||
|
{
|
||||||
|
if ( !written || feof_unlocked(fp) )
|
||||||
|
{
|
||||||
|
funlockfile(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(*lineptr)[written++] = c;
|
(*lineptr)[written++] = c;
|
||||||
} while ( c != delim );
|
} while ( c != delim );
|
||||||
funlockfile(fp);
|
funlockfile(fp);
|
||||||
(*lineptr)[written] = 0;
|
(*lineptr)[written] = 0;
|
||||||
return written;
|
return (ssize_t) written;
|
||||||
|
|
||||||
cleanup:
|
|
||||||
funlockfile(fp);
|
|
||||||
if ( malloced )
|
|
||||||
{
|
|
||||||
free(*lineptr);
|
|
||||||
*lineptr = NULL;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,6 +270,7 @@ void string_array_append_file(string_array_t* sa, FILE* fp)
|
||||||
entry[entry_length-1] = '\0';
|
entry[entry_length-1] = '\0';
|
||||||
string_array_append(sa, entry);
|
string_array_append(sa, entry);
|
||||||
}
|
}
|
||||||
|
free(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool string_array_append_file_path(string_array_t* sa, const char* path)
|
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;
|
continue;
|
||||||
string_array_append(sa, entry);
|
string_array_append(sa, entry);
|
||||||
}
|
}
|
||||||
|
free(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dictionary_append_file_path(string_array_t* sa, const char* path)
|
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;
|
size_t ret_size = 0;
|
||||||
ssize_t ret_len = getline(&ret, &ret_size, fp);
|
ssize_t ret_len = getline(&ret, &ret_size, fp);
|
||||||
if ( ret_len < 0 )
|
if ( ret_len < 0 )
|
||||||
|
{
|
||||||
|
free(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
if ( ret_len && ret[ret_len-1] == '\n' )
|
if ( ret_len && ret[ret_len-1] == '\n' )
|
||||||
ret[ret_len-1] = '\0';
|
ret[ret_len-1] = '\0';
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <error.h>
|
#include <error.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
@ -96,6 +97,7 @@ int main(int /*argc*/, char* argv[])
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
mode = next_mode;
|
mode = next_mode;
|
||||||
}
|
}
|
||||||
|
free(line);
|
||||||
int status;
|
int status;
|
||||||
waitpid(child_pid, &status, 0);
|
waitpid(child_pid, &status, 0);
|
||||||
return WEXITSTATUS(status);
|
return WEXITSTATUS(status);
|
||||||
|
|
|
@ -100,10 +100,9 @@ bool append_lines_from_file(FILE* fp,
|
||||||
ssize_t string_length = getline(&string, &string_size, fp);
|
ssize_t string_length = getline(&string, &string_size, fp);
|
||||||
if ( string_length < 0 )
|
if ( string_length < 0 )
|
||||||
{
|
{
|
||||||
|
free(string);
|
||||||
if ( feof(stdin) )
|
if ( feof(stdin) )
|
||||||
return true;
|
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 )
|
if ( errno == 0 )
|
||||||
return true;
|
return true;
|
||||||
error(0, errno, "getline: `%s'", fpname);
|
error(0, errno, "getline: `%s'", fpname);
|
||||||
|
|
|
@ -102,6 +102,7 @@ char* read_line(FILE* fp, const char* fpname, int delim)
|
||||||
ssize_t amount = getdelim(&line, &line_size, delim, fp);
|
ssize_t amount = getdelim(&line, &line_size, delim, fp);
|
||||||
if ( amount < 0 )
|
if ( amount < 0 )
|
||||||
{
|
{
|
||||||
|
free(line);
|
||||||
if ( ferror(fp) )
|
if ( ferror(fp) )
|
||||||
error(0, errno, "read: `%s'", fpname);
|
error(0, errno, "read: `%s'", fpname);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -67,6 +67,7 @@ bool processfp(const char* inputname, FILE* fp)
|
||||||
ssize_t linelen = getline(&line, &linesize, fp);
|
ssize_t linelen = getline(&line, &linesize, fp);
|
||||||
if ( linelen < 0 )
|
if ( linelen < 0 )
|
||||||
{
|
{
|
||||||
|
free(line);
|
||||||
if ( feof(fp) ) { break; }
|
if ( feof(fp) ) { break; }
|
||||||
error(1, errno, "error reading line: %s", inputname);
|
error(1, errno, "error reading line: %s", inputname);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ char* read_line(FILE* fp, const char* fpname, int delim)
|
||||||
ssize_t amount = getdelim(&line, &line_size, delim, fp);
|
ssize_t amount = getdelim(&line, &line_size, delim, fp);
|
||||||
if ( amount < 0 )
|
if ( amount < 0 )
|
||||||
{
|
{
|
||||||
|
free(line);
|
||||||
if ( ferror(fp) )
|
if ( ferror(fp) )
|
||||||
error(0, errno, "read: `%s'", fpname);
|
error(0, errno, "read: `%s'", fpname);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in New Issue