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 * fileio.c
* File reading utilities * 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 * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -17,17 +17,12 @@
#include <libpkgconf/libpkgconf.h> #include <libpkgconf/libpkgconf.h>
char * 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; bool quoted = false;
int c = '\0', c2; int c = '\0', c2;
if (s == NULL) while ((c = getc(stream)) != EOF)
return NULL;
while (s < end && (c = getc(stream)) != EOF)
{ {
if (c == '\\' && !quoted) if (c == '\\' && !quoted)
{ {
@ -41,11 +36,11 @@ pkgconf_fgetline(char *line, size_t size, FILE *stream)
do { do {
c = getc(stream); c = getc(stream);
} while (c != '\n' && c != EOF); } while (c != '\n' && c != EOF);
*s++ = c; pkgconf_buffer_push_byte(buffer, c);
break; break;
} }
else else
*s++ = c; pkgconf_buffer_push_byte(buffer, c);
quoted = false; quoted = false;
continue; continue;
@ -66,14 +61,14 @@ pkgconf_fgetline(char *line, size_t size, FILE *stream)
} }
else else
{ {
*s++ = c; pkgconf_buffer_push_byte(buffer, c);
} }
break; break;
} }
else if (c == '\r') else if (c == '\r')
{ {
*s++ = '\n'; pkgconf_buffer_push_byte(buffer, '\n');
if ((c2 = getc(stream)) == '\n') if ((c2 = getc(stream)) == '\n')
{ {
@ -99,26 +94,24 @@ pkgconf_fgetline(char *line, size_t size, FILE *stream)
else else
{ {
if (quoted) { if (quoted) {
*s++ = '\\'; pkgconf_buffer_push_byte(buffer, '\\');
quoted = false; 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; return NULL;
*s = '\0';
/* Remove newline character. */ /* Remove newline character. */
if (s > line && *(--s) == '\n') { if (pkgconf_buffer_lastc(buffer) == '\n')
*s = '\0'; pkgconf_buffer_trim_byte(buffer);
if (s > line && *(--s) == '\r') if (pkgconf_buffer_lastc(buffer) == '\r')
*s = '\0'; 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 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); 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 */ /* 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 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); 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 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) 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; size_t lineno = 0;
while (pkgconf_fgetline(readbuf, PKGCONF_BUFSIZE, f) != NULL) while (pkgconf_fgetline(&readbuf, f) != NULL)
{ {
char op, *p, *key, *value; char op, *p, *key, *value;
bool warned_key_whitespace = false, warned_value_whitespace = false; bool warned_key_whitespace = false, warned_value_whitespace = false;
lineno++; lineno++;
p = readbuf; p = readbuf.base;
while (*p && isspace((unsigned char)*p)) while (*p && isspace((unsigned char)*p))
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", warnfunc(data, "%s:" SIZE_FMT_SPECIFIER ": warning: whitespace encountered while parsing key section\n",
filename, lineno); 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]) if (ops[(unsigned char) op])
ops[(unsigned char) op](data, lineno, key, value); ops[(unsigned char) op](data, lineno, key, value);
pkgconf_buffer_reset(&readbuf);
} }
fclose(f); fclose(f);