cap_primitives/rustix/fs/
open_unchecked.rs1use super::compute_oflags;
2use crate::fs::{stat_unchecked, OpenOptions, OpenUncheckedError};
3use crate::AmbientAuthority;
4use io_lifetimes::AsFilelike;
5use rustix::fs::{openat, Mode, CWD};
6use rustix::io;
7use std::fs;
8use std::path::Path;
9
10pub(crate) fn open_unchecked(
13 start: &fs::File,
14 path: &Path,
15 options: &OpenOptions,
16) -> Result<fs::File, OpenUncheckedError> {
17 let oflags = compute_oflags(options).map_err(OpenUncheckedError::Other)?;
18
19 #[allow(clippy::useless_conversion)]
20 #[cfg(not(target_os = "wasi"))]
21 let mode = Mode::from_bits_truncate(options.ext.mode as _);
22 #[cfg(target_os = "wasi")]
23 let mode = Mode::empty();
24
25 let err = match openat(start, path, oflags, mode) {
26 Ok(file) => {
27 return Ok(fs::File::from(file));
28 }
29 Err(err) => err,
30 };
31 match err {
32 #[cfg(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd")))]
35 io::Errno::LOOP => Err(OpenUncheckedError::Symlink(err.into(), ())),
36
37 #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
39 io::Errno::MLINK => Err(OpenUncheckedError::Symlink(err.into(), ())),
40
41 #[cfg(target_os = "netbsd")]
43 io::Errno::FTYPE => Err(OpenUncheckedError::Symlink(err.into(), ())),
44
45 io::Errno::NOENT => Err(OpenUncheckedError::NotFound(err.into())),
46 io::Errno::NOTDIR => {
47 if options.dir_required
48 && stat_unchecked(start, path, options.follow)
49 .map(|m| m.file_type().is_symlink())
50 .unwrap_or(false)
51 {
52 Err(OpenUncheckedError::Symlink(err.into(), ()))
53 } else {
54 Err(OpenUncheckedError::NotFound(err.into()))
55 }
56 }
57 _ => Err(OpenUncheckedError::Other(err.into())),
58 }
59}
60
61#[inline]
64pub(crate) fn open_ambient_impl(
65 path: &Path,
66 options: &OpenOptions,
67 ambient_authority: AmbientAuthority,
68) -> Result<fs::File, OpenUncheckedError> {
69 let _ = ambient_authority;
70 open_unchecked(&CWD.as_filelike_view::<fs::File>(), path, options)
71}