]> git.proxmox.com Git - proxmox-backup.git/blame - src/bin/pxar.rs
pxar: pass feature_flags to encoder/decoder instead of individual flags
[proxmox-backup.git] / src / bin / pxar.rs
CommitLineData
c60d34bd
DM
1extern crate proxmox_backup;
2
3use failure::*;
4
ce7ba139 5use proxmox_backup::tools;
4de0e142 6use proxmox_backup::cli::*;
ef2f2efb 7use proxmox_backup::api_schema::*;
dc9a007b 8use proxmox_backup::api_schema::router::*;
c60d34bd
DM
9
10use serde_json::{Value};
11
37940aa1 12use std::io::Write;
1ef46b81 13use std::path::{Path, PathBuf};
c60d34bd 14
3dbfe5b1 15use proxmox_backup::pxar;
e86c4924 16
6049b71f 17fn print_filenames(
37940aa1 18 param: Value,
6049b71f
DM
19 _info: &ApiMethod,
20 _rpcenv: &mut RpcEnvironment,
21) -> Result<Value, Error> {
e86c4924 22
6049b71f 23 let archive = tools::required_string_param(&param, "archive")?;
e86c4924
DM
24 let file = std::fs::File::open(archive)?;
25
26 let mut reader = std::io::BufReader::new(file);
27
b344461b
CE
28 let mut feature_flags = pxar::CA_FORMAT_DEFAULT;
29 feature_flags ^= pxar::CA_FORMAT_WITH_XATTRS;
30 feature_flags ^= pxar::CA_FORMAT_WITH_FCAPS;
31 let mut decoder = pxar::SequentialDecoder::new(&mut reader, feature_flags);
e86c4924
DM
32
33 let stdout = std::io::stdout();
34 let mut out = stdout.lock();
35
37940aa1
DM
36 let mut path = PathBuf::from(".");
37 decoder.dump_entry(&mut path, false, &mut out)?;
e86c4924
DM
38
39 Ok(Value::Null)
40}
41
6049b71f
DM
42fn dump_archive(
43 param: Value,
44 _info: &ApiMethod,
45 _rpcenv: &mut RpcEnvironment,
46) -> Result<Value, Error> {
c60d34bd 47
6049b71f 48 let archive = tools::required_string_param(&param, "archive")?;
40360fde 49 let file = std::fs::File::open(archive)?;
c60d34bd 50
40360fde 51 let mut reader = std::io::BufReader::new(file);
c60d34bd 52
b344461b
CE
53 let mut feature_flags = pxar::CA_FORMAT_DEFAULT;
54 feature_flags ^= pxar::CA_FORMAT_WITH_XATTRS;
55 feature_flags ^= pxar::CA_FORMAT_WITH_FCAPS;
56 let mut decoder = pxar::SequentialDecoder::new(&mut reader, feature_flags);
c60d34bd 57
40360fde
DM
58 let stdout = std::io::stdout();
59 let mut out = stdout.lock();
c60d34bd 60
40360fde 61 println!("PXAR dump: {}", archive);
c60d34bd 62
37940aa1
DM
63 let mut path = PathBuf::new();
64 decoder.dump_entry(&mut path, true, &mut out)?;
c60d34bd
DM
65
66 Ok(Value::Null)
67}
68
1ef46b81
DM
69fn extract_archive(
70 param: Value,
71 _info: &ApiMethod,
72 _rpcenv: &mut RpcEnvironment,
73) -> Result<Value, Error> {
74
75 let archive = tools::required_string_param(&param, "archive")?;
76 let target = tools::required_string_param(&param, "target")?;
77 let verbose = param["verbose"].as_bool().unwrap_or(false);
0d9bab05
CE
78 let no_xattrs = param["no-xattrs"].as_bool().unwrap_or(false);
79 let no_fcaps = param["no-fcaps"].as_bool().unwrap_or(false);
1ef46b81
DM
80
81 let file = std::fs::File::open(archive)?;
82
83 let mut reader = std::io::BufReader::new(file);
b344461b
CE
84 let mut feature_flags = pxar::CA_FORMAT_DEFAULT;
85 if no_xattrs {
86 feature_flags ^= pxar::CA_FORMAT_WITH_XATTRS;
87 }
88 if no_fcaps {
89 feature_flags ^= pxar::CA_FORMAT_WITH_FCAPS;
90 }
1ef46b81 91
b344461b 92 let mut decoder = pxar::SequentialDecoder::new(&mut reader, feature_flags);
1ef46b81
DM
93
94 decoder.restore(Path::new(target), & |path| {
95 if verbose {
96 println!("{:?}", path);
97 }
98 Ok(())
99 })?;
100
101 Ok(Value::Null)
102}
103
6049b71f
DM
104fn create_archive(
105 param: Value,
106 _info: &ApiMethod,
107 _rpcenv: &mut RpcEnvironment,
108) -> Result<Value, Error> {
c60d34bd 109
6049b71f
DM
110 let archive = tools::required_string_param(&param, "archive")?;
111 let source = tools::required_string_param(&param, "source")?;
2689810c 112 let verbose = param["verbose"].as_bool().unwrap_or(false);
e3c30c50 113 let all_file_systems = param["all-file-systems"].as_bool().unwrap_or(false);
0d9bab05
CE
114 let no_xattrs = param["no-xattrs"].as_bool().unwrap_or(false);
115 let no_fcaps = param["no-fcaps"].as_bool().unwrap_or(false);
02c7d8e5 116
1ef46b81 117 let source = PathBuf::from(source);
02c7d8e5
DM
118
119 let mut dir = nix::dir::Dir::open(
120 &source, nix::fcntl::OFlag::O_NOFOLLOW, nix::sys::stat::Mode::empty())?;
121
122 let file = std::fs::OpenOptions::new()
123 .create_new(true)
124 .write(true)
125 .open(archive)?;
126
127 let mut writer = std::io::BufWriter::with_capacity(1024*1024, file);
b344461b
CE
128 let mut feature_flags = pxar::CA_FORMAT_DEFAULT;
129 if no_xattrs {
130 feature_flags ^= pxar::CA_FORMAT_WITH_XATTRS;
131 }
132 if no_fcaps {
133 feature_flags ^= pxar::CA_FORMAT_WITH_FCAPS;
134 }
135
136 pxar::Encoder::encode(source, &mut dir, &mut writer, all_file_systems, verbose, feature_flags)?;
c60d34bd 137
02c7d8e5 138 writer.flush()?;
c60d34bd
DM
139
140 Ok(Value::Null)
141}
142
143fn main() {
144
145 let cmd_def = CliCommandMap::new()
146 .insert("create", CliCommand::new(
147 ApiMethod::new(
02c7d8e5 148 create_archive,
8968258b 149 ObjectSchema::new("Create new .pxar archive.")
c60d34bd
DM
150 .required("archive", StringSchema::new("Archive name"))
151 .required("source", StringSchema::new("Source directory."))
2689810c 152 .optional("verbose", BooleanSchema::new("Verbose output.").default(false))
0d9bab05
CE
153 .optional("no-xattrs", BooleanSchema::new("Ignore extended file attributes.").default(false))
154 .optional("no-fcaps", BooleanSchema::new("Ignore file capabilities.").default(false))
e3c30c50
DM
155 .optional("all-file-systems", BooleanSchema::new("Include mounted sudirs.").default(false))
156 ))
c60d34bd 157 .arg_param(vec!["archive", "source"])
ce7ba139
DM
158 .completion_cb("archive", tools::complete_file_name)
159 .completion_cb("source", tools::complete_file_name)
160 .into()
c60d34bd 161 )
1ef46b81
DM
162 .insert("extract", CliCommand::new(
163 ApiMethod::new(
164 extract_archive,
165 ObjectSchema::new("Extract an archive.")
166 .required("archive", StringSchema::new("Archive name."))
167 .required("target", StringSchema::new("Target directory."))
168 .optional("verbose", BooleanSchema::new("Verbose output.").default(false))
0d9bab05
CE
169 .optional("no-xattrs", BooleanSchema::new("Ignore extended file attributes.").default(false))
170 .optional("no-fcaps", BooleanSchema::new("Ignore file capabilities.").default(false))
1ef46b81
DM
171 ))
172 .arg_param(vec!["archive", "target"])
173 .completion_cb("archive", tools::complete_file_name)
174 .completion_cb("target", tools::complete_file_name)
175 .into()
176 )
e86c4924
DM
177 .insert("list", CliCommand::new(
178 ApiMethod::new(
179 print_filenames,
180 ObjectSchema::new("List the contents of an archive.")
181 .required("archive", StringSchema::new("Archive name."))
182 ))
183 .arg_param(vec!["archive"])
ce7ba139 184 .completion_cb("archive", tools::complete_file_name)
e86c4924
DM
185 .into()
186 )
c60d34bd
DM
187 .insert("dump", CliCommand::new(
188 ApiMethod::new(
189 dump_archive,
190 ObjectSchema::new("Textual dump of archive contents (debug toolkit).")
191 .required("archive", StringSchema::new("Archive name."))
192 ))
193 .arg_param(vec!["archive"])
ce7ba139 194 .completion_cb("archive", tools::complete_file_name)
c60d34bd
DM
195 .into()
196 );
197
698d9d44 198 run_cli_command(cmd_def.into());
c60d34bd 199}