@@ -10,27 +10,27 @@ pub mod path_splitting {
10
10
11
11
/// Errors encountered during path splitting.
12
12
#[ derive( Debug , Display , Error ) ]
13
- pub enum PathSplitError {
14
- /// entry path format error : {0:?}
15
- PathFormat ( String ) ,
16
- /// duplicate path used for file and directory : {0:?}
17
- DuplicateFileDirPath ( String ) ,
13
+ pub enum PathSplitError < ' a > {
14
+ /// entry path {0:?} would escape extraction dir : {0:?}
15
+ ExtractionPathEscapesDirectory ( & ' a str , & ' static str ) ,
16
+ /// duplicate entry path {0:?} used : {0:?}
17
+ DuplicatePath ( & ' a str , & ' static str ) ,
18
18
}
19
19
20
20
/* NB: path_to_string() performs some of this logic, but is intended to coerce filesystems
21
21
* paths into zip entry names, whereas we are processing entry names from a zip archive, so we
22
22
* perform much less error handling. */
23
23
pub ( crate ) fn normalize_parent_dirs < ' a > (
24
24
entry_path : & ' a str ,
25
- ) -> Result < ( Vec < & ' a str > , bool ) , PathSplitError > {
25
+ ) -> Result < ( Vec < & ' a str > , bool ) , PathSplitError < ' a > > {
26
26
/* The ZIP spec states (APPNOTE 4.4.17) that file paths are in Unix format, and Unix
27
27
* filesystems treat a backslash as a normal character. Thus they should be allowed on Unix
28
28
* and replaced with \u{fffd} on Windows. */
29
29
if entry_path. starts_with ( '/' ) {
30
- return Err ( PathSplitError :: PathFormat ( format ! (
31
- "path {:?} began with '/' and is absolute" ,
32
- entry_path
33
- ) ) ) ;
30
+ return Err ( PathSplitError :: ExtractionPathEscapesDirectory (
31
+ entry_path ,
32
+ "path began with '/' and is absolute" ,
33
+ ) ) ;
34
34
}
35
35
let is_dir = is_dir ( entry_path) ;
36
36
@@ -45,10 +45,10 @@ pub mod path_splitting {
45
45
/* If ".." is present, pop off the last element or return an error. */
46
46
".." => {
47
47
if ret. pop ( ) . is_none ( ) {
48
- return Err ( PathSplitError :: PathFormat ( format ! (
49
- "path {:?} has too many '..' components and would escape the containing dir" ,
50
- entry_path
51
- ) ) ) ;
48
+ return Err ( PathSplitError :: ExtractionPathEscapesDirectory (
49
+ entry_path ,
50
+ "path has too many '..' components and would escape the containing dir" ,
51
+ ) ) ;
52
52
}
53
53
}
54
54
_ => {
@@ -57,10 +57,10 @@ pub mod path_splitting {
57
57
}
58
58
}
59
59
if ret. is_empty ( ) {
60
- return Err ( PathSplitError :: PathFormat ( format ! (
61
- "path {:?} resolves to the top-level directory" ,
62
- entry_path
63
- ) ) ) ;
60
+ return Err ( PathSplitError :: ExtractionPathEscapesDirectory (
61
+ entry_path ,
62
+ "path resolves to the top-level directory" ,
63
+ ) ) ;
64
64
}
65
65
66
66
Ok ( ( ret, is_dir) )
@@ -113,7 +113,7 @@ pub mod path_splitting {
113
113
* any other data for the top-level extraction directory. */
114
114
pub ( crate ) fn lexicographic_entry_trie < ' a , Data > (
115
115
all_entries : impl IntoIterator < Item = ( & ' a str , Data ) > ,
116
- ) -> Result < BTreeMap < & ' a str , Box < FSEntry < ' a , Data > > > , PathSplitError >
116
+ ) -> Result < BTreeMap < & ' a str , Box < FSEntry < ' a , Data > > > , PathSplitError < ' a > >
117
117
where
118
118
Data : DirByMode ,
119
119
{
@@ -139,10 +139,10 @@ pub mod path_splitting {
139
139
. or_insert_with ( || Box :: new ( FSEntry :: Dir ( DirEntry :: default ( ) ) ) ) ;
140
140
cur_dir = match next_subdir. as_mut ( ) {
141
141
FSEntry :: File ( _) => {
142
- return Err ( PathSplitError :: DuplicateFileDirPath ( format ! (
143
- "a file was already registered at the same path as the dir entry {:?}" ,
144
- entry_path
145
- ) ) ) ;
142
+ return Err ( PathSplitError :: DuplicatePath (
143
+ entry_path ,
144
+ "a file was already registered at the same path as this dir entry" ,
145
+ ) ) ;
146
146
}
147
147
FSEntry :: Dir ( ref mut subdir) => subdir,
148
148
}
@@ -152,10 +152,10 @@ pub mod path_splitting {
152
152
/* We can't handle duplicate file paths, as that might mess up our
153
153
* parallelization strategy. */
154
154
if cur_dir. children . contains_key ( filename) {
155
- return Err ( PathSplitError :: DuplicateFileDirPath ( format ! (
156
- "another file or directory was already registered at the same path as the file entry {:?}" ,
157
- entry_path
158
- ) ) ) ;
155
+ return Err ( PathSplitError :: DuplicatePath (
156
+ entry_path ,
157
+ "an entry was already registered at the same path as this file entry" ,
158
+ ) ) ;
159
159
}
160
160
cur_dir
161
161
. children
@@ -166,10 +166,10 @@ pub mod path_splitting {
166
166
* path, as it's not clear how to merge the possibility of two separate file
167
167
* permissions. */
168
168
if cur_dir. properties . replace ( data) . is_some ( ) {
169
- return Err ( PathSplitError :: DuplicateFileDirPath ( format ! (
170
- "another directory was already registered at the path {:?}" ,
171
- entry_path
172
- ) ) ) ;
169
+ return Err ( PathSplitError :: DuplicatePath (
170
+ entry_path ,
171
+ "another directory was already registered at this path" ,
172
+ ) ) ;
173
173
}
174
174
}
175
175
}
@@ -640,11 +640,18 @@ pub mod split_extraction {
640
640
/// zip error: {0}
641
641
Zip ( #[ from] ZipError ) ,
642
642
/// path split error: {0}
643
- PathSplit ( # [ from ] PathSplitError ) ,
643
+ PathSplit ( String ) ,
644
644
/// handle creation error: {0}
645
645
HandleCreation ( #[ from] HandleCreationError ) ,
646
646
}
647
647
648
+ impl < ' a > From < PathSplitError < ' a > > for SplitExtractionError {
649
+ fn from ( e : PathSplitError < ' a > ) -> Self {
650
+ let msg = format ! ( "{}" , e) ;
651
+ Self :: PathSplit ( msg)
652
+ }
653
+ }
654
+
648
655
/* TODO: make this share code with find_data_start()! */
649
656
fn get_or_find_data_start < InF > ( data : & ZipFileData , input_file : InF ) -> Result < u64 , ZipError >
650
657
where
0 commit comments