@@ -557,8 +557,7 @@ int add_excludes_from_file_to_list(const char *fname,
557557 buf = xrealloc (buf , size + 1 );
558558 buf [size ++ ] = '\n' ;
559559 }
560- }
561- else {
560+ } else {
562561 size = xsize_t (st .st_size );
563562 if (size == 0 ) {
564563 close (fd );
@@ -793,17 +792,19 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
793792
794793 group = & dir -> exclude_list_group [EXC_DIRS ];
795794
796- /* Pop the exclude lists from the EXCL_DIRS exclude_list_group
795+ /*
796+ * Pop the exclude lists from the EXCL_DIRS exclude_list_group
797797 * which originate from directories not in the prefix of the
798- * path being checked. */
798+ * path being checked.
799+ */
799800 while ((stk = dir -> exclude_stack ) != NULL ) {
800801 if (stk -> baselen <= baselen &&
801- !strncmp (dir -> basebuf , base , stk -> baselen ))
802+ !strncmp (dir -> basebuf . buf , base , stk -> baselen ))
802803 break ;
803804 el = & group -> el [dir -> exclude_stack -> exclude_ix ];
804805 dir -> exclude_stack = stk -> prev ;
805806 dir -> exclude = NULL ;
806- free ((char * )el -> src ); /* see strdup () below */
807+ free ((char * )el -> src ); /* see strbuf_detach () below */
807808 clear_exclude_list (el );
808809 free (stk );
809810 group -> nr -- ;
@@ -813,17 +814,25 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
813814 if (dir -> exclude )
814815 return ;
815816
817+ /*
818+ * Lazy initialization. All call sites currently just
819+ * memset(dir, 0, sizeof(*dir)) before use. Changing all of
820+ * them seems lots of work for little benefit.
821+ */
822+ if (!dir -> basebuf .buf )
823+ strbuf_init (& dir -> basebuf , PATH_MAX );
824+
816825 /* Read from the parent directories and push them down. */
817826 current = stk ? stk -> baselen : -1 ;
827+ strbuf_setlen (& dir -> basebuf , current < 0 ? 0 : current );
818828 while (current < baselen ) {
819829 struct exclude_stack * stk = xcalloc (1 , sizeof (* stk ));
820830 const char * cp ;
821831
822832 if (current < 0 ) {
823833 cp = base ;
824834 current = 0 ;
825- }
826- else {
835+ } else {
827836 cp = strchr (base + current + 1 , '/' );
828837 if (!cp )
829838 die ("oops in prep_exclude" );
@@ -833,48 +842,47 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
833842 stk -> baselen = cp - base ;
834843 stk -> exclude_ix = group -> nr ;
835844 el = add_exclude_list (dir , EXC_DIRS , NULL );
836- memcpy ( dir -> basebuf + current , base + current ,
837- stk -> baselen - current );
845+ strbuf_add ( & dir -> basebuf , base + current , stk -> baselen - current );
846+ assert ( stk -> baselen == dir -> basebuf . len );
838847
839848 /* Abort if the directory is excluded */
840849 if (stk -> baselen ) {
841850 int dt = DT_DIR ;
842- dir -> basebuf [stk -> baselen - 1 ] = 0 ;
851+ dir -> basebuf . buf [stk -> baselen - 1 ] = 0 ;
843852 dir -> exclude = last_exclude_matching_from_lists (dir ,
844- dir -> basebuf , stk -> baselen - 1 ,
845- dir -> basebuf + current , & dt );
846- dir -> basebuf [stk -> baselen - 1 ] = '/' ;
853+ dir -> basebuf . buf , stk -> baselen - 1 ,
854+ dir -> basebuf . buf + current , & dt );
855+ dir -> basebuf . buf [stk -> baselen - 1 ] = '/' ;
847856 if (dir -> exclude &&
848857 dir -> exclude -> flags & EXC_FLAG_NEGATIVE )
849858 dir -> exclude = NULL ;
850859 if (dir -> exclude ) {
851- dir -> basebuf [stk -> baselen ] = 0 ;
852860 dir -> exclude_stack = stk ;
853861 return ;
854862 }
855863 }
856864
857- /* Try to read per-directory file unless path is too long */
858- if (dir -> exclude_per_dir &&
859- stk -> baselen + strlen (dir -> exclude_per_dir ) < PATH_MAX ) {
860- strcpy (dir -> basebuf + stk -> baselen ,
861- dir -> exclude_per_dir );
865+ /* Try to read per-directory file */
866+ if (dir -> exclude_per_dir ) {
862867 /*
863868 * dir->basebuf gets reused by the traversal, but we
864869 * need fname to remain unchanged to ensure the src
865870 * member of each struct exclude correctly
866871 * back-references its source file. Other invocations
867872 * of add_exclude_list provide stable strings, so we
868- * strdup () and free() here in the caller.
873+ * strbuf_detach () and free() here in the caller.
869874 */
870- el -> src = strdup (dir -> basebuf );
871- add_excludes_from_file_to_list (dir -> basebuf ,
872- dir -> basebuf , stk -> baselen , el , 1 );
875+ struct strbuf sb = STRBUF_INIT ;
876+ strbuf_addbuf (& sb , & dir -> basebuf );
877+ strbuf_addstr (& sb , dir -> exclude_per_dir );
878+ el -> src = strbuf_detach (& sb , NULL );
879+ add_excludes_from_file_to_list (el -> src , el -> src ,
880+ stk -> baselen , el , 1 );
873881 }
874882 dir -> exclude_stack = stk ;
875883 current = stk -> baselen ;
876884 }
877- dir -> basebuf [ baselen ] = '\0' ;
885+ strbuf_setlen ( & dir -> basebuf , baselen ) ;
878886}
879887
880888/*
@@ -1671,4 +1679,5 @@ void clear_directory(struct dir_struct *dir)
16711679 free (stk );
16721680 stk = prev ;
16731681 }
1682+ strbuf_release (& dir -> basebuf );
16741683}
0 commit comments