hare

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

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