@@ -522,6 +522,53 @@ static int match_basename(const char *basename, int basenamelen,
522522 return 0 ;
523523}
524524
525+ static int match_pathname (const char * pathname , int pathlen ,
526+ const char * base , int baselen ,
527+ const char * pattern , int prefix , int patternlen ,
528+ int flags )
529+ {
530+ const char * name ;
531+ int namelen ;
532+
533+ /*
534+ * match with FNM_PATHNAME; the pattern has base implicitly
535+ * in front of it.
536+ */
537+ if (* pattern == '/' ) {
538+ pattern ++ ;
539+ prefix -- ;
540+ }
541+
542+ /*
543+ * baselen does not count the trailing slash. base[] may or
544+ * may not end with a trailing slash though.
545+ */
546+ if (pathlen < baselen + 1 ||
547+ (baselen && pathname [baselen ] != '/' ) ||
548+ strncmp_icase (pathname , base , baselen ))
549+ return 0 ;
550+
551+ namelen = baselen ? pathlen - baselen - 1 : pathlen ;
552+ name = pathname + pathlen - namelen ;
553+
554+ if (prefix ) {
555+ /*
556+ * if the non-wildcard part is longer than the
557+ * remaining pathname, surely it cannot match.
558+ */
559+ if (prefix > namelen )
560+ return 0 ;
561+
562+ if (strncmp_icase (pattern , name , prefix ))
563+ return 0 ;
564+ pattern += prefix ;
565+ name += prefix ;
566+ namelen -= prefix ;
567+ }
568+
569+ return fnmatch_icase (pattern , name , FNM_PATHNAME ) == 0 ;
570+ }
571+
525572/* Scan the list and let the last match determine the fate.
526573 * Return 1 for exclude, 0 for include and -1 for undecided.
527574 */
@@ -536,9 +583,9 @@ int excluded_from_list(const char *pathname,
536583
537584 for (i = el -> nr - 1 ; 0 <= i ; i -- ) {
538585 struct exclude * x = el -> excludes [i ];
539- const char * name , * exclude = x -> pattern ;
586+ const char * exclude = x -> pattern ;
540587 int to_exclude = x -> to_exclude ;
541- int namelen , prefix = x -> nowildcardlen ;
588+ int prefix = x -> nowildcardlen ;
542589
543590 if (x -> flags & EXC_FLAG_MUSTBEDIR ) {
544591 if (* dtype == DT_UNKNOWN )
@@ -556,36 +603,10 @@ int excluded_from_list(const char *pathname,
556603 continue ;
557604 }
558605
559- /* match with FNM_PATHNAME:
560- * exclude has base (baselen long) implicitly in front of it.
561- */
562- if (* exclude == '/' ) {
563- exclude ++ ;
564- prefix -- ;
565- }
566-
567- if (pathlen < x -> baselen ||
568- (x -> baselen && pathname [x -> baselen - 1 ] != '/' ) ||
569- strncmp_icase (pathname , x -> base , x -> baselen ))
570- continue ;
571-
572- namelen = x -> baselen ? pathlen - x -> baselen : pathlen ;
573- name = pathname + pathlen - namelen ;
574-
575- /* if the non-wildcard part is longer than the
576- remaining pathname, surely it cannot match */
577- if (prefix > namelen )
578- continue ;
579-
580- if (prefix ) {
581- if (strncmp_icase (exclude , name , prefix ))
582- continue ;
583- exclude += prefix ;
584- name += prefix ;
585- namelen -= prefix ;
586- }
587-
588- if (!fnmatch_icase (exclude , name , FNM_PATHNAME ))
606+ assert (x -> baselen == 0 || x -> base [x -> baselen - 1 ] == '/' );
607+ if (match_pathname (pathname , pathlen ,
608+ x -> base , x -> baselen ? x -> baselen - 1 : 0 ,
609+ exclude , prefix , x -> patternlen , x -> flags ))
589610 return to_exclude ;
590611 }
591612 return -1 ; /* undecided */
0 commit comments