hare

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

fs.ha (3311B)


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