blind

suckless command-line video editing utility
git clone git://git.suckless.org/blind
Log | Files | Refs | README | LICENSE

commit 19ad368f68164b99a2cfedb11747d7ca2d040ee0
parent 6b998b5ed066aeece1146fe245b35965319b3cbd
Author: Mattias Andrée <maandree@kth.se>
Date:   Wed, 10 May 2017 21:29:46 +0200

Cleaner code

Signed-off-by: Mattias Andrée <maandree@kth.se>

Diffstat:
Mman/blind-transpose.1 | 3---
Msrc/blind-arithm.c | 2+-
Msrc/blind-compress.c | 2+-
Msrc/blind-concat.c | 33++++++++++++++++-----------------
Msrc/blind-cut.c | 26+++++++-------------------
Msrc/blind-dissolve.c | 2+-
Msrc/blind-from-text.c | 2+-
Msrc/blind-invert-luma.c | 2+-
Msrc/blind-next-frame.c | 27++++++++-------------------
Msrc/blind-repeat.c | 104+++++++++++++++++++++++++-------------------------------------------------------
Msrc/blind-set-alpha.c | 2+-
Msrc/blind-set-saturation.c | 2+-
Msrc/blind-single-colour.c | 2+-
Msrc/blind-skip-pattern.c | 34++++------------------------------
Msrc/blind-split.c | 37++++++++++---------------------------
Msrc/blind-stack.c | 2+-
Msrc/blind-to-text.c | 2+-
Msrc/blind-to-video.c | 2+-
Msrc/stream.c | 42++++++++++++++++++++++++++++++++++++++++++
Msrc/stream.h | 4++++
Msrc/util.c | 30+++++++++++++++++++++++++++++-
Msrc/util.h | 2+-
Msrc/util/emalloc.h | 29++++++++++++++++++++++++++---
Msrc/util/io.h | 16++++++++++++++++
24 files changed, 206 insertions(+), 203 deletions(-)

