@@ -79,14 +79,54 @@ fn push_pattern<P: AsRef<Path>, F: Fn(&str) -> Result<Pattern, glob::PatternErro
79
79
) -> crate :: Result < ( ) > {
80
80
let path: PathBuf = pattern. as_ref ( ) . components ( ) . collect ( ) ;
81
81
list. insert ( f ( & path. to_string_lossy ( ) ) ?) ;
82
- #[ cfg( windows) ]
83
- {
84
- if let Ok ( p) = std:: fs:: canonicalize ( & path) {
85
- list. insert ( f ( & p. to_string_lossy ( ) ) ?) ;
82
+
83
+ let mut path = path;
84
+ let mut checked_path = None ;
85
+
86
+ // attempt to canonicalize parents in case we have a path like `/data/user/0/appid/**`
87
+ // where `**` obviously does not exist but we need to canonicalize the parent
88
+ //
89
+ // example: given the `/data/user/0/appid/assets/*` path,
90
+ // it's a glob pattern so it won't exist (canonicalize() fails);
91
+ //
92
+ // the second iteration needs to check `/data/user/0/appid/assets` and save the `*` component to append later.
93
+ //
94
+ // if it also does not exist, a third iteration is required to check `/data/user/0/appid`
95
+ // with `assets/*` as the cached value (`checked_path` variable)
96
+ // on Android that gets canonicalized to `/data/data/appid` so the final value will be `/data/data/appid/assets/*`
97
+ // which is the value we want to check when we execute the `is_allowed` function
98
+ let canonicalized = loop {
99
+ if let Ok ( path) = path. canonicalize ( ) {
100
+ break Some ( if let Some ( p) = checked_path {
101
+ path. join ( p)
102
+ } else {
103
+ path
104
+ } ) ;
105
+ }
106
+
107
+ // get the last component of the path as an OsStr
108
+ let last = path. iter ( ) . next_back ( ) . map ( PathBuf :: from) ;
109
+ if let Some ( mut p) = last {
110
+ // remove the last component of the path
111
+ // so the next iteration checks its parent
112
+ path. pop ( ) ;
113
+ // append the already checked path to the last component
114
+ if let Some ( checked_path) = & checked_path {
115
+ p. push ( checked_path) ;
116
+ }
117
+ // replace the checked path with the current value
118
+ checked_path. replace ( p) ;
86
119
} else {
87
- list . insert ( f ( & format ! ( " \\ \\ ? \\ {}" , path . display ( ) ) ) ? ) ;
120
+ break None ;
88
121
}
122
+ } ;
123
+
124
+ if let Some ( p) = canonicalized {
125
+ list. insert ( f ( & p. to_string_lossy ( ) ) ?) ;
126
+ } else if cfg ! ( windows) {
127
+ list. insert ( f ( & format ! ( "\\ \\ ?\\ {}" , path. display( ) ) ) ?) ;
89
128
}
129
+
90
130
Ok ( ( ) )
91
131
}
92
132
0 commit comments