int regmatch (struct Expr *expr, struct Probe *probe) { struct Probe *base = (struct Probe *)((uchar *)expr + expr->size); int ch; if( probe->off == expr->amt ) return 0; // match pattern switch( ch = *probe->node->type->pattern ) { case '.': return 1; default: if( expr->val[probe->off] == ch ) return 1; return 0; case '[': if( probe->node->typelen > 2 ) if( regfilter (probe->node->type->pattern + 1, probe->node->typelen - 2, expr->val[probe->off]) ) return 1; return 0; } }
regfilterspcl (uchar ch, uchar tst) { switch( ch ) { case 'd': return regfilter ("[0-9]", 5, tst); case 'D': return regfilter ("[^0-9]", 6, tst); case 's': return regfilter ("[ ]", 2, tst); case 'S': return regfilter ("[^ ]", 3, tst); case 'i': return regfilter ("[a-zA-Z_:]", 8, tst); case 'I': return regfilter ("[^a-zA-Z_:]", 9, tst); } return regfilter (&ch, 1, tst); }
/* * Callbock from nftw() * If the file given from nftw by "path": * - is a directory: recurs into it and catch the files there, * as long the depth doesnt get bigger than max_depth and contains the pattern cmp_pattern * - a file: Push it back to the list, if it has "cmp_pattern" in it. (if --regex was given) * If the user interrupts, nftw() stops, and the program will do it'S magic. * * Not many comments, because man page of nftw will explain everything you'll need to understand * * Appendum: rmlint uses the inode to sort the contents before doing any I/O to speed up things. * This is nevertheless limited to Unix filesystems like ext*, reiserfs.. (might work in MacOSX - don't know) * If someone likes to port this to Windows he would to replace the inode number by the MFT entry point, or simply disable it * I personally don't have a win comp and won't port it, as I don't found many users knowing what that black window with white * white letters can do ;-) */ static int eval_file(const char *path, const struct stat *ptr, int flag, struct FTW *ftwbuf) { if(set->depth && ftwbuf->level > set->depth) { /* Do not recurse in this subdir */ return FTW_SKIP_SIBLINGS; } if(iAbort) { return FTW_STOP; } if(flag == FTW_SLN) { list_append(path, 0,ptr->st_dev,ptr->st_ino,TYPE_BLNK); return FTW_CONTINUE; } if(path) { if(!dir_done) { char *orig_path = set->paths[get_cpindex()]; size_t orig_path_len = strlen(set->paths[get_cpindex()]); if(orig_path[orig_path_len - 1] == '/') { orig_path_len -= 1; } if(!strncmp(set->paths[get_cpindex()], path, orig_path_len)) { dir_done = true; return FTW_CONTINUE; } } if(flag == FTW_F && (set->minsize <= ptr->st_size || set->minsize < 0) && (set->maxsize >= ptr->st_size || set->maxsize < 0)) { if(regfilter(path, set->fpattern)) { return FTW_CONTINUE; } if(junkinstr(rmlint_basename(path))) { list_append(path, 0,ptr->st_dev,ptr->st_ino,TYPE_JNK_FILENAME); if(set->collide) { return FTW_CONTINUE; } } if(set->findbadids) { bool has_gid, has_uid; if(userlist_contains(global_ug_list,ptr->st_uid,ptr->st_gid,&has_uid,&has_gid) == false) { if(has_gid == false) list_append(path,0,ptr->st_dev,ptr->st_ino,TYPE_BADGID); if(has_uid == false) list_append(path,0,ptr->st_dev,ptr->st_ino,TYPE_BADUID); if(set->collide) { return FTW_CONTINUE; } } } if(set->nonstripped) { if(check_binary_to_be_stripped(path)) { list_append(path, 0,ptr->st_dev,ptr->st_ino,TYPE_NBIN); if(set->collide) { return FTW_CONTINUE; } } } if(set->doldtmp) { /* This checks only for *~ and .*.swp */ size_t len = strlen(path); if(path[len-1] == '~' || (len>3&&path[len-1] == 'p'&&path[len-2] == 'w'&&path[len-3] == 's'&&path[len-4] == '.')) { char *cpy = NULL; struct stat stat_buf; if(path[len - 1] == '~') { cpy = strndup(path,len-1); } else { char * p = strrchr(path,'/'); size_t p_len = p-path; char * front = alloca(p_len+1); memset(front, '\0', p_len+1); strncpy(front, path, p_len); cpy = strdup_printf("%s/%s",front,p+2); cpy[strlen(cpy)-4] = 0; } if(!stat(cpy, &stat_buf)) { if(ptr->st_mtime - stat_buf.st_mtime >= set->oldtmpdata) { list_append(path, 0,ptr->st_dev,ptr->st_ino,TYPE_OTMP); } } if(cpy) { free(cpy); } if(set->collide) { return FTW_CONTINUE; } } } /* Check this to be a valid file and NOT a blockfile (reading /dev/null does funny things) */ if(flag == FTW_F && !(S_ISCHR(ptr->st_mode) || S_ISBLK(ptr->st_mode)) && (set->listemptyfiles || ptr->st_size != 0)) { if(!access(path,R_OK)) { if(set->ignore_hidden) { char *base = rmlint_basename(path); if(*base != '.') { dircount++; list_append(path, ptr->st_size,ptr->st_dev,ptr->st_ino,1); } } else { dircount++; list_append(path, ptr->st_size,ptr->st_dev,ptr->st_ino,1); } } return FTW_CONTINUE; } } if(flag == FTW_D) { if(regfilter(path, set->dpattern) && dir_done) { return FTW_SKIP_SUBTREE; } if(junkinstr(rmlint_basename(path))) { list_append(path, 0,ptr->st_dev,ptr->st_ino,TYPE_JNK_DIRNAME); if(set->collide) { return FTW_SKIP_SUBTREE; } } if(set->findemptydirs) { int dir_counter = 0; DIR *dir_e = opendir(path); struct dirent *dir_p = NULL; if(dir_e) { while((dir_p=readdir(dir_e)) && dir_counter < 2) { dir_counter++; } closedir(dir_e); if(dir_counter == 2 && dir_p == NULL) { list_append(path, 0,ptr->st_dev,ptr->st_ino,TYPE_EDIR); return FTW_SKIP_SUBTREE; } } } if(set->ignore_hidden && path) { char *base = rmlint_basename(path); if(*base == '.' && dir_done) { return FTW_SKIP_SUBTREE; } } } } return FTW_CONTINUE; }