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))
}
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())
}
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())
}
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
pub(crate) fn stat(start: &fs::File, path: &Path, follow: FollowSymlinks) -> io::Result<Metadata> {
// POSIX returns `ENOENT` on an empty path. TODO: On Windows, we should
// be compatible with what Windows does instead.
if path.as_os_str().is_empty() {
return Err(errors::no_such_file_or_directory());
}
let mut options = OpenOptions::new();
options.follow(follow);
let mut symlink_count = 0;
let mut ctx = Context::new(MaybeOwnedFile::borrowed(start), path, &options, None);
assert!(!ctx.dir_precluded);
while let Some(c) = ctx.components.pop() {
match c {
CowComponent::PrefixOrRootDir => return Err(errors::escape_attempt()),
CowComponent::CurDir => ctx.cur_dir()?,
CowComponent::ParentDir => ctx.parent_dir()?,
CowComponent::Normal(one) => {
if ctx.components.is_empty() {
// If this is the last component, do a non-following
// `stat_unchecked` on it.
let stat = stat_unchecked(&ctx.base, one.as_ref(), FollowSymlinks::No)?;
// If we weren't asked to follow symlinks, or it wasn't a
// symlink, we're done.
if options.follow == FollowSymlinks::No || !stat.file_type().is_symlink() {
if stat.is_dir() {
if ctx.dir_precluded {
return Err(errors::is_directory());
}
} else if ctx.dir_required {
return Err(errors::is_not_directory());
}
return Ok(stat);
}
// On Windows, symlinks know whether they are a file or
// directory.
#[cfg(windows)]
if stat.file_attributes() & FILE_ATTRIBUTE_DIRECTORY != 0 {
ctx.dir_required = true;
} else {
ctx.dir_precluded = true;
}
// If it was a symlink and we're asked to follow symlinks,
// dereference it.
ctx.symlink(&one, &mut symlink_count)?
} else {
// Otherwise open the path component normally.
ctx.normal(&one, &options, &mut symlink_count)?
}
}
}
}
// If the path ended in `.` (explicit or implied) or `..`, we may have
// opened the directory with eg. `O_PATH` on Linux, or we may have skipped
// checking for search access to `.`, so re-check it.
if ctx.follow_with_dot {
if ctx.dir_precluded {
return Err(errors::is_directory());
}
ctx.check_dot_access()?;
}
// If the path ended in `.` or `..`, we already have it open, so just do
// `.metadata()` on it.
Metadata::from_file(&*ctx.base)
}
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
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())
}
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())
}
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
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())
}
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())
}
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