os: fix binary mode read/write on windows (#6431)

pull/6434/head
Marcin 2020-09-20 16:28:45 +02:00 committed by GitHub
parent 3454677eb9
commit 34884c1631
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 50 deletions

View File

@ -6,6 +6,7 @@ const (
o_wronly = 000000001 // open the file write-only.
o_rdwr = 000000002 // open the file read-write.
o_create = 000000100 // create a new file if none exists.
o_binary = 000008000 // input and output is not translated.
o_excl = 000000200 // used with o_create, file must not exist.
o_noctty = 000000400 // if file is terminal, don't make it the controller terminal
o_trunc = 000001000 // truncate regular writable file when opened.

View File

@ -100,6 +100,7 @@ const (
o_rdwr = 0x0002 // open the file read-write.
o_append = 0x0008 // append data to the file when writing.
o_create = 0x0100 // create a new file if none exists.
o_binary = 0x8000 // input and output is not translated.
o_trunc = 0x0200 // truncate regular writable file when opened.
o_excl = 0x0400 // used with o_create, file must not exist.
o_sync = 0x0000 // open for synchronous I/O (ignored on Windows)

View File

@ -267,6 +267,7 @@ pub fn open_file(path string, mode string, options ...int) ?File {
match m {
`r` { flags |= o_rdonly }
`w` { flags |= o_create | o_trunc }
`b` { flags |= o_binary }
`a` { flags |= o_create | o_append }
`s` { flags |= o_sync }
`n` { flags |= o_nonblock }

View File

@ -4,23 +4,23 @@ const (
// tfolder will contain all the temporary files/subfolders made by
// the different tests. It would be removed in testsuite_end(), so
// individual os tests do not need to clean up after themselves.
tfolder = os.join_path( os.temp_dir(), 'v', 'tests', 'os_test')
tfolder = os.join_path(os.temp_dir(), 'v', 'tests', 'os_test')
)
fn testsuite_begin() {
eprintln('testsuite_begin, tfolder = $tfolder')
os.rmdir_all( tfolder )
assert !os.is_dir( tfolder )
os.mkdir_all( tfolder )
os.chdir( tfolder )
assert os.is_dir( tfolder )
os.rmdir_all(tfolder)
assert !os.is_dir(tfolder)
os.mkdir_all(tfolder)
os.chdir(tfolder)
assert os.is_dir(tfolder)
}
fn testsuite_end() {
os.chdir( os.wd_at_startup )
os.rmdir_all( tfolder )
assert !os.is_dir( tfolder )
//eprintln('testsuite_end , tfolder = $tfolder removed.')
os.chdir(os.wd_at_startup)
os.rmdir_all(tfolder)
assert !os.is_dir(tfolder)
// eprintln('testsuite_end , tfolder = $tfolder removed.')
}
fn test_open_file() {
@ -43,6 +43,27 @@ fn test_open_file() {
os.rm(filename)
}
fn test_open_file_binary() {
filename := './test1.dat'
hello := 'hello \n world!'
os.open_file(filename, 'r+', 0o666) or {
assert err == 'No such file or directory'
os.File{}
}
mut file := os.open_file(filename, 'wb+', 0o666) or {
panic(err)
}
bytes := hello.bytes()
file.write_bytes(bytes.data, bytes.len)
file.close()
assert hello.len == os.file_size(filename)
read_hello := os.read_bytes(filename) or {
panic('error reading file $filename')
}
assert bytes == read_hello
os.rm(filename)
}
fn test_file_get_line() {
filename := './fgetline.txt'
os.write_file(filename, 'line 1\nline 2')
@ -50,12 +71,16 @@ fn test_file_get_line() {
assert false
return
}
line1 := f.get_line() or { '' }
line2 := f.get_line() or { '' }
line1 := f.get_line() or {
''
}
line2 := f.get_line() or {
''
}
f.close()
//
//eprintln('line1: $line1')
//eprintln('line2: $line2')
// eprintln('line1: $line1')
// eprintln('line2: $line2')
assert line1 == 'line 1\n'
assert line2 == 'line 2'
}
@ -74,9 +99,9 @@ fn test_create_file() {
fn test_is_file() {
// Setup
work_dir := os.join_path(os.getwd(),'is_file_test')
work_dir := os.join_path(os.getwd(), 'is_file_test')
os.mkdir_all(work_dir)
tfile := os.join_path(work_dir,'tmp_file')
tfile := os.join_path(work_dir, 'tmp_file')
// Test things that shouldn't be a file
assert os.is_file(work_dir) == false
assert os.is_file('non-existent_file.tmp') == false
@ -88,7 +113,7 @@ fn test_is_file() {
$if windows {
assert true
} $else {
dsymlink := os.join_path(work_dir,'dir_symlink')
dsymlink := os.join_path(work_dir, 'dir_symlink')
os.system('ln -s $work_dir $dsymlink')
assert os.is_file(dsymlink) == false
}
@ -96,7 +121,7 @@ fn test_is_file() {
$if windows {
assert true
} $else {
fsymlink := os.join_path(work_dir,'file_symlink')
fsymlink := os.join_path(work_dir, 'file_symlink')
os.system('ln -s $tfile $fsymlink')
assert os.is_file(fsymlink)
}
@ -117,35 +142,27 @@ fn test_write_and_read_string_to_file() {
// test_write_and_read_bytes checks for regressions made in the functions
// read_bytes, read_bytes_at and write_bytes.
fn test_write_and_read_bytes() {
file_name := './byte_reader_writer.tst'
payload := [byte(`I`), `D`, `D`, `Q`, `D`]
file_name := './byte_reader_writer.tst'
payload := [byte(`I`), `D`, `D`, `Q`, `D`]
mut file_write := os.create(os.real_path(file_name)) or {
eprintln('failed to create file $file_name')
return
}
// We use the standard write_bytes function to write the payload and
// compare the length of the array with the file size (have to match).
file_write.write_bytes(payload.data, 5)
file_write.close()
assert payload.len == os.file_size(file_name)
mut file_read := os.open(os.real_path(file_name)) or {
eprintln('failed to open file $file_name')
return
}
// We only need to test read_bytes because this function calls
// read_bytes_at with second parameter zeroed (size, 0).
rbytes := file_read.read_bytes(5)
// eprintln('rbytes: $rbytes')
// eprintln('payload: $payload')
assert rbytes == payload
// check that trying to read data from EOF doesn't error and returns 0
mut a := []byte{len: 5}
nread := file_read.read_bytes_into(5, a) or {
@ -153,7 +170,6 @@ fn test_write_and_read_bytes() {
int(-1)
}
assert nread == 0
file_read.close()
// We finally delete the test file.
os.rm(file_name)
@ -212,42 +228,42 @@ fn test_cp() {
}
fn test_mv() {
work_dir := os.join_path(os.getwd(),'mv_test')
work_dir := os.join_path(os.getwd(), 'mv_test')
os.mkdir_all(work_dir)
// Setup test files
tfile1 := os.join_path(work_dir,'file')
tfile2 := os.join_path(work_dir,'file.test')
tfile3 := os.join_path(work_dir,'file.3')
tfile1 := os.join_path(work_dir, 'file')
tfile2 := os.join_path(work_dir, 'file.test')
tfile3 := os.join_path(work_dir, 'file.3')
tfile_content := 'temporary file'
os.write_file(tfile1, tfile_content)
os.write_file(tfile2, tfile_content)
// Setup test dirs
tdir1 := os.join_path(work_dir,'dir')
tdir2 := os.join_path(work_dir,'dir2')
tdir3 := os.join_path(work_dir,'dir3')
tdir1 := os.join_path(work_dir, 'dir')
tdir2 := os.join_path(work_dir, 'dir2')
tdir3 := os.join_path(work_dir, 'dir3')
mkdir(tdir1)
mkdir(tdir2)
// Move file with no extension to dir
os.mv(tfile1,tdir1)
mut expected := os.join_path(tdir1,'file')
os.mv(tfile1, tdir1)
mut expected := os.join_path(tdir1, 'file')
assert os.exists(expected) && !is_dir(expected) == true
// Move dir with contents to other dir
os.mv(tdir1,tdir2)
expected = os.join_path(tdir2,'dir')
os.mv(tdir1, tdir2)
expected = os.join_path(tdir2, 'dir')
assert os.exists(expected) && is_dir(expected) == true
expected = os.join_path(tdir2,'dir','file')
expected = os.join_path(tdir2, 'dir', 'file')
assert os.exists(expected) && !is_dir(expected) == true
// Move dir with contents to other dir (by renaming)
os.mv(os.join_path(tdir2,'dir'),tdir3)
os.mv(os.join_path(tdir2, 'dir'), tdir3)
expected = tdir3
assert os.exists(expected) && is_dir(expected) == true
assert os.is_dir_empty(tdir2) == true
// Move file with extension to dir
os.mv(tfile2,tdir2)
expected = os.join_path(tdir2,'file.test')
os.mv(tfile2, tdir2)
expected = os.join_path(tdir2, 'file.test')
assert os.exists(expected) && !is_dir(expected) == true
// Move file to dir (by renaming)
os.mv(os.join_path(tdir2,'file.test'),tfile3)
os.mv(os.join_path(tdir2, 'file.test'), tfile3)
expected = tfile3
assert os.exists(expected) && !is_dir(expected) == true
}
@ -415,9 +431,9 @@ fn test_is_abs() {
fn test_join() {
$if windows {
assert os.join_path('v','vlib','os') == 'v\\vlib\\os'
assert os.join_path('v', 'vlib', 'os') == 'v\\vlib\\os'
} $else {
assert os.join_path('v','vlib','os') == 'v/vlib/os'
assert os.join_path('v', 'vlib', 'os') == 'v/vlib/os'
}
}
@ -469,8 +485,8 @@ fn test_write_file_array_bytes() {
panic(err)
}
assert arr == rarr
//eprintln(arr.str())
//eprintln(rarr.str())
// eprintln(arr.str())
// eprintln(rarr.str())
}
fn test_write_file_array_structs() {
@ -483,5 +499,5 @@ fn test_write_file_array_structs() {
rarr := os.read_file_array<IntPoint>(fpath)
assert rarr == arr
assert rarr.len == maxn
//eprintln( rarr.str().replace('\n', ' ').replace('},', '},\n'))
// eprintln( rarr.str().replace('\n', ' ').replace('},', '},\n'))
}