1
2
3
4
5
6
7
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
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//! # **Li**nux specific **Sy**stem API
//!
//! Higher level APIs targeting newer Linux kernel features.
//!
//! This crate provides somewhat higher level access to more modern features of the Linux kernel, such
//! as builder-style access to the new mount API, `openat2(2)` call with a builder for the `struct
//! open_how` parameters, all the new features of the `statx(2)` system call (such as finding out
//! whether a path is a mount point), or to build user namespace file descriptors (which requires
//! spawning processes and is therefore somewhat inconvenient to do manually).
//!
//! # The new `open` API:
//!
//! In the standard library files are simply opened by path, but this leaves out some important
//! features:
//!
//! - Opening files relative to a directory handle.
//! - Treating such a handle as if we were `chroot`ed into the directory.
//! - Deciding whether or not symlinks should be followed, *not only* for the final component, but also
//! during the entire path traversal.
//!
//! The `OpenHow` builder can be used for these things.
//!
//! ``` rust, no_run
//! # use std::io;
//! #
//! # trait Context: Sized {
//! # fn context(self, _: &str) -> Self {
//! # self
//! # }
//! # }
//! #
//! # impl<T, E> Context for Result<T, E> {}
//! #
//! # fn code() -> io::Result<()> {
//! #
//! use lisy::open::OpenHow;
//!
//! let ct_dir = OpenHow::new_directory() // start with `O_DIRECTORY | O_CLOEXEC | O_NOCTTY`
//! .resolve_no_symlinks(true) // do not allow *any* symlinks in the path
//! .resolve_no_xdev(true) // do not allow crossing file system boundaries
//! .open("/my/container") // returns an `OwnedFd`
//! .context("failed to open /my/container")?;
//!
//! // Now open a file within `/my/container` as if it was the root file system:
//! let file_in_container = OpenHow::new_read()
//! .at_fd(&ct_dir) // open relative to `ct_dir`
//! .resolve_in_root(true) // virtually "chroot" into `ct_dir`
//! .open_file("/usr/share/some/file") // convenience method to get a `std::fs::File`
//! .context("failed to open /my/container/usr/share/some/file")?;
//! #
//! # Ok(())
//! # }
//! ```
//!
//! # The new `mount` API:
//!
//! This provides handles representing file systems, superblocks and mount trees.
//!
//! ``` rust, no_run
//! # use std::io;
//! #
//! # trait Context: Sized {
//! # fn context(self, _: &str) -> Self {
//! # self
//! # }
//! # }
//! #
//! # impl<T, E> Context for Result<T, E> {}
//! #
//! # fn code() -> io::Result<()> {
//! #
//! use lisy::mount::{Mount, MountSetAttr, MoveMount, OpenTree};
//! use lisy::userns::{IdMapping, Userns};
//!
//! // Open a directory as a new detached mount tree:
//! let mount = Mount::open_tree("/mnt/a", OpenTree::CLOEXEC | OpenTree::CLONE, 0)
//! .context("failed to clone tree at /mnt/a")?;
//!
//! // Prepare a user namespace for ID mapping
//! let userns = Userns::builder().context("failed to prepare user namespace")?;
//! userns.map_gids(&[IdMapping::new(0..65536, 100000)])?;
//! userns.map_uids(&[IdMapping::new(0..65536, 100000)])?;
//! let userns = userns
//! .into_fd()
//! .context("failed to finish creating user namespace")?;
//!
//! // Apply the namespace
//! mount
//! .setattr(
//! &MountSetAttr::new().idmap(&userns),
//! libc::AT_RECURSIVE | libc::AT_NO_AUTOMOUNT,
//! )
//! .context("failed to apply idmapping to mount tree")?;
//!
//! // Bind-mount into place:
//! mount
//! .move_mount("/mnt/mapped", MoveMount::empty())
//! .context("failed to move id-mapped mount into place")?;
//! #
//! # Ok(())
//! # }
//! ```
pub
use c_pathCPath;
// BEGIN internal helpers
// Getting the feature cfgs right is a bit of a PITA, so it would be nice if there was some tooling
// there?
pub
pub
pub
pub
pub
// END internal helpers