1use std::ffi::CString;
2use std::fs::File;
3use std::io::{self, Error, ErrorKind};
4use std::os::fd::{AsFd, AsRawFd, BorrowedFd, RawFd};
5
6use libc::{AT_FDCWD, c_char};
7use o3::marker::ThreadBound;
8
9use crate::backend::RawSqe;
10use crate::driver::token::Token;
11
12pub struct RawMetadata {
13 pub len: u64,
14 pub modified: Option<(i64, u32)>,
15 pub regular: bool,
16}
17
18pub struct OsFile {
19 inner: File,
20 _thread: ThreadBound,
21}
22
23impl OsFile {
24 pub fn create(path: &str) -> io::Result<Self> {
25 let inner = File::options()
26 .write(true)
27 .create(true)
28 .truncate(true)
29 .open(path)?;
30 Ok(Self {
31 inner,
32 _thread: ThreadBound::NEW,
33 })
34 }
35
36 pub fn open(path: &str) -> io::Result<Self> {
37 let inner = File::options().read(true).open(path)?;
38 Ok(Self {
39 inner,
40 _thread: ThreadBound::NEW,
41 })
42 }
43
44 pub fn try_len(&self) -> io::Result<u64> {
45 Ok(self.inner.metadata()?.len())
46 }
47
48 pub fn try_is_empty(&self) -> io::Result<bool> {
49 Ok(self.try_len()? == 0)
50 }
51
52 pub fn fd(&self) -> RawFd {
53 self.inner.as_raw_fd()
54 }
55
56 pub fn as_fd(&self) -> BorrowedFd<'_> {
57 self.inner.as_fd()
58 }
59}
60
61pub struct OpenPath {
62 path: CString,
63}
64
65impl OpenPath {
66 pub fn new(path: &str) -> io::Result<Self> {
67 let path = CString::new(path)
68 .map_err(|_| Error::new(ErrorKind::InvalidInput, "dope: path has interior nul"))?;
69 Ok(Self { path })
70 }
71
72 pub fn as_ptr(&self) -> *const c_char {
73 self.path.as_ptr()
74 }
75
76 pub fn open_at(&self, flags: i32, op: Token) -> RawSqe {
77 RawSqe::openat(AT_FDCWD, self.path.as_ptr(), flags, 0, op)
78 }
79}
80
81pub const O_RDONLY: i32 = libc::O_RDONLY;
82pub const O_CLOEXEC: i32 = libc::O_CLOEXEC;