finished 64 bit file offset support. Hopefully rsync can now transfer
[rsync.git] / exclude.c
1 /* 
2    Copyright (C) Andrew Tridgell 1996
3    Copyright (C) Paul Mackerras 1996
4    
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.
9    
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.
14    
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.
18 */
19
20 /*
21   a lot of this stuff was derived from GNU tar
22   */
23
24 #include "rsync.h"
25
26 extern int verbose;
27
28 static char **exclude_list;
29
30 static int is_regex(char *str)
31 {
32   return strchr(str, '*') || strchr(str, '[') || strchr(str, '?');
33 }
34
35
36 static int check_one_exclude(char *name,char *pattern)
37 {
38   char *p;
39
40   if (!strchr(pattern,'/') && (p=strrchr(name,'/')))
41     name = p+1;
42
43   if (!name[0]) return 0;
44
45   if (is_regex(pattern)) {
46     if (fnmatch(pattern, name, 0) == 0)
47       return 1;
48   } else {
49     int l1 = strlen(name);
50     int l2 = strlen(pattern);
51     if (l2 <= l1 && 
52         strcmp(name+(l1-l2),pattern) == 0 &&
53         (l1==l2 || name[l1-(l2+1)] == '/'))
54       return 1;
55   }
56
57   return 0;
58 }
59
60
61 int check_exclude(char *name,char **local_exclude_list)
62 {
63   int n;
64
65   if (exclude_list) {
66     for (n=0; exclude_list[n]; n++)
67       if (check_one_exclude(name,exclude_list[n]))
68         return 1;
69   }
70
71   if (local_exclude_list) {
72     for (n=0; local_exclude_list[n]; n++)
73       if (check_one_exclude(name,local_exclude_list[n]))
74         return 1;      
75   }
76
77   return 0;
78 }
79
80
81 void add_exclude_list(char *pattern,char ***list)
82 {
83   int len=0;
84   if (list && *list)
85     for (; (*list)[len]; len++) ;
86
87   if (strcmp(pattern,"!") == 0) {
88     if (verbose > 2)
89       fprintf(FERROR,"clearing exclude list\n");
90     while ((len)--) 
91       free((*list)[len]);
92     free((*list));
93     *list = NULL;
94     return;
95   }
96
97   if (!*list) {
98     *list = (char **)malloc(sizeof(char *)*2);
99   } else {
100     *list = (char **)realloc(*list,sizeof(char *)*(len+2));
101   }
102
103   if (!*list || !((*list)[len] = strdup(pattern)))
104     out_of_memory("add_exclude");
105
106   if (verbose > 2)
107     fprintf(FERROR,"add_exclude(%s)\n",pattern);
108   
109   (*list)[len+1] = NULL;
110 }
111
112 void add_exclude(char *pattern)
113 {
114   add_exclude_list(pattern,&exclude_list);
115 }
116
117 char **make_exclude_list(char *fname,char **list1,int fatal)
118 {
119   char **list=list1;
120   FILE *f = fopen(fname,"r");
121   char line[MAXPATHLEN];
122   if (!f) {
123     if (fatal) {
124       fprintf(FERROR,"%s : %s\n",fname,strerror(errno));
125       exit_cleanup(1);
126     }
127     return list;
128   }
129
130   while (fgets(line,MAXPATHLEN,f)) {
131     int l = strlen(line);
132     if (l && line[l-1] == '\n') l--;
133     line[l] = 0;
134     if (line[0]) add_exclude_list(line,&list);
135   }
136   fclose(f);
137   return list;
138 }
139
140
141 void add_exclude_file(char *fname,int fatal)
142 {
143   exclude_list = make_exclude_list(fname,exclude_list,fatal);
144 }
145
146
147 void send_exclude_list(int f)
148 {
149   int i;
150   if (exclude_list) 
151     for (i=0;exclude_list[i];i++) {
152       int l = strlen(exclude_list[i]);
153       if (l == 0) continue;
154       write_int(f,l);
155       write_buf(f,exclude_list[i],l);
156     }    
157   write_int(f,0);
158 }
159
160
161 void recv_exclude_list(int f)
162 {
163   char line[MAXPATHLEN];
164   int l;
165   while ((l=read_int(f))) {
166     read_buf(f,line,l);
167     line[l] = 0;
168     add_exclude(line);
169   }
170 }
171
172
173 static char *cvs_ignore_list[] = {
174   "RCS","SCCS","CVS","CVS.adm","RCSLOG","cvslog.*",
175   "tags","TAGS",".make.state",".nse_depinfo",
176   "*~", "#*", ".#*", ",*", "*.old", "*.bak", "*.BAK", "*.orig",
177   "*.rej", ".del-*", "*.a", "*.o", "*.obj", "*.so", "*.Z", "*.elc", "*.ln",
178   "core",NULL};
179
180
181
182 void add_cvs_excludes(void)
183 {
184   char fname[MAXPATHLEN];
185   char *p;
186   int i;
187   
188   for (i=0; cvs_ignore_list[i]; i++)
189     add_exclude(cvs_ignore_list[i]);
190
191   if ((p=getenv("HOME")) && strlen(p) < (MAXPATHLEN-12)) {
192     sprintf(fname,"%s/.cvsignore",p);
193     add_exclude_file(fname,0);
194   }
195
196   if ((p=getenv("CVSIGNORE"))) {
197     char *tok;
198     for (tok=strtok(p," "); tok; tok=strtok(NULL," "))
199       add_exclude(tok);
200   }
201 }