os: implement os.truncate() + improve error handling (#9752)
parent
8cb44ed9db
commit
aa49bc2708
|
@ -33,6 +33,10 @@ fn C._wstat64(&char, voidptr) u64
|
||||||
|
|
||||||
fn C.chown(&char, int, int) int
|
fn C.chown(&char, int, int) int
|
||||||
|
|
||||||
|
fn C.ftruncate(voidptr, u64) int
|
||||||
|
|
||||||
|
fn C._chsize_s(voidptr, u64) int
|
||||||
|
|
||||||
// fn C.proc_pidpath(int, byteptr, int) int
|
// fn C.proc_pidpath(int, byteptr, int) int
|
||||||
struct C.stat {
|
struct C.stat {
|
||||||
st_size u64
|
st_size u64
|
||||||
|
@ -130,7 +134,28 @@ pub fn read_file(path string) ?string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ***************************** OS ops ************************
|
// ***************************** OS ops ************************
|
||||||
// file_size returns the size of the file located in `path`.
|
|
||||||
|
// truncate changes the size of the file located in `path` to `len`.
|
||||||
|
pub fn truncate(path string, len u64) ? {
|
||||||
|
fp := C.open(&char(path.str), o_wronly | o_trunc)
|
||||||
|
defer {
|
||||||
|
C.close(fp)
|
||||||
|
}
|
||||||
|
if fp < 0 {
|
||||||
|
return error('open file failed')
|
||||||
|
}
|
||||||
|
$if windows {
|
||||||
|
if C._chsize_s(fp, len) != 0 {
|
||||||
|
return error_with_code(posix_get_error_msg(C.errno), C.errno)
|
||||||
|
}
|
||||||
|
} $else {
|
||||||
|
if C.ftruncate(fp, len) != 0 {
|
||||||
|
return error_with_code(posix_get_error_msg(C.errno), C.errno)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// file_size returns the size of the file located in `path`. In case of error -1 is returned.
|
||||||
pub fn file_size(path string) u64 {
|
pub fn file_size(path string) u64 {
|
||||||
mut s := C.stat{}
|
mut s := C.stat{}
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -157,7 +182,7 @@ pub fn file_size(path string) u64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// mv moves files or folders from `src` to `dst`.
|
// mv moves files or folders from `src` to `dst`.
|
||||||
|
@ -201,16 +226,18 @@ pub fn cp(src string, dst string) ? {
|
||||||
return error_with_code('cp (permission): failed to write to $dst (fp_to: $fp_to)',
|
return error_with_code('cp (permission): failed to write to $dst (fp_to: $fp_to)',
|
||||||
int(fp_to))
|
int(fp_to))
|
||||||
}
|
}
|
||||||
|
// TODO use defer{} to close files in case of error or return.
|
||||||
|
// Currently there is a C-Error when building.
|
||||||
mut buf := [1024]byte{}
|
mut buf := [1024]byte{}
|
||||||
mut count := 0
|
mut count := 0
|
||||||
for {
|
for {
|
||||||
// FIXME: use sizeof, bug: 'os__buf' undeclared
|
count = C.read(fp_from, &buf[0], sizeof(buf))
|
||||||
// count = C.read(fp_from, buf, sizeof(buf))
|
|
||||||
count = C.read(fp_from, &buf[0], 1024)
|
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if C.write(fp_to, &buf[0], count) < 0 {
|
if C.write(fp_to, &buf[0], count) < 0 {
|
||||||
|
C.close(fp_to)
|
||||||
|
C.close(fp_from)
|
||||||
return error_with_code('cp: failed to write to $dst', int(-1))
|
return error_with_code('cp: failed to write to $dst', int(-1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,6 +246,8 @@ pub fn cp(src string, dst string) ? {
|
||||||
C.stat(&char(src.str), &from_attr)
|
C.stat(&char(src.str), &from_attr)
|
||||||
}
|
}
|
||||||
if C.chmod(&char(dst.str), from_attr.st_mode) < 0 {
|
if C.chmod(&char(dst.str), from_attr.st_mode) < 0 {
|
||||||
|
C.close(fp_to)
|
||||||
|
C.close(fp_from)
|
||||||
return error_with_code('failed to set permissions for $dst', int(-1))
|
return error_with_code('failed to set permissions for $dst', int(-1))
|
||||||
}
|
}
|
||||||
C.close(fp_to)
|
C.close(fp_to)
|
||||||
|
@ -830,11 +859,11 @@ pub fn flush() {
|
||||||
// Octals like `0o600` can be used.
|
// Octals like `0o600` can be used.
|
||||||
pub fn chmod(path string, mode int) {
|
pub fn chmod(path string, mode int) {
|
||||||
if C.chmod(&char(path.str), mode) != 0 {
|
if C.chmod(&char(path.str), mode) != 0 {
|
||||||
panic(posix_get_error_msg(C.errno))
|
panic('chmod failed: ' + posix_get_error_msg(C.errno))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// chown change owner and group attributes of path to `owner` and `group`.
|
// chown changes the owner and group attributes of `path` to `owner` and `group`.
|
||||||
pub fn chown(path string, owner int, group int) ? {
|
pub fn chown(path string, owner int, group int) ? {
|
||||||
$if windows {
|
$if windows {
|
||||||
return error('os.chown() not implemented for Windows')
|
return error('os.chown() not implemented for Windows')
|
||||||
|
|
|
@ -573,3 +573,16 @@ fn test_exists_in_system_path() {
|
||||||
}
|
}
|
||||||
assert os.exists_in_system_path('ls')
|
assert os.exists_in_system_path('ls')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_truncate() {
|
||||||
|
filename := './test_trunc.txt'
|
||||||
|
hello := 'hello world!'
|
||||||
|
mut f := os.create(filename) or { panic(err) }
|
||||||
|
f.write_string(hello) or { panic(err) }
|
||||||
|
f.close()
|
||||||
|
assert hello.len == os.file_size(filename)
|
||||||
|
newlen := u64(40000)
|
||||||
|
os.truncate(filename, newlen) or { panic(err) }
|
||||||
|
assert newlen == os.file_size(filename)
|
||||||
|
os.rm(filename) or { panic(err) }
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue