FileRead
Description
Read bytes from a file. Two arities via OVERLOAD:
FileRead(f, buf, n) - low-level: up to n bytes into buf. Short reads are normal at EOF and on signal interruption (we don’t retry on EINTR for you – callers loop if they need that). Sets at_eof when the syscall reports zero bytes. FileRead(f, out) - read to EOF into the container out. out may be a Buf * (binary payload – preferred for parser-input slurps) or a Str * (text payload – only when the caller knows the file is text). Existing length is overwritten; out grows through its own allocator.
out must be an already-init’d Buf * or Str * (its allocator drives the growth). Calling FileRead(f, out) more than once on the same container simply overwrites previous content. Both forms place a trailing zero past length (NUL terminator for the Str form, a benign sentinel byte for Buf).
Success
3-arg form returns bytes read (>= 0); 2-arg form returns total bytes loaded (== BufLength(out) / StrLen(out)).
Failure
Returns -1 on I/O error. The 2-arg form may leave out in a partial state.
Usage example (Cross-references)
Usage examples (Cross-references)
- In
Io.c:1146:
LOG_INFO("Reading from non-seekable channel.");
char buf_byte = 0;
while (FileRead(file, &buf_byte, 1) == 1) {
StrPushBackR(&buffer, buf_byte);
}- In
Io.c:1167:
if (file_len > 0) {
StrReserve(&buffer, (u64)file_len);
i64 got = FileRead(file, StrBegin(&buffer), (u64)file_len);
if (got < 0) {
LOG_ERROR("FileRead failed during f_read_fmt");- In
Io.c:1169:
i64 got = FileRead(file, StrBegin(&buffer), (u64)file_len);
if (got < 0) {
LOG_ERROR("FileRead failed during f_read_fmt");
StrDeinit(&buffer);
DefaultAllocatorDeinit(&scratch);- In
Dns.c:110:
char *data = StrBegin(&chunk);
for (;;) {
i64 n = FileRead(&f, data, 4096);
if (n < 0) {
ok = false;- In
ProcMaps.c:215:
if (!StrReserve(raw, grown_to))
return false;
i64 n = FileRead(f, StrEnd(raw), CHUNK);
if (n < 0)
return false;- In
ProcMaps.c:244:
FileClose(&f);
if (!ok) {
LOG_ERROR("ProcMapsLoad: FileRead failed");
ProcMapsDeinit(out);
return false;- In
ProcMaps.c:269:
}
if (!proc_maps_read_all(f, &out->raw)) {
LOG_ERROR("ProcMapsLoadFrom: FileRead failed");
ProcMapsDeinit(out);
return false;- In
File.c:31:
bool test_file_read_into_str(void) {
WriteFmt("Testing FileRead into Str (whole-file load)\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
File.c:51:
Str body = StrInit(alloc_base);
i64 got = FileRead(&f, &body);
FileClose(&f);- In
File.c:65:
bool test_file_read_grows_str(void) {
WriteFmt("Testing FileRead grows the Str backing buffer\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
File.c:85:
Str body = StrInit(alloc_base);
i64 got = FileRead(&f, &body);
FileClose(&f);- In
File.c:123:
char scratch[8] = {0};
ok = ok && (FileRead(&f, scratch, sizeof(scratch)) == -1);
ok = ok && (FileWrite(&f, "x", 1) == -1);
ok = ok && (FileSeek(&f, 0, FILE_SEEK_SET) == -1);- In
File.c:169:
// observable values.
bool test_write_seek_read_roundtrip(void) {
WriteFmt("Testing FileWrite/FileSeek/FileTell/FileRead round-trip\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
File.c:193:
char got[4] = {0};
i64 n = FileRead(&f, got, 4);
ok = ok && (n == 4) && got[0] == 'c' && got[1] == 'd' && got[2] == 'e' && got[3] == 'f';- In
File.c:229:
// A zero-byte request returns 0 and must NOT flag eof.
char scratch[4] = {0};
ok = ok && (FileRead(&f, scratch, 0) == 0) && !FileIsEof(&f);
// Drain the 2 bytes of content.
- In
File.c:232:
// Drain the 2 bytes of content.
ok = ok && (FileRead(&f, scratch, 2) == 2) && !FileIsEof(&f);
// The next read hits EOF: 0 bytes, eof flag set.
- In
File.c:235:
// The next read hits EOF: 0 bytes, eof flag set.
ok = ok && (FileRead(&f, scratch, 2) == 0) && FileIsEof(&f);
FileClose(&f);- In
File.c:267:
ok = ok && FileIsOpen(&r);
Str body = StrInit(alloc_base);
i64 got = FileRead(&r, &body);
FileClose(&r);- In
File.c:301:
File r = FileOpen(&path, "rb");
Str body = StrInit(alloc_base);
i64 got = FileRead(&r, &body);
FileClose(&r);- In
File.c:432:
Str body = StrInit(alloc_base);
File r = FileOpen(&path, "rb");
i64 got = FileRead(&r, &body);
FileClose(&r);
ok = ok && (got == 10) && ZstrCompare(StrBegin(&body), "AAA3456789") == 0;- In
File.c:462:
ok = ok && FileIsOpen(&f);
char buf[8] = {0};
i64 got = FileRead(&f, buf, 7);
// Real "r" (O_RDONLY) reads the 7 seeded bytes intact; and a write is
// rejected. A constant flags value drops O_RDONLY and/or adds O_TRUNC,
- In
File.c:603:
// byte counts the read/write syscalls report.
bool test_fm_249_read_exact_count(void) {
WriteFmt("Testing FileRead returns the exact byte count for a partial read\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
File.c:620:
char buf[5] = {0};
// Exact 5-byte read of the leading content.
i64 got = FileRead(&f, buf, 5);
ok = ok && (got == 5) && (MemCompare(buf, "ABCDE", 5) == 0);
FileClose(&f);- In
File.c:632:
// L270 `f->at_eof = true`: a zero-byte read at EOF sets the eof flag.
bool test_fm_270_read_sets_eof(void) {
WriteFmt("Testing FileRead at EOF sets the eof flag\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
File.c:647:
ok = ok && FileIsOpen(&f);
char buf[4] = {0};
ok = ok && (FileRead(&f, buf, 2) == 2) && !FileIsEof(&f);
// The next read hits EOF: 0 bytes and at_eof becomes true.
ok = ok && (FileRead(&f, buf, 2) == 0) && FileIsEof(&f);- In
File.c:649:
ok = ok && (FileRead(&f, buf, 2) == 2) && !FileIsEof(&f);
// The next read hits EOF: 0 bytes and at_eof becomes true.
ok = ok && (FileRead(&f, buf, 2) == 0) && FileIsEof(&f);
FileClose(&f);- In
File.c:681:
char buf[8] = {0};
// Drain to EOF to set at_eof.
ok = ok && (FileRead(&f, buf, 6) == 6);
ok = ok && (FileRead(&f, buf, 2) == 0) && FileIsEof(&f);- In
File.c:682:
// Drain to EOF to set at_eof.
ok = ok && (FileRead(&f, buf, 6) == 6);
ok = ok && (FileRead(&f, buf, 2) == 0) && FileIsEof(&f);
// Seek back to start: returns offset 0 and clears the eof flag.
- In
File.c:689:
// And reading now succeeds again from the top.
char buf2[3] = {0};
ok = ok && (FileRead(&f, buf2, 3) == 3) && (MemCompare(buf2, "abc", 3) == 0);
FileClose(&f);- In
File.c:719:
ok = ok && (FileSeek(&f, 4, FILE_SEEK_CUR) == 7);
char buf[2] = {0};
ok = ok && (FileRead(&f, buf, 1) == 1) && (buf[0] == '7');
FileClose(&f);- In
File.c:737:
// right or the slurp drops/duplicates bytes.
bool test_fm_403_remaining_size_from_midfile(void) {
WriteFmt("Testing FileRead-to-EOF from a mid-file cursor reads only the tail\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
File.c:755:
Str body = StrInit(alloc_base);
i64 got = FileRead(&f, &body);
FileClose(&f);- In
File.c:770:
// total when here == 0; guards the `end < here` and reserve logic).
bool test_fm_394_remaining_size_full(void) {
WriteFmt("Testing FileRead-to-EOF from start reads the whole file exactly\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
File.c:786:
ok = ok && FileIsOpen(&f);
Str body = StrInit(alloc_base);
i64 got = FileRead(&f, &body);
FileClose(&f);- In
File.c:807:
// total and full content (guards the reserve-size and grow-loop).
bool test_fm_427_read_to_buf_large(void) {
WriteFmt("Testing FileRead-to-Buf slurps a multi-chunk payload exactly\n");
DefaultAllocator alloc = DefaultAllocatorInit();- In
File.c:833:
ok = ok && FileIsOpen(&r);
Buf dst = BufInit(alloc_base);
i64 got = FileRead(&r, &dst);
FileClose(&r);- In
File.c:1005:
ok = ok && (FileSeek(&f, 0, FILE_SEEK_SET) == 0);
char buf[10] = {0};
ok = ok && (FileRead(&f, buf, 9) == 9) && (MemCompare(buf, "temp-data", 9) == 0);
FileClose(&f);- In
ArgParse.c:631:
FileSeek(&tmp, 0, FILE_SEEK_SET);
FileRead(&tmp, out);
FileClose(&tmp);
}- In
ArgParse.c:900:
bool ok = (rc == ARG_RUN_HELP);
FileSeek(&tmp, 0, FILE_SEEK_SET);
FileRead(&tmp, out);
FileClose(&tmp);
return ok;- In
ArgParse.c:1785:
FileSeek(&tmp, 0, FILE_SEEK_SET);
FileRead(&tmp, out);
FileClose(&tmp);
return rc;- In
Write.c:1014:
if (FileIsOpen(&f)) {
Str back = StrInit(&alloc);
FileRead(&f, &back);
ok = (ZstrCompare(StrBegin(&back), expect) == 0);
StrDeinit(&back);- In
Write.c:4999:
if (FileIsOpen(&r)) {
Str back = StrInit(&alloc);
FileRead(&r, &back);
ok = ok && (ZstrCompare(StrBegin(&back), "n=42\n") == 0);
StrDeinit(&back);- In
Write.c:5030:
if (FileIsOpen(&r)) {
Str back = StrInit(&alloc);
FileRead(&r, &back);
ok = ok && (ZstrCompare(StrBegin(&back), "X") == 0);
StrDeinit(&back);- In
Read.c:2714:
// position must still be 0: read the first raw byte.
char c = 0;
i64 got = FileRead(&f, &c, 1);
ok = (v == 123) && (got == 1) && (c == 'x');
FileClose(&f);