0
点赞
收藏
分享

微信扫一扫

linux c语言简单实现ftw()函数myftw().

上善若水的道 2022-04-13 阅读 58

源代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

typedef	int Myfn(const char *, const struct stat *, int);
enum{
	FTW_F = 1,
	FTW_D,
	FTW_DNR,
	FTW_NS
};

static int myDispose(const char *path);
static int myfn(const char *fpath, const struct stat *sb, int typeflag);
static int myDisposeNext(Myfn *myfn);

static char *cptPath; //complete path
static size_t cptPathLen = NAME_MAX;
static Myfn myfn;
static unsigned long int reg, dir, blk, fifo, chr, slink, sock;
static unsigned long int total;

static int myfn(const char *fpath, const struct stat *sb, int typeflag){

	switch(typeflag){
		case FTW_F:
			total++;
			switch(sb->st_mode & S_IFMT){
				case S_IFDIR:
					fprintf(stderr, "why dir here\n");
					return(1);
				case S_IFREG:	reg++;		break;
				case S_IFBLK:	blk++;		break;
				case S_IFCHR:	chr++;		break;
				case S_IFIFO:	fifo++;		break;
				case S_IFSOCK:	sock++;		break;
				case S_IFLNK:	slink++;	break;
			}
			break;
		case FTW_D:
			total++;
			dir++;
			break;
		case FTW_NS:
			fprintf(stderr, "can not open %s, may be not have permission\n", fpath);
			break;
		case FTW_DNR:
			fprintf(stderr, "can not read %s\n", fpath);
			break;
		default:
			fprintf(stderr, "myfn() typeflag error!\n");
			exit(1);
	}

	return 0;
}

static int myDisposeNext(Myfn *myfn){

	struct stat statMsg;
	DIR *dp;
	struct dirent *dirMsg;
	int ret;
	size_t dirlen;

	ret = lstat(cptPath, &statMsg);
	if(ret < 0){
		return(myfn(cptPath, &statMsg, FTW_NS));
	}
	if(!S_ISDIR(statMsg.st_mode)){ //not a dir
		return(myfn(cptPath, &statMsg, FTW_F));
	}

	//dir
	ret = myfn(cptPath, &statMsg, FTW_D);
	dirlen = strlen(cptPath);
	cptPath[dirlen] = '/';
	cptPath[dirlen+1] =	'\0'; 
	dp = opendir(cptPath);
	if(dp == NULL){
		return(myfn(cptPath, &statMsg, FTW_DNR));
	}
	while(1){
		dirMsg = readdir(dp);
		if(dirMsg == NULL){
			break;
		}
		if(strcmp(dirMsg->d_name, ".") == 0 || strcmp(dirMsg->d_name, "..") == 0){
			continue;
		}
		strcpy(&cptPath[dirlen+1], dirMsg->d_name);
		ret = myDispose(cptPath);
		if(ret != 0){
			break;
		}
	}
	cptPath[dirlen] = '\0';
	closedir(dp);

	return(ret);
}

static int myDispose(const char *path){

	size_t pathLen = strlen(path);
	
	if(cptPath == NULL){
		if((cptPath = malloc(cptPathLen)) == NULL){
			perror("cptPath malloc()");
			exit(1);
		}
	}
	while(cptPathLen <= pathLen){
		cptPathLen *= 2;
		if((cptPath = realloc(cptPath, cptPathLen)) == NULL){
			perror("cptPath realloc()");
			exit(1);
		}
	}

	strncpy(cptPath, path, pathLen);

	return(myDisposeNext(myfn));
}

int main(int argc, char **argv){

	if(argc < 2){
		fprintf(stderr, "Usage: ./mytfw path ... \n");
		exit(1);
	}


	int i, ret;

	for(i = 1; i < argc; i++){
		ret = myDispose(argv[i]);
		if(ret != 0){
			fprintf(stderr, "error!\n");
			break;
		}
		printf("------------------------------\n");
		printf("----------%-10s----------\n", argv[i]);
		printf("reg = %ld\n", reg);
		printf("dir = %ld\n", dir);
		printf("blk  = %ld\n", blk);
		printf("chr = %ld\n", chr);
		printf("fifo = %ld\n", fifo);
		printf("slink = %ld\n", slink);
		printf("sock = %ld\n", sock);
		printf("total = %ld\n", total);
		printf("------------------------------\n");
		printf("------------------------------\n");
		reg = 0;
		dir = 0;
		blk = 0;
		chr = 0;
		fifo = 0;
		slink = 0;
		sock = 0;
		total = 0;
		memset(cptPath, 0, cptPathLen);
		cptPathLen = NAME_MAX;
	}

	exit(0);
}

运行效果

        运行环境:Ubuntu 21.10, gcc version 11.2.0

 

 

举报

相关推荐

0 条评论