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