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 150 151 152 153 154 155
#![allow(clippy::comparison_chain)]
//! A pure-Rust library to manage extended attributes.
//!
//! It provides support for manipulating extended attributes
//! (`xattrs`) on modern Unix filesystems. See the `attr(5)`
//! manpage for more details.
//!
//! An extension trait [`FileExt`] is provided to directly work with
//! standard `File` objects and file descriptors.
//!
//! If the path argument is a symlink, the get/set/list/remove functions
//! operate on the symlink itself. To operate on the symlink target, use
//! the _deref variant of these functions.
//!
//! ```rust
//! let mut xattrs = xattr::list("/").unwrap().peekable();
//!
//! if xattrs.peek().is_none() {
//! println!("no xattr set on root");
//! return;
//! }
//!
//! println!("Extended attributes:");
//! for attr in xattrs {
//! println!(" - {:?}", attr);
//! }
//! ```
mod error;
mod sys;
mod util;
use std::ffi::OsStr;
use std::fs::File;
use std::io;
use std::os::unix::io::{AsRawFd, BorrowedFd};
use std::path::Path;
pub use error::UnsupportedPlatformError;
pub use sys::{XAttrs, SUPPORTED_PLATFORM};
/// Get an extended attribute for the specified file.
pub fn get<N, P>(path: P, name: N) -> io::Result<Option<Vec<u8>>>
where
P: AsRef<Path>,
N: AsRef<OsStr>,
{
util::extract_noattr(sys::get_path(path.as_ref(), name.as_ref(), false))
}
/// Get an extended attribute for the specified file (dereference symlinks).
pub fn get_deref<N, P>(path: P, name: N) -> io::Result<Option<Vec<u8>>>
where
P: AsRef<Path>,
N: AsRef<OsStr>,
{
util::extract_noattr(sys::get_path(path.as_ref(), name.as_ref(), true))
}
/// Set an extended attribute on the specified file.
pub fn set<N, P>(path: P, name: N, value: &[u8]) -> io::Result<()>
where
P: AsRef<Path>,
N: AsRef<OsStr>,
{
sys::set_path(path.as_ref(), name.as_ref(), value, false)
}
/// Set an extended attribute on the specified file (dereference symlinks).
pub fn set_deref<N, P>(path: P, name: N, value: &[u8]) -> io::Result<()>
where
P: AsRef<Path>,
N: AsRef<OsStr>,
{
sys::set_path(path.as_ref(), name.as_ref(), value, true)
}
/// Remove an extended attribute from the specified file.
pub fn remove<N, P>(path: P, name: N) -> io::Result<()>
where
P: AsRef<Path>,
N: AsRef<OsStr>,
{
sys::remove_path(path.as_ref(), name.as_ref(), false)
}
/// Remove an extended attribute from the specified file (dereference symlinks).
pub fn remove_deref<N, P>(path: P, name: N) -> io::Result<()>
where
P: AsRef<Path>,
N: AsRef<OsStr>,
{
sys::remove_path(path.as_ref(), name.as_ref(), true)
}
/// List extended attributes attached to the specified file.
///
/// Note: this may not list *all* attributes. Speficially, it definitely won't list any trusted
/// attributes unless you are root and it may not list system attributes.
pub fn list<P>(path: P) -> io::Result<XAttrs>
where
P: AsRef<Path>,
{
sys::list_path(path.as_ref(), false)
}
/// List extended attributes attached to the specified file (dereference symlinks).
pub fn list_deref<P>(path: P) -> io::Result<XAttrs>
where
P: AsRef<Path>,
{
sys::list_path(path.as_ref(), true)
}
/// Extension trait to manipulate extended attributes on `File`-like objects.
pub trait FileExt: AsRawFd {
/// Get an extended attribute for the specified file.
fn get_xattr<N>(&self, name: N) -> io::Result<Option<Vec<u8>>>
where
N: AsRef<OsStr>,
{
// SAFETY: Implement I/O safety later.
let fd = unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) };
util::extract_noattr(sys::get_fd(fd, name.as_ref()))
}
/// Set an extended attribute on the specified file.
fn set_xattr<N>(&self, name: N, value: &[u8]) -> io::Result<()>
where
N: AsRef<OsStr>,
{
let fd = unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) };
sys::set_fd(fd, name.as_ref(), value)
}
/// Remove an extended attribute from the specified file.
fn remove_xattr<N>(&self, name: N) -> io::Result<()>
where
N: AsRef<OsStr>,
{
let fd = unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) };
sys::remove_fd(fd, name.as_ref())
}
/// List extended attributes attached to the specified file.
///
/// Note: this may not list *all* attributes. Speficially, it definitely won't list any trusted
/// attributes unless you are root and it may not list system attributes.
fn list_xattr(&self) -> io::Result<XAttrs> {
let fd = unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) };
sys::list_fd(fd)
}
}
impl FileExt for File {}