Skip to content

Commit 74c2f5a

Browse files
authored
Merge pull request #85 from tromey/do-not-follow-symlinks
Do not follow symlinks
2 parents 775ad29 + 88f6a73 commit 74c2f5a

File tree

1 file changed

+23
-15
lines changed

1 file changed

+23
-15
lines changed

src/tarballer.rs

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::fs::File;
12-
use std::io::{self, Write, BufWriter};
11+
use std::fs::{read_link, symlink_metadata};
12+
use std::io::{self, empty, Write, BufWriter};
1313
use std::path::Path;
1414

1515
use flate2;
@@ -77,8 +77,7 @@ impl Tarballer {
7777
}
7878
for path in files {
7979
let src = Path::new(&self.work_dir).join(&path);
80-
let file = open_file(&src)?;
81-
builder.append_data(&mut header(&src, &file)?, &path, &file)
80+
append_path(&mut builder, &src, &path)
8281
.chain_err(|| format!("failed to tar file '{}'", src.display()))?;
8382
}
8483
let RayonTee(xz, gz) = builder.into_inner()
@@ -95,21 +94,30 @@ impl Tarballer {
9594
}
9695
}
9796

98-
fn header(src: &Path, file: &File) -> Result<Header> {
97+
fn append_path<W: Write>(builder: &mut Builder<W>, src: &Path, path: &String) -> Result<()> {
98+
let stat = symlink_metadata(src)?;
9999
let mut header = Header::new_gnu();
100-
header.set_metadata(&file.metadata()?);
101-
if cfg!(windows) {
102-
// Windows doesn't really have a mode, so `tar` never marks files executable.
103-
// Use an extension whitelist to update files that usually should be so.
104-
const EXECUTABLES: [&'static str; 4] = ["exe", "dll", "py", "sh"];
105-
if let Some(ext) = src.extension().and_then(|s| s.to_str()) {
106-
if EXECUTABLES.contains(&ext) {
107-
let mode = header.mode()?;
108-
header.set_mode(mode | 0o111);
100+
header.set_metadata(&stat);
101+
if stat.file_type().is_symlink() {
102+
let link = read_link(src)?;
103+
header.set_link_name(&link)?;
104+
builder.append_data(&mut header, path, &mut empty())?;
105+
} else {
106+
if cfg!(windows) {
107+
// Windows doesn't really have a mode, so `tar` never marks files executable.
108+
// Use an extension whitelist to update files that usually should be so.
109+
const EXECUTABLES: [&'static str; 4] = ["exe", "dll", "py", "sh"];
110+
if let Some(ext) = src.extension().and_then(|s| s.to_str()) {
111+
if EXECUTABLES.contains(&ext) {
112+
let mode = header.mode()?;
113+
header.set_mode(mode | 0o111);
114+
}
109115
}
110116
}
117+
let file = open_file(src)?;
118+
builder.append_data(&mut header, path, &file)?;
111119
}
112-
Ok(header)
120+
Ok(())
113121
}
114122

115123
/// Returns all `(directories, files)` under the source path

0 commit comments

Comments
 (0)