1 #include <stdio.h>
2 #include <errno.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <sys/signal.h>
7 #include <sys/types.h>
8 #include <sys/ioctl.h>
9 #include <sys/stat.h>
10 #include <pwd.h>
11 #include <grp.h>
12 #include "patchlevel.h"
13
14 #ifdef HAVEFNMATCH
15
16 #include <fnmatch.h>
17
18 #else
19
20 /* A limited fnmatch replacement. Only accepts patterns
21 in the form "ccccc" or "ccccc*". (These were the patterns accepted
22 by older afio versions.)
23
24 */
25
fnmatch(const char * p,const char * s,int flag)26 int fnmatch(const char *p, const char *s, int flag)
27 {
28 if(p[strlen(p)-1]=='*')
29 return strncmp(p,s,strlen(p)-1);
30 else
31 return strcmp(p,s);
32 }
33
34 #endif
35
36 #ifdef linux
37 #include <utime.h>
38 #endif
39
40 #include "afio.h"
41
42 STATIC int ignoreslash=1;
43
44 /*
45 * Pathnames to (or not to) be processed.
46 */
47 typedef struct pattern
48 {
49 struct pattern *p_forw; /* Forward chain */
50 char *p_str; /* String */
51 int p_len; /* Length of string */
52 int p_ptype; /* Pattern type */
53 /* types are: PATTYPE_MATCH, _NOMATCH, _EXT. */
54 int p_noglob; /* influenced by used of -7 flag */
55 } Pattern;
56
57 STATIC Pattern *pattern; /* Pathname matching patterns */
58
59 /*
60 * nameadd()
61 *
62 * Add a name to the pattern list.
63 */
64 STATIC void
nameadd(name,ptype)65 nameadd (name, ptype)
66 reg char *name;
67 int ptype;
68 {
69 reg Pattern *px;
70
71 px = (Pattern *) memget (sizeof (Pattern));
72 px->p_forw = pattern;
73 px->p_str = strdup(name);
74 if(px->p_str==NULL) fatal(name,"out of memory.");
75 px->p_len = strlen (name);
76 px->p_ptype = ptype;
77 px->p_noglob = noglob;
78 pattern = px;
79
80 /* fprintf(stderr,"--%s added\n",name); */
81 }
82
83 /*
84 * nameaddfile()
85 *
86 * Add a file of patterns to the pattern list.
87 * Returns 0 on failure, 1 on success.
88 */
89
90 STATIC int
nameaddfile(fname,ptype,parsewith0)91 nameaddfile(fname,ptype,parsewith0)
92 char *fname;
93 int ptype;
94 int parsewith0;
95 {
96 FILE *infile;
97 char pat[PATHSIZE+1];
98 int c,i;
99
100 infile=fopen(fname,"r");
101 if(infile==0) return 0;
102
103 if(parsewith0)
104 {
105 i=0;
106 while((c = fgetc(infile))!=EOF)
107 {
108 if(i > sizeof(pat))
109 fatal(pat,"Path name too long");
110
111 pat[i]=c;
112
113 if(c == '\0')
114 {
115 if(i>0) nameadd(pat,ptype);
116 i=0;
117 continue;
118 }
119 i++;
120 }
121 /* handle case where the last entry in the file does not end in \0 */
122 if(i>0 && i<sizeof(pat))
123 {
124 pat[i]=0;
125 nameadd(pat,ptype);
126 }
127 }
128 else
129 {
130 while(fgets(pat,PATHSIZE,infile)!=NULL)
131 {
132 /* remove \n */
133 pat[strlen(pat)-1]='\0';
134
135 if(strlen(pat)==0) continue; /* skip empty lines in file */
136
137 if(pat[strlen(pat)-1]==' ')
138 {
139 warn(pat,"warning: trailing space in this pattern.");
140 }
141
142 nameadd(pat,ptype);
143 }
144 }
145
146 fclose(infile);
147 return 1;
148 }
149
150
151 /*
152 * namecmp()
153 *
154 * Compare a pathname with the pattern list. Returns 0 for
155 * a match, -1 otherwise.
156 *
157 * This new version uses the GCC library function fnmatch()
158 * to provide real pattern matching.
159 *
160 * Also, this implementation assures that if a file matches a pattern
161 * in the `not to process' list, it is never processed.
162 * In the old version, this depended on several implementation details
163 * and the names in the `to process' list.
164 *
165 * Control files always match.
166 */
167 STATIC int
namecmp(name,asb)168 namecmp (name, asb)
169 reg char *name;
170 Stat *asb;
171 {
172 reg Pattern *px;
173 int existpospat; /* there are `to process' patterns in the list */
174 char *namedot,*p,*n;
175 char namec[PATHSIZE];
176
177 /* fprintf(stderr,"name:\"%s\" rdev:%d\n",name,
178 asb->sb_rdev);
179 */
180
181 if(asb && ISCONTROL(asb)) return 0;
182
183 strcpy(namec,name);
184 namedot = strrchr (namec, '.');
185 if (Zflag && asb && (asb->sb_mode & S_IFMT) == S_IFREG
186 && asb->sb_rdev == 0
187 && namedot && namedot[1] == 'z' && !namedot[2]
188 )
189 *namedot = '\0';
190 else
191 namedot = 0;
192
193 n=namec;
194 if(ignoreslash && (n[0]=='/')) n++;
195
196 for(px=pattern; px; px=px->p_forw)
197 if((px->p_ptype)==PATTYPE_NOMATCH)
198 {
199 p=px->p_str;
200 if(ignoreslash && (p[0]=='/')) p++;
201
202 if (px->p_noglob)
203 {
204 if(strcmp(p,n)==0) return -1;
205 }
206 else
207 {
208 if(fnmatch(p,n,0)==0) return -1;
209 }
210 }
211
212 existpospat=0;
213
214 for(px=pattern; px; px=px->p_forw)
215 if((px->p_ptype)==PATTYPE_MATCH)
216 {
217 existpospat=1;
218
219 p=px->p_str;
220 if(ignoreslash && (p[0]=='/')) p++;
221
222 if (px->p_noglob)
223 {
224 if(strcmp(p,n)==0) return 0;
225 }
226 else
227 {
228 if(fnmatch(p,n,0)==0) return 0;
229 }
230 }
231
232 if(!existpospat) return 0; else return -1;
233
234 }
235
236
237 /*
238 * namecmp_ext()
239 *
240 * Compare a pathname with the extensions list. Returns 0 for
241 * a match, -1 otherwise.
242 *
243 */
244 STATIC int
namecmp_ext(name)245 namecmp_ext (name)
246 reg char *name;
247 {
248 reg Pattern *px;
249 char *p,*n;
250
251 n=name;
252 if(ignoreslash && (n[0]=='/')) n++;
253
254 for(px=pattern; px; px=px->p_forw)
255 if((px->p_ptype)==PATTYPE_EXT)
256 {
257 p=px->p_str;
258 if(ignoreslash && (p[0]=='/')) p++;
259
260 if(fnmatch(p,n,0)==0) return 0;
261 }
262
263 return -1;
264 }
265
266
267