Function cap_primitives::fs::open
source · pub fn open(start: &File, path: &Path, options: &OpenOptions) -> Result<File>
Expand description
Perform an openat
-like operation, ensuring that the resolution of the
path never escapes the directory tree rooted at start
.
Examples found in repository?
src/fs/open_dir.rs (line 16)
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
pub fn open_dir(start: &fs::File, path: &Path) -> io::Result<fs::File> {
open(start, path, &dir_options())
}
/// Like `open_dir`, but additionally request the ability to read the directory
/// entries.
#[cfg(not(windows))]
#[inline]
pub(crate) fn open_dir_for_reading(
start: &fs::File,
path: &Path,
follow: FollowSymlinks,
) -> io::Result<fs::File> {
open(start, path, readdir_options().follow(follow))
}
/// Similar to `open_dir`, but fails if the path names a symlink.
#[inline]
pub fn open_dir_nofollow(start: &fs::File, path: &Path) -> io::Result<fs::File> {
open(start, path, dir_options().follow(FollowSymlinks::No))
}
More examples
src/rustix/fs/copy_impl.rs (line 17)
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
fn open_from(start: &fs::File, path: &Path) -> io::Result<(fs::File, fs::Metadata)> {
let reader = open(start, path, OpenOptions::new().read(true))?;
let metadata = reader.metadata()?;
if !metadata.is_file() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"the source path is not an existing regular file",
));
}
Ok((reader, metadata))
}
#[cfg(not(target_os = "wasi"))]
fn open_to_and_set_permissions(
start: &fs::File,
path: &Path,
reader_metadata: fs::Metadata,
) -> io::Result<(fs::File, fs::Metadata)> {
use rustix::fs::OpenOptionsExt;
use std::os::unix::fs::PermissionsExt;
let perm = reader_metadata.permissions();
let writer = open(
start,
path,
OpenOptions::new()
// create the file with the correct mode right away
.mode(perm.mode())
.write(true)
.create(true)
.truncate(true),
)?;
let writer_metadata = writer.metadata()?;
if writer_metadata.is_file() {
// Set the correct file permissions, in case the file already existed.
// Don't set the permissions on already existing non-files like
// pipes/FIFOs or device nodes.
writer.set_permissions(perm)?;
}
Ok((writer, writer_metadata))
}
src/rustix/fs/set_permissions_impl.rs (line 24)
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
pub(crate) fn set_permissions_impl(
start: &fs::File,
path: &Path,
perm: Permissions,
) -> io::Result<()> {
let std_perm = perm.into_std(start)?;
// Try `fchmod` with a normal handle. Normal handles need some kind of
// access, so first try read.
match open(start, path, OpenOptions::new().read(true)) {
Ok(file) => return set_file_permissions(&file, std_perm),
Err(err) => match Errno::from_io_error(&err) {
Some(Errno::ACCESS) => (),
_ => return Err(err),
},
}
// Next try write.
match open(start, path, OpenOptions::new().write(true)) {
Ok(file) => return set_file_permissions(&file, std_perm),
Err(err) => match Errno::from_io_error(&err) {
Some(Errno::ACCESS) | Some(Errno::ISDIR) => (),
_ => return Err(err),
},
}
// If neither of those worked, we're out of luck.
Err(Errno::NOTSUP.into())
}
src/rustix/fs/set_times_impl.rs (line 17)
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
pub(crate) fn set_times_impl(
start: &fs::File,
path: &Path,
atime: Option<SystemTimeSpec>,
mtime: Option<SystemTimeSpec>,
) -> io::Result<()> {
// Try `futimens` with a normal handle. Normal handles need some kind of
// access, so first try write.
match open(start, path, OpenOptions::new().write(true)) {
Ok(file) => {
return fs_set_times::SetTimes::set_times(
&file,
atime.map(SystemTimeSpec::into_std),
mtime.map(SystemTimeSpec::into_std),
)
}
Err(err) => match Errno::from_io_error(&err) {
Some(Errno::ACCESS) | Some(Errno::ISDIR) => (),
_ => return Err(err),
},
}
// Next try read.
match open(start, path, OpenOptions::new().read(true)) {
Ok(file) => {
return fs_set_times::SetTimes::set_times(
&file,
atime.map(SystemTimeSpec::into_std),
mtime.map(SystemTimeSpec::into_std),
)
}
Err(err) => match Errno::from_io_error(&err) {
Some(Errno::ACCESS) => (),
_ => return Err(err),
},
}
// It's not possible to do anything else with generic POSIX. Plain
// `utimensat` has two options:
// - Follow symlinks, which would open up a race in which a concurrent
// modification of the symlink could point outside the sandbox and we
// wouldn't be able to detect it, or
// - Don't follow symlinks, which would modify the timestamp of the symlink
// instead of the file we're trying to get to.
//
// So neither does what we need.
Err(Errno::NOTSUP.into())
}