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