diff options
author | dzwdz | 2022-07-29 16:16:24 +0200 |
---|---|---|
committer | dzwdz | 2022-07-29 16:16:24 +0200 |
commit | c6424fbc55298399f133ca1ede11e1f0b4a5c824 (patch) | |
tree | d8dd1c160a7184a99ea3c72779dce95b4bbee692 /src/shared/fsutil.c | |
parent | a0b16620e1699504e8d21a481e019dec40d7ee1b (diff) |
use a shared fs_normslice() function to handle offsets
Diffstat (limited to 'src/shared/fsutil.c')
-rw-r--r-- | src/shared/fsutil.c | 55 |
1 files changed, 55 insertions, 0 deletions
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 <camellia/fsutil.h> +#include <limits.h> + +// 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. */ + } +} |