From c6424fbc55298399f133ca1ede11e1f0b4a5c824 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Fri, 29 Jul 2022 16:16:24 +0200 Subject: use a shared fs_normslice() function to handle offsets --- src/shared/fsutil.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/shared/fsutil.c (limited to 'src/shared/fsutil.c') diff --git a/src/shared/fsutil.c b/src/shared/fsutil.c new file mode 100644 index 0000000..a1dabfd --- /dev/null +++ b/src/shared/fsutil.c @@ -0,0 +1,55 @@ +#include +#include + +// TODO shared assert +#define assert(...) {} + +void fs_normslice(long *restrict offset, size_t *restrict length, size_t max, bool expand) +{ + assert(max <= (size_t)LONG_MAX); + + if (*offset < 0) { + /* Negative offsets are relative to EOF + 1. + * Thus: + * write(-1) writes right after the file ends; atomic append + * write(-n) writes, overriding the last (n-1) bytes + * read(-n) reads the last (n-1) bytes + */ + *offset += max + 1; + if (*offset < 0) { + /* cursor went before the file, EOF */ + *length = *offset = 0; + goto end; + } + } + + if (expand) { + /* This is a write() to a file with a dynamic size. + * We don't care if it goes past the current size, because the + * driver can handle expanding it. */ + } else { + /* This operation can't extend the file, it's either: + * - any read() + * - a write() to a file with a static size (e.g. a framebuffer) + * *offset and *length describe a slice of a buffer with length max, + * so their sum must not overflow it. */ + if ((size_t)*offset <= max) { + size_t maxlen = max - (size_t)*offset; + if (true || *length > maxlen) + *length = maxlen; + } else { + /* regular EOF */ + *length = *offset = 0; + goto end; + } + } + +end: + if (*length > 0) { + assert(0 <= *offset); + if (!expand) + assert(*offset + *length <= max); + } else { + /* EOF, *offset is undefined. */ + } +} -- cgit v1.2.3