2 Copyright (C) Andrew Tridgell 1996
3 Copyright (C) Paul Mackerras 1996
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /* a lot of this stuff was originally derived from GNU tar, although
21 it has now changed so much that it is hard to tell :) */
26 extern int delete_mode
;
28 static struct exclude_struct
**exclude_list
;
31 * Optimization for special case when all included files are explicitly
32 * listed without wildcards in the "exclude" list followed by a "- *"
33 * to exclude the rest.
34 * Contributed by Dave Dykstra <dwd@bell-labs.com>
36 static int only_included_files
= 1;
37 static struct exclude_struct
*exclude_the_rest
;
39 int send_included_file_names(int f
,struct file_list
*flist
)
41 struct exclude_struct
*ex
, **ex_list
;
45 if (!only_included_files
|| (exclude_the_rest
== NULL
) || delete_mode
)
49 rprintf(FINFO
,"(using include-only optimization) ");
52 /* set exclude_list to NULL temporarily so check_exclude */
53 /* will always return true */
54 ex_list
= exclude_list
;
56 for (n
=0; (ex
= ex_list
[n
]) != NULL
; n
++) {
57 if (ex
== exclude_the_rest
)
61 /* skip the allowed beginning slashes */
64 /* silently skip files that don't exist to
65 be more like non-optimized case */
67 send_file_name(f
,flist
,p
,0,0);
69 exclude_list
= ex_list
;
74 /* build an exclude structure given a exclude pattern */
75 static struct exclude_struct
*make_exclude(char *pattern
, int include
)
77 struct exclude_struct
*ret
;
79 ret
= (struct exclude_struct
*)malloc(sizeof(*ret
));
80 if (!ret
) out_of_memory("make_exclude");
82 memset(ret
, 0, sizeof(*ret
));
84 if (strncmp(pattern
,"- ",2) == 0) {
86 } else if (strncmp(pattern
,"+ ",2) == 0) {
90 ret
->include
= include
;
93 ret
->pattern
= strdup(pattern
);
95 if (!ret
->pattern
) out_of_memory("make_exclude");
97 if (strpbrk(pattern
, "*[?")) {
98 if (!ret
->include
&& (*pattern
== '*') && (*(pattern
+1) == '\0')) {
99 exclude_the_rest
= ret
;
101 only_included_files
= 0;
103 ret
->regular_exp
= 1;
104 ret
->fnmatch_flags
= strstr(pattern
, "**") ? 0 : FNM_PATHNAME
;
105 } else if (!ret
->include
) {
106 only_included_files
= 0;
109 if (strlen(pattern
) > 1 && pattern
[strlen(pattern
)-1] == '/') {
110 ret
->pattern
[strlen(pattern
)-1] = 0;
114 if (!strchr(ret
->pattern
,'/')) {
121 static void free_exclude(struct exclude_struct
*ex
)
124 memset(ex
,0,sizeof(*ex
));
128 static int check_one_exclude(char *name
,struct exclude_struct
*ex
,
133 char *pattern
= ex
->pattern
;
135 if (ex
->local
&& (p
=strrchr(name
,'/')))
138 if (!name
[0]) return 0;
140 if (ex
->directory
&& !S_ISDIR(st
->st_mode
)) return 0;
142 if (*pattern
== '/' && *name
!= '/') {
147 if (ex
->regular_exp
) {
148 if (fnmatch(pattern
, name
, ex
->fnmatch_flags
) == 0)
151 int l1
= strlen(name
);
152 int l2
= strlen(pattern
);
154 strcmp(name
+(l1
-l2
),pattern
) == 0 &&
155 (l1
==l2
|| (!match_start
&& name
[l1
-(l2
+1)] == '/')))
163 int check_exclude(char *name
,struct exclude_struct
**local_exclude_list
,
168 if (name
&& (name
[0] == '.') && !name
[1])
169 /* never exclude '.', even if somebody does --exclude '*' */
173 for (n
=0; exclude_list
[n
]; n
++)
174 if (check_one_exclude(name
,exclude_list
[n
],st
))
175 return !exclude_list
[n
]->include
;
178 if (local_exclude_list
) {
179 for (n
=0; local_exclude_list
[n
]; n
++)
180 if (check_one_exclude(name
,local_exclude_list
[n
],st
))
181 return !local_exclude_list
[n
]->include
;
188 void add_exclude_list(char *pattern
,struct exclude_struct
***list
, int include
)
192 for (; (*list
)[len
]; len
++) ;
194 if (strcmp(pattern
,"!") == 0) {
196 rprintf(FINFO
,"clearing exclude list\n");
198 free_exclude((*list
)[len
]);
202 only_included_files
= 1;
203 exclude_the_rest
= NULL
;
207 *list
= (struct exclude_struct
**)Realloc(*list
,sizeof(struct exclude_struct
*)*(len
+2));
209 if (!*list
|| !((*list
)[len
] = make_exclude(pattern
, include
)))
210 out_of_memory("add_exclude");
213 rprintf(FINFO
,"add_exclude(%s)\n",pattern
);
215 (*list
)[len
+1] = NULL
;
218 void add_exclude(char *pattern
, int include
)
220 add_exclude_list(pattern
,&exclude_list
, include
);
223 struct exclude_struct
**make_exclude_list(char *fname
,
224 struct exclude_struct
**list1
,
225 int fatal
, int include
)
227 struct exclude_struct
**list
=list1
;
228 FILE *f
= fopen(fname
,"r");
229 char line
[MAXPATHLEN
];
232 rprintf(FERROR
,"%s : %s\n",fname
,strerror(errno
));
233 exit_cleanup(RERR_FILEIO
);
238 while (fgets(line
,MAXPATHLEN
,f
)) {
239 int l
= strlen(line
);
240 if (l
&& line
[l
-1] == '\n') l
--;
242 if (line
[0] && (line
[0] != ';') && (line
[0] != '#')) {
243 /* Skip lines starting with semicolon or pound.
244 It probably wouldn't cause any harm to not skip
245 them but there's no need to save them. */
246 add_exclude_list(line
,&list
,include
);
254 void add_exclude_file(char *fname
,int fatal
,int include
)
256 if (!fname
|| !*fname
) return;
258 exclude_list
= make_exclude_list(fname
,exclude_list
,fatal
,include
);
262 void send_exclude_list(int f
)
265 extern int remote_version
;
272 for (i
=0;exclude_list
[i
];i
++) {
274 char pattern
[MAXPATHLEN
];
276 strlcpy(pattern
,exclude_list
[i
]->pattern
,sizeof(pattern
));
277 if (exclude_list
[i
]->directory
) strlcat(pattern
,"/", sizeof(pattern
));
280 if (l
== 0) continue;
281 if (exclude_list
[i
]->include
) {
282 if (remote_version
< 19) {
283 rprintf(FERROR
,"remote rsync does not support include syntax - aborting\n");
284 exit_cleanup(RERR_UNSUPPORTED
);
291 write_buf(f
,pattern
,l
);
298 void recv_exclude_list(int f
)
300 char line
[MAXPATHLEN
];
302 while ((l
=read_int(f
))) {
303 if (l
>= MAXPATHLEN
) overflow("recv_exclude_list");
309 /* Get the next include/exclude arg from the string. It works in a similar way
310 ** to strtok - initially an arg is sent over, from then on NULL. This
311 ** routine takes into account any +/- in the strings and does not
312 ** consider the space following it as a delimeter.
314 char *get_exclude_tok(char *p
)
329 /* Skip over any initial spaces */
333 /* Are we at the end of the string? */
335 /* remember the beginning of the token */
338 /* Is this a '+' or '-' followed by a space (not whitespace)? */
339 if ((*s
=='+' || *s
=='-') && *(s
+1)==' ')
342 /* Skip to the next space or the end of the string */
343 while(!isspace(*s
) && *s
!='\0')
349 /* Have we reached the end of the string? */
358 void add_exclude_line(char *p
)
361 if (!p
|| !*p
) return;
363 if (!p
) out_of_memory("add_exclude_line");
364 for (tok
=get_exclude_tok(p
); tok
; tok
=get_exclude_tok(NULL
))
369 void add_include_line(char *p
)
372 if (!p
|| !*p
) return;
374 if (!p
) out_of_memory("add_include_line");
375 for (tok
=get_exclude_tok(p
); tok
; tok
=get_exclude_tok(NULL
))
381 static char *cvs_ignore_list
[] = {
382 "RCS","SCCS","CVS","CVS.adm","RCSLOG","cvslog.*",
383 "tags","TAGS",".make.state",".nse_depinfo",
384 "*~", "#*", ".#*", ",*", "*.old", "*.bak", "*.BAK", "*.orig",
385 "*.rej", ".del-*", "*.a", "*.o", "*.obj", "*.so", "*.Z", "*.elc", "*.ln",
390 void add_cvs_excludes(void)
392 char fname
[MAXPATHLEN
];
396 for (i
=0; cvs_ignore_list
[i
]; i
++)
397 add_exclude(cvs_ignore_list
[i
], 0);
399 if ((p
=getenv("HOME")) && strlen(p
) < (MAXPATHLEN
-12)) {
400 slprintf(fname
,sizeof(fname
), "%s/.cvsignore",p
);
401 add_exclude_file(fname
,0,0);
404 add_exclude_line(getenv("CVSIGNORE"));