os: improve documentation (#24790)

This commit is contained in:
Laurent Cheylus 2025-06-25 21:29:47 +02:00 committed by GitHub
parent 1573d4c99b
commit 80fed7add5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 108 additions and 78 deletions

View File

@ -1,6 +1,6 @@
module os module os
// debugger_present returns a bool indicating if the process is being debugged // debugger_present returns a bool indicating if the process is being debugged.
// Note: implementation available only on Darwin, FreeBSD, Linux, OpenBSD and // Note: implementation available only on Darwin, FreeBSD, Linux, OpenBSD and
// Windows. Otherwise, returns false. // Windows. Otherwise, returns false.
@[inline] @[inline]

View File

@ -10,13 +10,13 @@ fn C.GetEnvironmentStringsW() &u16
fn C.FreeEnvironmentStringsW(&u16) int fn C.FreeEnvironmentStringsW(&u16) int
// `getenv` returns the value of the environment variable named by the key. // getenv returns the value of the environment variable named by the key.
// If there is not one found, it returns an empty string ''. // If there is not one found, it returns an empty string ''.
pub fn getenv(key string) string { pub fn getenv(key string) string {
return getenv_opt(key) or { '' } return getenv_opt(key) or { '' }
} }
// `getenv_opt` returns the value of a given environment variable. // getenv_opt returns the value of a given environment variable.
// Returns `none` if the environment variable does not exist. // Returns `none` if the environment variable does not exist.
@[manualfree] @[manualfree]
pub fn getenv_opt(key string) ?string { pub fn getenv_opt(key string) ?string {
@ -42,7 +42,7 @@ pub fn getenv_opt(key string) ?string {
} }
} }
// os.setenv sets the value of an environment variable with `name` to `value`. // setenv sets the value of an environment variable with `name` to `value`.
pub fn setenv(name string, value string, overwrite bool) int { pub fn setenv(name string, value string, overwrite bool) int {
$if windows { $if windows {
format := '${name}=${value}'.to_wide() format := '${name}=${value}'.to_wide()
@ -68,7 +68,7 @@ pub fn setenv(name string, value string, overwrite bool) int {
} }
} }
// os.unsetenv clears an environment variable with `name`. // unsetenv clears an environment variable with `name`.
pub fn unsetenv(name string) int { pub fn unsetenv(name string) int {
$if windows { $if windows {
format := '${name}='.to_wide() format := '${name}='.to_wide()
@ -83,7 +83,7 @@ pub fn unsetenv(name string) int {
// See: https://linux.die.net/man/5/environ for unix platforms. // See: https://linux.die.net/man/5/environ for unix platforms.
// See: https://docs.microsoft.com/bg-bg/windows/win32/api/processenv/nf-processenv-getenvironmentstrings // See: https://docs.microsoft.com/bg-bg/windows/win32/api/processenv/nf-processenv-getenvironmentstrings
// os.environ returns a map of all the current environment variables // environ returns a map of all the current environment variables.
// TODO how to declare Virtual C globals? // TODO how to declare Virtual C globals?
// const C.environ &&char // const C.environ &&char

View File

@ -183,7 +183,7 @@ pub fn create(path string) !File {
} }
} }
// stdin - return an os.File for stdin // stdin returns an os.File for stdin.
pub fn stdin() File { pub fn stdin() File {
return File{ return File{
fd: 0 fd: 0
@ -192,7 +192,7 @@ pub fn stdin() File {
} }
} }
// stdout - return an os.File for stdout // stdout returns an os.File for stdout.
pub fn stdout() File { pub fn stdout() File {
return File{ return File{
fd: 1 fd: 1
@ -201,7 +201,7 @@ pub fn stdout() File {
} }
} }
// stderr - return an os.File for stderr // stderr returns an os.File for stderr.
pub fn stderr() File { pub fn stderr() File {
return File{ return File{
fd: 2 fd: 2
@ -210,7 +210,7 @@ pub fn stderr() File {
} }
} }
// eof returns true, when the end of file has been reached // eof returns true, when the end of file has been reached.
pub fn (f &File) eof() bool { pub fn (f &File) eof() bool {
cfile := unsafe { &C.FILE(f.cfile) } cfile := unsafe { &C.FILE(f.cfile) }
return C.feof(cfile) != 0 return C.feof(cfile) != 0
@ -290,7 +290,7 @@ pub fn (mut f File) writeln(s string) !int {
return written + 1 return written + 1
} }
// write_string writes the string `s` into the file // write_string writes the string `s` into the file.
// It returns how many bytes were actually written. // It returns how many bytes were actually written.
pub fn (mut f File) write_string(s string) !int { pub fn (mut f File) write_string(s string) !int {
unsafe { f.write_full_buffer(s.str, usize(s.len))! } unsafe { f.write_full_buffer(s.str, usize(s.len))! }
@ -578,7 +578,7 @@ fn error_size_of_type_0() IError {
return &SizeOfTypeIs0Error{} return &SizeOfTypeIs0Error{}
} }
// read_struct reads a single struct of type `T` // read_struct reads a single struct of type `T`.
pub fn (mut f File) read_struct[T](mut t T) ! { pub fn (mut f File) read_struct[T](mut t T) ! {
if !f.is_opened { if !f.is_opened {
return error_file_not_opened() return error_file_not_opened()
@ -593,7 +593,7 @@ pub fn (mut f File) read_struct[T](mut t T) ! {
} }
} }
// read_struct_at reads a single struct of type `T` at position specified in file // read_struct_at reads a single struct of type `T` at position specified in file.
pub fn (mut f File) read_struct_at[T](mut t T, pos u64) ! { pub fn (mut f File) read_struct_at[T](mut t T, pos u64) ! {
if !f.is_opened { if !f.is_opened {
return error_file_not_opened() return error_file_not_opened()
@ -624,7 +624,7 @@ pub fn (mut f File) read_struct_at[T](mut t T, pos u64) ! {
} }
} }
// read_raw reads and returns a single instance of type `T` // read_raw reads and returns a single instance of type `T`.
pub fn (mut f File) read_raw[T]() !T { pub fn (mut f File) read_raw[T]() !T {
if !f.is_opened { if !f.is_opened {
return error_file_not_opened() return error_file_not_opened()
@ -641,7 +641,8 @@ pub fn (mut f File) read_raw[T]() !T {
return t return t
} }
// read_raw_at reads and returns a single instance of type `T` starting at file byte offset `pos` // read_raw_at reads and returns a single instance of type `T` starting at file
// byte offset `pos`.
pub fn (mut f File) read_raw_at[T](pos u64) !T { pub fn (mut f File) read_raw_at[T](pos u64) !T {
if !f.is_opened { if !f.is_opened {
return error_file_not_opened() return error_file_not_opened()
@ -687,7 +688,7 @@ pub fn (mut f File) read_raw_at[T](pos u64) !T {
return t return t
} }
// write_struct writes a single struct of type `T` // write_struct writes a single struct of type `T`.
pub fn (mut f File) write_struct[T](t &T) ! { pub fn (mut f File) write_struct[T](t &T) ! {
if !f.is_opened { if !f.is_opened {
return error_file_not_opened() return error_file_not_opened()
@ -743,7 +744,7 @@ pub fn (mut f File) write_struct_at[T](t &T, pos u64) ! {
// TODO: `write_raw[_at]` implementations are copy-pasted from `write_struct[_at]` // TODO: `write_raw[_at]` implementations are copy-pasted from `write_struct[_at]`
// write_raw writes a single instance of type `T` // write_raw writes a single instance of type `T`.
pub fn (mut f File) write_raw[T](t &T) ! { pub fn (mut f File) write_raw[T](t &T) ! {
if !f.is_opened { if !f.is_opened {
return error_file_not_opened() return error_file_not_opened()

View File

@ -59,8 +59,8 @@ pub fn (m FileMode) bitmask() u32 {
} }
// inode returns the metadata of the file/inode, containing inode type, permission information, size and modification time. // inode returns the metadata of the file/inode, containing inode type, permission information, size and modification time.
// it supports windows for regular files, but it doesn't matter if you use owner, group or others when checking permissions on windows. // It supports Windows for regular files, but it doesn't matter if you use owner, group or others when checking permissions on Windows.
// if a symlink is targeted, it returns info on the link, not the target // if a symlink is targeted, it returns info on the link, not the target.
pub fn inode(path string) FileInfo { pub fn inode(path string) FileInfo {
attr := lstat(path) or { Stat{} } attr := lstat(path) or { Stat{} }
fm := attr.get_mode() fm := attr.get_mode()

View File

@ -334,7 +334,7 @@ fn posix_wait4_to_exit_status(waitret int) (int, bool) {
} }
} }
// posix_get_error_msg return error code representation in string. // posix_get_error_msg returns error code representation in string.
pub fn posix_get_error_msg(code int) string { pub fn posix_get_error_msg(code int) string {
ptr_text := C.strerror(code) // voidptr? ptr_text := C.strerror(code) // voidptr?
if ptr_text == 0 { if ptr_text == 0 {
@ -412,7 +412,7 @@ pub fn exists(path string) bool {
// is_executable returns `true` if `path` is executable. // is_executable returns `true` if `path` is executable.
// Warning: `is_executable()` is known to cause a TOCTOU vulnerability when used incorrectly // Warning: `is_executable()` is known to cause a TOCTOU vulnerability when used incorrectly
// (for more information: https://github.com/vlang/v/blob/master/vlib/os/README.md) // (for more information: https://github.com/vlang/v/blob/master/vlib/os/README.md).
pub fn is_executable(path string) bool { pub fn is_executable(path string) bool {
$if windows { $if windows {
// Note: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/access-waccess?view=vs-2019 // Note: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/access-waccess?view=vs-2019
@ -433,7 +433,7 @@ pub fn is_executable(path string) bool {
// is_writable returns `true` if `path` is writable. // is_writable returns `true` if `path` is writable.
// Warning: `is_writable()` is known to cause a TOCTOU vulnerability when used incorrectly // Warning: `is_writable()` is known to cause a TOCTOU vulnerability when used incorrectly
// (for more information: https://github.com/vlang/v/blob/master/vlib/os/README.md) // (for more information: https://github.com/vlang/v/blob/master/vlib/os/README.md).
@[manualfree] @[manualfree]
pub fn is_writable(path string) bool { pub fn is_writable(path string) bool {
$if windows { $if windows {
@ -450,7 +450,7 @@ pub fn is_writable(path string) bool {
// is_readable returns `true` if `path` is readable. // is_readable returns `true` if `path` is readable.
// Warning: `is_readable()` is known to cause a TOCTOU vulnerability when used incorrectly // Warning: `is_readable()` is known to cause a TOCTOU vulnerability when used incorrectly
// (for more information: https://github.com/vlang/v/blob/master/vlib/os/README.md) // (for more information: https://github.com/vlang/v/blob/master/vlib/os/README.md).
@[manualfree] @[manualfree]
pub fn is_readable(path string) bool { pub fn is_readable(path string) bool {
$if windows { $if windows {
@ -507,7 +507,7 @@ fn print_c_errno() {
eprintln('errno=${e} err=${se}') eprintln('errno=${e} err=${se}')
} }
// get_raw_line returns a one-line string from stdin along with '\n' if there is any. // get_raw_line returns a one-line string from stdin along with `\n` if there is any.
@[manualfree] @[manualfree]
pub fn get_raw_line() string { pub fn get_raw_line() string {
$if windows { $if windows {
@ -1041,7 +1041,8 @@ pub fn execve(cmdpath string, cmdargs []string, envs []string) ! {
} }
} }
// is_atty returns 1 if the `fd` file descriptor is open and refers to a terminal // is_atty returns 1 if the `fd` file descriptor is open and refers to a
// terminal.
pub fn is_atty(fd int) int { pub fn is_atty(fd int) int {
$if windows { $if windows {
mut mode := u32(0) mut mode := u32(0)
@ -1060,6 +1061,8 @@ pub fn write_file_array(path string, buffer array) ! {
f.close() f.close()
} }
// glob function searches for all the pathnames matching patterns and returns a
// sorted list of found pathnames.
@[manualfree] @[manualfree]
pub fn glob(patterns ...string) ![]string { pub fn glob(patterns ...string) ![]string {
mut matches := []string{} mut matches := []string{}
@ -1070,7 +1073,8 @@ pub fn glob(patterns ...string) ![]string {
return matches return matches
} }
// last_error returns a V error, formed by the last libc error (from GetLastError() on windows and from `errno` on !windows) // last_error returns a V error, formed by the last libc error (from
// `GetLastError()` on windows and from `errno` on !windows).
@[manualfree] @[manualfree]
pub fn last_error() IError { pub fn last_error() IError {
$if windows { $if windows {

View File

@ -383,7 +383,7 @@ pub fn input(prompt string) string {
return res return res
} }
// get_line returns a one-line string from stdin // get_line returns a one-line string from stdin.
pub fn get_line() string { pub fn get_line() string {
str := get_raw_line() str := get_raw_line()
$if windows { $if windows {
@ -441,7 +441,7 @@ pub fn get_raw_lines_joined() string {
} }
// get_trimmed_lines reads *all* input lines from stdin, as an array of strings. // get_trimmed_lines reads *all* input lines from stdin, as an array of strings.
// The ending new line characters \r and \n, are removed from each line. // The ending new line characters `\r` and `\n`, are removed from each line.
// Note: unlike os.get_lines, empty lines will be present in the output as empty strings ''. // Note: unlike os.get_lines, empty lines will be present in the output as empty strings ''.
// Reading is stopped, only on EOF of stdin. // Reading is stopped, only on EOF of stdin.
pub fn get_trimmed_lines() []string { pub fn get_trimmed_lines() []string {
@ -620,7 +620,7 @@ pub fn find_abs_path_of_executable(exe_name string) !string {
return error_failed_to_find_executable() return error_failed_to_find_executable()
} }
// exists_in_system_path returns `true` if `prog` exists in the system's PATH // exists_in_system_path returns `true` if `prog` exists in the system's PATH.
pub fn exists_in_system_path(prog string) bool { pub fn exists_in_system_path(prog string) bool {
find_abs_path_of_executable(prog) or { return false } find_abs_path_of_executable(prog) or { return false }
return true return true
@ -909,10 +909,10 @@ fn xdg_home_folder(ename string, lpath string) string {
// See: https://specifications.freedesktop.org/basedir-spec/latest/ . // See: https://specifications.freedesktop.org/basedir-spec/latest/ .
// There is a single base directory relative to which user-specific non-essential // There is a single base directory relative to which user-specific non-essential
// (cached) data should be written. This directory is defined by the environment // (cached) data should be written. This directory is defined by the environment
// variable $XDG_CACHE_HOME. // variable `$XDG_CACHE_HOME`.
// $XDG_CACHE_HOME defines the base directory relative to which user specific // `$XDG_CACHE_HOME` defines the base directory relative to which user specific
// non-essential data files should be stored. If $XDG_CACHE_HOME is either not set // non-essential data files should be stored. If `$XDG_CACHE_HOME` is either not set
// or empty, a default equal to $HOME/.cache should be used. // or empty, a default equal to `$HOME/.cache` should be used.
pub fn cache_dir() string { pub fn cache_dir() string {
return xdg_home_folder('XDG_CACHE_HOME', '.cache') return xdg_home_folder('XDG_CACHE_HOME', '.cache')
} }
@ -920,8 +920,9 @@ pub fn cache_dir() string {
// data_dir returns the path to a *writable* user-specific folder, suitable for writing application data. // data_dir returns the path to a *writable* user-specific folder, suitable for writing application data.
// See: https://specifications.freedesktop.org/basedir-spec/latest/ . // See: https://specifications.freedesktop.org/basedir-spec/latest/ .
// There is a single base directory relative to which user-specific data files should be written. // There is a single base directory relative to which user-specific data files should be written.
// This directory is defined by the environment variable $XDG_DATA_HOME. // This directory is defined by the environment variable `$XDG_DATA_HOME`.
// If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used. // If `$XDG_DATA_HOME` is either not set or empty, a default equal to
// `$HOME/.local/share` should be used.
pub fn data_dir() string { pub fn data_dir() string {
return xdg_home_folder('XDG_DATA_HOME', '.local/share') return xdg_home_folder('XDG_DATA_HOME', '.local/share')
} }
@ -930,8 +931,9 @@ pub fn data_dir() string {
// that should persist between (application) restarts, but that is not important or portable // that should persist between (application) restarts, but that is not important or portable
// enough to the user that it should be stored in os.data_dir(). // enough to the user that it should be stored in os.data_dir().
// See: https://specifications.freedesktop.org/basedir-spec/latest/ . // See: https://specifications.freedesktop.org/basedir-spec/latest/ .
// $XDG_STATE_HOME defines the base directory relative to which user-specific state files should be stored. // `$XDG_STATE_HOME` defines the base directory relative to which user-specific state files should be stored.
// If $XDG_STATE_HOME is either not set or empty, a default equal to $HOME/.local/state should be used. // If `$XDG_STATE_HOME` is either not set or empty, a default equal to
// `$HOME/.local/state should be used`.
// It may contain: // It may contain:
// * actions history (logs, history, recently used files, …) // * actions history (logs, history, recently used files, …)
// * current state of the application that can be reused on a restart (view, layout, open files, undo history, …) // * current state of the application that can be reused on a restart (view, layout, open files, undo history, …)
@ -941,7 +943,7 @@ pub fn state_dir() string {
// local_bin_dir returns `$HOME/.local/bin`, which is *guaranteed* to be in the PATH of the current user, for // local_bin_dir returns `$HOME/.local/bin`, which is *guaranteed* to be in the PATH of the current user, for
// distributions, following the XDG spec from https://specifications.freedesktop.org/basedir-spec/latest/ : // distributions, following the XDG spec from https://specifications.freedesktop.org/basedir-spec/latest/ :
// > User-specific executable files may be stored in $HOME/.local/bin . // > User-specific executable files may be stored in `$HOME/.local/bin`.
// > Distributions should ensure this directory shows up in the UNIX $PATH environment variable, at an appropriate place. // > Distributions should ensure this directory shows up in the UNIX $PATH environment variable, at an appropriate place.
pub fn local_bin_dir() string { pub fn local_bin_dir() string {
return xdg_home_folder('LOCAL_BIN_DIR', '.local/bin') // provides a way to test by setting an env variable return xdg_home_folder('LOCAL_BIN_DIR', '.local/bin') // provides a way to test by setting an env variable
@ -1015,8 +1017,7 @@ pub fn vmodules_dir() string {
} }
// vmodules_paths returns a list of paths, where v looks up for modules. // vmodules_paths returns a list of paths, where v looks up for modules.
// You can customize it through setting the environment variable VMODULES // You can customize it through setting the environment variable `VMODULES`.
// [manualfree]
pub fn vmodules_paths() []string { pub fn vmodules_paths() []string {
mut path := getenv('VMODULES') mut path := getenv('VMODULES')
if path == '' { if path == '' {
@ -1077,6 +1078,8 @@ pub mut:
machine string machine string
} }
// execute_or_panic returns the os.Result of executing `cmd`, or panic with its
// output on failure.
pub fn execute_or_panic(cmd string) Result { pub fn execute_or_panic(cmd string) Result {
res := execute(cmd) res := execute(cmd)
if res.exit_code != 0 { if res.exit_code != 0 {
@ -1087,6 +1090,8 @@ pub fn execute_or_panic(cmd string) Result {
return res return res
} }
// execute_or_exit returns the os.Result of executing `cmd`, or exit with its
// output on failure.
pub fn execute_or_exit(cmd string) Result { pub fn execute_or_exit(cmd string) Result {
res := execute(cmd) res := execute(cmd)
if res.exit_code != 0 { if res.exit_code != 0 {
@ -1121,11 +1126,11 @@ pub fn quoted_path(path string) string {
} }
// config_dir returns the path to the user configuration directory (depending on the platform). // config_dir returns the path to the user configuration directory (depending on the platform).
// On windows, that is `%AppData%`. // On Windows, that is `%AppData%`.
// On macos, that is `~/Library/Application Support`. // On macOS, that is `~/Library/Application Support`.
// On the rest, that is `$XDG_CONFIG_HOME`, or if that is not available, `~/.config`. // On the rest, that is `$XDG_CONFIG_HOME`, or if that is not available, `~/.config`.
// If the path cannot be determined, it returns an error. // If the path cannot be determined, it returns an error.
// (for example, when $HOME on linux, or %AppData% on windows is not defined) // (for example, when `$HOME` on Linux, or `%AppData%` on Windows is not defined)
pub fn config_dir() !string { pub fn config_dir() !string {
$if windows { $if windows {
app_data := getenv('AppData') app_data := getenv('AppData')

View File

@ -214,6 +214,9 @@ fn native_glob_pattern(pattern string, mut matches []string) ! {
} }
} }
// utime changes the access and modification times of the inode specified by
// path to the actime and modtime fields of times respectively, or returns POSIX
// error message if utime call fails.
pub fn utime(path string, actime int, modtime int) ! { pub fn utime(path string, actime int, modtime int) ! {
u := C.utimbuf{actime, modtime} u := C.utimbuf{actime, modtime}
if C.utime(&char(path.str), &u) != 0 { if C.utime(&char(path.str), &u) != 0 {
@ -253,6 +256,8 @@ pub fn uname() Uname {
return u return u
} }
// hostname returns the hostname (system's DNS name) or POSIX error message if
// the hostname call fails.
pub fn hostname() !string { pub fn hostname() !string {
mut hstnme := '' mut hstnme := ''
size := 256 size := 256
@ -265,6 +270,8 @@ pub fn hostname() !string {
return error(posix_get_error_msg(C.errno)) return error(posix_get_error_msg(C.errno))
} }
// loginname returns the name of the user logged in on the controlling terminal
// of the process or POSIX error message if the getlogin call fails.
pub fn loginname() !string { pub fn loginname() !string {
x := C.getlogin() x := C.getlogin()
if !isnil(x) { if !isnil(x) {
@ -420,6 +427,8 @@ pub fn (mut c Command) close() ! {
} }
} }
// symlink creates a symbolic link named target, which points to origin
// or returns POSIX error message if symlink call fails.
pub fn symlink(origin string, target string) ! { pub fn symlink(origin string, target string) ! {
res := C.symlink(&char(origin.str), &char(target.str)) res := C.symlink(&char(origin.str), &char(target.str))
if res == 0 { if res == 0 {
@ -428,6 +437,8 @@ pub fn symlink(origin string, target string) ! {
return error(posix_get_error_msg(C.errno)) return error(posix_get_error_msg(C.errno))
} }
// link creates a new link (also known as a hard link) to an existing file or
// returns POSIX error message if link call fails.
pub fn link(origin string, target string) ! { pub fn link(origin string, target string) ! {
res := C.link(&char(origin.str), &char(target.str)) res := C.link(&char(origin.str), &char(target.str))
if res == 0 { if res == 0 {
@ -476,37 +487,43 @@ pub fn ensure_folder_is_writable(folder string) ! {
rm(tmp_perm_check)! rm(tmp_perm_check)!
} }
// getpid returns the process ID (PID) of the calling process.
@[inline] @[inline]
pub fn getpid() int { pub fn getpid() int {
return C.getpid() return C.getpid()
} }
// getppid returns the process ID of the parent of the calling process.
@[inline] @[inline]
pub fn getppid() int { pub fn getppid() int {
return C.getppid() return C.getppid()
} }
// getuid returns the real user ID of the calling process.
@[inline] @[inline]
pub fn getuid() int { pub fn getuid() int {
return C.getuid() return C.getuid()
} }
// geteuid returns the effective user ID of the calling process.
@[inline] @[inline]
pub fn geteuid() int { pub fn geteuid() int {
return C.geteuid() return C.geteuid()
} }
// getgid returns the real group ID of the calling process.
@[inline] @[inline]
pub fn getgid() int { pub fn getgid() int {
return C.getgid() return C.getgid()
} }
// getegid returns the effective group ID of the calling process.
@[inline] @[inline]
pub fn getegid() int { pub fn getegid() int {
return C.getegid() return C.getegid()
} }
// Turns the given bit on or off, depending on the `enable` parameter // Turns the given bit on or off, depending on the `enable` parameter.
pub fn posix_set_permission_bit(path_s string, mode u32, enable bool) { pub fn posix_set_permission_bit(path_s string, mode u32, enable bool) {
mut new_mode := u32(0) mut new_mode := u32(0)
if s := stat(path_s) { if s := stat(path_s) {
@ -539,7 +556,7 @@ struct C.statvfs {
f_bavail usize f_bavail usize
} }
// disk_usage returns disk usage of `path` // disk_usage returns disk usage of `path`.
@[manualfree] @[manualfree]
pub fn disk_usage(path string) !DiskUsage { pub fn disk_usage(path string) !DiskUsage {
mpath := if path == '' { '.' } else { path } mpath := if path == '' { '.' } else { path }

View File

@ -85,7 +85,7 @@ pub fn (st Stat) get_filetype() FileType {
} }
// get_mode returns the file type and permissions (readable, writable, executable) // get_mode returns the file type and permissions (readable, writable, executable)
// in owner/group/others format // in owner/group/others format.
pub fn (st Stat) get_mode() FileMode { pub fn (st Stat) get_mode() FileMode {
return FileMode{ return FileMode{
typ: st.get_filetype() typ: st.get_filetype()
@ -115,13 +115,13 @@ pub fn is_dir(path string) bool {
// is_link returns a boolean indicating whether `path` is a link. // is_link returns a boolean indicating whether `path` is a link.
// Warning: `is_link()` is known to cause a TOCTOU vulnerability when used incorrectly // Warning: `is_link()` is known to cause a TOCTOU vulnerability when used incorrectly
// (for more information: https://github.com/vlang/v/blob/master/vlib/os/README.md) // (for more information: https://github.com/vlang/v/blob/master/vlib/os/README.md).
pub fn is_link(path string) bool { pub fn is_link(path string) bool {
attr := lstat(path) or { return false } attr := lstat(path) or { return false }
return attr.get_filetype() == .symbolic_link return attr.get_filetype() == .symbolic_link
} }
// kind_of_existing_path identifies whether path is a file, directory, or link // kind_of_existing_path identifies whether path is a file, directory, or link.
fn kind_of_existing_path(path string) PathKind { fn kind_of_existing_path(path string) PathKind {
mut res := PathKind{} mut res := PathKind{}
attr := lstat(path) or { return res } attr := lstat(path) or { return res }

View File

@ -7,7 +7,7 @@ pub enum ChildProcessPipeKind {
stderr stderr
} }
// signal_kill - kills the process, after that it is no longer running // signal_kill kills the process, after that it is no longer running.
pub fn (mut p Process) signal_kill() { pub fn (mut p Process) signal_kill() {
if p.status !in [.running, .stopped] { if p.status !in [.running, .stopped] {
return return
@ -16,7 +16,7 @@ pub fn (mut p Process) signal_kill() {
p.status = .aborted p.status = .aborted
} }
// signal_term - terminate the process // signal_term terminates the process.
pub fn (mut p Process) signal_term() { pub fn (mut p Process) signal_term() {
if p.status !in [.running, .stopped] { if p.status !in [.running, .stopped] {
return return
@ -24,7 +24,7 @@ pub fn (mut p Process) signal_term() {
p._signal_term() p._signal_term()
} }
// signal_pgkill - kills the whole process group // signal_pgkill kills the whole process group.
pub fn (mut p Process) signal_pgkill() { pub fn (mut p Process) signal_pgkill() {
if p.status !in [.running, .stopped] { if p.status !in [.running, .stopped] {
return return
@ -32,7 +32,7 @@ pub fn (mut p Process) signal_pgkill() {
p._signal_pgkill() p._signal_pgkill()
} }
// signal_stop - stops the process, you can resume it with p.signal_continue() // signal_stop stops the process, you can resume it with p.signal_continue().
pub fn (mut p Process) signal_stop() { pub fn (mut p Process) signal_stop() {
if p.status != .running { if p.status != .running {
return return
@ -41,7 +41,7 @@ pub fn (mut p Process) signal_stop() {
p.status = .stopped p.status = .stopped
} }
// signal_continue - tell a stopped process to continue/resume its work // signal_continue tell a stopped process to continue/resume its work.
pub fn (mut p Process) signal_continue() { pub fn (mut p Process) signal_continue() {
if p.status != .stopped { if p.status != .stopped {
return return
@ -50,7 +50,7 @@ pub fn (mut p Process) signal_continue() {
p.status = .running p.status = .running
} }
// wait - wait for a process to finish. // wait for a process to finish.
// Note: You have to call p.wait(), otherwise a finished process // Note: You have to call p.wait(), otherwise a finished process
// would get to a zombie state, and its resources will not get // would get to a zombie state, and its resources will not get
// released fully, until its parent process exits. // released fully, until its parent process exits.
@ -66,7 +66,7 @@ pub fn (mut p Process) wait() {
p._wait() p._wait()
} }
// close - free the OS resources associated with the process. // free the OS resources associated with the process.
// Can be called multiple times, but will free the resources just once. // Can be called multiple times, but will free the resources just once.
// This sets the process state to .closed, which is final. // This sets the process state to .closed, which is final.
pub fn (mut p Process) close() { pub fn (mut p Process) close() {
@ -94,8 +94,7 @@ pub fn (mut p Process) free() {
} }
} }
// // _spawn should not be called directly, but only by p.run()/p.wait().
// _spawn - should not be called directly, but only by p.run()/p.wait() .
// It encapsulates the fork/execve mechanism that allows the // It encapsulates the fork/execve mechanism that allows the
// asynchronous starting of the new child process. // asynchronous starting of the new child process.
fn (mut p Process) _spawn() int { fn (mut p Process) _spawn() int {
@ -117,7 +116,7 @@ fn (mut p Process) _spawn() int {
return 0 return 0
} }
// is_alive - query whether the process p.pid is still alive // is_alive query whether the process is still alive.
pub fn (mut p Process) is_alive() bool { pub fn (mut p Process) is_alive() bool {
mut res := false mut res := false
if p.status in [.running, .stopped] { if p.status in [.running, .stopped] {
@ -146,7 +145,8 @@ pub fn (mut p Process) stdin_write(s string) {
p._write_to(.stdin, s) p._write_to(.stdin, s)
} }
// stdout_slurp will read from the stdout pipe, and will block until it either reads all the data, or until the pipe is closed (end of file). // stdout_slurp will read from the stdout pipe, and will block until it either
// reads all the data, or until the pipe is closed (end of file).
pub fn (mut p Process) stdout_slurp() string { pub fn (mut p Process) stdout_slurp() string {
p._check_redirection_call(@METHOD) p._check_redirection_call(@METHOD)
res := p._slurp_from(.stdout) res := p._slurp_from(.stdout)
@ -156,7 +156,8 @@ pub fn (mut p Process) stdout_slurp() string {
return res return res
} }
// stderr_slurp will read from the stderr pipe, and will block until it either reads all the data, or until the pipe is closed (end of file). // stderr_slurp will read from the stderr pipe, and will block until it either
// reads all the data, or until the pipe is closed (end of file).
pub fn (mut p Process) stderr_slurp() string { pub fn (mut p Process) stderr_slurp() string {
p._check_redirection_call(@METHOD) p._check_redirection_call(@METHOD)
res := p._slurp_from(.stderr) res := p._slurp_from(.stderr)
@ -166,8 +167,9 @@ pub fn (mut p Process) stderr_slurp() string {
return res return res
} }
// stdout_read reads a block of data, from the stdout pipe of the child process. It will block, if there is no data to be read. // stdout_read reads a block of data, from the stdout pipe of the child process.
// Call .is_pending() to check if there is data to be read, if you do not want to block. // It will block, if there is no data to be read. Call .is_pending() to check if
// there is data to be read, if you do not want to block.
pub fn (mut p Process) stdout_read() string { pub fn (mut p Process) stdout_read() string {
p._check_redirection_call(@METHOD) p._check_redirection_call(@METHOD)
res := p._read_from(.stdout) res := p._read_from(.stdout)
@ -177,8 +179,9 @@ pub fn (mut p Process) stdout_read() string {
return res return res
} }
// stderr_read reads a block of data, from the stderr pipe of the child process. It will block, if there is no data to be read. // stderr_read reads a block of data, from the stderr pipe of the child process.
// Call .is_pending() to check if there is data to be read, if you do not want to block. // It will block, if there is no data to be read. Call .is_pending() to check if
// there is data to be read, if you do not want to block.
pub fn (mut p Process) stderr_read() string { pub fn (mut p Process) stderr_read() string {
p._check_redirection_call(@METHOD) p._check_redirection_call(@METHOD)
res := p._read_from(.stderr) res := p._read_from(.stderr)
@ -216,7 +219,7 @@ pub fn (mut p Process) is_pending(pkind ChildProcessPipeKind) bool {
return res return res
} }
// _read_from should be called only from .stdout_read/0, .stderr_read/0 and .pipe_read/1 // _read_from should be called only from .stdout_read/0, .stderr_read/0 and .pipe_read/1.
fn (mut p Process) _read_from(pkind ChildProcessPipeKind) string { fn (mut p Process) _read_from(pkind ChildProcessPipeKind) string {
$if windows { $if windows {
s, _ := p.win_read_string(int(pkind), 4096) s, _ := p.win_read_string(int(pkind), 4096)
@ -227,7 +230,7 @@ fn (mut p Process) _read_from(pkind ChildProcessPipeKind) string {
} }
} }
// _slurp_from should be called only from stdout_slurp() and stderr_slurp() // _slurp_from should be called only from stdout_slurp() and stderr_slurp().
fn (mut p Process) _slurp_from(pkind ChildProcessPipeKind) string { fn (mut p Process) _slurp_from(pkind ChildProcessPipeKind) string {
$if windows { $if windows {
return p.win_slurp(int(pkind)) return p.win_slurp(int(pkind))
@ -236,7 +239,7 @@ fn (mut p Process) _slurp_from(pkind ChildProcessPipeKind) string {
} }
} }
// _write_to should be called only from stdin_write() // _write_to should be called only from stdin_write().
fn (mut p Process) _write_to(pkind ChildProcessPipeKind, s string) { fn (mut p Process) _write_to(pkind ChildProcessPipeKind, s string) {
$if windows { $if windows {
p.win_write_string(int(pkind), s) p.win_write_string(int(pkind), s)
@ -245,7 +248,7 @@ fn (mut p Process) _write_to(pkind ChildProcessPipeKind, s string) {
} }
} }
// _is_pending should be called only from is_pending() // _is_pending should be called only from is_pending().
fn (mut p Process) _is_pending(pkind ChildProcessPipeKind) bool { fn (mut p Process) _is_pending(pkind ChildProcessPipeKind) bool {
$if windows { $if windows {
return p.win_is_pending(int(pkind)) return p.win_is_pending(int(pkind))
@ -255,7 +258,7 @@ fn (mut p Process) _is_pending(pkind ChildProcessPipeKind) bool {
return false return false
} }
// _check_redirection_call - should be called just by stdxxx methods // _check_redirection_call should be called just by stdxxx methods.
fn (mut p Process) _check_redirection_call(fn_name string) { fn (mut p Process) _check_redirection_call(fn_name string) {
if !p.use_stdio_ctl { if !p.use_stdio_ctl {
panic('Call p.set_redirect_stdio() before calling p.' + fn_name) panic('Call p.set_redirect_stdio() before calling p.' + fn_name)
@ -265,7 +268,7 @@ fn (mut p Process) _check_redirection_call(fn_name string) {
} }
} }
// _signal_stop - should not be called directly, except by p.signal_stop // _signal_stop should not be called directly, except by p.signal_stop.
fn (mut p Process) _signal_stop() { fn (mut p Process) _signal_stop() {
$if windows { $if windows {
p.win_stop_process() p.win_stop_process()
@ -274,7 +277,7 @@ fn (mut p Process) _signal_stop() {
} }
} }
// _signal_continue - should not be called directly, just by p.signal_continue // _signal_continue should not be called directly, just by p.signal_continue.
fn (mut p Process) _signal_continue() { fn (mut p Process) _signal_continue() {
$if windows { $if windows {
p.win_resume_process() p.win_resume_process()
@ -283,7 +286,7 @@ fn (mut p Process) _signal_continue() {
} }
} }
// _signal_kill - should not be called directly, except by p.signal_kill // _signal_kill should not be called directly, except by p.signal_kill.
fn (mut p Process) _signal_kill() { fn (mut p Process) _signal_kill() {
$if windows { $if windows {
p.win_kill_process() p.win_kill_process()
@ -292,7 +295,7 @@ fn (mut p Process) _signal_kill() {
} }
} }
// _signal_term - should not be called directly, except by p.signal_term // _signal_term should not be called directly, except by p.signal_term.
fn (mut p Process) _signal_term() { fn (mut p Process) _signal_term() {
$if windows { $if windows {
p.win_term_process() p.win_term_process()
@ -301,7 +304,7 @@ fn (mut p Process) _signal_term() {
} }
} }
// _signal_pgkill - should not be called directly, except by p.signal_pgkill // _signal_pgkill should not be called directly, except by p.signal_pgkill.
fn (mut p Process) _signal_pgkill() { fn (mut p Process) _signal_pgkill() {
$if windows { $if windows {
p.win_kill_pgroup() p.win_kill_pgroup()
@ -310,7 +313,7 @@ fn (mut p Process) _signal_pgkill() {
} }
} }
// _wait - should not be called directly, except by p.wait() // _wait should not be called directly, except by p.wait().
fn (mut p Process) _wait() { fn (mut p Process) _wait() {
$if windows { $if windows {
p.win_wait() p.win_wait()
@ -319,7 +322,7 @@ fn (mut p Process) _wait() {
} }
} }
// _is_alive - should not be called directly, except by p.is_alive() // _is_alive should not be called directly, except by p.is_alive().
fn (mut p Process) _is_alive() bool { fn (mut p Process) _is_alive() bool {
$if windows { $if windows {
return p.win_is_alive() return p.win_is_alive()
@ -328,7 +331,7 @@ fn (mut p Process) _is_alive() bool {
} }
} }
// run - starts the new process // run starts the new process.
pub fn (mut p Process) run() { pub fn (mut p Process) run() {
if p.status != .not_started { if p.status != .not_started {
return return