|
1 | | -use crate::ffi; |
| 1 | +use core::marker::PhantomData; |
| 2 | + |
2 | 3 | use bitflags::bitflags; |
3 | 4 |
|
| 5 | +use crate::{ |
| 6 | + fd::{AsRawFd, BorrowedFd}, |
| 7 | + ffi, |
| 8 | +}; |
| 9 | + |
4 | 10 | bitflags! { |
5 | 11 | /// `MS_*` constants for use with [`mount`]. |
6 | 12 | /// |
@@ -280,6 +286,105 @@ bitflags! { |
280 | 286 | } |
281 | 287 | } |
282 | 288 |
|
| 289 | +bitflags! { |
| 290 | + /// `AT_*` flags accepted by [`mount_setattr`]. |
| 291 | + /// |
| 292 | + /// [`mount_setattr`]: crate::mount::mount_setattr |
| 293 | + #[repr(transparent)] |
| 294 | + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] |
| 295 | + pub struct MountSetAttrFlags: ffi::c_uint { |
| 296 | + /// `AT_EMPTY_PATH` |
| 297 | + const AT_EMPTY_PATH = linux_raw_sys::general::AT_EMPTY_PATH; |
| 298 | + |
| 299 | + /// `AT_RECURSIVE` |
| 300 | + const AT_RECURSIVE = linux_raw_sys::general::AT_RECURSIVE; |
| 301 | + |
| 302 | + /// `AT_SYMLINK_NOFOLLOW` |
| 303 | + const AT_SYMLINK_NOFOLLOW = linux_raw_sys::general::AT_SYMLINK_NOFOLLOW; |
| 304 | + |
| 305 | + /// `AT_NO_AUTOMOUNT` |
| 306 | + const AT_NO_AUTOMOUNT = linux_raw_sys::general::AT_NO_AUTOMOUNT; |
| 307 | + } |
| 308 | +} |
| 309 | + |
| 310 | +/// `MOUNT_ATTR_*` flags that also carry a parameter. |
| 311 | +#[cfg(linux_kernel)] |
| 312 | +pub enum MountAttrParamFlags<'a> { |
| 313 | + /// `MOUNT_ATTR_IDMAP`, which carries the descriptor of a user namespace. |
| 314 | + IdMap(BorrowedFd<'a>), |
| 315 | +} |
| 316 | + |
| 317 | +#[cfg(linux_kernel)] |
| 318 | +impl<'a> MountAttrParamFlags<'a> { |
| 319 | + fn apply(self, attr: MountAttr<'a>, operation: MountAttrOperation) -> MountAttr<'a> { |
| 320 | + let mut raw = attr.raw; |
| 321 | + let flags = match operation { |
| 322 | + MountAttrOperation::Set => &mut raw.attr_set, |
| 323 | + MountAttrOperation::Clear => &mut raw.attr_clr, |
| 324 | + }; |
| 325 | + |
| 326 | + match self { |
| 327 | + Self::IdMap(userns_fd) => { |
| 328 | + *flags |= MountAttrFlags::from_bits_retain( |
| 329 | + linux_raw_sys::general::MOUNT_ATTR_IDMAP as u32, |
| 330 | + ) |
| 331 | + .bits() as u64; |
| 332 | + raw.userns_fd = userns_fd.as_raw_fd() as u64; |
| 333 | + } |
| 334 | + } |
| 335 | + |
| 336 | + MountAttr { |
| 337 | + raw, |
| 338 | + userns_fd: PhantomData::<BorrowedFd<'a>>, |
| 339 | + } |
| 340 | + } |
| 341 | +} |
| 342 | + |
| 343 | +/// `struct mount_attr` |
| 344 | +#[cfg(linux_kernel)] |
| 345 | +#[derive(Clone)] |
| 346 | +#[doc(alias = "mount_attr")] |
| 347 | +pub struct MountAttr<'a> { |
| 348 | + pub(crate) raw: linux_raw_sys::general::mount_attr, |
| 349 | + userns_fd: PhantomData<BorrowedFd<'a>>, |
| 350 | +} |
| 351 | + |
| 352 | +#[cfg(linux_kernel)] |
| 353 | +impl<'a> MountAttr<'a> { |
| 354 | + /// Create a `MountAttr` with the given simple fields. |
| 355 | + pub fn new( |
| 356 | + attr_set: MountAttrFlags, |
| 357 | + attr_clr: MountAttrFlags, |
| 358 | + propagation: MountPropagationFlags, |
| 359 | + ) -> Self { |
| 360 | + Self { |
| 361 | + raw: linux_raw_sys::general::mount_attr { |
| 362 | + attr_set: attr_set.bits() as u64, |
| 363 | + attr_clr: attr_clr.bits() as u64, |
| 364 | + propagation: propagation.bits() as u64, |
| 365 | + userns_fd: 0, |
| 366 | + }, |
| 367 | + userns_fd: PhantomData, |
| 368 | + } |
| 369 | + } |
| 370 | + |
| 371 | + /// Set a parameterized flag. |
| 372 | + pub fn set_param_flag(self, param: MountAttrParamFlags<'a>) -> Self { |
| 373 | + param.apply(self, MountAttrOperation::Set) |
| 374 | + } |
| 375 | + |
| 376 | + /// Clear a parameterized flag. |
| 377 | + pub fn clear_param_flag(self, param: MountAttrParamFlags<'a>) -> Self { |
| 378 | + param.apply(self, MountAttrOperation::Clear) |
| 379 | + } |
| 380 | +} |
| 381 | + |
| 382 | +#[cfg(linux_kernel)] |
| 383 | +enum MountAttrOperation { |
| 384 | + Set, |
| 385 | + Clear, |
| 386 | +} |
| 387 | + |
283 | 388 | bitflags! { |
284 | 389 | /// `MS_*` constants for use with [`mount_change`]. |
285 | 390 | /// |
|
0 commit comments