hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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 };