Skip to content

Commit

Permalink
Properly distinguish between file and directory symlinks
Browse files Browse the repository at this point in the history
  • Loading branch information
nabijaczleweli committed Dec 10, 2021
1 parent 1e21bd5 commit 496e5c6
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 17 deletions.
21 changes: 11 additions & 10 deletions src/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ impl HttpHandler {
return self.handle_nonexistent(req, req_p);
}

let is_file = is_actually_file(&req_p.metadata().expect("Failed to get file metadata").file_type());
let is_file = is_actually_file(&req_p.metadata().expect("Failed to get file metadata").file_type(), &req_p);
let range = req.headers.get().map(|r: &headers::Range| (*r).clone());
let raw_fs = req.headers.get().map(|r: &RawFsApiHeader| r.0).unwrap_or(false);
if is_file {
Expand Down Expand Up @@ -687,7 +687,7 @@ impl HttpHandler {
}) || (self.follow_symlinks && self.sandbox_symlinks && symlink && !is_descendant_of(fp, &self.hosted_directory.1)))
})
.map(|f| {
let is_file = is_actually_file(&f.file_type().expect("Failed to get file type"));
let is_file = is_actually_file(&f.file_type().expect("Failed to get file type"), &f.path());
if is_file {
get_raw_fs_metadata(f.path())
} else {
Expand Down Expand Up @@ -792,13 +792,13 @@ impl HttpHandler {
}) || (self.follow_symlinks && self.sandbox_symlinks && symlink && !is_descendant_of(fp, &self.hosted_directory.1)))
})
.sorted_by(|lhs, rhs| {
(is_actually_file(&lhs.file_type().expect("Failed to get file type")),
(is_actually_file(&lhs.file_type().expect("Failed to get file type"), &lhs.path()),
lhs.file_name().to_str().expect("Failed to get file name").to_lowercase())
.cmp(&(is_actually_file(&rhs.file_type().expect("Failed to get file type")),
.cmp(&(is_actually_file(&rhs.file_type().expect("Failed to get file type"), &rhs.path()),
rhs.file_name().to_str().expect("Failed to get file name").to_lowercase()))
})
.fold("".to_string(), |cur, f| {
let is_file = is_actually_file(&f.file_type().expect("Failed to get file type"));
let is_file = is_actually_file(&f.file_type().expect("Failed to get file type"), &f.path());
let fmeta = f.metadata().expect("Failed to get requested file metadata");
let fname = f.file_name().into_string().expect("Failed to get file name");
let path = f.path();
Expand Down Expand Up @@ -900,13 +900,13 @@ impl HttpHandler {
}) || (self.follow_symlinks && self.sandbox_symlinks && symlink && !is_descendant_of(fp, &self.hosted_directory.1)))
})
.sorted_by(|lhs, rhs| {
(is_actually_file(&lhs.file_type().expect("Failed to get file type")),
(is_actually_file(&lhs.file_type().expect("Failed to get file type"), &lhs.path()),
lhs.file_name().to_str().expect("Failed to get file name").to_lowercase())
.cmp(&(is_actually_file(&rhs.file_type().expect("Failed to get file type")),
.cmp(&(is_actually_file(&rhs.file_type().expect("Failed to get file type"), &rhs.path()),
rhs.file_name().to_str().expect("Failed to get file name").to_lowercase()))
})
.fold("".to_string(), |cur, f| {
let is_file = is_actually_file(&f.file_type().expect("Failed to get file type"));
let is_file = is_actually_file(&f.file_type().expect("Failed to get file type"), &f.path());
let fmeta = f.metadata().expect("Failed to get requested file metadata");
let fname = f.file_name().into_string().expect("Failed to get file name");
let path = f.path();
Expand Down Expand Up @@ -1116,10 +1116,11 @@ impl HttpHandler {

fn handle_delete_path(&self, req: &mut Request, req_p: PathBuf, symlink: bool) -> IronResult<Response> {
let ft = req_p.metadata().expect("failed to get file metadata").file_type();
let is_file = is_actually_file(&ft, &req_p);
log!(self.log,
"{} deleted {blue}{} {magenta}{}{reset}",
self.remote_addresses(&req),
if is_actually_file(&ft) {
if is_file {
"file"
} else if symlink {
"symlink"
Expand All @@ -1128,7 +1129,7 @@ impl HttpHandler {
},
req_p.display());

if is_actually_file(&ft) {
if is_file {
fs::remove_file(req_p).expect("Failed to remove requested file");
} else {
fs::remove_dir_all(req_p).expect(if symlink {
Expand Down
6 changes: 3 additions & 3 deletions src/ops/webdav.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ impl HttpHandler {
return Ok(Response::with(status::PreconditionFailed));
}

if !is_actually_file(&dest_p.metadata().expect("Failed to get destination file metadata").file_type()) {
if !is_actually_file(&dest_p.metadata().expect("Failed to get destination file metadata").file_type(), &dest_p) {
// NB: this disallows overwriting non-empty directories
if fs::remove_dir(&dest_p).is_err() {
return Ok(Response::with(status::Locked));
Expand All @@ -339,7 +339,7 @@ impl HttpHandler {
overwritten = true;
}

let source_file = is_actually_file(&req_p.metadata().expect("Failed to get requested file metadata").file_type());
let source_file = is_actually_file(&req_p.metadata().expect("Failed to get requested file metadata").file_type(), &dest_p);
if let Some(sp) = source_path {
*sp = (req_p.clone(), source_file);
}
Expand Down Expand Up @@ -463,7 +463,7 @@ impl HttpHandler {

"resourcetype" => {
out.write(XmlWEvent::start_element((WEBDAV_XML_NAMESPACE_DAV.0, "resourcetype")))?;
if !is_actually_file(&meta.file_type()) {
if !is_actually_file(&meta.file_type(), path) {
out.write(XmlWEvent::start_element((WEBDAV_XML_NAMESPACE_DAV.0, "collection")))?;
out.write(XmlWEvent::end_element())?;
}
Expand Down
6 changes: 3 additions & 3 deletions src/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,8 @@ pub fn is_symlink<P: AsRef<Path>>(p: P) -> bool {
}

/// Check if a path refers to a file in a way that includes Unix devices and Windows symlinks.
pub fn is_actually_file(tp: &FileType) -> bool {
tp.is_file() || is_device(tp)
pub fn is_actually_file<P: AsRef<Path>>(tp: &FileType, p: P) -> bool {
tp.is_file() || (tp.is_symlink() && fs::metadata(p).map(|m| is_actually_file(&m.file_type(), "")).unwrap_or(false)) || is_device(tp)
}

/// Check if the specified path is a direct descendant (or an equal) of the specified path.
Expand Down Expand Up @@ -560,7 +560,7 @@ pub fn copy_dir(from: &Path, to: &Path) -> IoResult<Vec<(IoError, String)>> {

let target_path = to.join(relative_path);

if !is_actually_file(&source_metadata.file_type()) {
if !is_actually_file(&source_metadata.file_type(), entry.path()) {
push_error!(errors, relative_path, fs::create_dir(&target_path));
push_error!(errors, relative_path, fs::set_permissions(&target_path, source_metadata.permissions()));
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/util/os/non_windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn win32_file_attributes(meta: &Metadata, path: &Path) -> u32 {
attr |= FILE_ATTRIBUTE_HIDDEN;
}

if !is_actually_file(&meta.file_type()) {
if !is_actually_file(&meta.file_type(), &path) {
attr |= FILE_ATTRIBUTE_DIRECTORY;
} else {
// this is the 'Archive' bit, which is set by
Expand Down

0 comments on commit 496e5c6

Please sign in to comment.