os.ha (5318B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use fs; 5 use io; 6 use path; 7 8 // Provides an implementation of [[fs::fs]] for the current working directory. 9 export let cwd: *fs::fs = null: *fs::fs; 10 11 // Removes a file. 12 export fn remove(path: str) (void | fs::error) = fs::remove(cwd, path); 13 14 // Renames a file. This generally only works if the source and destination path 15 // are both on the same filesystem. See [[move]] for an implementation which 16 // falls back on a "copy & remove" procedure in this situation. 17 export fn rename(oldpath: str, newpath: str) (void | fs::error) = 18 fs::rename(cwd, oldpath, newpath); 19 20 // Moves a file. This will use [[rename]] if possible, and will fall back to 21 // copy and remove if necessary. 22 export fn move(oldpath: str, newpath: str) (void | fs::error) = 23 fs::move(cwd, oldpath, newpath); 24 25 // Creates an [[fs::iterator]] for a given directory to read its contents. The 26 // user should call [[fs::next]] to enumerate entries, and [[fs::finish]] when 27 // done using the object. 28 export fn iter(path: str) (*fs::iterator | fs::error) = fs::iter(cwd, path); 29 30 // Reads all entries from a directory. The caller must free the return value 31 // with [[fs::dirents_free]]. 32 export fn readdir(path: str) ([]fs::dirent | fs::error) = fs::readdir(cwd, path); 33 34 // Returns file information for a given path. If the target is a symlink, 35 // information is returned about the link, not its target. 36 export fn stat(path: str) (fs::filestat | fs::error) = fs::stat(cwd, path); 37 38 // Returns file information for an [[io::file]]. 39 export fn fstat(fd: io::file) (fs::filestat | fs::error) = fs::fstat(cwd, fd); 40 41 // Returns true if a node exists at the given path, or false if not. 42 // 43 // Note that testing for file existence before using the file can often lead to 44 // race conditions. If possible, prefer to simply attempt to use the file (e.g. 45 // via "open"), and handle the resulting error should the file not exist. 46 export fn exists(path: str) bool = fs::exists(cwd, path); 47 48 // Creates a directory. 49 export fn mkdir(path: str, mode: fs::mode) (void | fs::error) = fs::mkdir(cwd, path, mode); 50 51 // Creates a directory, and all non-extant directories in its path. 52 export fn mkdirs(path: str, mode: fs::mode) (void | fs::error) = fs::mkdirs(cwd, path, mode); 53 54 // Removes a directory. The target directory must be empty; see [[rmdirall]] to 55 // remove its contents as well. 56 export fn rmdir(path: str) (void | fs::error) = fs::rmdir(cwd, path); 57 58 // Removes a directory, and anything in it. 59 export fn rmdirall(path: str) (void | fs::error) = fs::rmdirall(cwd, path); 60 61 // Changes mode flags on a file or directory. Type bits are discared. 62 export fn chmod(path: str, mode: fs::mode) (void | fs::error) = fs::chmod(cwd, path, mode); 63 64 // Changes ownership of a file. 65 export fn chown(path: str, uid: uint, gid: uint) (void | fs::error) = fs::chown(cwd, path, uid, gid); 66 67 // Resolves a path to its absolute, normalized value. Relative paths will be 68 // rooted (if supported by the host filesystem), and "." and ".." components 69 // will be reduced. This function does not follow symlinks; see [[realpath]] if 70 // you need this behavior. The return value is statically allocated; use 71 // [[strings::dup]] to extend its lifetime. 72 export fn resolve(path: str) str = fs::resolve(cwd, path); 73 74 // Returns the path referred to by a symbolic link. The return value is 75 // statically allocated and will be overwritten on subsequent calls. 76 export fn readlink(path: str) (str | fs::error) = fs::readlink(cwd, path); 77 78 // Creates a new (hard) link at 'new' for the file at 'old'. 79 export fn link(old: str, new: str) (void | fs::error) = fs::link(cwd, old, new); 80 81 // Creates a new symbolic link at 'path' which points to 'target'. 82 export fn symlink(target: str, path: str) (void | fs::error) = 83 fs::symlink(cwd, target, path); 84 85 // Opens a file. 86 // 87 // If no flags are provided, [[fs::flag::RDONLY]] is used when opening the 88 // file. 89 // 90 // [[fs::flag::CREATE]] isn't very useful with this function, since the new 91 // file's mode is set to zero. For this use-case, use [[create]] instead. 92 export fn open(path: str, flags: fs::flag...) (io::file | fs::error) = 93 fs::open_file(cwd, path, flags...); 94 95 // Creates a new file with the given mode if it doesn't already exist and opens 96 // it for writing. 97 // 98 // If no flags are provided, [[fs::flag::WRONLY]] and [[fs::flag::TRUNC]] are 99 // used when opening the file. 100 // 101 // Only the permission bits of the mode are used. If other bits are set, they 102 // are discarded. 103 // 104 // To create a file without opening it, see [[mkfile]]. 105 export fn create( 106 path: str, 107 mode: fs::mode, 108 flags: fs::flag... 109 ) (io::file | fs::error) = fs::create_file(cwd, path, mode, flags...); 110 111 // Canonicalizes a path in this filesystem by resolving all symlinks and 112 // collapsing any "." or ".." path components. 113 // 114 // This function is a thin shim over [[fs::realpath]], and the return value is 115 // statically allocated by [[fs::realpath]]. Thus, calls to this function or to 116 // [[fs::realpath]] will overwrite the return value of either function. 117 export fn realpath(path: str) (str | fs::error) = fs::realpath(cwd, path); 118 119 // Opens a directory as a filesystem. 120 export fn diropen(path: str) (*fs::fs | fs::error) = { 121 const file = open(path, fs::flag::DIRECTORY | fs::flag::RDONLY)?; 122 return dirfdopen(file); 123 };