1 | #![allow (clippy::comparison_chain)] |
2 | //! A pure-Rust library to manage extended attributes. |
3 | //! |
4 | //! It provides support for manipulating extended attributes |
5 | //! (`xattrs`) on modern Unix filesystems. See the `attr(5)` |
6 | //! manpage for more details. |
7 | //! |
8 | //! An extension trait [`FileExt`] is provided to directly work with |
9 | //! standard `File` objects and file descriptors. |
10 | //! |
11 | //! If the path argument is a symlink, the get/set/list/remove functions |
12 | //! operate on the symlink itself. To operate on the symlink target, use |
13 | //! the _deref variant of these functions. |
14 | //! |
15 | //! ```rust |
16 | //! let mut xattrs = xattr::list("/" ).unwrap().peekable(); |
17 | //! |
18 | //! if xattrs.peek().is_none() { |
19 | //! println!("no xattr set on root" ); |
20 | //! return; |
21 | //! } |
22 | //! |
23 | //! println!("Extended attributes:" ); |
24 | //! for attr in xattrs { |
25 | //! println!(" - {:?}" , attr); |
26 | //! } |
27 | //! ``` |
28 | |
29 | mod error; |
30 | mod sys; |
31 | mod util; |
32 | |
33 | use std::ffi::OsStr; |
34 | use std::fs::File; |
35 | use std::io; |
36 | use std::os::unix::io::{AsRawFd, BorrowedFd}; |
37 | use std::path::Path; |
38 | |
39 | pub use error::UnsupportedPlatformError; |
40 | pub use sys::{XAttrs, SUPPORTED_PLATFORM}; |
41 | |
42 | /// Get an extended attribute for the specified file. |
43 | pub fn get<N, P>(path: P, name: N) -> io::Result<Option<Vec<u8>>> |
44 | where |
45 | P: AsRef<Path>, |
46 | N: AsRef<OsStr>, |
47 | { |
48 | util::extract_noattr(result:sys::get_path(path.as_ref(), name.as_ref(), deref:false)) |
49 | } |
50 | |
51 | /// Get an extended attribute for the specified file (dereference symlinks). |
52 | pub fn get_deref<N, P>(path: P, name: N) -> io::Result<Option<Vec<u8>>> |
53 | where |
54 | P: AsRef<Path>, |
55 | N: AsRef<OsStr>, |
56 | { |
57 | util::extract_noattr(result:sys::get_path(path.as_ref(), name.as_ref(), deref:true)) |
58 | } |
59 | |
60 | /// Set an extended attribute on the specified file. |
61 | pub fn set<N, P>(path: P, name: N, value: &[u8]) -> io::Result<()> |
62 | where |
63 | P: AsRef<Path>, |
64 | N: AsRef<OsStr>, |
65 | { |
66 | sys::set_path(path.as_ref(), name.as_ref(), value, deref:false) |
67 | } |
68 | |
69 | /// Set an extended attribute on the specified file (dereference symlinks). |
70 | pub fn set_deref<N, P>(path: P, name: N, value: &[u8]) -> io::Result<()> |
71 | where |
72 | P: AsRef<Path>, |
73 | N: AsRef<OsStr>, |
74 | { |
75 | sys::set_path(path.as_ref(), name.as_ref(), value, deref:true) |
76 | } |
77 | |
78 | /// Remove an extended attribute from the specified file. |
79 | pub fn remove<N, P>(path: P, name: N) -> io::Result<()> |
80 | where |
81 | P: AsRef<Path>, |
82 | N: AsRef<OsStr>, |
83 | { |
84 | sys::remove_path(path.as_ref(), name.as_ref(), deref:false) |
85 | } |
86 | |
87 | /// Remove an extended attribute from the specified file (dereference symlinks). |
88 | pub fn remove_deref<N, P>(path: P, name: N) -> io::Result<()> |
89 | where |
90 | P: AsRef<Path>, |
91 | N: AsRef<OsStr>, |
92 | { |
93 | sys::remove_path(path.as_ref(), name.as_ref(), deref:true) |
94 | } |
95 | |
96 | /// List extended attributes attached to the specified file. |
97 | /// |
98 | /// Note: this may not list *all* attributes. Speficially, it definitely won't list any trusted |
99 | /// attributes unless you are root and it may not list system attributes. |
100 | pub fn list<P>(path: P) -> io::Result<XAttrs> |
101 | where |
102 | P: AsRef<Path>, |
103 | { |
104 | sys::list_path(path.as_ref(), deref:false) |
105 | } |
106 | |
107 | /// List extended attributes attached to the specified file (dereference symlinks). |
108 | pub fn list_deref<P>(path: P) -> io::Result<XAttrs> |
109 | where |
110 | P: AsRef<Path>, |
111 | { |
112 | sys::list_path(path.as_ref(), deref:true) |
113 | } |
114 | |
115 | /// Extension trait to manipulate extended attributes on `File`-like objects. |
116 | pub trait FileExt: AsRawFd { |
117 | /// Get an extended attribute for the specified file. |
118 | fn get_xattr<N>(&self, name: N) -> io::Result<Option<Vec<u8>>> |
119 | where |
120 | N: AsRef<OsStr>, |
121 | { |
122 | // SAFETY: Implement I/O safety later. |
123 | let fd = unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }; |
124 | util::extract_noattr(sys::get_fd(fd, name.as_ref())) |
125 | } |
126 | |
127 | /// Set an extended attribute on the specified file. |
128 | fn set_xattr<N>(&self, name: N, value: &[u8]) -> io::Result<()> |
129 | where |
130 | N: AsRef<OsStr>, |
131 | { |
132 | let fd = unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }; |
133 | sys::set_fd(fd, name.as_ref(), value) |
134 | } |
135 | |
136 | /// Remove an extended attribute from the specified file. |
137 | fn remove_xattr<N>(&self, name: N) -> io::Result<()> |
138 | where |
139 | N: AsRef<OsStr>, |
140 | { |
141 | let fd = unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }; |
142 | sys::remove_fd(fd, name.as_ref()) |
143 | } |
144 | |
145 | /// List extended attributes attached to the specified file. |
146 | /// |
147 | /// Note: this may not list *all* attributes. Speficially, it definitely won't list any trusted |
148 | /// attributes unless you are root and it may not list system attributes. |
149 | fn list_xattr(&self) -> io::Result<XAttrs> { |
150 | let fd = unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }; |
151 | sys::list_fd(fd) |
152 | } |
153 | } |
154 | |
155 | impl FileExt for File {} |
156 | |