#include "internal.h" #include #include #include #include static int noDots(const struct dirent * e) { if ( e->d_name[0] == '.' && (e->d_name[1] == '\0' || (e->d_name[1] == '.' && e->d_name[2] == '\0')) ) return 0; else return 1; } extern int descend( struct FileInfo *oldInfo ,int (*function)(const struct FileInfo * i)) { char pathname[1024]; struct dirent * * names; struct dirent * * n; int length; char * filename; int status = 0; int count; if ( *oldInfo->source == '\0' ) { errno = EINVAL; return -1; } if ( oldInfo->stat.st_dev == 0 && oldInfo->stat.st_ino == 0 && oldInfo->stat.st_mode == 0 ) { if ( lstat(oldInfo->source, &oldInfo->stat) != 0 ) return -1; oldInfo->isSymbolicLink = ((oldInfo->stat.st_mode & S_IFMT) == S_IFLNK); if ( oldInfo->isSymbolicLink ) if ( stat(oldInfo->source, &oldInfo->stat) != 0 ) memset((void *)&oldInfo->stat, 0, sizeof(oldInfo->stat)); } if ( !oldInfo->processDirectoriesAfterTheirContents ) { if ( function ) status = (*function)(oldInfo); if ( status == 0 ) status = post_process(oldInfo); } if ( (count = scandir(oldInfo->source, &names, noDots, alphasort)) < 0 ) return -1; length = strlen(oldInfo->source); if ( oldInfo->source[length-1] == '/' ) length--; memcpy(pathname, oldInfo->source, length+1); pathname[length] = '/'; filename = &pathname[length+1]; n = names; while ( count-- > 0 ) { struct FileInfo i = *oldInfo; strcpy(filename, (*n)->d_name); free(*n++); if ( lstat(pathname, &i.stat) != 0 && errno != ENOENT ) { fprintf(stderr, "Can't stat %s: %s\n", pathname, strerror(errno)); return -1; } i.isSymbolicLink = ((i.stat.st_mode & S_IFMT) == S_IFLNK); if ( i.isSymbolicLink ) if ( stat(pathname, &i.stat) != 0 ) memset((void *)&i.stat, 0, sizeof(i.stat)); i.source = pathname; if ( i.dyadic ) { char d[1024]; i.destination = join_paths(d, i.destination, &i.source[i.directoryLength]); } else i.destination = i.source; if ( !i.isSymbolicLink && (i.stat.st_mode & S_IFMT) == S_IFDIR ) status = descend(&i, function); else { if ( function ) status = (*function)(&i); if ( status == 0 ) status = post_process(&i); } if ( !i.processDirectoriesAfterTheirContents && status == 0 && (i.stat.st_mode & S_IFMT) == S_IFDIR ) descend(&i, function); if ( status != 0 && !i.force ) { while ( count-- > 0 ) free(*n++); break; } } free(names); if ( oldInfo->processDirectoriesAfterTheirContents ) { if ( function ) status = (*function)(oldInfo); if ( status == 0 ) status = post_process(oldInfo); } return status; }