1#![allow(clippy::comparison_chain)]
2mod error;
30mod sys;
31mod util;
32
33use std::ffi::OsStr;
34use std::fs::File;
35use std::os::unix::io::{AsRawFd, BorrowedFd};
36use std::path::Path;
37use std::{fmt, io};
38
39pub use error::UnsupportedPlatformError;
40pub use sys::{XAttrs, SUPPORTED_PLATFORM};
41
42pub fn get<N, P>(path: P, name: N) -> io::Result<Option<Vec<u8>>>
44where
45 P: AsRef<Path>,
46 N: AsRef<OsStr>,
47{
48 util::extract_noattr(sys::get_path(path.as_ref(), name.as_ref(), false))
49}
50
51pub fn get_deref<N, P>(path: P, name: N) -> io::Result<Option<Vec<u8>>>
53where
54 P: AsRef<Path>,
55 N: AsRef<OsStr>,
56{
57 util::extract_noattr(sys::get_path(path.as_ref(), name.as_ref(), true))
58}
59
60pub fn set<N, P>(path: P, name: N, value: &[u8]) -> io::Result<()>
62where
63 P: AsRef<Path>,
64 N: AsRef<OsStr>,
65{
66 sys::set_path(path.as_ref(), name.as_ref(), value, false)
67}
68
69pub fn set_deref<N, P>(path: P, name: N, value: &[u8]) -> io::Result<()>
71where
72 P: AsRef<Path>,
73 N: AsRef<OsStr>,
74{
75 sys::set_path(path.as_ref(), name.as_ref(), value, true)
76}
77
78pub fn remove<N, P>(path: P, name: N) -> io::Result<()>
80where
81 P: AsRef<Path>,
82 N: AsRef<OsStr>,
83{
84 sys::remove_path(path.as_ref(), name.as_ref(), false)
85}
86
87pub fn remove_deref<N, P>(path: P, name: N) -> io::Result<()>
89where
90 P: AsRef<Path>,
91 N: AsRef<OsStr>,
92{
93 sys::remove_path(path.as_ref(), name.as_ref(), true)
94}
95
96pub fn list<P>(path: P) -> io::Result<XAttrs>
101where
102 P: AsRef<Path>,
103{
104 sys::list_path(path.as_ref(), false)
105}
106
107pub fn list_deref<P>(path: P) -> io::Result<XAttrs>
109where
110 P: AsRef<Path>,
111{
112 sys::list_path(path.as_ref(), true)
113}
114
115pub trait FileExt: AsRawFd {
117 fn get_xattr<N>(&self, name: N) -> io::Result<Option<Vec<u8>>>
119 where
120 N: AsRef<OsStr>,
121 {
122 let fd = unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) };
124 util::extract_noattr(sys::get_fd(fd, name.as_ref()))
125 }
126
127 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 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 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
155impl FileExt for File {}
156
157impl fmt::Debug for XAttrs {
158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159 struct AsList<'a>(&'a XAttrs);
161 impl<'a> fmt::Debug for AsList<'a> {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 f.debug_list().entries(self.0.clone()).finish()
164 }
165 }
166 f.debug_tuple("XAttrs").field(&AsList(self)).finish()
167 }
168}