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