]> git.proxmox.com Git - pxar.git/blob - src/util.rs
don't hold temp buffer mutex across await point
[pxar.git] / src / util.rs
1 #![allow(dead_code)]
2
3 use std::future::Future;
4 use std::io;
5 use std::pin::Pin;
6 use std::task::{Context, Poll};
7
8 pub const MAX_READ_BUF_LEN: usize = 4 * 1024 * 1024;
9
10 #[allow(clippy::uninit_vec)]
11 pub fn scale_read_buffer(buffer: &mut Vec<u8>, target: usize) {
12 let target = target.min(MAX_READ_BUF_LEN);
13
14 if buffer.len() >= target {
15 buffer.truncate(target);
16 return;
17 }
18
19 buffer.reserve(target - buffer.len());
20 unsafe {
21 buffer.set_len(target);
22 }
23 }
24
25 // from /usr/include/linux/magic.h
26 // and from casync util.h
27 #[rustfmt::skip]
28 #[allow(clippy::unreadable_literal)]
29 mod consts {
30 pub const BINFMTFS_MAGIC : i64 = 0x42494e4d;
31 pub const BTRFS_SUPER_MAGIC : i64 = 0x9123683E;
32 pub const CGROUP2_SUPER_MAGIC : i64 = 0x63677270;
33 pub const CGROUP_SUPER_MAGIC : i64 = 0x0027e0eb;
34 pub const CONFIGFS_MAGIC : i64 = 0x62656570;
35 pub const DEBUGFS_MAGIC : i64 = 0x64626720;
36 pub const DEVPTS_SUPER_MAGIC : i64 = 0x00001cd1;
37 pub const EFIVARFS_MAGIC : i64 = 0xde5e81e4;
38 pub const EXT4_SUPER_MAGIC : i64 = 0x0000EF53;
39 pub const FUSE_CTL_SUPER_MAGIC: i64 = 0x65735543;
40 pub const FUSE_SUPER_MAGIC : i64 = 0x65735546;
41 pub const HUGETLBFS_MAGIC : i64 = 0x958458f6;
42 pub const MQUEUE_MAGIC : i64 = 0x19800202;
43 pub const MSDOS_SUPER_MAGIC : i64 = 0x00004d44;
44 pub const NFSD_MAGIC : i64 = 0x6e667364;
45 pub const PROC_SUPER_MAGIC : i64 = 0x00009fa0;
46 pub const PSTOREFS_MAGIC : i64 = 0x6165676C;
47 pub const RAMFS_MAGIC : i64 = 0x858458f6;
48 pub const RPCAUTH_GSSMAGIC : i64 = 0x67596969;
49 pub const SECURITYFS_MAGIC : i64 = 0x73636673;
50 pub const SELINUX_MAGIC : i64 = 0xf97cff8c;
51 pub const SMACK_MAGIC : i64 = 0x43415d53;
52 pub const SYSFS_MAGIC : i64 = 0x62656572;
53 pub const TMPFS_MAGIC : i64 = 0x01021994;
54 pub const XFS_SUPER_MAGIC : i64 = 0x58465342;
55 pub const ZFS_SUPER_MAGIC : i64 = 0x2FC12FC1;
56 }
57
58 pub fn is_virtual_file_system(magic: i64) -> bool {
59 matches!(
60 magic,
61 consts::BINFMTFS_MAGIC
62 | consts::CGROUP2_SUPER_MAGIC
63 | consts::CGROUP_SUPER_MAGIC
64 | consts::CONFIGFS_MAGIC
65 | consts::DEBUGFS_MAGIC
66 | consts::DEVPTS_SUPER_MAGIC
67 | consts::EFIVARFS_MAGIC
68 | consts::FUSE_CTL_SUPER_MAGIC
69 | consts::HUGETLBFS_MAGIC
70 | consts::MQUEUE_MAGIC
71 | consts::NFSD_MAGIC
72 | consts::PROC_SUPER_MAGIC
73 | consts::PSTOREFS_MAGIC
74 | consts::RPCAUTH_GSSMAGIC
75 | consts::SECURITYFS_MAGIC
76 | consts::SELINUX_MAGIC
77 | consts::SMACK_MAGIC
78 | consts::SYSFS_MAGIC
79 )
80 }
81
82 /// Helper function to extract file names from binary archive.
83 pub fn read_os_string(buffer: &[u8]) -> std::ffi::OsString {
84 use std::os::unix::ffi::OsStrExt;
85 std::ffi::OsStr::from_bytes(if buffer.ends_with(&[0]) {
86 &buffer[..(buffer.len() - 1)]
87 } else {
88 buffer
89 })
90 .into()
91 }
92
93 #[inline]
94 pub unsafe fn vec_new_uninitialized<T>(len: usize) -> Vec<T> {
95 unsafe {
96 let data = std::alloc::alloc(std::alloc::Layout::array::<T>(len).unwrap());
97 Vec::from_raw_parts(data as *mut T, len, len)
98 }
99 }
100
101 pub fn io_err_other<E: std::fmt::Display>(err: E) -> io::Error {
102 io::Error::new(io::ErrorKind::Other, err.to_string())
103 }
104
105 pub fn poll_result_once<T, R>(mut fut: T) -> io::Result<R>
106 where
107 T: Future<Output = io::Result<R>>,
108 {
109 let waker = std::task::RawWaker::new(std::ptr::null(), &WAKER_VTABLE);
110 let waker = unsafe { std::task::Waker::from_raw(waker) };
111 let mut cx = Context::from_waker(&waker);
112 unsafe {
113 match Pin::new_unchecked(&mut fut).poll(&mut cx) {
114 Poll::Pending => Err(io_err_other("got Poll::Pending synchronous context")),
115 Poll::Ready(r) => r,
116 }
117 }
118 }
119
120 const WAKER_VTABLE: std::task::RawWakerVTable =
121 std::task::RawWakerVTable::new(forbid_clone, forbid_wake, forbid_wake, ignore_drop);
122
123 unsafe fn forbid_clone(_: *const ()) -> std::task::RawWaker {
124 panic!("tried to clone waker for synchronous task");
125 }
126
127 unsafe fn forbid_wake(_: *const ()) {
128 panic!("tried to wake synchronous task");
129 }
130
131 unsafe fn ignore_drop(_: *const ()) {}
132
133 pub const MAX_PATH_LEN: u64 = 4 * 1024;
134 // let's play it safe
135 pub const MAX_FILENAME_LEN: u64 = MAX_PATH_LEN;
136 // name + attr
137 pub const MAX_XATTR_LEN: u64 = 255 + 64 * 1024;
138
139 pub fn validate_filename(name: &[u8]) -> io::Result<()> {
140 if name.is_empty() {
141 io_bail!("illegal path found (empty)");
142 }
143
144 if name.contains(&b'/') {
145 io_bail!("illegal path found (contains slashes, this is a security concern)");
146 }
147
148 if name == b"." {
149 io_bail!("illegal path found: '.'");
150 }
151
152 if name == b".." {
153 io_bail!("illegal path found: '..'");
154 }
155
156 if (name.len() as u64) > MAX_FILENAME_LEN {
157 io_bail!("filename too long (> {})", MAX_FILENAME_LEN);
158 }
159
160 Ok(())
161 }