hare

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

file.ha (2118B)


      1 // License: MPL-2.0
      2 // (c) 2021 Bor Grošelj Simić <bor.groseljsimic@telemach.net>
      3 // (c) 2021-2022 Drew DeVault <sir@cmpwn.com>
      4 // (c) 2021 Eyal Sawady <ecs@d2evs.net>
      5 use errors;
      6 use rt;
      7 use strings;
      8 
      9 // This is an opaque type which encloses an OS-level file handle resource. It
     10 // can be used as a [[handle]] in most situations, but there are some APIs which
     11 // require a [[file]] with some OS-level handle backing it - this type is used
     12 // for such APIs.
     13 //
     14 // On Linux, [[file]] is a file descriptor.
     15 export type file = int;
     16 
     17 // Opens a Unix file descriptor as a file. This is a low-level interface, to
     18 // open files most programs will use something like [[os::open]]. This function
     19 // is not portable.
     20 export fn fdopen(fd: int) file = fd;
     21 
     22 fn fd_read(fd: file, buf: []u8) (size | EOF | error) = {
     23 	match (rt::read(fd, buf: *[*]u8, len(buf))) {
     24 	case let err: rt::errno =>
     25 		return errors::errno(err);
     26 	case let n: size =>
     27 		switch (n) {
     28 		case 0 =>
     29 			return EOF;
     30 		case =>
     31 			return n;
     32 		};
     33 	};
     34 };
     35 
     36 fn fd_write(fd: file, buf: const []u8) (size | error) = {
     37 	match (rt::write(fd, buf: *const [*]u8, len(buf))) {
     38 	case let err: rt::errno =>
     39 		return errors::errno(err);
     40 	case let n: size =>
     41 		return n;
     42 	};
     43 };
     44 
     45 fn fd_close(fd: file) (void | error) = {
     46 	match (rt::close(fd)) {
     47 	case void => void;
     48 	case let err: rt::errno =>
     49 		return errors::errno(err);
     50 	};
     51 };
     52 
     53 fn fd_seek(
     54 	fd: file,
     55 	offs: off,
     56 	whence: whence,
     57 ) (off | error) = {
     58 	match (rt::lseek(fd, offs: i64, whence: uint)) {
     59 	case let err: rt::errno =>
     60 		return errors::errno(err);
     61 	case let n: i64 =>
     62 		return n: off;
     63 	};
     64 };
     65 
     66 def SENDFILE_MAX: size = 2147479552z;
     67 
     68 fn fd_copy(to: file, from: file) (size | error) = {
     69 	let sum = 0z;
     70 	for (true) {
     71 		let n = match (rt::sendfile(to, from, null, SENDFILE_MAX)) {
     72 		case let err: rt::errno =>
     73 			switch (err) {
     74 			case rt::EINVAL =>
     75 				if (sum == 0) {
     76 					return errors::unsupported;
     77 				};
     78 				return errors::errno(err);
     79 			case =>
     80 				return errors::errno(err);
     81 			};
     82 		case let n: size =>
     83 			yield switch (n) {
     84 			case 0 =>
     85 				break;
     86 			case =>
     87 				yield n;
     88 			};
     89 		};
     90 		sum += n;
     91 	};
     92 	return sum;
     93 };