@@ -79,14 +79,54 @@ fn push_pattern<P: AsRef<Path>, F: Fn(&str) -> Result<Pattern, glob::PatternErro
7979) -> crate :: Result < ( ) > {
8080 let path: PathBuf = pattern. as_ref ( ) . components ( ) . collect ( ) ;
8181 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) ;
86119 } else {
87- list . insert ( f ( & format ! ( " \\ \\ ? \\ {}" , path . display ( ) ) ) ? ) ;
120+ break None ;
88121 }
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( ) ) ) ?) ;
89128 }
129+
90130 Ok ( ( ) )
91131}
92132
0 commit comments