xref: /drstd/dlibc/src/unix/header/stdio/helpers.rs (revision 86982c5e9b2eaa583327251616ee822c36288824)
1 use alloc::boxed::Box;
2 
3 use super::{constants::*, Buffer, FILE};
4 use crate::unix::header::{errno, fcntl::*, string::strchr};
5 use crate::unix::{
6     fs::File,
7     io::BufWriter,
8     sync::Mutex,
9 };
10 use alloc::vec::Vec;
11 
12 use crate::unix::header::stdio::{F_APP,F_NORD,F_NOWR};
13 use crate::unix::platform;
14 
15 /// Parse mode flags as a string and output a mode flags integer
16 pub unsafe fn parse_mode_flags(mode_str: *const ::c_char) -> i32 {
17     let mut flags = if !strchr(mode_str, b'+' as i32).is_null() {
18         ::O_RDWR
19     } else if (*mode_str) == b'r' as i8 {
20         ::O_RDONLY
21     } else {
22         ::O_WRONLY
23     };
24     if !strchr(mode_str, b'x' as i32).is_null() {
25         flags |= ::O_EXCL;
26     }
27     if !strchr(mode_str, b'e' as i32).is_null() {
28         flags |= ::O_CLOEXEC;
29     }
30     if (*mode_str) != b'r' as i8 {
31         flags |= ::O_CREAT;
32     }
33     if (*mode_str) == b'w' as i8 {
34         flags |= ::O_TRUNC;
35     } else if (*mode_str) == b'a' as i8 {
36         flags |= ::O_APPEND;
37     }
38 
39     flags
40 }
41 
42 /// Open a file with the file descriptor `fd` in the mode `mode`
43 pub unsafe fn _fdopen(fd: ::c_int, mode: *const ::c_char) -> Option<*mut FILE> {
44     if *mode != b'r' as i8 && *mode != b'w' as i8 && *mode != b'a' as i8 {
45         platform::errno = errno::EINVAL;
46         return None;
47     }
48 
49     let mut flags = 0;
50     if strchr(mode, b'+' as i32).is_null() {
51         flags |= if *mode == b'r' as i8 { F_NOWR } else { F_NORD };
52     }
53 
54     if !strchr(mode, b'e' as i32).is_null() {
55         sys_fcntl(fd, ::F_SETFD, ::FD_CLOEXEC);
56     }
57 
58     if *mode == 'a' as i8 {
59         let f = sys_fcntl(fd, ::F_GETFL, 0);
60         if (f & ::O_APPEND) == 0 {
61             sys_fcntl(fd, ::F_SETFL, f | ::O_APPEND);
62         }
63         flags |= F_APP;
64     }
65 
66     let file = File::new(fd);
67     let writer = Box::new(BufWriter::new(file.get_ref()));
68 
69     Some(Box::into_raw(Box::new(FILE {
70         lock: Mutex::new(()),
71 
72         file,
73         flags,
74         read_buf: Buffer::Owned(vec![0; ::BUFSIZ as usize]),
75         read_pos: 0,
76         read_size: 0,
77         unget: Vec::new(),
78         writer,
79 
80         pid: None,
81 
82         orientation: 0,
83     })))
84 }
85