fs.ha (3602B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use errors; 5 use fs; 6 use path; 7 use rt; 8 use types::c; 9 10 @init fn init_cwd() void = { 11 static let cwd_fs = os_filesystem { ... }; 12 cwd = static_dirfdopen(rt::AT_FDCWD, &cwd_fs); 13 }; 14 15 // Returns the current working directory. The return value is statically 16 // allocated and must be duplicated (see [[strings::dup]]) before calling getcwd 17 // again. 18 export fn getcwd() str = c::tostr(rt::getcwd() as *const u8: *const c::char)!; 19 20 // Change the current working directory. 21 export fn chdir(target: (*fs::fs | str)) (void | fs::error) = { 22 const path: str = match (target) { 23 case let fs: *fs::fs => 24 assert(fs.open == &fs_open); 25 let fs = fs: *os_filesystem; 26 match (rt::fchdir(fs.dirfd)) { 27 case let err: rt::errno => 28 return errno_to_fs(err); 29 case void => 30 return; 31 }; 32 case let s: str => 33 yield s; 34 }; 35 match (rt::chdir(path)) { 36 case let err: rt::errno => 37 return errno_to_fs(err); 38 case void => void; 39 }; 40 }; 41 42 // Changes the root directory of the process. Generally requires the caller to 43 // have root or otherwise elevated permissions. 44 // 45 // This function is not appropriate for sandboxing. 46 export fn chroot(target: str) (void | fs::error) = { 47 match (rt::chroot(target)) { 48 case let err: rt::errno => 49 return errno_to_fs(err); 50 case void => void; 51 }; 52 }; 53 54 // Makes a FIFO node. This function is only available on Unix systems. 55 export fn mkfifo(path: str, mode: fs::mode) (void | fs::error) = { 56 match (rt::mknodat(rt::AT_FDCWD, path, 57 mode: rt::mode_t | rt::S_IFIFO, 0)) { 58 case let err: rt::errno => 59 return errno_to_fs(err); 60 case void => void; 61 }; 62 }; 63 64 // Makes a block device node. This function is only available on Unix-like 65 // systems. 66 export fn mkblk( 67 path: str, 68 mode: fs::mode, 69 major: uint, 70 minor: uint, 71 ) (void | fs::error) = { 72 match (rt::mknodat(rt::AT_FDCWD, path, 73 mode: rt::mode_t | rt::S_IFBLK, 74 rt::mkdev(major: u32, minor: u32))) { 75 case let err: rt::errno => 76 return errno_to_fs(err); 77 case void => void; 78 }; 79 }; 80 81 // Makes a character device node. This function is only available on Unix-like 82 // systems. 83 export fn mkchr( 84 path: str, 85 mode: fs::mode, 86 major: uint, 87 minor: uint, 88 ) (void | fs::error) = { 89 match (rt::mknodat(rt::AT_FDCWD, path, mode: rt::mode_t | rt::S_IFCHR, 90 rt::mkdev(major: u32, minor: u32))) { 91 case let err: rt::errno => 92 return errno_to_fs(err); 93 case void => void; 94 }; 95 }; 96 97 // Makes a regular file. This function is only available on Unix-like systems. 98 // This function should only be used if you have a special reason; most of the 99 // time you should use [[create]] instead. 100 export fn mkfile(path: str, mode: fs::mode) (void | fs::error) = { 101 match (rt::mknodat(rt::AT_FDCWD, path, 102 mode: rt::mode_t | rt::S_IFREG, 0)) { 103 case let err: rt::errno => 104 return errors::errno(err); 105 case void => void; 106 }; 107 }; 108 109 // Access modes for [[access]]. 110 export type amode = enum int { 111 F_OK = rt::F_OK, 112 R_OK = rt::R_OK, 113 W_OK = rt::W_OK, 114 X_OK = rt::X_OK, 115 }; 116 117 // Returns true if the given mode of access is permissible. The use of this 118 // function is discouraged as it can allow for a race condition to occur betwen 119 // testing for the desired access mode and actually using the file should the 120 // permissions of the file change between these operations. It is recommended 121 // instead to attempt to use the file directly and to handle any errors that 122 // should occur at that time. 123 export fn access(path: str, mode: amode) (bool | fs::error) = { 124 match (rt::access(path, mode)) { 125 case let b: bool => 126 return b; 127 case let err: rt::errno => 128 return errno_to_fs(err); 129 }; 130 };