summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLieuwe Rooijakkers <lieuwerooijakkers@gmail.com>2024-08-06 16:41:29 +0200
committerLieuwe Rooijakkers <lieuwerooijakkers@gmail.com>2024-08-06 16:41:29 +0200
commit37669147781468a0908c1240b26055898ca1e431 (patch)
treeb05fa996a23eee1530f6efced56c8713542bbf11 /src
parenta99acbb3e6c85313d938724e5fcb15de9394c345 (diff)
hoofd: don't read whole file in memory
Diffstat (limited to 'src')
-rw-r--r--src/hoofd.c61
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);
}