1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
/*
* Written by Felix von Leitner [see dietlibc]
* minor modifications by Michael Piotrowski
* The license for the diet libc is the GNU General Public License, version 2
* (as included in the file LICENSE).
*/
#include <sys/stat.h>
#include <unistd.h>
#include <limits.h>
#include <ftw.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
int ftw(const char*dir,int(*f)(const char*file,const struct stat*sb,int flag),
int dpth){
char* cd;
size_t cdl;
DIR* d;
struct dirent* de;
struct stat sb;
int r;
unsigned int oldlen=0;
char* filename; /* the warning gcc issues here is bogus */
/* Argument is not a directory */
if (chdir(dir)){
int flg;
if (!lstat(dir, &sb)){
if (S_ISLNK(sb.st_mode))
flg = FTW_SL;
else
flg = FTW_F;
}
else flg = FTW_NS;
r = f(dir, &sb, flg);
return r;
}
cd=alloca(PATH_MAX+1);
if(!getcwd(cd,PATH_MAX))return-1;
cd[PATH_MAX]='\0';
cdl=strlen(cd);
if(!(d=opendir(".")))return-1;
while((de=readdir(d))){
int flg;
size_t nl;
if(de->d_name[0]=='.'){
if(!de->d_name[1])continue;
if(de->d_name[1]=='.'&&!de->d_name[2])continue;
}
nl=strlen(de->d_name);
if (nl+cdl+2>oldlen)
filename=alloca(oldlen=nl+cdl+2);
memmove(filename,cd,cdl);
filename[cdl]='/';
memmove(filename+cdl+1,de->d_name,nl+1);
if(!lstat(de->d_name,&sb)){
if(S_ISLNK(sb.st_mode))flg=FTW_SL;
else if(S_ISDIR(sb.st_mode))flg=FTW_D; else flg=FTW_F;
}else flg=FTW_NS;
r=f(filename,&sb,flg);
if(r){
closedir(d);
return r;
}
if(flg==FTW_D&&dpth){
r=ftw(filename,f,dpth-1);
#if defined __NetBSD__ || defined __FreeBSD__
fchdir(d->dd_fd);
#else
fchdir(d->fd);
#endif
if (r){
closedir(d);
return r;
}
}
}
return closedir(d);
}
|