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