#include #include #include #include #include #include #include #include #include #include #include #include "patchlevel.h" #ifdef HAVEFNMATCH #include #else /* A limited fnmatch replacement. Only accepts patterns in the form "ccccc" or "ccccc*". (These were the patterns accepted by older afio versions.) */ int fnmatch(const char *p, const char *s, int flag) { if(p[strlen(p)-1]=='*') return strncmp(p,s,strlen(p)-1); else return strcmp(p,s); } #endif #ifdef linux #include #endif #include "afio.h" STATIC int ignoreslash=1; /* * Pathnames to (or not to) be processed. */ typedef struct pattern { struct pattern *p_forw; /* Forward chain */ char *p_str; /* String */ int p_len; /* Length of string */ int p_ptype; /* Pattern type */ /* types are: PATTYPE_MATCH, _NOMATCH, _EXT. */ } Pattern; STATIC Pattern *pattern; /* Pathname matching patterns */ /* * nameadd() * * Add a name to the pattern list. */ STATIC void nameadd (name, ptype) reg char *name; int ptype; { reg Pattern *px; px = (Pattern *) memget (sizeof (Pattern)); px->p_forw = pattern; px->p_str = strdup(name); if(px->p_str==NULL) fatal(name,"out of memory."); px->p_len = strlen (name); px->p_ptype = ptype; pattern = px; /* fprintf(stderr,"--%s added\n",name); */ } /* * nameaddfile() * * Add a file of patterns to the pattern list. * Returns 0 on failure, 1 on success. */ STATIC int nameaddfile(fname,ptype) char *fname; int ptype; { FILE *infile; char pat[PATHSIZE+1]; infile=fopen(fname,"r"); if(infile==0) return 0; while(fgets(pat,PATHSIZE,infile)!=NULL) { /* remove \n */ pat[strlen(pat)-1]='\0'; if(strlen(pat)==0) continue; /* skip empty lines in file */ if(pat[strlen(pat)-1]==' ') { warn(pat,"warning: trailing space in this pattern."); } nameadd(pat,ptype); } fclose(infile); return 1; } /* * namecmp() * * Compare a pathname with the pattern list. Returns 0 for * a match, -1 otherwise. * * This new version uses the GCC library function fnmatch() * to provide real pattern matching. * * Also, this implementation assures that if a file matches a pattern * in the `not to process' list, it is never processed. * In the old version, this depended on several implementation details * and the names in the `to process' list. * * Control files always match. */ STATIC int namecmp (name, asb) reg char *name; Stat *asb; { reg Pattern *px; int existpospat; /* there are `to process' patterns in the list */ char *namedot,*p,*n; char namec[PATHSIZE]; /* fprintf(stderr,"name:\"%s\" rdev:%d\n",name, asb->sb_rdev); */ if(asb && ISCONTROL(asb)) return 0; strcpy(namec,name); namedot = strrchr (namec, '.'); if (Zflag && asb && (asb->sb_mode & S_IFMT) == S_IFREG && asb->sb_rdev == 0 && namedot && namedot[1] == 'z' && !namedot[2] ) *namedot = '\0'; else namedot = 0; n=namec; if(ignoreslash && (n[0]=='/')) n++; for(px=pattern; px; px=px->p_forw) if((px->p_ptype)==PATTYPE_NOMATCH) { p=px->p_str; if(ignoreslash && (p[0]=='/')) p++; if(fnmatch(p,n,0)==0) return -1; } existpospat=0; for(px=pattern; px; px=px->p_forw) if((px->p_ptype)==PATTYPE_MATCH) { existpospat=1; p=px->p_str; if(ignoreslash && (p[0]=='/')) p++; if(fnmatch(p,n,0)==0) return 0; } if(!existpospat) return 0; else return -1; } /* * namecmp_ext() * * Compare a pathname with the extensions list. Returns 0 for * a match, -1 otherwise. * */ STATIC int namecmp_ext (name) reg char *name; { reg Pattern *px; char *p,*n; n=name; if(ignoreslash && (n[0]=='/')) n++; for(px=pattern; px; px=px->p_forw) if((px->p_ptype)==PATTYPE_EXT) { p=px->p_str; if(ignoreslash && (p[0]=='/')) p++; if(fnmatch(p,n,0)==0) return 0; } return -1; }