types.ha (10395B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use encoding::utf8; 5 use errors; 6 use io; 7 use strings; 8 use time; 9 10 // An entry of a particular type was sought, but is something else in practice. 11 // For example, opening a file with [[iter]]. 12 export type wrongtype = !void; 13 14 // Returned from [[rename]] if this rename is not possible due to technical 15 // constraints, such as if it would cause a file to move between filesystems. In 16 // this situation, other operations (such as copy & remove) may succeed if 17 // attempted. 18 export type cannotrename = !void; 19 20 // All possible fs error types. 21 export type error = !( 22 errors::noentry | 23 errors::noaccess | 24 errors::exists | 25 errors::busy | 26 errors::invalid | 27 errors::unsupported | 28 utf8::invalid | 29 wrongtype | 30 cannotrename | 31 io::error); 32 33 // Returns a human-friendly representation of an error. 34 export fn strerror(err: error) const str = match (err) { 35 case wrongtype => 36 yield "Wrong entry type for requested operation"; 37 case cannotrename => 38 yield "Unable to perform rename operation (try move instead)"; 39 case errors::noentry => 40 yield "File or directory not found"; 41 case errors::noaccess => 42 yield "Permission denied"; 43 case errors::exists => 44 yield "File or directory exists"; 45 case errors::invalid => 46 yield "Invalid argument"; 47 case errors::busy => 48 yield "Device is busy"; 49 case errors::unsupported => 50 yield "Operation not supported"; 51 case let err: utf8::invalid => 52 yield utf8::strerror(err); 53 case let err: io::error => 54 yield io::strerror(err); 55 }; 56 57 // File mode information. These bits do not necessarily reflect the underlying 58 // operating system's mode representation, though they were chosen to be 59 // consistent with typical Unix file permissions. All implementations shall 60 // support at least USER_RW, DIR, and REG. 61 export type mode = enum uint { 62 // Read, write, and execute permissions for the file owner 63 USER_RWX = 0o700, 64 // Read and write permissions for the file owner 65 USER_RW = 0o600, 66 // Read and execute permissions for the file owner 67 USER_RX = 0o500, 68 // Read permissions for the file owner 69 USER_R = 0o400, 70 // Write permissions for the file owner 71 USER_W = 0o200, 72 // Execute permissions for the file owner 73 USER_X = 0o100, 74 75 // Read, write, and execute permissions for group members 76 GROUP_RWX = 0o070, 77 // Read and write permissions for group members 78 GROUP_RW = 0o060, 79 // Read and execute permissions for group members 80 GROUP_RX = 0o050, 81 // Read permissions for group members 82 GROUP_R = 0o040, 83 // Write permissions for group members 84 GROUP_W = 0o020, 85 // Execute permissions for group members 86 GROUP_X = 0o010, 87 88 // Read, write, and execute permissions for other users 89 OTHER_RWX = 0o007, 90 // Read and write permissions for other users 91 OTHER_RW = 0o006, 92 // Read and execute permissions for other users 93 OTHER_RX = 0o005, 94 // Read permissions for other users 95 OTHER_R = 0o004, 96 // Write permissions for other users 97 OTHER_W = 0o002, 98 // Execute permissions for other users 99 OTHER_X = 0o001, 100 101 // Entry has the set-uid bit set 102 SETUID = 0o4000, 103 // Entry has the set-gid bit set 104 SETGID = 0o2000, 105 // Entry has the sticky bit set 106 STICKY = 0o1000, 107 108 // Entry is of an unknown type 109 UNKNOWN = 0, 110 // Entry is a FIFO (named pipe) 111 FIFO = 0o010000, 112 // Entry is a directory 113 DIR = 0o040000, 114 // Entry is a character device 115 CHR = 0o020000, 116 // Entry is a block device 117 BLK = 0o060000, 118 // Entry is a regular file 119 REG = 0o100000, 120 // Entry is a symbolic link 121 LINK = 0o120000, 122 // Entry is a Unix socket 123 SOCK = 0o140000, 124 }; 125 126 // A mask defining what items are populated in the stat structure. 127 export type stat_mask = enum uint { 128 UID = 1 << 0, 129 GID = 1 << 1, 130 SIZE = 1 << 2, 131 INODE = 1 << 3, 132 ATIME = 1 << 4, 133 MTIME = 1 << 5, 134 CTIME = 1 << 6, 135 }; 136 137 // Information about a file or directory. The mask field defines what other 138 // fields are set; mode is always set. 139 export type filestat = struct { 140 mask: stat_mask, 141 mode: mode, 142 uid: uint, 143 gid: uint, 144 sz: size, 145 inode: u64, 146 atime: time::instant, 147 mtime: time::instant, 148 ctime: time::instant, 149 }; 150 151 // An entry in a directory. This may be borrowed from the filesystem's internal 152 // state. If you want to keep this around beyond one call to [[next]], use 153 // [[dirent_dup]]. 154 export type dirent = struct { 155 // The name of this entry. Not fully qualified: for example, 156 // "foo/bar/baz.txt" would store "baz.txt" here. 157 name: str, 158 159 // The type of this entry. The permission bits may be unset. 160 ftype: mode, 161 }; 162 163 // Duplicates a [[dirent]] object. Call [[dirent_finish]] to get rid of it 164 // later. 165 export fn dirent_dup(e: *dirent) dirent = { 166 let new = *e; 167 new.name = strings::dup(e.name); 168 return new; 169 }; 170 171 // Frees memory associated with a [[dirent]] object which was duplicated with 172 // [[dirent_dup]]. 173 export fn dirent_finish(e: *dirent) void = free(e.name); 174 175 // Flags to use for opening a file. Not all operating systems support all flags; 176 // at a minimum, RDONLY, WRONLY, RDWR, CREATE, and TRUNC will be supported. 177 // Note that NOCTTY and CLOEXEC are on by default, and the CTTY/NOCLOEXEC flags 178 // respectively disable them. 179 export type flag = enum int { 180 RDONLY = 0, 181 WRONLY = 1, 182 RDWR = 2, 183 CREATE = 0o100, 184 EXCL = 0o200, 185 CTTY = 0o400, 186 TRUNC = 0o1000, 187 APPEND = 0o2000, 188 NONBLOCK = 0o4000, 189 DSYNC = 0o10000, 190 SYNC = 0o4010000, 191 RSYNC = 0o4010000, 192 DIRECTORY = 0o200000, 193 NOFOLLOW = 0o400000, 194 NOATIME = 0o1000000, 195 NOCLOEXEC = 0o2000000, 196 PATH = 0o10000000, 197 TMPFILE = 0o20200000, 198 }; 199 200 export type closefunc = fn(fs: *fs) void; 201 export type removefunc = fn(fs: *fs, path: str) (void | error); 202 export type renamefunc = fn(fs: *fs, oldpath: str, newpath: str) (void | error); 203 export type iterfunc = fn(fs: *fs, path: str) (*iterator | error); 204 export type statfunc = fn(fs: *fs, path: str) (filestat | error); 205 export type fstatfunc = fn(fs: *fs, file: io::file) (filestat | error); 206 export type mkdirfunc = fn(fs: *fs, path: str, mode: mode) (void | error); 207 export type rmdirfunc = fn(fs: *fs, path: str) (void | error); 208 export type chmodfunc = fn(fs: *fs, path: str, mode: mode) (void | error); 209 export type fchmodfunc = fn(fd: io::file, mode: mode) (void | error); 210 export type chownfunc = fn(fs: *fs, path: str, uid: uint, gid: uint) (void | error); 211 export type fchownfunc = fn(fd: io::file, uid: uint, gid: uint) (void | error); 212 export type chtimesfunc = fn(fs: *fs, path: str, atime: (time::instant | void), 213 mtime: (time::instant | void)) (void | error); 214 export type fchtimesfunc = fn(fd: io::file, atime: (time::instant | void), 215 mtime: (time::instant | void)) (void | error); 216 export type resolvefunc = fn(fs: *fs, path: str) str; 217 export type readlinkfunc = fn(fs: *fs, path: str) (str | error); 218 export type linkfunc = fn(fs: *fs, old: str, new: str) (void | error); 219 export type symlinkfunc = fn(fs: *fs, target: str, path: str) (void | error); 220 221 export type openfunc = fn( 222 fs: *fs, 223 path: str, 224 flags: flag, 225 ) (io::handle | error); 226 227 export type openfilefunc = fn( 228 fs: *fs, 229 path: str, 230 flags: flag, 231 ) (io::file | error); 232 233 export type createfunc = fn( 234 fs: *fs, 235 path: str, 236 mode: mode, 237 flags: flag, 238 ) (io::handle | error); 239 240 export type createfilefunc = fn( 241 fs: *fs, 242 path: str, 243 mode: mode, 244 flags: flag, 245 ) (io::file | error); 246 247 // An abstract implementation of a filesystem, which provides common filesystem 248 // operations such as file creation and deletion, but which may be backed by any 249 // underlying storage system. See [[os::cwd]] for access to the host filesystem. 250 // 251 // To create a custom filesystem implementation, embed this type as the first 252 // member of a struct with user-specific data and fill out these fields as 253 // appropriate. 254 export type fs = struct { 255 // Frees resources associated with this filesystem. 256 close: nullable *closefunc, 257 258 // Opens a file. 259 open: nullable *openfunc, 260 261 // Opens a file as an [[io::file]]. 262 openfile: nullable *openfilefunc, 263 264 // Creates a new file. 265 create: nullable *createfunc, 266 267 // Creates a new file as an [[io::file]]. 268 createfile: nullable *createfilefunc, 269 270 // Removes a file. 271 remove: nullable *removefunc, 272 273 // Renames a file. 274 rename: nullable *renamefunc, 275 276 // Returns an iterator for a path, which yields the contents of a 277 // directory. Pass empty string to yield from the root. 278 // 279 // The iterator must return all entries without error. If an error would 280 // occur, it should be identified here and returned upfront. 281 iter: nullable *iterfunc, 282 283 // Obtains information about a file or directory. If the target is a 284 // symbolic link, information is returned about the link, not its 285 // target. 286 stat: nullable *statfunc, 287 288 // Obtains information about an [[io::file]]. 289 fstat: nullable *fstatfunc, 290 291 // Returns the path referred to by a symbolic link. The caller will free 292 // the return value. 293 readlink: nullable *readlinkfunc, 294 295 // Creates a directory. 296 mkdir: nullable *mkdirfunc, 297 298 // Removes a directory. The target directory must be empty. 299 rmdir: nullable *rmdirfunc, 300 301 // Changes mode flags on a file or directory. 302 chmod: nullable *chmodfunc, 303 304 // Changes mode flags on a [[io::file]]. 305 fchmod: nullable *fchmodfunc, 306 307 // Changes ownership of a file. 308 chown: nullable *chownfunc, 309 310 // Changes ownership of a [[io::file]]. 311 fchown: nullable *fchownfunc, 312 313 // Changes access and modification time of a file. 314 chtimes: nullable *chtimesfunc, 315 316 // Changes access and modification time of an [[io::file]]. 317 fchtimes: nullable *fchtimesfunc, 318 319 // Resolves a path to its absolute, normalized value. If the fs 320 // implementation does not provide this, [resolve] presumes that 321 // relative paths are rooted (i.e. "foo" == "/foo"). 322 resolve: nullable *resolvefunc, 323 324 // Creates a new (hard) link. 325 link: nullable *linkfunc, 326 327 // Creates a new symbolic link. 328 symlink: nullable *symlinkfunc, 329 }; 330 331 // A function which returns the next directory from an [[iterator]]. 332 export type nextfunc = fn(iter: *iterator) (dirent | done | error); 333 334 // A function which frees state associated with an [[iterator]]. 335 export type finishfunc = fn(iter: *iterator) void; 336 337 // A directory iterator. To implement a directory iterator for a filesystem, 338 // subtype this struct to store any necessary state and populate the pointers 339 // with your implementation. 340 export type iterator = struct { 341 // Returns the next member of the directory, or done if there are none 342 // remaining. 343 next: *nextfunc, 344 // Frees resources associated with the iterator. 345 finish: nullable *finishfunc, 346 };