]> git.proxmox.com Git - proxmox-backup.git/blame - src/catar/encoder.rs
src/bin/proxmox-backup-client.rs: impl option all-file-systems
[proxmox-backup.git] / src / catar / encoder.rs
CommitLineData
4fa71e05
DM
1//! *catar* format encoder.
2//!
3//! This module contain the code to generate *catar* archive files.
4
fb8365b7 5use failure::*;
4f6892eb 6use endian_trait::Endian;
fb8365b7
DM
7
8use super::format_definition::*;
95bd5dfe 9use super::binary_search_tree::*;
fb8365b7
DM
10
11use std::io::Write;
12use std::os::unix::io::AsRawFd;
13use std::os::unix::ffi::OsStrExt;
45281d49 14use std::os::unix::io::RawFd;
d2b03f23 15use std::path::{Path, PathBuf};
45281d49 16
a0cc09b5 17use std::ffi::CStr;
248c17af 18
2e4ae0e2 19use nix::NixPath;
0ff55999
DM
20use nix::fcntl::OFlag;
21use nix::sys::stat::Mode;
d2b03f23 22use nix::errno::Errno;
3192ae96 23use nix::sys::stat::FileStat;
fb8365b7 24
389e5625
DM
25/// The format requires to build sorted directory lookup tables in
26/// memory, so we restrict the number of allowed entries to limit
27/// maximum memory usage.
28pub const MAX_DIRECTORY_ENTRIES: usize = 256*1024;
2e4ae0e2 29
5e7a09be 30pub struct CaTarEncoder<'a, W: Write> {
d2b03f23 31 current_path: PathBuf, // used for error reporting
5e7a09be 32 writer: &'a mut W,
248c17af 33 writer_pos: usize,
9f49fe1d 34 _size: usize,
248c17af 35 file_copy_buffer: Vec<u8>,
79c281fd
DM
36 all_file_systems: bool,
37 root_st_dev: u64,
219ef0e6 38 verbose: bool,
fb8365b7
DM
39}
40
5e7a09be 41impl <'a, W: Write> CaTarEncoder<'a, W> {
a0cc09b5 42
4c0fd487
DM
43 pub fn encode(
44 path: PathBuf,
45 dir: &mut nix::dir::Dir,
219ef0e6 46 writer: &'a mut W,
eed6db39 47 all_file_systems: bool,
219ef0e6 48 verbose: bool,
4c0fd487 49 ) -> Result<(), Error> {
248c17af 50
389e5625
DM
51 const FILE_COPY_BUFFER_SIZE: usize = 1024*1024;
52
248c17af
DM
53 let mut file_copy_buffer = Vec::with_capacity(FILE_COPY_BUFFER_SIZE);
54 unsafe { file_copy_buffer.set_len(FILE_COPY_BUFFER_SIZE); }
55
fb8365b7
DM
56
57 // todo: use scandirat??
4f6892eb 58
13d98013
DM
59 let dir_fd = dir.as_raw_fd();
60 let stat = match nix::sys::stat::fstat(dir_fd) {
4f6892eb 61 Ok(stat) => stat,
79c281fd 62 Err(err) => bail!("fstat {:?} failed - {}", path, err),
4f6892eb
DM
63 };
64
65 if (stat.st_mode & libc::S_IFMT) != libc::S_IFDIR {
79c281fd 66 bail!("got unexpected file type {:?} (not a directory)", path);
4f6892eb
DM
67 }
68
13d98013 69 let magic = detect_fs_type(dir_fd)?;
1c4804cf 70
a8a04956
DM
71 if is_virtual_file_system(magic) {
72 bail!("backup virtual file systems is disabled!");
73 }
74
79c281fd
DM
75 let mut me = Self {
76 current_path: path,
77 writer: writer,
78 writer_pos: 0,
79 _size: 0,
80 file_copy_buffer,
81 all_file_systems,
82 root_st_dev: stat.st_dev,
83 verbose,
84 };
4c0fd487 85
219ef0e6
DM
86 if verbose { println!("{:?}", me.current_path); }
87
1c4804cf 88 me.encode_dir(dir, &stat, magic)?;
fb8365b7
DM
89
90 Ok(())
91 }
92
248c17af 93 fn write(&mut self, buf: &[u8]) -> Result<(), Error> {
c7fa4872 94 self.writer.write_all(buf)?;
248c17af
DM
95 self.writer_pos += buf.len();
96 Ok(())
97 }
98
8c1dfa6c 99 fn write_item<T: Endian>(&mut self, item: T) -> Result<(), Error> {
4f6892eb 100
8c1dfa6c 101 let data = item.to_le();
4f6892eb
DM
102
103 let buffer = unsafe { std::slice::from_raw_parts(
104 &data as *const T as *const u8,
105 std::mem::size_of::<T>()
106 )};
107
108 self.write(buffer)?;
109
110 Ok(())
111 }
112
248c17af 113 fn flush_copy_buffer(&mut self, size: usize) -> Result<(), Error> {
c7fa4872 114 self.writer.write_all(&self.file_copy_buffer[..size])?;
248c17af
DM
115 self.writer_pos += size;
116 Ok(())
117 }
118
3192ae96
DM
119 fn write_header(&mut self, htype: u64, size: u64) -> Result<(), Error> {
120
4f6892eb 121 let size = size + (std::mem::size_of::<CaFormatHeader>() as u64);
8c1dfa6c 122 self.write_item(CaFormatHeader { size, htype })?;
248c17af
DM
123
124 Ok(())
125 }
126
127 fn write_filename(&mut self, name: &CStr) -> Result<(), Error> {
128
129 let buffer = name.to_bytes_with_nul();
130 self.write_header(CA_FORMAT_FILENAME, buffer.len() as u64)?;
131 self.write(buffer)?;
3192ae96
DM
132
133 Ok(())
248c17af 134 }
3192ae96 135
4f6892eb 136 fn create_entry(&self, stat: &FileStat) -> Result<CaFormatEntry, Error> {
3192ae96 137
4f6892eb
DM
138 let mode = if (stat.st_mode & libc::S_IFMT) == libc::S_IFLNK {
139 (libc::S_IFLNK | 0o777) as u64
140 } else {
141 (stat.st_mode & (libc::S_IFMT | 0o7777)) as u64
142 };
3192ae96 143
4f6892eb
DM
144 let mtime = stat.st_mtime * 1_000_000_000 + stat.st_mtime_nsec;
145 if mtime < 0 {
146 bail!("got strange mtime ({}) from fstat for {:?}.", mtime, self.current_path);
147 }
3192ae96 148
3192ae96 149
4f6892eb 150 let entry = CaFormatEntry {
b41d1aab 151 feature_flags: CA_FORMAT_DEFAULT, // fixme: ??
4f6892eb
DM
152 mode: mode,
153 flags: 0,
154 uid: stat.st_uid as u64,
155 gid: stat.st_gid as u64,
156 mtime: mtime as u64,
157 };
3192ae96 158
4f6892eb
DM
159 Ok(entry)
160 }
3192ae96 161
4f6892eb 162 fn read_chattr(&self, fd: RawFd, entry: &mut CaFormatEntry) -> Result<(), Error> {
3192ae96 163
5c76c2f3
DM
164 let mut attr: usize = 0;
165
166 let res = unsafe { read_attr_fd(fd, &mut attr)};
167 if let Err(err) = res {
168 if let nix::Error::Sys(errno) = err {
169 if errno_is_unsupported(errno) { return Ok(()) };
170 }
171 bail!("read_attr_fd failed for {:?} - {}", self.current_path, err);
172 }
173
174 let flags = ca_feature_flags_from_chattr(attr as u32);
175 entry.flags = entry.flags | flags;
176
177 Ok(())
178 }
179
d7bfac86
DM
180 fn read_fat_attr(&self, fd: RawFd, magic: i64, entry: &mut CaFormatEntry) -> Result<(), Error> {
181
182 if magic != MSDOS_SUPER_MAGIC && magic != FUSE_SUPER_MAGIC { return Ok(()); }
5c76c2f3
DM
183
184 let mut attr: u32 = 0;
185
186 let res = unsafe { read_fat_attr_fd(fd, &mut attr)};
187 if let Err(err) = res {
188 if let nix::Error::Sys(errno) = err {
189 if errno_is_unsupported(errno) { return Ok(()) };
190 }
191 bail!("read_fat_attr_fd failed for {:?} - {}", self.current_path, err);
4f6892eb
DM
192 }
193
5c76c2f3
DM
194 let flags = ca_feature_flags_from_fat_attr(attr);
195 entry.flags = entry.flags | flags;
196
4f6892eb
DM
197 Ok(())
198 }
3192ae96 199
8c1dfa6c 200 fn write_entry(&mut self, entry: CaFormatEntry) -> Result<(), Error> {
4f6892eb
DM
201
202 self.write_header(CA_FORMAT_ENTRY, std::mem::size_of::<CaFormatEntry>() as u64)?;
203 self.write_item(entry)?;
3192ae96
DM
204
205 Ok(())
206 }
d2b03f23 207
1b0dc9f6
DM
208 fn write_goodbye_table(&mut self, goodbye_offset: usize, goodbye_items: &mut [CaFormatGoodbyeItem]) -> Result<(), Error> {
209
210 goodbye_items.sort_unstable_by(|a, b| a.hash.cmp(&b.hash));
985567fb
DM
211
212 let item_count = goodbye_items.len();
213
214 let goodbye_table_size = (item_count + 1)*std::mem::size_of::<CaFormatGoodbyeItem>();
215
216 self.write_header(CA_FORMAT_GOODBYE, goodbye_table_size as u64)?;
217
9409255a
DM
218 if self.file_copy_buffer.len() < goodbye_table_size {
219 let need = goodbye_table_size - self.file_copy_buffer.len();
389e5625
DM
220 self.file_copy_buffer.reserve(need);
221 unsafe { self.file_copy_buffer.set_len(self.file_copy_buffer.capacity()); }
985567fb
DM
222 }
223
224 let buffer = &mut self.file_copy_buffer;
985567fb
DM
225
226 copy_binary_search_tree(item_count, |s, d| {
227 let item = &goodbye_items[s];
228 let offset = d*std::mem::size_of::<CaFormatGoodbyeItem>();
229 let dest = crate::tools::map_struct_mut::<CaFormatGoodbyeItem>(&mut buffer[offset..]).unwrap();
230 dest.offset = u64::to_le(item.offset);
231 dest.size = u64::to_le(item.size);
232 dest.hash = u64::to_le(item.hash);
233 });
234
235 // append CaFormatGoodbyeTail as last item
236 let offset = item_count*std::mem::size_of::<CaFormatGoodbyeItem>();
237 let dest = crate::tools::map_struct_mut::<CaFormatGoodbyeItem>(&mut buffer[offset..]).unwrap();
238 dest.offset = u64::to_le(goodbye_offset as u64);
239 dest.size = u64::to_le((goodbye_table_size + std::mem::size_of::<CaFormatHeader>()) as u64);
240 dest.hash = u64::to_le(CA_FORMAT_GOODBYE_TAIL_MARKER);
241
242 self.flush_copy_buffer(goodbye_table_size)?;
243
244 Ok(())
245 }
246
1c4804cf 247 fn encode_dir(&mut self, dir: &mut nix::dir::Dir, dir_stat: &FileStat, magic: i64) -> Result<(), Error> {
fb8365b7 248
0433db19 249 //println!("encode_dir: {:?} start {}", self.current_path, self.writer_pos);
fb8365b7
DM
250
251 let mut name_list = vec![];
252
253 let rawfd = dir.as_raw_fd();
254
4f6892eb 255 let dir_start_pos = self.writer_pos;
fb8365b7 256
4f6892eb 257 let mut dir_entry = self.create_entry(&dir_stat)?;
2e4ae0e2 258
4f6892eb 259 self.read_chattr(rawfd, &mut dir_entry)?;
d7bfac86 260 self.read_fat_attr(rawfd, magic, &mut dir_entry)?;
3192ae96 261
8c1dfa6c 262 self.write_entry(dir_entry)?;
248c17af 263
389e5625
DM
264 let mut dir_count = 0;
265
79c281fd 266 let include_children;
4c0fd487
DM
267 if is_virtual_file_system(magic) {
268 include_children = false;
269 } else {
79c281fd 270 include_children = (self.root_st_dev == dir_stat.st_dev) || self.all_file_systems;
4c0fd487
DM
271 }
272
273 if include_children {
13d98013
DM
274 for entry in dir.iter() {
275 dir_count += 1;
276 if dir_count > MAX_DIRECTORY_ENTRIES {
277 bail!("too many directory items in {:?} (> {})",
278 self.current_path, MAX_DIRECTORY_ENTRIES);
279 }
389e5625 280
13d98013
DM
281 let entry = match entry {
282 Ok(entry) => entry,
283 Err(err) => bail!("readir {:?} failed - {}", self.current_path, err),
284 };
285 let filename = entry.file_name().to_owned();
fb8365b7 286
13d98013
DM
287 let name = filename.to_bytes_with_nul();
288 let name_len = name.len();
289 if name_len == 2 && name[0] == b'.' && name[1] == 0u8 { continue; }
290 if name_len == 3 && name[0] == b'.' && name[1] == b'.' && name[2] == 0u8 { continue; }
fb8365b7 291
13d98013
DM
292 name_list.push(filename);
293 }
65092b1e
DM
294 } else {
295 eprintln!("skip mount point: {:?}", self.current_path);
fb8365b7
DM
296 }
297
4f6892eb 298 name_list.sort_unstable_by(|a, b| a.cmp(&b));
fb8365b7 299
985567fb 300 let mut goodbye_items = vec![];
a0cc09b5 301
4f6892eb 302 for filename in &name_list {
45281d49 303 self.current_path.push(std::ffi::OsStr::from_bytes(filename.as_bytes()));
fb8365b7 304
219ef0e6
DM
305 if self.verbose { println!("{:?}", self.current_path); }
306
4f6892eb
DM
307 let stat = match nix::sys::stat::fstatat(rawfd, filename.as_ref(), nix::fcntl::AtFlags::AT_SYMLINK_NOFOLLOW) {
308 Ok(stat) => stat,
309 Err(nix::Error::Sys(Errno::ENOENT)) => {
310 self.report_vanished_file(&self.current_path)?;
311 continue;
312 }
313 Err(err) => bail!("fstat {:?} failed - {}", self.current_path, err),
314 };
315
a0cc09b5
DM
316 let start_pos = self.writer_pos;
317
a7e37131
DM
318 let ifmt = stat.st_mode & libc::S_IFMT;
319
320 if ifmt == libc::S_IFDIR {
a0cc09b5 321
1c4804cf
DM
322 let mut dir = match nix::dir::Dir::openat(rawfd, filename.as_ref(), OFlag::O_DIRECTORY|OFlag::O_NOFOLLOW, Mode::empty()) {
323 Ok(dir) => dir,
324 Err(nix::Error::Sys(Errno::ENOENT)) => {
325 self.report_vanished_file(&self.current_path)?;
326 continue; // fixme!!
327 },
d2b03f23 328 Err(err) => bail!("open dir {:?} failed - {}", self.current_path, err),
1c4804cf
DM
329 };
330
331 let child_magic = if dir_stat.st_dev != stat.st_dev {
13d98013 332 detect_fs_type(dir.as_raw_fd())?
1c4804cf
DM
333 } else {
334 magic
335 };
336
337 self.write_filename(&filename)?;
338 self.encode_dir(&mut dir, &stat, child_magic)?;
3192ae96 339
a7e37131 340 } else if ifmt == libc::S_IFREG {
1c4804cf
DM
341 let filefd = match nix::fcntl::openat(rawfd, filename.as_ref(), OFlag::O_NOFOLLOW, Mode::empty()) {
342 Ok(filefd) => filefd,
343 Err(nix::Error::Sys(Errno::ENOENT)) => {
344 self.report_vanished_file(&self.current_path)?;
345 continue;
346 },
d2b03f23 347 Err(err) => bail!("open file {:?} failed - {}", self.current_path, err),
1c4804cf
DM
348 };
349
13d98013
DM
350 let child_magic = if dir_stat.st_dev != stat.st_dev {
351 detect_fs_type(filefd)?
352 } else {
353 magic
354 };
355
1c4804cf 356 self.write_filename(&filename)?;
13d98013 357 let res = self.encode_file(filefd, &stat, child_magic);
1c4804cf
DM
358 let _ = nix::unistd::close(filefd); // ignore close errors
359 res?;
360
a7e37131 361 } else if ifmt == libc::S_IFLNK {
0ff55999 362 let mut buffer = [0u8; libc::PATH_MAX as usize];
3192ae96 363
3192ae96 364 let res = filename.with_nix_path(|cstr| {
d05f9321 365 unsafe { libc::readlinkat(rawfd, cstr.as_ptr(), buffer.as_mut_ptr() as *mut libc::c_char, buffer.len()-1) }
3192ae96
DM
366 })?;
367
368 match Errno::result(res) {
d05f9321
DM
369 Ok(len) => {
370 buffer[len as usize] = 0u8; // add Nul byte
1c4804cf 371 self.write_filename(&filename)?;
d05f9321
DM
372 self.encode_symlink(&buffer[..((len+1) as usize)], &stat)?
373 }
1c4804cf
DM
374 Err(nix::Error::Sys(Errno::ENOENT)) => {
375 self.report_vanished_file(&self.current_path)?;
376 continue;
377 }
d2b03f23
DM
378 Err(err) => bail!("readlink {:?} failed - {}", self.current_path, err),
379 }
a7e37131 380 } else if (ifmt == libc::S_IFBLK) || (ifmt == libc::S_IFCHR) {
1c4804cf 381 self.write_filename(&filename)?;
a7e37131 382 self.encode_device(&stat)?;
490683ec 383 } else if (ifmt == libc::S_IFIFO) || (ifmt == libc::S_IFSOCK) {
1c4804cf
DM
384 self.write_filename(&filename)?;
385 self.encode_special(&stat)?;
45281d49
DM
386 } else {
387 bail!("unsupported file type (mode {:o} {:?})", stat.st_mode, self.current_path);
fb8365b7 388 }
45281d49 389
a0cc09b5
DM
390 let end_pos = self.writer_pos;
391
985567fb 392 goodbye_items.push(CaFormatGoodbyeItem {
a0cc09b5
DM
393 offset: start_pos as u64,
394 size: (end_pos - start_pos) as u64,
0866748d 395 hash: compute_goodbye_hash(filename.to_bytes()),
a0cc09b5
DM
396 });
397
45281d49 398 self.current_path.pop();
248c17af
DM
399 }
400
0433db19 401 //println!("encode_dir: {:?} end {}", self.current_path, self.writer_pos);
45281d49 402
985567fb
DM
403 // fixup goodby item offsets
404 let goodbye_start = self.writer_pos as u64;
405 for item in &mut goodbye_items {
406 item.offset = goodbye_start - item.offset;
a0cc09b5
DM
407 }
408
985567fb 409 let goodbye_offset = self.writer_pos - dir_start_pos;
a0cc09b5 410
1b0dc9f6 411 self.write_goodbye_table(goodbye_offset, &mut goodbye_items)?;
a0cc09b5 412
0433db19 413 //println!("encode_dir: {:?} end1 {}", self.current_path, self.writer_pos);
45281d49
DM
414 Ok(())
415 }
416
13d98013 417 fn encode_file(&mut self, filefd: RawFd, stat: &FileStat, magic: i64) -> Result<(), Error> {
45281d49 418
0433db19 419 //println!("encode_file: {:?}", self.current_path);
45281d49 420
4f6892eb 421 let mut entry = self.create_entry(&stat)?;
2e4ae0e2 422
4f6892eb 423 self.read_chattr(filefd, &mut entry)?;
d7bfac86 424 self.read_fat_attr(filefd, magic, &mut entry)?;
2e4ae0e2 425
8c1dfa6c 426 self.write_entry(entry)?;
2e4ae0e2 427
79c281fd 428 let include_payload;
13d98013 429 if is_virtual_file_system(magic) {
4c0fd487
DM
430 include_payload = false;
431 } else {
79c281fd 432 include_payload = (stat.st_dev == self.root_st_dev) || self.all_file_systems;
4c0fd487
DM
433 }
434
435 if !include_payload {
65092b1e 436 eprintln!("skip content: {:?}", self.current_path);
13d98013
DM
437 self.write_header(CA_FORMAT_PAYLOAD, 0)?;
438 return Ok(());
439 }
440
2e4ae0e2
DM
441 let size = stat.st_size as u64;
442
443 self.write_header(CA_FORMAT_PAYLOAD, size)?;
444
445 let mut pos: u64 = 0;
446 loop {
447 let n = match nix::unistd::read(filefd, &mut self.file_copy_buffer) {
448 Ok(n) => n,
449 Err(nix::Error::Sys(Errno::EINTR)) => continue /* try again */,
450 Err(err) => bail!("read {:?} failed - {}", self.current_path, err),
451 };
452 if n == 0 { // EOF
453 if pos != size {
454 // Note:: casync format cannot handle that
455 bail!("detected shrinked file {:?} ({} < {})", self.current_path, pos, size);
456 }
457 break;
458 }
459
460 let mut next = pos + (n as u64);
461
462 if next > size { next = size; }
463
464 let count = (next - pos) as usize;
465
248c17af 466 self.flush_copy_buffer(count)?;
2e4ae0e2 467
f0f3029e 468 pos = next;
2e4ae0e2
DM
469
470 if pos >= size { break; }
471 }
3192ae96 472
45281d49
DM
473 Ok(())
474 }
475
a7e37131
DM
476 fn encode_device(&mut self, stat: &FileStat) -> Result<(), Error> {
477
1c4804cf 478 let entry = self.create_entry(&stat)?;
a7e37131
DM
479
480 self.write_entry(entry)?;
481
482 let major = unsafe { libc::major(stat.st_rdev) } as u64;
483 let minor = unsafe { libc::minor(stat.st_rdev) } as u64;
484
6b64d25d 485 //println!("encode_device: {:?} {} {} {}", self.current_path, stat.st_rdev, major, minor);
a7e37131
DM
486
487 self.write_header(CA_FORMAT_DEVICE, std::mem::size_of::<CaFormatDevice>() as u64)?;
488 self.write_item(CaFormatDevice { major, minor })?;
489
490 Ok(())
491 }
492
1c4804cf
DM
493 // FIFO or Socket
494 fn encode_special(&mut self, stat: &FileStat) -> Result<(), Error> {
495
496 let entry = self.create_entry(&stat)?;
497
498 self.write_entry(entry)?;
499
500 Ok(())
501 }
502
a0cc09b5 503 fn encode_symlink(&mut self, target: &[u8], stat: &FileStat) -> Result<(), Error> {
45281d49 504
0433db19 505 //println!("encode_symlink: {:?} -> {:?}", self.current_path, target);
fb8365b7 506
4f6892eb 507 let entry = self.create_entry(&stat)?;
8c1dfa6c 508 self.write_entry(entry)?;
3192ae96 509
2e4ae0e2 510 self.write_header(CA_FORMAT_SYMLINK, target.len() as u64)?;
248c17af 511 self.write(target)?;
3192ae96 512
fb8365b7
DM
513 Ok(())
514 }
d2b03f23
DM
515
516 // the report_XXX method may raise and error - depending on encoder configuration
3192ae96 517
d2b03f23
DM
518 fn report_vanished_file(&self, path: &Path) -> Result<(), Error> {
519
520 eprintln!("WARNING: detected vanished file {:?}", path);
521
522 Ok(())
523 }
a0cc09b5 524}
4f6892eb
DM
525
526fn errno_is_unsupported(errno: Errno) -> bool {
527
528 match errno {
529 Errno::ENOTTY | Errno::ENOSYS | Errno::EBADF | Errno::EOPNOTSUPP | Errno::EINVAL => {
530 true
531 }
532 _ => false,
533 }
534}
535
13d98013 536fn detect_fs_type(fd: RawFd) -> Result<i64, Error> {
1c4804cf 537 let mut fs_stat: libc::statfs = unsafe { std::mem::uninitialized() };
13d98013
DM
538 let res = unsafe { libc::fstatfs(fd, &mut fs_stat) };
539 Errno::result(res)?;
1c4804cf
DM
540
541 Ok(fs_stat.f_type)
542}
543
4f6892eb 544use nix::{convert_ioctl_res, request_code_read, ioc};
8c1dfa6c 545
4f6892eb
DM
546// /usr/include/linux/fs.h: #define FS_IOC_GETFLAGS _IOR('f', 1, long)
547/// read Linux file system attributes (see man chattr)
548nix::ioctl_read!(read_attr_fd, b'f', 1, usize);
549
5c76c2f3
DM
550// /usr/include/linux/msdos_fs.h: #define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32)
551// read FAT file system attributes
552nix::ioctl_read!(read_fat_attr_fd, b'r', 0x10, u32);
80881f60
DM
553
554
555// from /usr/include/linux/magic.h
556// and from casync util.h
9f49fe1d
DM
557pub const BINFMTFS_MAGIC: i64 = 0x42494e4d;
558pub const CGROUP2_SUPER_MAGIC: i64 = 0x63677270;
559pub const CGROUP_SUPER_MAGIC: i64 = 0x0027e0eb;
560pub const CONFIGFS_MAGIC: i64 = 0x62656570;
561pub const DEBUGFS_MAGIC: i64 = 0x64626720;
562pub const DEVPTS_SUPER_MAGIC: i64 = 0x00001cd1;
563pub const EFIVARFS_MAGIC: i64 = 0xde5e81e4;
564pub const FUSE_CTL_SUPER_MAGIC: i64 = 0x65735543;
565pub const HUGETLBFS_MAGIC: i64 = 0x958458f6;
566pub const MQUEUE_MAGIC: i64 = 0x19800202;
567pub const NFSD_MAGIC: i64 = 0x6e667364;
568pub const PROC_SUPER_MAGIC: i64 = 0x00009fa0;
569pub const PSTOREFS_MAGIC: i64 = 0x6165676C;
570pub const RPCAUTH_GSSMAGIC: i64 = 0x67596969;
571pub const SECURITYFS_MAGIC: i64 = 0x73636673;
572pub const SELINUX_MAGIC: i64 = 0xf97cff8c;
573pub const SMACK_MAGIC: i64 = 0x43415d53;
574pub const RAMFS_MAGIC: i64 = 0x858458f6;
575pub const TMPFS_MAGIC: i64 = 0x01021994;
576pub const SYSFS_MAGIC: i64 = 0x62656572;
577pub const MSDOS_SUPER_MAGIC: i64 = 0x00004d44;
578pub const FUSE_SUPER_MAGIC: i64 = 0x65735546;
d7bfac86 579
80881f60
DM
580
581#[inline(always)]
9f49fe1d 582pub fn is_temporary_file_system(magic: i64) -> bool {
80881f60
DM
583 magic == RAMFS_MAGIC || magic == TMPFS_MAGIC
584}
585
9f49fe1d 586pub fn is_virtual_file_system(magic: i64) -> bool {
80881f60
DM
587
588 match magic {
589 BINFMTFS_MAGIC |
590 CGROUP2_SUPER_MAGIC |
591 CGROUP_SUPER_MAGIC |
592 CONFIGFS_MAGIC |
593 DEBUGFS_MAGIC |
594 DEVPTS_SUPER_MAGIC |
595 EFIVARFS_MAGIC |
596 FUSE_CTL_SUPER_MAGIC |
597 HUGETLBFS_MAGIC |
598 MQUEUE_MAGIC |
599 NFSD_MAGIC |
600 PROC_SUPER_MAGIC |
601 PSTOREFS_MAGIC |
602 RPCAUTH_GSSMAGIC |
603 SECURITYFS_MAGIC |
604 SELINUX_MAGIC |
605 SMACK_MAGIC |
606 SYSFS_MAGIC => true,
607 _ => false
608 }
609}