Struct cap_primitives::fs::OpenOptions
source · pub struct OpenOptions { /* private fields */ }
Expand description
Options and flags which can be used to configure how a file is opened.
This corresponds to std::fs::OpenOptions
.
This OpenOptions
has no open
method. To open a file with an
OptionOptions
, first obtain a Dir
containing the path, and then call
Dir::open_with
.
Implementations§
source§impl OpenOptions
impl OpenOptions
sourcepub const fn new() -> Self
pub const fn new() -> Self
Creates a blank new set of options ready for configuration.
This corresponds to std::fs::OpenOptions::new
.
Examples found in repository?
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
pub(crate) fn dir_options() -> OpenOptions {
OpenOptions::new().read(true).dir_required(true).clone()
}
/// Like `dir_options`, but additionally request the ability to read the
/// directory entries.
pub(crate) fn readdir_options() -> OpenOptions {
OpenOptions::new()
.read(true)
.dir_required(true)
.readdir_required(true)
.clone()
}
/// Return an `OpenOptions` for canonicalizing paths.
pub(crate) fn canonicalize_options() -> OpenOptions {
OpenOptions::new().read(true).clone()
}
More examples
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))
}
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
pub(crate) fn set_permissions_through_proc_self_fd(
start: &fs::File,
path: &Path,
perm: fs::Permissions,
) -> io::Result<()> {
let opath = open(
start,
path,
OpenOptions::new()
.read(true)
.custom_flags(OFlags::PATH.bits() as i32),
)?;
let dirfd = proc_self_fd()?;
let mode = Mode::from_bits(perm.mode() as RawMode).ok_or_else(errors::invalid_flags)?;
Ok(chmodat(&dirfd, DecInt::from_fd(&opath), mode)?)
}
pub(crate) fn set_times_through_proc_self_fd(
start: &fs::File,
path: &Path,
atime: Option<SystemTimeSpec>,
mtime: Option<SystemTimeSpec>,
) -> io::Result<()> {
let opath = open(
start,
path,
OpenOptions::new()
.read(true)
.custom_flags(OFlags::PATH.bits() as i32),
)?;
// Don't pass `AT_SYMLINK_NOFOLLOW`, because we do actually want to follow
// the first symlink. We don't want to follow any subsequent symlinks, but
// omitting `O_NOFOLLOW` above ensures that the destination of the link
// isn't a symlink.
set_times_follow_unchecked(
proc_self_fd()?.as_fd(),
DecInt::from_fd(&opath).as_ref(),
atime,
mtime,
)
}
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
pub(crate) fn stat_impl(
start: &fs::File,
path: &Path,
follow: FollowSymlinks,
) -> io::Result<Metadata> {
use std::os::unix::fs::OpenOptionsExt;
// Open the path with `O_PATH`. Use `read(true)` even though we don't need
// `read` permissions, because Rust's libstd requires an access mode, and
// Linux ignores `O_RDONLY` with `O_PATH`.
let result = open_beneath(
start,
path,
OpenOptions::new()
.read(true)
.follow(follow)
.custom_flags(OFlags::PATH.bits() as i32),
);
// If that worked, call `fstat`.
match result {
Ok(file) => file_metadata(&file),
Err(err) => match rustix::io::Errno::from_io_error(&err) {
// `ENOSYS` from `open_beneath` means `openat2` is unavailable
// and we should use a fallback.
Some(rustix::io::Errno::NOSYS) => manually::stat(start, path, follow),
_ => Err(err),
},
}
}
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
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 rustix::io::Errno::from_io_error(&err) {
Some(rustix::io::Errno::ACCESS) | Some(rustix::io::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 rustix::io::Errno::from_io_error(&err) {
Some(rustix::io::Errno::ACCESS) => (),
_ => return Err(err),
},
}
// If neither of those worked, turn to `/proc`.
set_times_through_proc_self_fd(start, path, atime, mtime)
}
sourcepub fn read(&mut self, read: bool) -> &mut Self
pub fn read(&mut self, read: bool) -> &mut Self
Sets the option for read access.
This corresponds to std::fs::OpenOptions::read
.
Examples found in repository?
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
pub(crate) fn dir_options() -> OpenOptions {
OpenOptions::new().read(true).dir_required(true).clone()
}
/// Like `dir_options`, but additionally request the ability to read the
/// directory entries.
pub(crate) fn readdir_options() -> OpenOptions {
OpenOptions::new()
.read(true)
.dir_required(true)
.readdir_required(true)
.clone()
}
/// Return an `OpenOptions` for canonicalizing paths.
pub(crate) fn canonicalize_options() -> OpenOptions {
OpenOptions::new().read(true).clone()
}
More examples
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
pub(crate) fn set_permissions_through_proc_self_fd(
start: &fs::File,
path: &Path,
perm: fs::Permissions,
) -> io::Result<()> {
let opath = open(
start,
path,
OpenOptions::new()
.read(true)
.custom_flags(OFlags::PATH.bits() as i32),
)?;
let dirfd = proc_self_fd()?;
let mode = Mode::from_bits(perm.mode() as RawMode).ok_or_else(errors::invalid_flags)?;
Ok(chmodat(&dirfd, DecInt::from_fd(&opath), mode)?)
}
pub(crate) fn set_times_through_proc_self_fd(
start: &fs::File,
path: &Path,
atime: Option<SystemTimeSpec>,
mtime: Option<SystemTimeSpec>,
) -> io::Result<()> {
let opath = open(
start,
path,
OpenOptions::new()
.read(true)
.custom_flags(OFlags::PATH.bits() as i32),
)?;
// Don't pass `AT_SYMLINK_NOFOLLOW`, because we do actually want to follow
// the first symlink. We don't want to follow any subsequent symlinks, but
// omitting `O_NOFOLLOW` above ensures that the destination of the link
// isn't a symlink.
set_times_follow_unchecked(
proc_self_fd()?.as_fd(),
DecInt::from_fd(&opath).as_ref(),
atime,
mtime,
)
}
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
pub(crate) fn stat_impl(
start: &fs::File,
path: &Path,
follow: FollowSymlinks,
) -> io::Result<Metadata> {
use std::os::unix::fs::OpenOptionsExt;
// Open the path with `O_PATH`. Use `read(true)` even though we don't need
// `read` permissions, because Rust's libstd requires an access mode, and
// Linux ignores `O_RDONLY` with `O_PATH`.
let result = open_beneath(
start,
path,
OpenOptions::new()
.read(true)
.follow(follow)
.custom_flags(OFlags::PATH.bits() as i32),
);
// If that worked, call `fstat`.
match result {
Ok(file) => file_metadata(&file),
Err(err) => match rustix::io::Errno::from_io_error(&err) {
// `ENOSYS` from `open_beneath` means `openat2` is unavailable
// and we should use a fallback.
Some(rustix::io::Errno::NOSYS) => manually::stat(start, path, follow),
_ => Err(err),
},
}
}
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
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 rustix::io::Errno::from_io_error(&err) {
Some(rustix::io::Errno::ACCESS) | Some(rustix::io::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 rustix::io::Errno::from_io_error(&err) {
Some(rustix::io::Errno::ACCESS) => (),
_ => return Err(err),
},
}
// If neither of those worked, turn to `/proc`.
set_times_through_proc_self_fd(start, path, atime, mtime)
}
sourcepub fn write(&mut self, write: bool) -> &mut Self
pub fn write(&mut self, write: bool) -> &mut Self
Sets the option for write access.
This corresponds to std::fs::OpenOptions::write
.
Examples found in repository?
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_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))
}
More examples
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
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 rustix::io::Errno::from_io_error(&err) {
Some(rustix::io::Errno::ACCESS) | Some(rustix::io::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 rustix::io::Errno::from_io_error(&err) {
Some(rustix::io::Errno::ACCESS) => (),
_ => return Err(err),
},
}
// If neither of those worked, turn to `/proc`.
set_times_through_proc_self_fd(start, path, atime, mtime)
}
8 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
pub(crate) fn set_permissions_impl(
start: &fs::File,
path: &Path,
perm: Permissions,
) -> io::Result<()> {
let std_perm = perm.into_std(start)?;
// First try using `O_PATH` and doing a chmod on `/proc/self/fd/{}`
// (`fchmod` doesn't work on `O_PATH` file descriptors).
//
// This may fail, due to older Linux versions not supporting `O_PATH`, or
// due to procfs being unavailable, but if it does work, go with it, as
// `O_PATH` tells Linux that we don't actually need to read or write the
// file, which may avoid side effects associated with opening device files.
let result = set_permissions_through_proc_self_fd(start, path, std_perm.clone());
if let Ok(()) = result {
return Ok(());
}
// Then 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 rustix::io::Errno::from_io_error(&err) {
Some(rustix::io::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 rustix::io::Errno::from_io_error(&err) {
Some(rustix::io::Errno::ACCESS) | Some(rustix::io::Errno::ISDIR) => (),
_ => return Err(err),
},
}
// Nothing worked, so just return the original error.
result
}
sourcepub fn append(&mut self, append: bool) -> &mut Self
pub fn append(&mut self, append: bool) -> &mut Self
Sets the option for the append mode.
This corresponds to std::fs::OpenOptions::append
.
sourcepub fn truncate(&mut self, truncate: bool) -> &mut Self
pub fn truncate(&mut self, truncate: bool) -> &mut Self
Sets the option for truncating a previous file.
This corresponds to std::fs::OpenOptions::truncate
.
Examples found in repository?
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_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))
}
sourcepub fn create(&mut self, create: bool) -> &mut Self
pub fn create(&mut self, create: bool) -> &mut Self
Sets the option to create a new file.
This corresponds to std::fs::OpenOptions::create
.
Examples found in repository?
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_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))
}
sourcepub fn create_new(&mut self, create_new: bool) -> &mut Self
pub fn create_new(&mut self, create_new: bool) -> &mut Self
Sets the option to always create a new file.
This corresponds to std::fs::OpenOptions::create_new
.
Trait Implementations§
source§impl Clone for OpenOptions
impl Clone for OpenOptions
source§fn clone(&self) -> OpenOptions
fn clone(&self) -> OpenOptions
1.0.0 · source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read more