os.ha (6030B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use fs; 5 use io; 6 use time; 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 mode flags on a [[io::file]]. Type bits are discared. 65 export fn fchmod(fd: io::file, mode: fs::mode) (void | fs::error) = fs::fchmod(cwd, fd, mode); 66 67 // Changes ownership of a file. 68 export fn chown(path: str, uid: uint, gid: uint) (void | fs::error) = fs::chown(cwd, path, uid, gid); 69 70 // Changes ownership of a [io::file]]. 71 export fn fchown(fd: io::file, uid: uint, gid: uint) (void | fs::error) = fs::fchown(cwd, fd, uid, gid); 72 73 // Changes the access and modification time of a file. A void value will leave 74 // the corresponding time unchanged. 75 export fn chtimes( 76 path: str, 77 atime: (time::instant | void), 78 mtime: (time::instant | void) 79 ) (void | fs::error) = fs::chtimes(cwd, path, atime, mtime); 80 81 // Changes the access and modification time of an [[io::file]]. A void value 82 // will leave the corresponding time unchanged. 83 export fn fchtimes( 84 fd: io::file, 85 atime: (time::instant | void), 86 mtime: (time::instant | void) 87 ) (void | fs::error) = fs::fchtimes(cwd, fd, atime, mtime); 88 89 // Resolves a path to its absolute, normalized value. Relative paths will be 90 // rooted (if supported by the host filesystem), and "." and ".." components 91 // will be reduced. This function does not follow symlinks; see [[realpath]] if 92 // you need this behavior. The return value is statically allocated; use 93 // [[strings::dup]] to extend its lifetime. 94 export fn resolve(path: str) str = fs::resolve(cwd, path); 95 96 // Returns the path referred to by a symbolic link. The return value is 97 // statically allocated and will be overwritten on subsequent calls. 98 export fn readlink(path: str) (str | fs::error) = fs::readlink(cwd, path); 99 100 // Creates a new (hard) link at 'new' for the file at 'old'. 101 export fn link(old: str, new: str) (void | fs::error) = fs::link(cwd, old, new); 102 103 // Creates a new symbolic link at 'path' which points to 'target'. 104 export fn symlink(target: str, path: str) (void | fs::error) = 105 fs::symlink(cwd, target, path); 106 107 // Opens a file. 108 // 109 // [[fs::flag::CREATE]] isn't very useful with this function, since the new 110 // file's mode is set to zero. For this use-case, use [[create]] instead. 111 export fn open( 112 path: str, 113 flags: fs::flag = fs::flag::RDONLY, 114 ) (io::file | fs::error) = fs::open_file(cwd, path, flags); 115 116 // Creates a new file with the given mode if it doesn't already exist and opens 117 // it for writing. 118 // 119 // Only the permission bits of the mode are used. If other bits are set, they 120 // are discarded. 121 // 122 // To create a file without opening it, see [[mkfile]]. 123 export fn create( 124 path: str, 125 mode: fs::mode, 126 flags: fs::flag = fs::flag::WRONLY | fs::flag::TRUNC, 127 ) (io::file | fs::error) = fs::create_file(cwd, path, mode, flags); 128 129 // Canonicalizes a path in this filesystem by resolving all symlinks and 130 // collapsing any "." or ".." path components. 131 // 132 // This function is a thin shim over [[fs::realpath]], and the return value is 133 // statically allocated by [[fs::realpath]]. Thus, calls to this function or to 134 // [[fs::realpath]] will overwrite the return value of either function. 135 export fn realpath(path: str) (str | fs::error) = fs::realpath(cwd, path); 136 137 // Opens a directory as a filesystem. 138 export fn diropen(path: str) (*fs::fs | fs::error) = { 139 const file = open(path, fs::flag::DIRECTORY | fs::flag::RDONLY)?; 140 return dirfdopen(file); 141 };