/rust/registry/src/index.crates.io-1949cf8c6b5b557f/xattr-1.6.1/src/util.rs
Line | Count | Source |
1 | | use std::io; |
2 | | use std::mem::MaybeUninit; |
3 | | |
4 | 0 | pub fn extract_noattr(result: io::Result<Vec<u8>>) -> io::Result<Option<Vec<u8>>> { |
5 | 0 | result.map(Some).or_else(|e| { |
6 | 0 | if e.raw_os_error() == Some(crate::sys::ENOATTR) { |
7 | 0 | Ok(None) |
8 | | } else { |
9 | 0 | Err(e) |
10 | | } |
11 | 0 | }) |
12 | 0 | } |
13 | | |
14 | | /// Calls `get_value` to with a buffer and `get_size` to estimate the size of the buffer if/when |
15 | | /// `get_value` returns ERANGE. |
16 | | #[allow(dead_code)] |
17 | 0 | pub fn allocate_loop<F, S>(mut get_value: F, mut get_size: S) -> io::Result<Vec<u8>> |
18 | 0 | where |
19 | 0 | F: for<'a> FnMut(&'a mut [MaybeUninit<u8>]) -> io::Result<&'a mut [u8]>, |
20 | 0 | S: FnMut() -> io::Result<usize>, |
21 | | { |
22 | | // Start by assuming the return value is <= 4KiB. If it is, we can do this in one syscall. |
23 | | const INITIAL_BUFFER_SIZE: usize = 4096; |
24 | 0 | match get_value(&mut [MaybeUninit::<u8>::uninit(); INITIAL_BUFFER_SIZE]) { |
25 | 0 | Ok(val) => return Ok(val.to_vec()), |
26 | 0 | Err(e) if e.raw_os_error() != Some(crate::sys::ERANGE) => return Err(e), |
27 | 0 | _ => {} |
28 | | } |
29 | | |
30 | | // If that fails, we ask for the size and try again with a buffer of the correct size. |
31 | 0 | let mut vec: Vec<u8> = Vec::new(); |
32 | | loop { |
33 | 0 | vec.reserve_exact(get_size()?); |
34 | 0 | match get_value(vec.spare_capacity_mut()) { |
35 | 0 | Ok(initialized) => { |
36 | | unsafe { |
37 | 0 | let len = initialized.len(); |
38 | 0 | assert_eq!( |
39 | 0 | initialized.as_ptr(), |
40 | 0 | vec.as_ptr(), |
41 | 0 | "expected the same buffer" |
42 | | ); |
43 | 0 | vec.set_len(len); |
44 | | } |
45 | | // Only shrink to fit if we've over-allocated by MORE than one byte. Unfortunately, |
46 | | // on FreeBSD, we have to over-allocate by one byte to determine if we've read all |
47 | | // the attributes. |
48 | 0 | if vec.capacity() > vec.len() + 1 { |
49 | 0 | vec.shrink_to_fit(); |
50 | 0 | } |
51 | 0 | return Ok(vec); |
52 | | } |
53 | 0 | Err(e) if e.raw_os_error() != Some(crate::sys::ERANGE) => return Err(e), |
54 | 0 | _ => {} // try again |
55 | | } |
56 | | } |
57 | 0 | } Unexecuted instantiation: xattr::util::allocate_loop::<xattr::sys::linux_macos::get_fd::{closure#0}, xattr::sys::linux_macos::get_fd::{closure#1}>Unexecuted instantiation: xattr::util::allocate_loop::<xattr::sys::linux_macos::list_fd::{closure#0}, xattr::sys::linux_macos::list_fd::{closure#1}>Unexecuted instantiation: xattr::util::allocate_loop::<xattr::sys::linux_macos::get_path::{closure#0}, xattr::sys::linux_macos::get_path::{closure#1}>Unexecuted instantiation: xattr::util::allocate_loop::<xattr::sys::linux_macos::get_path::{closure#2}, xattr::sys::linux_macos::get_path::{closure#3}>Unexecuted instantiation: xattr::util::allocate_loop::<xattr::sys::linux_macos::list_path::{closure#0}, xattr::sys::linux_macos::list_path::{closure#1}>Unexecuted instantiation: xattr::util::allocate_loop::<xattr::sys::linux_macos::list_path::{closure#2}, xattr::sys::linux_macos::list_path::{closure#3}> |