1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

os: fix os.open_file('text.txt', 'wb', 0o666), add test (#15420)

This commit is contained in:
Delyan Angelov 2022-08-14 09:50:05 +03:00 committed by GitHub
parent cae7bc9a9a
commit 8f98f1db9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 28 deletions

View File

@ -1,16 +1,15 @@
module os module os
// File modes
const ( const (
o_rdonly = 0o00000000 // open the file read-only. o_binary = 0 // input and output is not translated; the default on unix
o_wronly = 0o00000001 // open the file write-only. o_rdonly = C.O_RDONLY // open the file read-only.
o_rdwr = 0o00000002 // open the file read-write. o_wronly = C.O_WRONLY // open the file write-only.
o_binary = 0o00000000 // input and output is not translated; the default on unix o_rdwr = C.O_RDWR // open the file read-write.
o_create = 0o00000100 // create a new file if none exists. o_create = C.O_CREAT // create a new file if none exists.
o_excl = 0o00000200 // used with o_create, file must not exist. o_excl = C.O_EXCL // used with o_create, file must not exist.
o_noctty = 0o00000400 // if file is terminal, don't make it the controller terminal o_noctty = C.O_NOCTTY // if file is terminal, don't make it the controller terminal
o_trunc = 0o00001000 // truncate regular writable file when opened. o_trunc = C.O_TRUNC // truncate regular writable file when opened.
o_append = 0o00002000 // append data to the file when writing. o_append = C.O_APPEND // append data to the file when writing.
o_nonblock = 0o00004000 // prevents blocking when opening files o_nonblock = C.O_NONBLOCK // prevents blocking when opening files
o_sync = 0o04010000 // open for synchronous I/O. o_sync = C.O_SYNC // open for synchronous I/O.
) )

View File

@ -54,28 +54,41 @@ fn fix_windows_path(path string) string {
// open_file can be used to open or create a file with custom flags and permissions and returns a `File` object. // open_file can be used to open or create a file with custom flags and permissions and returns a `File` object.
pub fn open_file(path string, mode string, options ...int) ?File { pub fn open_file(path string, mode string, options ...int) ?File {
mut flags := 0 mut flags := 0
mut seek_to_end := false
for m in mode { for m in mode {
match m { match m {
`w` { flags |= o_create | o_trunc } `w` {
`a` { flags |= o_create | o_append } flags |= o_create | o_trunc | o_wronly
`r` { flags |= o_rdonly } }
`b` { flags |= o_binary } `a` {
`s` { flags |= o_sync } flags |= o_create | o_append | o_wronly
`n` { flags |= o_nonblock } seek_to_end = true
`c` { flags |= o_noctty } }
`+` { flags |= o_rdwr } `r` {
flags |= o_rdonly
}
`b` {
flags |= o_binary
}
`s` {
flags |= o_sync
}
`n` {
flags |= o_nonblock
}
`c` {
flags |= o_noctty
}
`+` {
flags &= ~o_wronly
flags |= o_rdwr
}
else {} else {}
} }
} }
if mode == 'r+' { if mode == 'r+' {
flags = o_rdwr flags = o_rdwr
} }
if mode == 'w' {
flags = o_wronly | o_create | o_trunc
}
if mode == 'a' {
flags = o_wronly | o_create | o_append
}
mut permission := 0o666 mut permission := 0o666
if options.len > 0 { if options.len > 0 {
permission = options[0] permission = options[0]
@ -92,10 +105,19 @@ pub fn open_file(path string, mode string, options ...int) ?File {
if fd == -1 { if fd == -1 {
return error(posix_get_error_msg(C.errno)) return error(posix_get_error_msg(C.errno))
} }
cfile := C.fdopen(fd, &char(mode.str)) fdopen_mode := mode.replace('b', '')
cfile := C.fdopen(fd, &char(fdopen_mode.str))
if isnil(cfile) { if isnil(cfile) {
return error('Failed to open or create file "$path"') return error('Failed to open or create file "$path"')
} }
if seek_to_end {
// ensure appending will work, even on bsd/macos systems:
$if windows {
C._fseeki64(cfile, 0, C.SEEK_END)
} $else {
C.fseeko(cfile, 0, C.SEEK_END)
}
}
return File{ return File{
cfile: cfile cfile: cfile
fd: fd fd: fd

View File

@ -388,7 +388,7 @@ fn test_reopen() ? {
f2.reopen(tfile1, 'r')? f2.reopen(tfile1, 'r')?
assert !f2.eof() assert !f2.eof()
z := f2.read(mut line_buffer)? z := f2.read(mut line_buffer) or { panic(err) }
assert f2.eof() assert f2.eof()
assert z > 0 assert z > 0
content := line_buffer#[..z].bytestr() content := line_buffer#[..z].bytestr()
@ -406,3 +406,16 @@ fn test_eof() ? {
f.read_bytes(100) f.read_bytes(100)
assert f.eof() assert f.eof()
} }
fn test_open_file_wb_ab() ? {
os.rm(tfile) or {}
mut wfile := os.open_file('text.txt', 'wb', 0o666)?
wfile.write_string('hello')?
wfile.close()
assert os.read_file('text.txt')? == 'hello'
//
mut afile := os.open_file('text.txt', 'ab', 0o666)?
afile.write_string('hello')?
afile.close()
assert os.read_file('text.txt')? == 'hellohello'
}