hare

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

+freebsd.ha (3341B)


      1 // License: MPL-2.0
      2 // (c) 2022 Alexey Yerin <yyp@disroot.org>
      3 // (c) 2021-2022 Drew DeVault <sir@cmpwn.com>
      4 // (c) 2021 Eyal Sawady <ecs@d2evs.net>
      5 // (c) 2022 Jon Eskin <eskinjp@gmail.com>
      6 use crypto::random;
      7 use encoding::hex;
      8 use errors;
      9 use fmt;
     10 use fs;
     11 use io;
     12 use os;
     13 use path;
     14 use strio;
     15 
     16 fn get_tmpdir() str = os::tryenv("TMPDIR", "/tmp");
     17 
     18 // Creates an unnamed temporary file. The file may or may not have a name; not
     19 // all systems support the creation of temporary inodes which are not linked to
     20 // any directory. If it is necessary to create a real file, it will be removed
     21 // when the stream is closed.
     22 //
     23 // The I/O mode must be either [[io::mode::WRITE]] or [[io::mode::RDWR]].
     24 //
     25 // Only one variadic argument may be provided, if at all, to specify the mode of
     26 // the new file. The default is 0o644.
     27 export fn file(
     28 	iomode: io::mode,
     29 	mode: fs::mode...
     30 ) (io::file | fs::error) = {
     31 	// TODO: Add a custom "close" function which removes the named file
     32 	let file = named(os::cwd, get_tmpdir(), iomode, mode...)?;
     33 	free(file.1);
     34 	return file.0;
     35 };
     36 
     37 // Creates a named temporary file in the given directory of the given
     38 // filesystem. The caller is responsible for closing and removing the file when
     39 // they're done with it. The name is statically allocated, and will be
     40 // overwritten on subsequent calls.
     41 //
     42 // The I/O mode must be either [[io::mode::WRITE]] or [[io::mode::RDWR]].
     43 //
     44 // Only one variadic argument may be provided, if at all, to specify the mode of
     45 // the new file. The default is 0o644.
     46 export fn named(
     47 	fs: *fs::fs,
     48 	path: str,
     49 	iomode: io::mode,
     50 	mode: fs::mode...
     51 ) ((io::file, str) | fs::error) = {
     52 	assert(iomode == io::mode::WRITE || iomode == io::mode::RDWR);
     53 	assert(len(mode) == 0 || len(mode) == 1);
     54 
     55 	let fmode = if (len(mode) != 0) mode[0] else 0o644: fs::mode;
     56 	let oflags = fs::flags::EXCL;
     57 	if (iomode == io::mode::RDWR) {
     58 		oflags |= fs::flags::RDWR;
     59 	} else {
     60 		oflags |= fs::flags::WRONLY;
     61 	};
     62 
     63 	static let pathbuf = path::buffer { ... };
     64 	static let namebuf: [32]u8 = [0...];
     65 	for (true) {
     66 		let rand: [size(u64)]u8 = [0...];
     67 		random::buffer(rand);
     68 
     69 		const id = *(&rand[0]: *u64);
     70 		const name = fmt::bsprintf(namebuf, "temp.{}", id);
     71 		const path = path::set(&pathbuf, path, name)!;
     72 
     73 		match (fs::create_file(fs, path, fmode, oflags)) {
     74 		case errors::exists =>
     75 			continue;
     76 		case let err: fs::error =>
     77 			return err;
     78 		case let f: io::file =>
     79 			return (f, path);
     80 		};
     81 	};
     82 	abort(); // Unreachable
     83 };
     84 
     85 // Creates a temporary directory. This function only guarantees that the
     86 // directory will have a unique name and be placed in the system temp directory,
     87 // but not that it will be removed automatically; the caller must remove it when
     88 // they're done using it via [[os::rmdir]] or [[os::rmdirall]].
     89 //
     90 // The return value is statically allocated and will be overwritten on
     91 // subsequent calls.
     92 export fn dir() str = {
     93 	let buf: [8]u8 = [0...], name: [16]u8 = [0...];
     94 	random::buffer(buf[..]);
     95 
     96 	let sink = strio::fixed(name);
     97 	const enc = hex::newencoder(&sink);
     98 	io::write(&enc, buf)!;
     99 	let name = strio::string(&sink);
    100 
    101 	static let buf = path::buffer { ... };
    102 	path::set(&buf, get_tmpdir(), name)!;
    103 	const path = path::string(&buf);
    104 	match (os::mkdir(path,0o755)) {
    105 	case let err: fs::error => abort("Could not create temp directory");
    106 	case void => void;
    107 	};
    108 	return path;
    109 };