1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use std::fmt::Debug;
use std::fs::{self, File};
use std::io;
#[cfg(not(target_os = "windows"))]
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
use std::time::UNIX_EPOCH;
use walkdir::WalkDir;
use crate::error::{Error, ErrorKind};
pub fn create_tar(dir: &Path, to: &Path) -> Result<(), Error> {
log::info!("create_tar_chown(), dir: {:?}, to: {:?}", dir, to);
let to_file = File::create(to)?;
let mut builder = tar::Builder::new(to_file);
if let Some(dirname) = dir.file_name() {
builder.append_dir_all(dirname, dir)?;
builder.finish()?;
Ok(())
} else {
Err(Error::from_string(
ErrorKind::InvalidDirname,
format!("Failed to create tar file located at: {:?}", to),
))
}
}
pub fn create_tar_without_rootdir(dir: &Path, to: &Path) -> Result<(), Error> {
log::info!("create_tar_without_rootdir() {:?} > {:?}", dir, to);
let to_file = File::create(to)?;
let mut builder = tar::Builder::new(to_file);
builder.append_dir_all(".", dir)?;
builder.finish()?;
Ok(())
}
pub fn create_tar_chown(dir: &Path, to: &Path) -> Result<(), Error> {
log::info!("create_tar_chown() {:?} > {:?}", dir, to);
let to_file = File::create(to)?;
let mut builder = tar::Builder::new(to_file);
for entry in WalkDir::new(dir) {
let entry = entry?;
let path = entry.path();
let metadata = fs::metadata(path)?;
let mtime = metadata.modified()?;
let mtime = mtime.duration_since(UNIX_EPOCH)?.as_secs();
let filename = path.strip_prefix(dir)?;
#[cfg(not(target_os = "windows"))]
let mode = metadata.permissions().mode();
if path.is_file() {
let mut header = tar::Header::new_gnu();
header.set_mtime(mtime);
header.set_size(metadata.len());
#[cfg(not(target_os = "windows"))]
header.set_mode(mode);
let path_str = filename.to_string_lossy().to_string();
header.set_path(&path_str)?;
header.set_cksum();
let fd = File::open(path)?;
builder.append(&mut header, fd)?;
} else if path.is_dir() {
let mut header = tar::Header::new_gnu();
header.set_mtime(mtime);
header.set_size(0);
header.set_mode(0o755);
if filename.as_os_str().is_empty() {
continue;
}
let dir_path = Path::new("./.").join(filename);
let mut path_str = dir_path.to_string_lossy().to_string();
if !path_str.ends_with('/') {
path_str += "/";
}
header.set_path(&filename)?;
header.set_entry_type(tar::EntryType::Directory);
header.set_cksum();
builder.append(&mut header, &mut io::empty())?;
}
}
builder.finish()?;
Ok(())
}
pub fn create_ar(dir: &Path, to: &Path) -> Result<(), Error> {
log::info!("create_ar() {:?} > {:?}", dir, to);
let to_file = File::create(to)?;
let mut builder = ar::Builder::new(to_file);
for entry in WalkDir::new(dir) {
let entry = entry?;
let path = entry.path();
if path.is_file() {
builder.append_path(path)?;
}
}
Ok(())
}
pub fn create_ar_files<P>(files: &[&P], to: &Path) -> Result<(), Error>
where
P: AsRef<Path> + Debug,
{
log::info!("create_ar_files() files: {:?}, to: {:?}", files, to);
let to_file = File::create(to)?;
let mut builder = ar::Builder::new(to_file);
for path in files {
let path = path.as_ref();
if path.is_file() {
builder.append_path(path)?;
}
}
Ok(())
}