]> git.proxmox.com Git - pxar.git/blob - tests/simple/fs.rs
af763391f817119698843bcce3a4816138f98f68
[pxar.git] / tests / simple / fs.rs
1 use std::ffi::CString;
2 use std::path::PathBuf;
3
4 use anyhow::{bail, Error};
5
6 use pxar::decoder::sync as decoder;
7 use pxar::decoder::SeqRead;
8 use pxar::encoder::sync as encoder;
9 use pxar::encoder::{LinkOffset, SeqWrite};
10 use pxar::format::{self, mode};
11 use pxar::Metadata;
12
13 #[derive(Debug, Eq, PartialEq)]
14 pub enum EntryKind {
15 Invalid,
16 File(Vec<u8>),
17 Directory(Vec<Entry>),
18 Symlink(PathBuf),
19 Hardlink, // TODO
20 Device(format::Device),
21 Socket,
22 Fifo,
23 }
24
25 #[derive(Debug, Eq, PartialEq)]
26 pub struct Entry {
27 pub name: String,
28 pub metadata: Metadata,
29 pub entry: EntryKind,
30 }
31
32 impl Entry {
33 pub fn new(name: &str) -> Self {
34 Self {
35 name: name.to_string(),
36 metadata: Metadata::default(),
37 entry: EntryKind::Invalid,
38 }
39 }
40
41 pub fn metadata(mut self, metadata: impl Into<Metadata>) -> Self {
42 self.metadata = metadata.into();
43 self
44 }
45
46 pub fn entry(mut self, entry: EntryKind) -> Self {
47 self.entry = entry;
48 self
49 }
50
51 pub fn encode_into<T>(&self, encoder: &mut encoder::Encoder<T>) -> Result<(), Error>
52 where
53 T: SeqWrite,
54 {
55 match &self.entry {
56 EntryKind::Invalid => bail!("invalid entry encountered"),
57
58 EntryKind::File(data) => {
59 let _link: LinkOffset = encoder.add_file(
60 &self.metadata,
61 &self.name,
62 data.len() as u64,
63 &mut &data[..],
64 )?;
65 }
66
67 EntryKind::Directory(entries) => {
68 let mut dir = encoder.create_directory(&self.name, &self.metadata)?;
69 for entry in entries {
70 entry.encode_into(&mut dir)?;
71 }
72 dir.finish()?;
73 }
74
75 EntryKind::Symlink(path) => {
76 let _: () = encoder.add_symlink(&self.metadata, &self.name, path)?;
77 }
78
79 other => bail!("TODO: encode_entry for {:?}", other),
80 }
81 Ok(())
82 }
83
84 pub fn decode_from<T: SeqRead>(decoder: &mut decoder::Decoder<T>) -> Result<(), Error> {
85 todo!();
86 }
87 }
88
89 #[rustfmt::skip]
90 pub fn test_fs() -> Entry {
91 Entry::new("/")
92 .metadata(Metadata::dir_builder(0o755))
93 .entry(EntryKind::Directory(vec![
94 Entry::new("home")
95 .metadata(Metadata::dir_builder(0o755))
96 .entry(EntryKind::Directory(vec![
97 Entry::new("user")
98 .metadata(Metadata::dir_builder(0o700).owner(1000, 1000))
99 .entry(EntryKind::Directory(vec![
100 Entry::new(".profile")
101 .metadata(Metadata::file_builder(0o644).owner(1000, 1000))
102 .entry(EntryKind::File(b"#umask 022".to_vec())),
103 Entry::new("data")
104 .metadata(Metadata::file_builder(0o644).owner(1000, 1000))
105 .entry(EntryKind::File(b"a file from a user".to_vec())),
106 ])),
107 ])),
108 Entry::new("bin")
109 .metadata(Metadata::builder(mode::IFLNK | 0o777))
110 .entry(EntryKind::Symlink(PathBuf::from("usr/bin"))),
111 ]))
112 }