diff --git a/man/blind-transpose.1 b/man/blind-transpose.1 @@ -15,9 +15,6 @@ X and Y coordinates. requires enough free memory to load one full frames and one input column into memory. A frame requires 32 bytes per pixel it contains. -.B blind-transpose -has not been optimised for memory usage, but instead -for code simplicity. .SH SEE ALSO .BR blind (7), .BR blind-flip (1), diff --git a/src/blind-arithm.c b/src/blind-arithm.c @@ -74,7 +74,7 @@ int main(int argc, char *argv[]) { struct stream left, right; - process_func process = NULL; + process_func process; ARGBEGIN { case 'a': diff --git a/src/blind-compress.c b/src/blind-compress.c @@ -17,7 +17,7 @@ compare(const char *restrict new, const char *restrict old, size_t n, size_t **c (*cmp)[ptr - 1] += same + diff; } else { if (ptr + 2 > *cmpsize) - *cmp = erealloc(*cmp, (*cmpsize += 128) * sizeof(size_t)); + *cmp = erealloc2(*cmp, *cmpsize += 128, sizeof(size_t)); (*cmp)[ptr++] = same; (*cmp)[ptr++] = diff; } diff --git a/src/blind-concat.c b/src/blind-concat.c @@ -17,7 +17,7 @@ concat_to_stdout(int argc, char *argv[], const char *fname) size_t frames = 0; int i; - streams = emalloc((size_t)argc * sizeof(*streams)); + streams = emalloc2((size_t)argc, sizeof(*streams)); for (i = 0; i < argc; i++) { eopen_stream(streams + i, argv[i]); @@ -33,10 +33,7 @@ concat_to_stdout(int argc, char *argv[], const char *fname) efflush(stdout, fname); for (i = 0; i < argc; i++) { - do { - ewriteall(STDOUT_FILENO, streams[i].buf, streams[i].ptr, fname); - streams[i].ptr = 0; - } while (eread_stream(streams + i, SIZE_MAX)); + esend_stream(streams + i, STDOUT_FILENO, fname); close(streams[i].fd); } @@ -50,7 +47,9 @@ concat_to_file(int argc, char *argv[], char *output_file) int first = 1; int fd = eopen(output_file, O_RDWR | O_CREAT | O_TRUNC, 0666); char head[STREAM_HEAD_MAX]; - ssize_t headlen, size = 0; + ssize_t headlen; + size_t size = 0; + off_t pos; char *data; for (; argc--; argv++) { @@ -66,23 +65,23 @@ concat_to_file(int argc, char *argv[], char *output_file) echeck_compat(&stream, &refstream); } - do { - ewriteall(fd, stream.buf, stream.ptr, output_file); - size += stream.ptr; - stream.ptr = 0; - } while (eread_stream(&stream, SIZE_MAX)); + esend_stream(&stream, fd, output_file); close(stream.fd); } SPRINTF_HEAD_ZN(head, stream.frames, stream.width, stream.height, stream.pixfmt, &headlen); ewriteall(fd, head, (size_t)headlen, output_file); - data = mmap(0, size + (size_t)headlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if ((pos = elseek(fd, 0, SEEK_CUR, output_file)) > SIZE_MAX) + eprintf("%s\n", strerror(EFBIG)); + size = pos; + + data = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data == MAP_FAILED) eprintf("mmap %s:", output_file); - memmove(data + headlen, data, size); + memmove(data + headlen, data, size - (size_t)headlen); memcpy(data, head, (size_t)headlen); - munmap(data, size + (size_t)headlen); + munmap(data, size); close(fd); } @@ -108,9 +107,9 @@ concat_to_file_parallel(int argc, char *argv[], char *output_file, size_t jobs) jobs = (size_t)argc; fd = eopen(output_file, O_RDWR | O_CREAT | O_TRUNC, 0666); - events = emalloc(jobs * sizeof(*events)); - streams = emalloc((size_t)argc * sizeof(*streams)); - ptrs = emalloc((size_t)argc * sizeof(*ptrs)); + events = emalloc2(jobs, sizeof(*events)); + streams = emalloc2((size_t)argc, sizeof(*streams)); + ptrs = emalloc2((size_t)argc, sizeof(*ptrs)); for (i = 0; i < argc; i++) { eopen_stream(streams + i, argv[i]); diff --git a/src/blind-cut.c b/src/blind-cut.c @@ -10,9 +10,7 @@ int main(int argc, char *argv[]) { struct stream stream; - size_t start = 0, end = 0, ptr, max; - ssize_t r; - char buf[BUFSIZ]; + size_t start = 0, end = 0; int to_end = 0; UNOFLAGS(argc != 3); @@ -32,26 +30,16 @@ main(int argc, char *argv[]) end = stream.frames; else if (end > stream.frames) eprintf("end point is after end of video\n"); - stream.frames = end - start; - echeck_dimensions(&stream, WIDTH | HEIGHT | LENGTH, NULL); - fprint_stream_head(stdout, &stream); - efflush(stdout, "<stdout>"); - if (start >= end) eprintf("%s\n", start > end ? "start point is after end point" : "refusing to create video with zero frames"); - end = end * stream.frame_size + stream.headlen; - start = start * stream.frame_size + stream.headlen; - - fadvise_sequential(stream.fd, start, end - start); - for (ptr = start; ptr < end; ptr += (size_t)r) { - max = end - ptr; - max = MIN(max, sizeof(buf)); - if (!(r = epread(stream.fd, buf, max, ptr, stream.file))) - eprintf("%s: file is shorter than expected\n", stream.file); - ewriteall(STDOUT_FILENO, buf, (size_t)r, "<stdout>"); - } + stream.frames = end - start; + fprint_stream_head(stdout, &stream); + efflush(stdout, "<stdout>"); + + esend_frames(&stream, -1, start, NULL); + esend_frames(&stream, STDOUT_FILENO, start - end, "<stdout>"); close(stream.fd); return 0; diff --git a/src/blind-dissolve.c b/src/blind-dissolve.c @@ -31,7 +31,7 @@ main(int argc, char *argv[]) { struct stream stream; int reverse = 0; - void (*process)(struct stream *stream, size_t n, size_t f) = NULL; + void (*process)(struct stream *stream, size_t n, size_t f); ARGBEGIN { case 'r': diff --git a/src/blind-from-text.c b/src/blind-from-text.c @@ -33,7 +33,7 @@ main(int argc, char *argv[]) size_t size = 0; char *line = NULL; ssize_t len; - void (*process)(void) = NULL; + void (*process)(void); UNOFLAGS(argc); diff --git a/src/blind-invert-luma.c b/src/blind-invert-luma.c @@ -58,7 +58,7 @@ main(int argc, char *argv[]) { int invert = 0, whitepoint = 0; struct stream colour, mask; - void (*process)(struct stream *colour, struct stream *mask, size_t n) = NULL; + void (*process)(struct stream *colour, struct stream *mask, size_t n); ARGBEGIN { case 'i': diff --git a/src/blind-next-frame.c b/src/blind-next-frame.c @@ -10,15 +10,15 @@ int main(int argc, char *argv[]) { struct stream stream; - size_t n, w, h = 0; - int i, anything = 0; + size_t n; + int i; char *p; stream.frames = 1; ARGBEGIN { case 'f': - stream.frames = etozu_flag('f', UARGF(), 1, SIZE_MAX); + stream.frames = entozu_flag(2, 'f', UARGF(), 1, SIZE_MAX); break; default: usage(); @@ -51,21 +51,10 @@ main(int argc, char *argv[]) fprint_stream_head(stdout, &stream); enfflush(2, stdout, "<stdout>"); - w = stream.width * stream.pixel_size; - for (; stream.frames; stream.frames--) { - for (h = stream.height; h; h--) { - for (n = w; n; n -= stream.ptr, stream.ptr = 0) { - if (!stream.ptr && !enread_stream(2, &stream, n)) - goto done; - anything = 1; - enwriteall(2, STDOUT_FILENO, stream.buf, stream.ptr, "<stdout>"); - } - } - } -done: - - if (anything && stream.frames) + n = ensend_frames(2, &stream, STDOUT_FILENO, stream.frames, "<stdout>"); + if (!n) + return 1; + else if (n < stream.frames) enprintf(2, "%s: is shorter than expected\n", stream.file); - - return !anything; + return 0; } diff --git a/src/blind-repeat.c b/src/blind-repeat.c @@ -6,96 +6,56 @@ USAGE("(count | 'inf') file") -static void -repeat_regular_file(char *file, size_t count, int inf) -{ - struct stream stream; - char buf[BUFSIZ]; - size_t ptr; - ssize_t r; - - eopen_stream(&stream, file); - if (count > SIZE_MAX / stream.frames) - eprintf("%s: video is too long\n", stream.file); - stream.frames *= count; - fprint_stream_head(stdout, &stream); - efflush(stdout, "<stdout>"); +static size_t count = 0; +static int inf; +static struct stream stream; +static int +repeat_regular_file(void) +{ while (inf || count--) { fadvise_sequential(stream.fd, stream.headlen, 0); - for (ptr = stream.headlen;; ptr += (size_t)r) { - if (!(r = epread(stream.fd, buf, sizeof(buf), ptr, stream.file))) - break; - if (writeall(STDOUT_FILENO, buf, (size_t)r)) { - if (!inf || errno != EPIPE) - eprintf("write <stdout>:"); - return; - } - } + elseek(stream.fd, stream.headlen, SEEK_SET, stream.file); + if (esend_stream(&stream, STDOUT_FILENO, NULL)) + return -1; } - - close(stream.fd); + return 0; } -static void -repeat_stdin(size_t count, int inf) +static int +repeat_stdin(void) { - struct stream stream; - char *buf; - size_t ptr, size; - ssize_t r; - - eopen_stream(&stream, NULL); - if (count > SIZE_MAX / stream.frames) - eprintf("%s: video is too long\n", stream.file); - stream.frames *= count; - fprint_stream_head(stdout, &stream); - efflush(stdout, "<stdout>"); - - ptr = stream.ptr; - size = MAX(ptr, BUFSIZ); - buf = emalloc(size); - memcpy(buf, stream.buf, ptr); - - for (;;) { - if (ptr == size) - buf = erealloc(buf, size <<= 1); - if (!(r = eread(STDIN_FILENO, buf + ptr, size - ptr, "<stdout>"))) - break; - ptr += (size_t)r; - } - - while (inf || count--) { - if (writeall(STDOUT_FILENO, buf, ptr)) { - if (!inf || errno != EPIPE) - eprintf("write <stdout>:"); - return; - } - } - - free(buf); + size_t ptr = stream.ptr; + size_t size = MAX(ptr, BUFSIZ); + char *buf = memcpy(emalloc(size), stream.buf, ptr); + egetfile(STDIN_FILENO, &buf, &ptr, &size, "<stdout>"); + while (inf || count--) + if (writeall(STDOUT_FILENO, buf, ptr)) + return free(buf), -1; + return free(buf), 0; } int main(int argc, char *argv[]) { - size_t count = 0; - int inf = 0; - UNOFLAGS(argc != 2); - if (!strcmp(argv[0], "inf")) - inf = 1; + if ((inf = !strcmp(argv[0], "inf"))) + einf_check_fd(STDOUT_FILENO, "<stdout>"); else count = etozu_arg("the count", argv[0], 0, SIZE_MAX); - if (inf) - einf_check_fd(STDOUT_FILENO, "<stdout>"); + eopen_stream(&stream, !strcmp(argv[1], "-") ? NULL : argv[1]); + if (count > SIZE_MAX / stream.frames) + eprintf("%s: video is too long\n", stream.file); + stream.frames *= count; + fprint_stream_head(stdout, &stream); + efflush(stdout, "<stdout>"); - if (!strcmp(argv[1], "-")) - repeat_stdin(count, inf); - else - repeat_regular_file(argv[1], count, inf); + if (!strcmp(argv[1], "-") ? repeat_stdin() : repeat_regular_file()) + if (!inf || errno != EPIPE) + eprintf("write <stdout>:"); + close(stream.fd); return 0; } diff --git a/src/blind-set-alpha.c b/src/blind-set-alpha.c @@ -27,7 +27,7 @@ main(int argc, char *argv[]) { int invert = 0; struct stream colour, alpha; - void (*process)(struct stream *colour, struct stream *alpha, size_t n) = NULL; + void (*process)(struct stream *colour, struct stream *alpha, size_t n); ARGBEGIN { case 'i': diff --git a/src/blind-set-saturation.c b/src/blind-set-saturation.c @@ -54,7 +54,7 @@ main(int argc, char *argv[]) { struct stream colour, satur; int whitepoint = 0; - void (*process)(struct stream *colour, struct stream *satur, size_t n) = NULL; + void (*process)(struct stream *colour, struct stream *satur, size_t n); ARGBEGIN { case 'w': diff --git a/src/blind-single-colour.c b/src/blind-single-colour.c @@ -39,7 +39,7 @@ main(int argc, char *argv[]) { char *arg; const char *pixfmt = "xyza"; - void (*process)(void) = NULL; + void (*process)(void); ARGBEGIN { case 'f': diff --git a/src/blind-skip-pattern.c b/src/blind-skip-pattern.c @@ -6,35 +6,11 @@ USAGE("(skipped-frames | +included-frames) ...") -static int -process_frame(struct stream *stream, int include) -{ - size_t h, n, m; - int anything = 0; - - for (h = stream->height; h; h--) { - for (n = stream->row_size; n; n -= m, anything = 1) { - if (!stream->ptr && !eread_stream(stream, n)) - goto done; - m = MIN(stream->ptr, n); - if (include) - ewriteall(STDOUT_FILENO, stream->buf, m, "<stdout>"); - memmove(stream->buf, stream->buf + m, stream->ptr -= m); - } - } -done: - - if (anything && h) - eprintf("%s: is shorter than expected\n", stream->file); - - return anything; -} - int main(int argc, char *argv[]) { struct stream stream; - int i, include; + int i, include, outfd; size_t f, n, total = 0; char *includes; size_t *ns; @@ -68,13 +44,11 @@ main(int argc, char *argv[]) efflush(stdout, "<stdout>"); for (i = 0;; i = (i + 1) % argc) { - include = (int)includes[i]; - for (n = ns[i]; n--;) - if (!process_frame(&stream, include)) - goto done; + outfd = includes[i] ? STDOUT_FILENO : -1; + if (!esend_frames(&stream, outfd, ns[i], "<stdout>")) + break; } -done: free(includes); free(ns); return 0; diff --git a/src/blind-split.c b/src/blind-split.c @@ -11,7 +11,7 @@ int main(int argc, char *argv[]) { struct stream stream; - size_t *ends, i, parts, ptr, end, n; + size_t *ends, i, parts, n; char *to_end; FILE *fp; int fd, unknown_length = 0; @@ -28,54 +28,37 @@ main(int argc, char *argv[]) usage(); eopen_stream(&stream, NULL); - echeck_dimensions(&stream, WIDTH | HEIGHT | LENGTH, NULL); + echeck_dimensions(&stream, WIDTH | HEIGHT, NULL); parts = (size_t)argc / 2; ends = alloca(parts * sizeof(*ends)); to_end = alloca(parts); for (i = 0; i < parts; i++) { - to_end[i] = 0; - if (!strcmp(argv[i * 2 + 1], "end")) { + if ((to_end[i] = !strcmp(argv[i * 2 + 1], "end"))) ends[i] = unknown_length ? SIZE_MAX : stream.frames; - to_end[i] = 1; - } else if (tozu(argv[i * 2 + 1], 0, SIZE_MAX, ends + i)) { + else if (tozu(argv[i * 2 + 1], 0, SIZE_MAX, ends + i)) eprintf("the end point must be an integer in [0, %zu]\n", SIZE_MAX); - } + if (i && ends[i] <= ends[i - 1]) eprintf("the end points must be in strictly ascending order\n"); if (!unknown_length && ends[i] > stream.frames) eprintf("frame %zu is beyond the end of the video\n", ends[i]); } - ptr = 0; for (i = 0; i < parts; i++) { fd = eopen(argv[i * 2], O_WRONLY | O_CREAT | O_TRUNC, 0666); - fp = fdopen(fd, "wb"); - if (!fp) + if (!(fp = fdopen(fd, "wb"))) eprintf("fdopen %s:", argv[i * 2]); - stream.frames = ends[i] - (i ? ends[i - 1] : 0); + n = ends[i] - (i ? ends[i - 1] : 0); + stream.frames = (to_end[i] && unknown_length) ? 0 : n; fprint_stream_head(fp, &stream); efflush(fp, argv[i * 2]); - for (end = to_end[i] ? SIZE_MAX : ends[i] * stream.frame_size; ptr < end; ptr += n) { - n = end - ptr; - if (stream.ptr) { - n = MIN(stream.ptr, n); - ewriteall(fd, stream.buf, n, argv[i * 2]); - memmove(stream.buf, stream.buf + n, stream.ptr -= n); - } else if ((n = eread_stream(&stream, n))) { - ewriteall(fd, stream.buf, n, argv[i * 2]); - stream.ptr = 0; - } else if (ptr % stream.frame_size) { - eprintf("%s: incomplete frame\n", stream.file); - } else if (!unknown_length || !to_end[i]) { + if (esend_frames(&stream, fd, n, argv[i * 2]) != n) + if (!unknown_length || !to_end[i]) eprintf("%s: file is shorter than expected\n", stream.file); - } else { - break; - } - } if (fclose(fp)) eprintf("%s:", argv[i * 2]); diff --git a/src/blind-stack.c b/src/blind-stack.c @@ -46,7 +46,7 @@ main(int argc, char *argv[]) struct stream *streams; size_t n_streams, i, frames = 0, tmp; int blend = 0; - void (*process)(struct stream *streams, size_t n_streams, size_t n) = NULL; + void (*process)(struct stream *streams, size_t n_streams, size_t n); ARGBEGIN { case 'b': diff --git a/src/blind-to-text.c b/src/blind-to-text.c @@ -24,7 +24,7 @@ int main(int argc, char *argv[]) { struct stream stream; - void (*process)(struct stream *stream, size_t n) = NULL; + void (*process)(struct stream *stream, size_t n); UNOFLAGS(argc); diff --git a/src/blind-to-video.c b/src/blind-to-video.c @@ -72,7 +72,7 @@ main(int argc, char *argv[]) size_t n = 0; int status, pipe_rw[2]; pid_t pid; - void (*process)(struct stream *stream, size_t n) = NULL; + void (*process)(struct stream *stream, size_t n); ARGBEGIN { case 'd': diff --git a/src/stream.c b/src/stream.c @@ -276,6 +276,48 @@ enread_segment(int status, struct stream *stream, void *buf, size_t n) } +size_t +ensend_frames(int status, struct stream *stream, int outfd, size_t frames, const char *outfname) +{ + size_t h, w, p; + size_t ret = 0; + + for (ret = 0; ret < frames; ret++) { + for (p = stream->pixel_size; p; p--) { + for (h = stream->height; h; h--) { + for (w = stream->width; w; w -= stream->ptr, stream->ptr = 0) { + if (!stream->ptr && !enread_stream(status, stream, w)) + goto done; + if (outfd >= 0) + enwriteall(status, outfd, stream->buf, stream->ptr, outfname); + } + } + } + } + + return ret; +done: + if (p != stream->pixel_size || h != stream->height || w != stream->width) + enprintf(status, "%s: incomplete frame", stream->file); + return ret; +} + + +int +ensend_stream(int status, struct stream *stream, int outfd, const char *outfname) +{ + do { + if (writeall(outfd, stream->buf, stream->ptr)) { + if (outfname) + eprintf("write %s:", outfname); + return -1; + } + stream->ptr = 0; + } while (enread_stream(status, stream, SIZE_MAX)); + return 0; +} + + void nprocess_stream(int status, struct stream *stream, void (*process)(struct stream *stream, size_t n)) { diff --git a/src/stream.h b/src/stream.h @@ -32,6 +32,8 @@ #define eread_segment(...) enread_segment(1, __VA_ARGS__) #define eread_frame(...) enread_frame(1, __VA_ARGS__) #define eread_row(...) enread_row(1, __VA_ARGS__) +#define esend_frames(...) ensend_frames(1, __VA_ARGS__) +#define esend_stream(...) ensend_stream(1, __VA_ARGS__) #define process_stream(...) nprocess_stream(1, __VA_ARGS__) #define process_each_frame_segmented(...) nprocess_each_frame_segmented(1, __VA_ARGS__) @@ -76,6 +78,8 @@ void encheck_dimensions(int status, const struct stream *stream, enum dimension void encheck_compat(int status, const struct stream *a, const struct stream *b); const char *get_pixel_format(const char *specified, const char *current); int enread_segment(int status, struct stream *stream, void *buf, size_t n); +size_t ensend_frames(int status, struct stream *stream, int outfd, size_t frames, const char *outfname); +int ensend_stream(int status, struct stream *stream, int outfd, const char *outfname); void nprocess_stream(int status, struct stream *stream, void (*process)(struct stream *stream, size_t n)); diff --git a/src/util.c b/src/util.c @@ -166,6 +166,34 @@ writezeroes(int fd, void *buf, size_t bufsize, size_t n) return 0; } +int +getfile(int fd, void *buffer, size_t *restrict ptr, size_t *restrict size) +{ + char *restrict *restrict buf = buffer; + void *new; + size_t r; + + for (;;) { + if (*ptr == *size) { + if (!(new = realloc(*buf, *size << 1))) { + errno = ENOMEM; + return -1; + } + *buf = new; + *size <<= 1; + } + r = read(fd, *buf + *ptr, *size - *ptr); + if (r <= 0) { + if (r) + return -1; + break; + } + *ptr += (size_t)r; + } + + return 0; +} + static inline pid_t enfork(int status) @@ -193,7 +221,7 @@ enfork_jobs(int status, size_t *start, size_t *end, size_t jobs, pid_t **pids) return 1; } *end = n / jobs + s; - *pids = enmalloc(status, jobs * sizeof(**pids)); + *pids = enmalloc2(status, jobs, sizeof(**pids)); for (j = 1; j < jobs; j++) { pid = enfork(status); if (!pid) { diff --git a/src/util.h b/src/util.h @@ -6,7 +6,7 @@ #define MAX(A, B) ((A) > (B) ? (A) : (B)) #define CLIP(A, B, C) ((B) < (A) ? (A) : (B) > (C) ? (C) : (B)) #define STRLEN(STR) (sizeof(STR) - 1) -#define INTSTRLEN(TYPE) ((sizeof(TYPE) == 1 ? 3 : (5 * sizeof(TYPE) / 2)) + (TYPE)-1 < 0) +#define INTSTRLEN(TYPE) ((sizeof(TYPE) == 1 ? 3 : (5 * sizeof(TYPE) / 2)) + ((TYPE)-1 < 0)) #define USAGE(SYNOPSIS)\ static void usage(void)\ diff --git a/src/util/emalloc.h b/src/util/emalloc.h @@ -1,9 +1,15 @@ /* See LICENSE file for copyright and license details. */ #include <stdlib.h> +#include <stdint.h> -#define emalloc(...) enmalloc(1, __VA_ARGS__) -#define ecalloc(...) encalloc(1, __VA_ARGS__) -#define erealloc(...) enrealloc(1, __VA_ARGS__) +#define emalloc(...) enmalloc(1, __VA_ARGS__) +#define emalloc2(...) enmalloc2(1, __VA_ARGS__) +#define ecalloc(...) encalloc(1, __VA_ARGS__) +#define erealloc(...) enrealloc(1, __VA_ARGS__) +#define erealloc2(...) enrealloc2(1, __VA_ARGS__) + +#define malloc2(n, m) malloc(n * m); +#define realloc3(p, n, m) realloc(p, n * m); static inline void * enmalloc(int status, size_t n) @@ -15,6 +21,15 @@ enmalloc(int status, size_t n) } static inline void * +enmalloc2(int status, size_t n, size_t m) +{ + void *ptr; + if (n > SIZE_MAX / m || !(ptr = malloc(n * m))) + enprintf(status, "malloc: out of memory\n"); + return ptr; +} + +static inline void * encalloc(int status, size_t n, size_t m) { void *ptr = calloc(n, m); @@ -31,3 +46,11 @@ enrealloc(int status, void *ptr, size_t n) enprintf(status, "realloc: out of memory\n"); return ptr; } + +static inline void * +enrealloc2(int status, void *ptr, size_t n, size_t m) +{ + if (n > SIZE_MAX / m || !(ptr = realloc(ptr, n * m))) + enprintf(status, "realloc: out of memory\n"); + return ptr; +} diff --git a/src/util/io.h b/src/util/io.h @@ -1,5 +1,6 @@ /* See LICENSE file for copyright and license details. */ #include <fcntl.h> +#include <errno.h> #if defined(POSIX_FADV_SEQUENTIAL) # define fadvise_sequential(...) posix_fadvise(__VA_ARGS__, POSIX_FADV_SEQUENTIAL) @@ -17,6 +18,7 @@ #define ereadall(...) enreadall(1, __VA_ARGS__) #define epwriteall(...) enpwriteall(1, __VA_ARGS__) #define ewritezeroes(...) enwritezeroes(1, __VA_ARGS__) +#define egetfile(...) engetfile(1, __VA_ARGS__) int writeall(int fd, void *buf, size_t n); @@ -55,3 +57,17 @@ enwritezeroes(int status, int fd, void *buf, size_t bufsize, size_t n, const cha if (writezeroes(fd, buf, bufsize, n)) enprintf(status, "write %s:", fname); } + +int getfile(int fd, void *bufp, size_t *restrict ptrp, size_t *restrict sizep); + +static inline void +engetfile(int status, int fd, void *bufp, size_t *restrict ptrp, + size_t *restrict sizep, const char *fname) +{ + if (getfile(fd, bufp, ptrp, sizep)) { + if (errno == ENOMEM) + enprintf(status, "realloc:"); + else + enprintf(status, "read %s:", fname); + } +}