diff options
author | Lieuwe Rooijakkers <lieuwerooijakkers@gmail.com> | 2024-08-06 16:41:29 +0200 |
---|---|---|
committer | Lieuwe Rooijakkers <lieuwerooijakkers@gmail.com> | 2024-08-06 16:41:29 +0200 |
commit | 37669147781468a0908c1240b26055898ca1e431 (patch) | |
tree | b05fa996a23eee1530f6efced56c8713542bbf11 /src | |
parent | a99acbb3e6c85313d938724e5fcb15de9394c345 (diff) |
hoofd: don't read whole file in memory
Diffstat (limited to 'src')
-rw-r--r-- | src/hoofd.c | 61 |
1 files changed, 48 insertions, 13 deletions
diff --git a/src/hoofd.c b/src/hoofd.c index ffb5563..596461a 100644 --- a/src/hoofd.c +++ b/src/hoofd.c @@ -1,3 +1,5 @@ +#include <assert.h> +#include <errno.h> #include <getopt.h> #include <pwd.h> #include <stdlib.h> @@ -7,7 +9,7 @@ #include "util/debug.h" #include "util/error.h" -#include "util/loop_files.h" +#include "util/loop_args.h" #include "util/versie.h" #include "io/read_file.h" @@ -59,28 +61,61 @@ static char** parse_options(int argc, char **argv, int *n, int *c) { return argv + optind; } -// TODO: be smarter, hoofd doesn't have to read the whole file in memory (for -// unmappable files) +static int process(char *fname, bool isstdin) { + FILE *stream = NULL; + if (isstdin) { + stream = stdin; + } else { + stream = fopen(fname, "rb"); + } + + if (gc != -1) { + char *buf = calloc(gc, 1); -static int process(struct filebuf *fb, char*, bool) { - int n = gn, c = gc; + if (fread(buf, 1, gc, stream) != (unsigned int)gc) { + printf("hoofd: fout bij lezen uit bestand '%s'\n", fname); + exit(1); + } - size_t i; - for (i = 0; i < fb->sz && (n > 0 || n == -1) && (c > 0 || c == -1); i++) { - if (fb->buf[i] == '\n') { - if (n != -1) n--; + if (fwrite(buf, 1, gc, stdout) != (unsigned int)gc) { + printf("hoofd: fout bij schrijven naar stanaard uitvoer\n"); + exit(1); } - if (c != -1) c--; + + free(buf); + goto done; + } + + assert(gn >= 0); + int n = gn; + + char *line = NULL; + size_t linen = 0; + + ssize_t nread = 0; + while ((errno = 0, nread = getline(&line, &linen, stream)) != -1) { + if (n == 0) break; + printf("%s", line); + n--; } - fwrite(fb->buf, 1, i, stdout); - free_filebuf(fb); + free(line); + + if (errno != 0) { + printf("hoofd: fout bij lezen uit bestand '%s'\n", fname); + exit(1); + } +done: + if (!isstdin) { + fclose(stream); + } return 0; } int entry_hoofd(int argc, char **argv) { gn = 10, gc = -1; char **args = parse_options(argc, argv, &gn, &gc); - return loop_files(args, process); + + return loop_args(args, process); } |