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