mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
os: add open_file function
This commit is contained in:
parent
5deb29a7c9
commit
ae3d84df6b
@ -1,16 +1,6 @@
|
||||
module os
|
||||
// (Must be realized in Syscall) (Must be specified)
|
||||
// File modes.
|
||||
const (
|
||||
O_RDONLY = 1 // open the file read-only.
|
||||
O_WRONLY = 2 // open the file write-only.
|
||||
O_RDWR = 3 // open the file read-write.
|
||||
O_APPEND = 8 // append data to the file when writing.
|
||||
O_CREATE = 16 // create a new file if none exists.
|
||||
O_EXCL = 32 // used with O_CREATE, file must not exist.
|
||||
O_SYNC = 64 // open for synchronous I/O.
|
||||
O_TRUNC = 128 // truncate regular writable file when opened.
|
||||
)
|
||||
|
||||
// ref: http://www.ccfit.nsu.ru/~deviv/courses/unix/unix/ng7c229.html
|
||||
const (
|
||||
S_IFMT = 0xF000 // type of file
|
||||
|
15
vlib/os/const_nix.v
Normal file
15
vlib/os/const_nix.v
Normal file
@ -0,0 +1,15 @@
|
||||
module os
|
||||
|
||||
// File modes
|
||||
const (
|
||||
O_RDONLY = 000000000 // open the file read-only.
|
||||
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_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.
|
||||
O_APPEND = 000002000 // append data to the file when writing.
|
||||
O_NONBLOCK = 000004000 // prevents blocking when opening files
|
||||
O_SYNC = 000010000 // open for synchronous I/O.
|
||||
)
|
@ -89,3 +89,16 @@ const (
|
||||
ENABLE_LVB_GRID_WORLDWIDE = 0x0010
|
||||
)
|
||||
|
||||
// File modes
|
||||
const (
|
||||
O_RDONLY = 0 // open the file read-only.
|
||||
O_WRONLY = 1 // open the file write-only.
|
||||
O_RDWR = 2 // 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_TRUNC = 0x0200 // truncate regular writable file when opened.
|
||||
O_EXCL = 0x0400 // used with O_CREATE, file must not exist.
|
||||
O_SYNC = 0 // open for synchronous I/O (ignored on Windows)
|
||||
O_NOCTTY = 0 // make file non-controlling tty (ignored on Windows)
|
||||
O_NONBLOCK = 0 // don't block on opening file (ignored on Windows)
|
||||
)
|
||||
|
69
vlib/os/os.v
69
vlib/os/os.v
@ -7,6 +7,7 @@ import filepath
|
||||
|
||||
#include <sys/stat.h> // #include <signal.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
struct dirent {
|
||||
d_ino int
|
||||
@ -31,6 +32,7 @@ pub const (
|
||||
|
||||
pub struct File {
|
||||
cfile voidptr // Using void* instead of FILE*
|
||||
pub:
|
||||
fd int
|
||||
mut:
|
||||
opened bool
|
||||
@ -71,6 +73,12 @@ fn C.getenv(byteptr) &char
|
||||
fn C.sigaction(int, voidptr, int)
|
||||
|
||||
|
||||
fn C.open(charptr, int, int) int
|
||||
|
||||
|
||||
fn C.fdopen(int, string) voidptr
|
||||
|
||||
|
||||
pub fn (f File) is_opened() bool {
|
||||
return f.opened
|
||||
}
|
||||
@ -292,6 +300,58 @@ pub fn open_append(path string) ?File {
|
||||
return file
|
||||
}
|
||||
|
||||
// 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 {
|
||||
mut flags := 0
|
||||
for m in mode {
|
||||
match m {
|
||||
`r` { flags |= O_RDONLY }
|
||||
`w` { flags |= O_CREATE | O_TRUNC }
|
||||
`a` { flags |= O_CREATE | O_APPEND }
|
||||
`s` { flags |= O_SYNC }
|
||||
`n` { flags |= O_NONBLOCK }
|
||||
`c` { flags |= O_NOCTTY }
|
||||
`+` { flags |= O_RDWR }
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
||||
mut permission := 0666
|
||||
if options.len > 0 {
|
||||
permission = options[0]
|
||||
}
|
||||
|
||||
$if windows {
|
||||
if permission < 0600 {
|
||||
permission = 0x0100
|
||||
}
|
||||
else {
|
||||
permission = 0x0100 | 0x0080
|
||||
}
|
||||
}
|
||||
|
||||
mut p := path
|
||||
$if windows {
|
||||
p = path.replace('/', '\\')
|
||||
}
|
||||
|
||||
fd := C.open(charptr(p.str), flags, permission)
|
||||
if fd == -1 {
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
|
||||
cfile := C.fdopen(fd, charptr(mode.str))
|
||||
if isnil(cfile) {
|
||||
return error('Failed to open or create file "$path"')
|
||||
}
|
||||
|
||||
return File{
|
||||
cfile: cfile
|
||||
fd: fd
|
||||
opened: true
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
pub fn (f mut File) write_bytes_at(data voidptr, size, pos int) {
|
||||
$if linux {
|
||||
@ -344,6 +404,15 @@ fn posix_wait4_to_exit_status(waitret int) (int,bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// posix_get_error_msg return error code representation in string.
|
||||
pub fn posix_get_error_msg(code int) string {
|
||||
ptr_text := C.strerror(code) // voidptr?
|
||||
if ptr_text == 0 {
|
||||
return ''
|
||||
}
|
||||
return tos3(ptr_text)
|
||||
}
|
||||
|
||||
fn vpclose(f voidptr) int {
|
||||
$if windows {
|
||||
return C._pclose(f)
|
||||
|
@ -2,6 +2,8 @@ module os
|
||||
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
pub const (
|
||||
path_separator = '/'
|
||||
)
|
||||
@ -14,7 +16,6 @@ const (
|
||||
|
||||
fn C.symlink(charptr, charptr) int
|
||||
|
||||
|
||||
pub fn init_os_args(argc int, argv &byteptr) []string {
|
||||
mut args := []string
|
||||
for i in 0 .. argc {
|
||||
@ -23,15 +24,6 @@ pub fn init_os_args(argc int, argv &byteptr) []string {
|
||||
return args
|
||||
}
|
||||
|
||||
// get_error_msg return error code representation in string.
|
||||
pub fn get_error_msg(code int) string {
|
||||
ptr_text := C.strerror(code) // voidptr?
|
||||
if ptr_text == 0 {
|
||||
return ''
|
||||
}
|
||||
return tos3(ptr_text)
|
||||
}
|
||||
|
||||
pub fn ls(path string) ?[]string {
|
||||
mut res := []string
|
||||
dir := C.opendir(path.str)
|
||||
@ -68,9 +60,8 @@ pub fn is_dir(path string) bool {
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// open opens a file at the specified and returns back a read-only `File` object
|
||||
pub fn open(path string) ?File {
|
||||
mut file := File{}
|
||||
/*
|
||||
$if linux {
|
||||
$if !android {
|
||||
@ -85,9 +76,8 @@ pub fn open(path string) ?File {
|
||||
}
|
||||
}
|
||||
*/
|
||||
cpath := path.str
|
||||
file = File{
|
||||
cfile: C.fopen(charptr(cpath), 'rb')
|
||||
file := File{
|
||||
cfile: C.fopen(charptr(path.str), 'rb')
|
||||
opened: true
|
||||
}
|
||||
if isnil(file.cfile) {
|
||||
@ -96,10 +86,8 @@ pub fn open(path string) ?File {
|
||||
return file
|
||||
}
|
||||
|
||||
// create creates a file at a specified location and returns a writable `File` object.
|
||||
// create creates or opens a file at a specified location and returns a write-only `File` object
|
||||
pub fn create(path string) ?File {
|
||||
mut fd := 0
|
||||
mut file := File{}
|
||||
/*
|
||||
// NB: android/termux/bionic is also a kind of linux,
|
||||
// but linux syscalls there sometimes fail,
|
||||
@ -123,7 +111,7 @@ pub fn create(path string) ?File {
|
||||
}
|
||||
}
|
||||
*/
|
||||
file = File{
|
||||
file := File{
|
||||
cfile: C.fopen(charptr(path.str), 'wb')
|
||||
opened: true
|
||||
}
|
||||
@ -187,7 +175,7 @@ pub fn mkdir(path string) ?bool {
|
||||
$if !android {
|
||||
ret := C.syscall(sys_mkdir, apath.str, 511)
|
||||
if ret == -1 {
|
||||
return error(get_error_msg(C.errno))
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -195,7 +183,7 @@ pub fn mkdir(path string) ?bool {
|
||||
*/
|
||||
r := C.mkdir(apath.str, 511)
|
||||
if r == -1 {
|
||||
return error(get_error_msg(C.errno))
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -231,7 +219,12 @@ pub fn symlink(origin, target string) ?bool {
|
||||
if res == 0 {
|
||||
return true
|
||||
}
|
||||
return error(get_error_msg(C.errno))
|
||||
return error(posix_get_error_msg(C.errno))
|
||||
}
|
||||
|
||||
// get_error_msg return error code representation in string.
|
||||
pub fn get_error_msg(code int) string {
|
||||
return posix_get_error_msg(code)
|
||||
}
|
||||
|
||||
// convert any value to []byte (LittleEndian) and write it
|
||||
|
@ -24,6 +24,27 @@ fn test_unsetenv() {
|
||||
assert os.getenv('foo') == ''
|
||||
}
|
||||
|
||||
fn test_open_file() {
|
||||
filename := './test1.txt'
|
||||
hello := 'hello world!'
|
||||
os.open_file(filename, "r+", 0666) or {
|
||||
assert err == "No such file or directory"
|
||||
}
|
||||
|
||||
mut file := os.open_file(filename, "w+", 0666) or { panic(err) }
|
||||
file.write(hello)
|
||||
file.close()
|
||||
|
||||
assert hello.len == os.file_size(filename)
|
||||
|
||||
read_hello := os.read_file(filename) or {
|
||||
panic('error reading file $filename')
|
||||
}
|
||||
assert hello == read_hello
|
||||
|
||||
os.rm(filename)
|
||||
}
|
||||
|
||||
fn test_write_and_read_string_to_file() {
|
||||
filename := './test1.txt'
|
||||
hello := 'hello world!'
|
||||
|
Loading…
Reference in New Issue
Block a user