libpkgconf: fileio: rework to use pkgconf_buffer, allowing larger than 64KB lines

Fixes: 130907d ("fileio: add routine for portably yanking lines out of a FILE stream")
Signed-off-by: Ariadne Conill <ariadne@ariadne.space>
master
Ariadne Conill 2025-02-02 01:33:06 -08:00
parent 83a2ae0434
commit d0f8f3f228
3 changed files with 22 additions and 30 deletions

View File

@ -2,7 +2,7 @@
* fileio.c
* File reading utilities
*
* Copyright (c) 2012 pkgconf authors (see AUTHORS).
* Copyright (c) 2012, 2025 pkgconf authors (see AUTHORS).
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -17,17 +17,12 @@
#include <libpkgconf/libpkgconf.h>
char *
pkgconf_fgetline(char *line, size_t size, FILE *stream)
pkgconf_fgetline(pkgconf_buffer_t *buffer, FILE *stream)
{
char *s = line;
char *end = line + size - 2;
bool quoted = false;
int c = '\0', c2;
if (s == NULL)
return NULL;
while (s < end && (c = getc(stream)) != EOF)
while ((c = getc(stream)) != EOF)
{
if (c == '\\' && !quoted)
{
@ -41,11 +36,11 @@ pkgconf_fgetline(char *line, size_t size, FILE *stream)
do {
c = getc(stream);
} while (c != '\n' && c != EOF);
*s++ = c;
pkgconf_buffer_push_byte(buffer, c);
break;
}
else
*s++ = c;
pkgconf_buffer_push_byte(buffer, c);
quoted = false;
continue;
@ -66,14 +61,14 @@ pkgconf_fgetline(char *line, size_t size, FILE *stream)
}
else
{
*s++ = c;
pkgconf_buffer_push_byte(buffer, c);
}
break;
}
else if (c == '\r')
{
*s++ = '\n';
pkgconf_buffer_push_byte(buffer, '\n');
if ((c2 = getc(stream)) == '\n')
{
@ -99,26 +94,24 @@ pkgconf_fgetline(char *line, size_t size, FILE *stream)
else
{
if (quoted) {
*s++ = '\\';
pkgconf_buffer_push_byte(buffer, '\\');
quoted = false;
}
*s++ = c;
pkgconf_buffer_push_byte(buffer, c);
}
}
if (c == EOF && (s == line || ferror(stream)))
if (c == EOF && ((!buffer->base || !*buffer->base) || ferror(stream)))
return NULL;
*s = '\0';
/* Remove newline character. */
if (s > line && *(--s) == '\n') {
*s = '\0';
if (pkgconf_buffer_lastc(buffer) == '\n')
pkgconf_buffer_trim_byte(buffer);
if (s > line && *(--s) == '\r')
*s = '\0';
}
if (pkgconf_buffer_lastc(buffer) == '\r')
pkgconf_buffer_trim_byte(buffer);
return line;
return pkgconf_buffer_str(buffer);
}

View File

@ -379,9 +379,6 @@ PKGCONF_API void pkgconf_fragment_render_buf(const pkgconf_list_t *list, char *b
PKGCONF_API char *pkgconf_fragment_render(const pkgconf_list_t *list, bool escape, const pkgconf_fragment_render_ops_t *ops);
PKGCONF_API bool pkgconf_fragment_has_system_dir(const pkgconf_client_t *client, const pkgconf_fragment_t *frag);
/* fileio.c */
PKGCONF_API char *pkgconf_fgetline(char *line, size_t size, FILE *stream);
/* tuple.c */
PKGCONF_API pkgconf_tuple_t *pkgconf_tuple_add(const pkgconf_client_t *client, pkgconf_list_t *parent, const char *key, const char *value, bool parse, unsigned int flags);
PKGCONF_API char *pkgconf_tuple_find(const pkgconf_client_t *client, pkgconf_list_t *list, const char *key);

View File

@ -33,20 +33,20 @@
void
pkgconf_parser_parse(FILE *f, void *data, const pkgconf_parser_operand_func_t *ops, const pkgconf_parser_warn_func_t warnfunc, const char *filename)
{
char readbuf[PKGCONF_BUFSIZE];
pkgconf_buffer_t readbuf = PKGCONF_BUFFER_INITIALIZER;
size_t lineno = 0;
while (pkgconf_fgetline(readbuf, PKGCONF_BUFSIZE, f) != NULL)
while (pkgconf_fgetline(&readbuf, f) != NULL)
{
char op, *p, *key, *value;
bool warned_key_whitespace = false, warned_value_whitespace = false;
lineno++;
p = readbuf;
p = readbuf.base;
while (*p && isspace((unsigned char)*p))
p++;
if (*p && p != readbuf)
if (*p && p != readbuf.base)
{
warnfunc(data, "%s:" SIZE_FMT_SPECIFIER ": warning: whitespace encountered while parsing key section\n",
filename, lineno);
@ -100,6 +100,8 @@ pkgconf_parser_parse(FILE *f, void *data, const pkgconf_parser_operand_func_t *o
}
if (ops[(unsigned char) op])
ops[(unsigned char) op](data, lineno, key, value);
pkgconf_buffer_reset(&readbuf);
}
fclose(f);