]>
Commit | Line | Data |
---|---|---|
6cd4f635 WB |
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 | ||
e72062a9 WB |
8 | pub const MAX_READ_BUF_LEN: usize = 4 * 1024 * 1024; |
9 | ||
10 | pub 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)] | |
28 | mod 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 | ||
57 | pub 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. | |
79 | pub 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] | |
90 | pub 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 | ||
98 | pub fn io_err_other<E: std::fmt::Display>(err: E) -> io::Error { | |
99 | io::Error::new(io::ErrorKind::Other, err.to_string()) | |
100 | } | |
101 | ||
102 | pub fn poll_result_once<T, R>(mut fut: T) -> io::Result<R> | |
103 | where | |
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 | ||
117 | const WAKER_VTABLE: std::task::RawWakerVTable = | |
118 | std::task::RawWakerVTable::new(forbid_clone, forbid_wake, forbid_wake, ignore_drop); | |
119 | ||
120 | unsafe fn forbid_clone(_: *const ()) -> std::task::RawWaker { | |
121 | panic!("tried to clone waker for synchronous task"); | |
122 | } | |
123 | ||
124 | unsafe fn forbid_wake(_: *const ()) { | |
125 | panic!("tried to wake synchronous task"); | |
126 | } | |
127 | ||
128 | unsafe fn ignore_drop(_: *const ()) {} | |
f3ac1c51 | 129 | |
710e6c8b | 130 | pub const MAX_PATH_LEN: u64 = 4 * 1024; |
ec0761f9 | 131 | // let's play it safe |
710e6c8b | 132 | pub const MAX_FILENAME_LEN: u64 = MAX_PATH_LEN; |
ec0761f9 | 133 | // name + attr |
710e6c8b | 134 | pub const MAX_XATTR_LEN: u64 = 255 + 64 * 1024; |
ec0761f9 | 135 | |
f3ac1c51 WB |
136 | pub 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 | } |