hare

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

+linux.ha (3156B)


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