hare

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

fs.ha (4748B)


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