file.ha (1969B)
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 Ember 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: int)) { 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) match (rt::sendfile(to, from, null, SENDFILE_MAX)) { 71 case let err: rt::errno => 72 if (err == rt::EINVAL && sum == 0) { 73 return errors::unsupported; 74 }; 75 return errors::errno(err); 76 case let n: size => 77 if (n == 0) break; 78 sum += n; 79 }; 80 return sum; 81 };