os: add open_file function
parent
5deb29a7c9
commit
ae3d84df6b
|
@ -1,16 +1,6 @@
|
||||||
module os
|
module os
|
||||||
// (Must be realized in Syscall) (Must be specified)
|
// (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
|
// ref: http://www.ccfit.nsu.ru/~deviv/courses/unix/unix/ng7c229.html
|
||||||
const (
|
const (
|
||||||
S_IFMT = 0xF000 // type of file
|
S_IFMT = 0xF000 // type of 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
|
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 <sys/stat.h> // #include <signal.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
struct dirent {
|
struct dirent {
|
||||||
d_ino int
|
d_ino int
|
||||||
|
@ -31,6 +32,7 @@ pub const (
|
||||||
|
|
||||||
pub struct File {
|
pub struct File {
|
||||||
cfile voidptr // Using void* instead of FILE*
|
cfile voidptr // Using void* instead of FILE*
|
||||||
|
pub:
|
||||||
fd int
|
fd int
|
||||||
mut:
|
mut:
|
||||||
opened bool
|
opened bool
|
||||||
|
@ -71,6 +73,12 @@ fn C.getenv(byteptr) &char
|
||||||
fn C.sigaction(int, voidptr, int)
|
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 {
|
pub fn (f File) is_opened() bool {
|
||||||
return f.opened
|
return f.opened
|
||||||
}
|
}
|
||||||
|
@ -292,6 +300,58 @@ pub fn open_append(path string) ?File {
|
||||||
return 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) {
|
pub fn (f mut File) write_bytes_at(data voidptr, size, pos int) {
|
||||||
$if linux {
|
$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 {
|
fn vpclose(f voidptr) int {
|
||||||
$if windows {
|
$if windows {
|
||||||
return C._pclose(f)
|
return C._pclose(f)
|
||||||
|
|
|
@ -2,6 +2,8 @@ module os
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
path_separator = '/'
|
path_separator = '/'
|
||||||
)
|
)
|
||||||
|
@ -14,7 +16,6 @@ const (
|
||||||
|
|
||||||
fn C.symlink(charptr, charptr) int
|
fn C.symlink(charptr, charptr) int
|
||||||
|
|
||||||
|
|
||||||
pub fn init_os_args(argc int, argv &byteptr) []string {
|
pub fn init_os_args(argc int, argv &byteptr) []string {
|
||||||
mut args := []string
|
mut args := []string
|
||||||
for i in 0 .. argc {
|
for i in 0 .. argc {
|
||||||
|
@ -23,15 +24,6 @@ pub fn init_os_args(argc int, argv &byteptr) []string {
|
||||||
return args
|
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 {
|
pub fn ls(path string) ?[]string {
|
||||||
mut res := []string
|
mut res := []string
|
||||||
dir := C.opendir(path.str)
|
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 {
|
pub fn open(path string) ?File {
|
||||||
mut file := File{}
|
|
||||||
/*
|
/*
|
||||||
$if linux {
|
$if linux {
|
||||||
$if !android {
|
$if !android {
|
||||||
|
@ -85,9 +76,8 @@ pub fn open(path string) ?File {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
cpath := path.str
|
file := File{
|
||||||
file = File{
|
cfile: C.fopen(charptr(path.str), 'rb')
|
||||||
cfile: C.fopen(charptr(cpath), 'rb')
|
|
||||||
opened: true
|
opened: true
|
||||||
}
|
}
|
||||||
if isnil(file.cfile) {
|
if isnil(file.cfile) {
|
||||||
|
@ -96,10 +86,8 @@ pub fn open(path string) ?File {
|
||||||
return 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 {
|
pub fn create(path string) ?File {
|
||||||
mut fd := 0
|
|
||||||
mut file := File{}
|
|
||||||
/*
|
/*
|
||||||
// NB: android/termux/bionic is also a kind of linux,
|
// NB: android/termux/bionic is also a kind of linux,
|
||||||
// but linux syscalls there sometimes fail,
|
// 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')
|
cfile: C.fopen(charptr(path.str), 'wb')
|
||||||
opened: true
|
opened: true
|
||||||
}
|
}
|
||||||
|
@ -187,7 +175,7 @@ pub fn mkdir(path string) ?bool {
|
||||||
$if !android {
|
$if !android {
|
||||||
ret := C.syscall(sys_mkdir, apath.str, 511)
|
ret := C.syscall(sys_mkdir, apath.str, 511)
|
||||||
if ret == -1 {
|
if ret == -1 {
|
||||||
return error(get_error_msg(C.errno))
|
return error(posix_get_error_msg(C.errno))
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -195,7 +183,7 @@ pub fn mkdir(path string) ?bool {
|
||||||
*/
|
*/
|
||||||
r := C.mkdir(apath.str, 511)
|
r := C.mkdir(apath.str, 511)
|
||||||
if r == -1 {
|
if r == -1 {
|
||||||
return error(get_error_msg(C.errno))
|
return error(posix_get_error_msg(C.errno))
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -231,7 +219,12 @@ pub fn symlink(origin, target string) ?bool {
|
||||||
if res == 0 {
|
if res == 0 {
|
||||||
return true
|
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
|
// convert any value to []byte (LittleEndian) and write it
|
||||||
|
|
|
@ -24,6 +24,27 @@ fn test_unsetenv() {
|
||||||
assert os.getenv('foo') == ''
|
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() {
|
fn test_write_and_read_string_to_file() {
|
||||||
filename := './test1.txt'
|
filename := './test1.txt'
|
||||||
hello := 'hello world!'
|
hello := 'hello world!'
|
||||||
|
|
Loading…
Reference in New Issue