Skip to content

Commit f7887f6

Browse files
committed
Fix links
1 parent 8f260c2 commit f7887f6

File tree

1 file changed

+91
-49
lines changed

1 file changed

+91
-49
lines changed

src/file/reader.rs

Lines changed: 91 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -649,35 +649,44 @@ impl BoxFileReader {
649649
let symlinks_start = Instant::now();
650650
for (path, record) in symlinks {
651651
if let Record::Link(link) = &record {
652-
let link_target = self
653-
.resolve_link(link)
654-
.map_err(|e| ExtractError::ResolveLinkFailed(e, link.clone().into_owned()))?;
652+
let link_path = output_path.join(path.to_path_buf());
653+
654+
// Create parent directory if needed
655+
if let Some(parent) = link_path.parent() {
656+
fs::create_dir_all(parent)
657+
.await
658+
.map_err(|e| ExtractError::CreateDirFailed(e, parent.to_path_buf()))?;
659+
}
655660

656-
let source = output_path.join(path.to_path_buf());
657-
let destination = output_path.join(link_target.path.to_path_buf());
661+
// Use the target as-is (may be relative or absolute)
662+
let target = link.target.to_path_buf();
658663

659664
#[cfg(unix)]
660665
{
661-
tokio::fs::symlink(&destination, &source)
662-
.await
663-
.map_err(|e| {
664-
ExtractError::CreateLinkFailed(e, source.clone(), destination)
665-
})?;
666+
tokio::fs::symlink(&target, &link_path).await.map_err(|e| {
667+
ExtractError::CreateLinkFailed(e, link_path.clone(), target)
668+
})?;
666669
}
667670

668671
#[cfg(windows)]
669672
{
670-
if link_target.record.as_directory().is_some() {
671-
tokio::fs::symlink_dir(&destination, &source)
673+
// On Windows, we need to know if it's a dir or file symlink
674+
let is_dir = self
675+
.resolve_link(link)
676+
.map(|r| r.record.as_directory().is_some())
677+
.unwrap_or(false);
678+
679+
if is_dir {
680+
tokio::fs::symlink_dir(&target, &link_path)
672681
.await
673682
.map_err(|e| {
674-
ExtractError::CreateLinkFailed(e, source.clone(), destination)
683+
ExtractError::CreateLinkFailed(e, link_path.clone(), target)
675684
})?;
676685
} else {
677-
tokio::fs::symlink_file(&destination, &source)
686+
tokio::fs::symlink_file(&target, &link_path)
678687
.await
679688
.map_err(|e| {
680-
ExtractError::CreateLinkFailed(e, source.clone(), destination)
689+
ExtractError::CreateLinkFailed(e, link_path.clone(), target)
681690
})?;
682691
}
683692
}
@@ -939,34 +948,51 @@ impl BoxFileReader {
939948
}
940949
#[cfg(unix)]
941950
Record::Link(link) => {
942-
let link_target = self
943-
.resolve_link(link)
944-
.map_err(|e| ExtractError::ResolveLinkFailed(e, link.clone().into_owned()))?;
951+
let link_path = output_path.join(path.to_path_buf());
945952

946-
let source = output_path.join(path.to_path_buf());
947-
let destination = output_path.join(link_target.path.to_path_buf());
953+
// Create parent directory if needed
954+
if let Some(parent) = link_path.parent() {
955+
fs::create_dir_all(parent)
956+
.await
957+
.map_err(|e| ExtractError::CreateDirFailed(e, parent.to_path_buf()))?;
958+
}
959+
960+
// Use the target as-is (may be relative or absolute)
961+
let target = link.target.to_path_buf();
948962

949-
tokio::fs::symlink(&source, &destination)
963+
tokio::fs::symlink(&target, &link_path)
950964
.await
951-
.map_err(|e| ExtractError::CreateLinkFailed(e, source, destination))
965+
.map_err(|e| ExtractError::CreateLinkFailed(e, link_path, target))
952966
}
953967
#[cfg(windows)]
954968
Record::Link(link) => {
955-
let link_target = self
956-
.resolve_link(link)
957-
.map_err(|e| ExtractError::ResolveLinkFailed(e, link.clone().into_owned()))?;
969+
let link_path = output_path.join(path.to_path_buf());
970+
971+
// Create parent directory if needed
972+
if let Some(parent) = link_path.parent() {
973+
fs::create_dir_all(parent)
974+
.await
975+
.map_err(|e| ExtractError::CreateDirFailed(e, parent.to_path_buf()))?;
976+
}
958977

959-
let source = output_path.join(path.to_path_buf());
960-
let destination = output_path.join(link_target.path.to_path_buf());
978+
// Use the target as-is
979+
let target = link.target.to_path_buf();
961980

962-
if link_target.record.as_directory().is_some() {
963-
tokio::fs::symlink_dir(&source, &destination)
981+
// On Windows, we need to know if it's a dir or file symlink
982+
// Try to resolve to check, but fall back to file symlink
983+
let is_dir = self
984+
.resolve_link(link)
985+
.map(|r| r.record.as_directory().is_some())
986+
.unwrap_or(false);
987+
988+
if is_dir {
989+
tokio::fs::symlink_dir(&target, &link_path)
964990
.await
965-
.map_err(|e| ExtractError::CreateLinkFailed(e, source, destination))
991+
.map_err(|e| ExtractError::CreateLinkFailed(e, link_path, target))
966992
} else {
967-
tokio::fs::symlink_file(&source, &destination)
993+
tokio::fs::symlink_file(&target, &link_path)
968994
.await
969-
.map_err(|e| ExtractError::CreateLinkFailed(e, source, destination))
995+
.map_err(|e| ExtractError::CreateLinkFailed(e, link_path, target))
970996
}
971997
}
972998
}
@@ -1041,36 +1067,52 @@ impl BoxFileReader {
10411067
}
10421068
#[cfg(unix)]
10431069
Record::Link(link) => {
1044-
let link_target = self
1045-
.resolve_link(link)
1046-
.map_err(|e| ExtractError::ResolveLinkFailed(e, link.clone().into_owned()))?;
1070+
let link_path = output_path.join(path.to_path_buf());
1071+
1072+
// Create parent directory if needed
1073+
if let Some(parent) = link_path.parent() {
1074+
fs::create_dir_all(parent)
1075+
.await
1076+
.map_err(|e| ExtractError::CreateDirFailed(e, parent.to_path_buf()))?;
1077+
}
10471078

1048-
let source = output_path.join(path.to_path_buf());
1049-
let destination = output_path.join(link_target.path.to_path_buf());
1079+
// Use the target as-is (may be relative or absolute)
1080+
let target = link.target.to_path_buf();
10501081

1051-
tokio::fs::symlink(&source, &destination)
1082+
tokio::fs::symlink(&target, &link_path)
10521083
.await
1053-
.map_err(|e| ExtractError::CreateLinkFailed(e, source, destination))?;
1084+
.map_err(|e| ExtractError::CreateLinkFailed(e, link_path, target))?;
10541085
stats.links_created += 1;
10551086
Ok(())
10561087
}
10571088
#[cfg(windows)]
10581089
Record::Link(link) => {
1059-
let link_target = self
1060-
.resolve_link(link)
1061-
.map_err(|e| ExtractError::ResolveLinkFailed(e, link.clone().into_owned()))?;
1090+
let link_path = output_path.join(path.to_path_buf());
1091+
1092+
// Create parent directory if needed
1093+
if let Some(parent) = link_path.parent() {
1094+
fs::create_dir_all(parent)
1095+
.await
1096+
.map_err(|e| ExtractError::CreateDirFailed(e, parent.to_path_buf()))?;
1097+
}
1098+
1099+
// Use the target as-is
1100+
let target = link.target.to_path_buf();
10621101

1063-
let source = output_path.join(path.to_path_buf());
1064-
let destination = output_path.join(link_target.path.to_path_buf());
1102+
// On Windows, we need to know if it's a dir or file symlink
1103+
let is_dir = self
1104+
.resolve_link(link)
1105+
.map(|r| r.record.as_directory().is_some())
1106+
.unwrap_or(false);
10651107

1066-
if link_target.record.as_directory().is_some() {
1067-
tokio::fs::symlink_dir(&source, &destination)
1108+
if is_dir {
1109+
tokio::fs::symlink_dir(&target, &link_path)
10681110
.await
1069-
.map_err(|e| ExtractError::CreateLinkFailed(e, source, destination))?;
1111+
.map_err(|e| ExtractError::CreateLinkFailed(e, link_path, target))?;
10701112
} else {
1071-
tokio::fs::symlink_file(&source, &destination)
1113+
tokio::fs::symlink_file(&target, &link_path)
10721114
.await
1073-
.map_err(|e| ExtractError::CreateLinkFailed(e, source, destination))?;
1115+
.map_err(|e| ExtractError::CreateLinkFailed(e, link_path, target))?;
10741116
}
10751117
stats.links_created += 1;
10761118
Ok(())

0 commit comments

Comments
 (0)