From 7ba13a415ab67ab5225d311e920a96379490fde7 Mon Sep 17 00:00:00 2001 From: Henrixounez <30901439+Henrixounez@users.noreply.github.com> Date: Mon, 12 Apr 2021 09:26:08 +0200 Subject: [PATCH] os: handle fread errors (#9687) --- vlib/os/os_c.v | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/vlib/os/os_c.v b/vlib/os/os_c.v index 7fe3503d0d..81a11247ee 100644 --- a/vlib/os/os_c.v +++ b/vlib/os/os_c.v @@ -21,6 +21,10 @@ fn C.open(&char, int, ...int) int fn C.fdopen(fd int, mode &char) &C.FILE +fn C.ferror(stream &C.FILE) int + +fn C.feof(stream &C.FILE) int + fn C.CopyFile(&u16, &u16, bool) int // fn C.lstat(charptr, voidptr) u64 @@ -101,11 +105,24 @@ pub fn read_file(path string) ?string { unsafe { mut str := malloc(fsize + 1) nelements := int(C.fread(str, fsize, 1, fp)) - if nelements == 0 && fsize > 0 { + is_eof := int(C.feof(fp)) + is_error := int(C.ferror(fp)) + if is_eof == 0 && is_error != 0 { free(str) return error('fread failed') } str[fsize] = 0 + if nelements == 0 { + // It is highly likely that the file was a virtual file from + // /sys or /proc, with information generated on the fly, so + // fsize was not reliably reported. Using vstring() here is + // slower (it calls strlen internally), but will return more + // consistent results. + // For example reading from /sys/class/sound/card0/id produces + // a `PCH\n` string, but fsize is 4096, and otherwise you would + // get a V string with .len = 4096 and .str = "PCH\n\\000". + return str.vstring() + } return str.vstring_with_len(fsize) } }