hare

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

fs.ha (3602B)


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