mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
os: fix file read end-of-file detection (#10070)
This commit is contained in:
100
vlib/os/file.c.v
100
vlib/os/file.c.v
@@ -321,6 +321,31 @@ pub fn (mut f File) write_ptr_at(data voidptr, size int, pos u64) int {
|
||||
}
|
||||
|
||||
// **************************** Read ops ***************************
|
||||
|
||||
// fread wraps C.fread and handles error and end-of-file detection.
|
||||
fn fread(ptr voidptr, item_size int, items int, stream &C.FILE) ?int {
|
||||
nbytes := int(C.fread(ptr, item_size, items, stream))
|
||||
// If no bytes were read, check for errors and end-of-file.
|
||||
if nbytes <= 0 {
|
||||
// If fread encountered end-of-file return the none error. Note that fread
|
||||
// may read data and encounter the end-of-file, but we shouldn't return none
|
||||
// in that case which is why we only check for end-of-file if no data was
|
||||
// read. The caller will get none on their next call because there will be
|
||||
// no data available and the end-of-file will be encountered again.
|
||||
if C.feof(stream) != 0 {
|
||||
return none
|
||||
}
|
||||
// If fread encountered an error, return it. Note that fread and ferror do
|
||||
// not tell us what the error was, so we can't return anything more specific
|
||||
// than there was an error. This is because fread and ferror do not set
|
||||
// errno.
|
||||
if C.ferror(stream) != 0 {
|
||||
return error('file read error')
|
||||
}
|
||||
}
|
||||
return nbytes
|
||||
}
|
||||
|
||||
// read_bytes reads bytes from the beginning of the file.
|
||||
// Utility method, same as .read_bytes_at(size, 0).
|
||||
pub fn (f &File) read_bytes(size int) []byte {
|
||||
@@ -348,23 +373,14 @@ pub fn (f &File) read_bytes_into(pos u64, mut buf []byte) ?int {
|
||||
$if windows {
|
||||
// Note: fseek errors if pos == os.file_size, which we accept
|
||||
C._fseeki64(f.cfile, pos, C.SEEK_SET)
|
||||
// errno is only set if fread fails, so clear it first to tell
|
||||
C.errno = 0
|
||||
nbytes := int(C.fread(buf.data, 1, buf.len, f.cfile))
|
||||
if C.errno != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes := fread(buf.data, 1, buf.len, f.cfile) ?
|
||||
$if debug {
|
||||
C._fseeki64(f.cfile, 0, C.SEEK_SET)
|
||||
}
|
||||
return nbytes
|
||||
} $else {
|
||||
C.fseeko(f.cfile, pos, C.SEEK_SET)
|
||||
C.errno = 0
|
||||
nbytes := int(C.fread(buf.data, 1, buf.len, f.cfile))
|
||||
if C.errno != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes := fread(buf.data, 1, buf.len, f.cfile) ?
|
||||
$if debug {
|
||||
C.fseeko(f.cfile, 0, C.SEEK_SET)
|
||||
}
|
||||
@@ -373,11 +389,7 @@ pub fn (f &File) read_bytes_into(pos u64, mut buf []byte) ?int {
|
||||
}
|
||||
$if x32 {
|
||||
C.fseek(f.cfile, pos, C.SEEK_SET)
|
||||
C.errno = 0
|
||||
nbytes := int(C.fread(buf.data, 1, buf.len, f.cfile))
|
||||
if C.errno != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes := fread(buf.data, 1, buf.len, f.cfile) ?
|
||||
$if debug {
|
||||
C.fseek(f.cfile, 0, C.SEEK_SET)
|
||||
}
|
||||
@@ -391,11 +403,7 @@ pub fn (f &File) read(mut buf []byte) ?int {
|
||||
if buf.len == 0 {
|
||||
return 0
|
||||
}
|
||||
C.errno = 0
|
||||
nbytes := int(C.fread(buf.data, 1, buf.len, f.cfile))
|
||||
if C.errno != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes := fread(buf.data, 1, buf.len, f.cfile) ?
|
||||
return nbytes
|
||||
}
|
||||
|
||||
@@ -417,20 +425,12 @@ pub fn (f &File) read_from(pos u64, mut buf []byte) ?int {
|
||||
C.fseeko(f.cfile, pos, C.SEEK_SET)
|
||||
}
|
||||
|
||||
C.errno = 0
|
||||
nbytes := int(C.fread(buf.data, 1, buf.len, f.cfile))
|
||||
if C.errno != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes := fread(buf.data, 1, buf.len, f.cfile) ?
|
||||
return nbytes
|
||||
}
|
||||
$if x32 {
|
||||
C.fseek(f.cfile, pos, C.SEEK_SET)
|
||||
C.errno = 0
|
||||
nbytes := int(C.fread(buf.data, 1, buf.len, f.cfile))
|
||||
if C.errno != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes := fread(buf.data, 1, buf.len, f.cfile) ?
|
||||
return nbytes
|
||||
}
|
||||
return error('Could not read file')
|
||||
@@ -461,11 +461,7 @@ pub fn (mut f File) read_struct<T>(mut t T) ? {
|
||||
if tsize == 0 {
|
||||
return none
|
||||
}
|
||||
C.errno = 0
|
||||
nbytes := int(C.fread(t, 1, tsize, f.cfile))
|
||||
if C.errno != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes := fread(t, 1, tsize, f.cfile) ?
|
||||
if nbytes != tsize {
|
||||
return error_with_code('incomplete struct read', nbytes)
|
||||
}
|
||||
@@ -480,27 +476,23 @@ pub fn (mut f File) read_struct_at<T>(mut t T, pos u64) ? {
|
||||
if tsize == 0 {
|
||||
return none
|
||||
}
|
||||
C.errno = 0
|
||||
mut nbytes := 0
|
||||
$if x64 {
|
||||
$if windows {
|
||||
C._fseeki64(f.cfile, pos, C.SEEK_SET)
|
||||
nbytes = int(C.fread(t, 1, tsize, f.cfile))
|
||||
nbytes = fread(t, 1, tsize, f.cfile) ?
|
||||
C._fseeki64(f.cfile, 0, C.SEEK_END)
|
||||
} $else {
|
||||
C.fseeko(f.cfile, pos, C.SEEK_SET)
|
||||
nbytes = int(C.fread(t, 1, tsize, f.cfile))
|
||||
nbytes = fread(t, 1, tsize, f.cfile) ?
|
||||
C.fseeko(f.cfile, 0, C.SEEK_END)
|
||||
}
|
||||
}
|
||||
$if x32 {
|
||||
C.fseek(f.cfile, pos, C.SEEK_SET)
|
||||
nbytes = int(C.fread(t, 1, tsize, f.cfile))
|
||||
nbytes = fread(t, 1, tsize, f.cfile) ?
|
||||
C.fseek(f.cfile, 0, C.SEEK_END)
|
||||
}
|
||||
if C.errno != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
if nbytes != tsize {
|
||||
return error_with_code('incomplete struct read', nbytes)
|
||||
}
|
||||
@@ -515,12 +507,8 @@ pub fn (mut f File) read_raw<T>() ?T {
|
||||
if tsize == 0 {
|
||||
return none
|
||||
}
|
||||
C.errno = 0
|
||||
mut t := T{}
|
||||
nbytes := int(C.fread(&t, 1, tsize, f.cfile))
|
||||
if C.errno != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes := fread(&t, 1, tsize, f.cfile) ?
|
||||
if nbytes != tsize {
|
||||
return error_with_code('incomplete struct read', nbytes)
|
||||
}
|
||||
@@ -536,7 +524,6 @@ pub fn (mut f File) read_raw_at<T>(pos u64) ?T {
|
||||
if tsize == 0 {
|
||||
return none
|
||||
}
|
||||
C.errno = 0
|
||||
mut nbytes := 0
|
||||
mut t := T{}
|
||||
$if x64 {
|
||||
@@ -544,10 +531,7 @@ pub fn (mut f File) read_raw_at<T>(pos u64) ?T {
|
||||
if C._fseeki64(f.cfile, pos, C.SEEK_SET) != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes = int(C.fread(&t, 1, tsize, f.cfile))
|
||||
if C.errno != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes = fread(&t, 1, tsize, f.cfile) ?
|
||||
if C._fseeki64(f.cfile, 0, C.SEEK_END) != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
@@ -555,10 +539,7 @@ pub fn (mut f File) read_raw_at<T>(pos u64) ?T {
|
||||
if C.fseeko(f.cfile, pos, C.SEEK_SET) != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes = int(C.fread(&t, 1, tsize, f.cfile))
|
||||
if C.errno != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes = fread(&t, 1, tsize, f.cfile) ?
|
||||
if C.fseeko(f.cfile, 0, C.SEEK_END) != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
@@ -568,10 +549,7 @@ pub fn (mut f File) read_raw_at<T>(pos u64) ?T {
|
||||
if C.fseek(f.cfile, pos, C.SEEK_SET) != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes = int(C.fread(&t, 1, tsize, f.cfile))
|
||||
if C.errno != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
nbytes = fread(&t, 1, tsize, f.cfile) ?
|
||||
if C.fseek(f.cfile, 0, C.SEEK_END) != 0 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user