blob: a1dabfdf07483248b92289537637da21e0637365 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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. */
}
}
|