summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2018-07-12 11:12:20 -0600
committerTom Tromey <tom@tromey.com>2018-07-12 11:12:20 -0600
commit88f6a73b9b34bf2a9c7f0072a0a635f6556cf5fa (patch)
tree59dd7720c0e147c29fe4bfadc99565a0fd098182
parent775ad299c437418d0c5043b05367a462272e2a96 (diff)
downloadrust-installer-88f6a73b9b34bf2a9c7f0072a0a635f6556cf5fa.tar.gz
Do not follow symlinks
The lldb repository has a symlink in it, and so for the tarballer to work when lldb is included, it must not follow symlinks.
-rw-r--r--src/tarballer.rs38
1 files changed, 23 insertions, 15 deletions
diff --git a/src/tarballer.rs b/src/tarballer.rs
index 42bb2a0..caee556 100644
--- a/src/tarballer.rs
+++ b/src/tarballer.rs
@@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::fs::File;
-use std::io::{self, Write, BufWriter};
+use std::fs::{read_link, symlink_metadata};
+use std::io::{self, empty, Write, BufWriter};
use std::path::Path;
use flate2;
@@ -77,8 +77,7 @@ impl Tarballer {
}
for path in files {
let src = Path::new(&self.work_dir).join(&path);
- let file = open_file(&src)?;
- builder.append_data(&mut header(&src, &file)?, &path, &file)
+ append_path(&mut builder, &src, &path)
.chain_err(|| format!("failed to tar file '{}'", src.display()))?;
}
let RayonTee(xz, gz) = builder.into_inner()
@@ -95,21 +94,30 @@ impl Tarballer {
}
}
-fn header(src: &Path, file: &File) -> Result<Header> {
+fn append_path<W: Write>(builder: &mut Builder<W>, src: &Path, path: &String) -> Result<()> {
+ let stat = symlink_metadata(src)?;
let mut header = Header::new_gnu();
- header.set_metadata(&file.metadata()?);
- if cfg!(windows) {
- // Windows doesn't really have a mode, so `tar` never marks files executable.
- // Use an extension whitelist to update files that usually should be so.
- const EXECUTABLES: [&'static str; 4] = ["exe", "dll", "py", "sh"];
- if let Some(ext) = src.extension().and_then(|s| s.to_str()) {
- if EXECUTABLES.contains(&ext) {
- let mode = header.mode()?;
- header.set_mode(mode | 0o111);
+ header.set_metadata(&stat);
+ if stat.file_type().is_symlink() {
+ let link = read_link(src)?;
+ header.set_link_name(&link)?;
+ builder.append_data(&mut header, path, &mut empty())?;
+ } else {
+ if cfg!(windows) {
+ // Windows doesn't really have a mode, so `tar` never marks files executable.
+ // Use an extension whitelist to update files that usually should be so.
+ const EXECUTABLES: [&'static str; 4] = ["exe", "dll", "py", "sh"];
+ if let Some(ext) = src.extension().and_then(|s| s.to_str()) {
+ if EXECUTABLES.contains(&ext) {
+ let mode = header.mode()?;
+ header.set_mode(mode | 0o111);
+ }
}
}
+ let file = open_file(src)?;
+ builder.append_data(&mut header, path, &file)?;
}
- Ok(header)
+ Ok(())
}
/// Returns all `(directories, files)` under the source path