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.

We need to define our own version because the libstd `OpenOptions` doesn't have public accessors that we can use.

Implementations§

Creates a blank new set of options ready for configuration.

This corresponds to std::fs::OpenOptions::new.

Examples found in repository?
src/rustix/fs/dir_utils.rs (line 77)
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
Hide additional examples
src/fs/dir_entry.rs (line 31)
30
31
32
    pub fn open(&self) -> io::Result<fs::File> {
        self.open_with(OpenOptions::new().read(true))
    }
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/linux/fs/procfs.rs (line 42)
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,
    )
}
src/rustix/linux/fs/stat_impl.rs (line 26)
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),
        },
    }
}
src/rustix/linux/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
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)
}

Sets the option for read access.

This corresponds to std::fs::OpenOptions::read.

Examples found in repository?
src/rustix/fs/dir_utils.rs (line 77)
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
Hide additional examples
src/fs/dir_entry.rs (line 31)
30
31
32
    pub fn open(&self) -> io::Result<fs::File> {
        self.open_with(OpenOptions::new().read(true))
    }
src/rustix/fs/copy_impl.rs (line 17)
16
17
18
19
20
21
22
23
24
25
26
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))
}
src/rustix/linux/fs/procfs.rs (line 43)
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,
    )
}
src/rustix/linux/fs/stat_impl.rs (line 27)
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),
        },
    }
}
src/rustix/linux/fs/set_times_impl.rs (line 32)
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)
}

Sets the option for write access.

This corresponds to std::fs::OpenOptions::write.

Examples found in repository?
src/rustix/fs/copy_impl.rs (line 44)
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
Hide additional examples
src/rustix/linux/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
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)
}
src/rustix/linux/fs/set_permissions_impl.rs (line 38)
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
}

Sets the option for the append mode.

This corresponds to std::fs::OpenOptions::append.

Sets the option for truncating a previous file.

This corresponds to std::fs::OpenOptions::truncate.

Examples found in repository?
src/rustix/fs/copy_impl.rs (line 46)
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))
}

Sets the option to create a new file.

This corresponds to std::fs::OpenOptions::create.

Examples found in repository?
src/rustix/fs/copy_impl.rs (line 45)
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))
}

Sets the option to always create a new file.

This corresponds to std::fs::OpenOptions::create_new.

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Sets the mode bits that a new file will be created with. Read more
Pass custom flags to the flags argument of open. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.