目录树的遍历实验报告(unix操作系统系)---3
实验3 目录树的遍历实验报告
一.实验目的:
掌握与文件和目录树有关的系统调用和库函数。
二.实验要求:
1、编写程序myfind
命令语法:
myfind <pathname> [-comp <filename> | -name <str>…]
命令语义:
(1)myfind <pathname> 的功能:
除了具有与程序4-7相同的功能外,还要输出在<pathname>目录子树之下,文件长度不大于4096字节的常规文件,在所有允许访问的普通文件中所占的百分比。程序不允许打印出任何路径名。
(2)myfind <pathname> -comp <filename>的功能:
<filename>是常规文件的路径名(非目录名,但是其路径可以包含目录)。命令仅仅输出在<pathname>目录子树之下,所有与<filename>文件内容一致的文件的绝对路径名。不允许输出任何其它的路径名,包括不可访问的路径名。
(3)myfind <pathname> -name <str>…的功能:
<str>…是一个以空格分隔的文件名序列(不带路径)。命令输出在<pathname>目录子树之下,所有与<str>…序列中文件名相同的文件的绝对路径名。不允许输出不可访问的或无关的路径名。
<pathname>和<filename>均既可以是绝对路径名,也可以是相对路径名。<pathname>既可以是目录,也可以是文件,此时,目录为当前工作目录。
2、注意尽可能地提高程序的效率。注意避免因打开太多文件而产生的错误。
3、遍历目录树时,访问结点(目录项)的具体操作应当由遍历函数dopath携带的函数指针参数决定。这样程序的结构清晰,可扩充性好。
三.实验源代码
#include "apue.h" #include <dirent.h> #include <limits.h> #include<malloc.h> #include<fcntl.h> #include<unistd.h> /* function type that is called for each filename */ typedef int Myfunc(const char *, const struct stat *, int); static Myfunc myfunc; static Myfunc myfunc1; static Myfunc myfunc2; static int myftw(char *, Myfunc *); static int dopath(Myfunc *); char *argv0[100]; static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot; int num=0,i=0; int temp,now; int f,f_le; char *fcontd; int fo,fo_le; char *focontd; static long nreg0=0; /*char *path_alloc(int *size) char *p=NULL; if(!size) return NULL; p=malloc(256); if(p) *size=256; else *size=0; return p; }*/ int main(int argc, char *argv[]) { int ret; if(argc==2)//两个参数 { ret = myftw(argv[1], myfunc); /* does it all */ ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock; if (ntot == 0) ntot = 1; /* avoid divide by 0; print 0 for all counts */ printf("regular files = %7ld, %5.2f %%\n", nreg, nreg*100.0/ntot); printf("size<4096 in regular =%7ld, %4,2 %%\n",nreg0,nreg0*100.0/ntot); printf("directories = %7ld, %5.2f %%\n", ndir, ndir*100.0/ntot); printf("block special = %7ld, %5.2f %%\n", nblk, nblk*100.0/ntot); printf("char special = %7ld, %5.2f %%\n", nchr, nchr*100.0/ntot); printf("FIFOs = %7ld, %5.2f %%\n", nfifo, nfifo*100.0/ntot); printf("symbolic links = %7ld, %5.2f %%\n", nslink, nslink*100.0/ntot); printf("sockets = %7ld, %5.2f %%\n", nsock, nsock*100.0/ntot); } if(argc==4&& 0 ==strcmp(argv[2],"-comp"))//四个参数 { f=open(argv[3],O_RDWR); f_le=lseek(f,0,SEEK_END); temp=lseek(f,0,SEEK_SET); fcontd=(char *)malloc(sizeof(char)*f_le); now=read(f,fcontd,f_le); ret =myftw(argv[1],myfunc1); } if(argc>=4&& 0 ==strcmp(argv[2],"-name"))//大于四个参数 { i=3; for(i=3;i<argc;i++) {argv0[i-3]=argv[i];} i++; num=argc-3; ret =myftw(argv[1],myfunc2); } exit(ret); } /* * Descend through the hierarchy, starting at "pathname". * The caller's func() is called for every file. */ #define FTW_F 1 /* file other than directory */ #define FTW_D 2 /* directory */ #define FTW_DNR 3 /* directory that can't be read */ #define FTW_NS 4 /* file that we can't stat */ static char *fullpath; /* contains full pathname for every file */ static int /* we return whatever func() returns */ myftw(char *pathname, Myfunc *func) { int len; fullpath = path_alloc(&len); /* malloc's for PATH_MAX+1 bytes */ /* ({Prog pathalloc}) */ strncpy(fullpath, pathname, len); /* protect against */ fullpath[len-1] = 0; /* buffer overrun */ return(dopath(func)); } /* * Descend through the hierarchy, starting at "fullpath". * If "fullpath" is anything other than a directory, we lstat() it, * call func(), and return. For a directory, we call ourself * recursively for each name in the directory. */ static int /* we return whatever func() returns */ dopath(Myfunc* func) { struct stat statbuf; struct dirent *dirp; DIR *dp; int ret; char *ptr; if (lstat(fullpath, &statbuf) < 0) /* stat error */ return(func(fullpath, &statbuf, FTW_NS)); if (S_ISDIR(statbuf.st_mode) == 0) /* not a directory */ return(func(fullpath, &statbuf, FTW_F)); /* * It's a directory. First call func() for the directory, * then process each filename in the directory. */ if ((ret = func(fullpath, &statbuf, FTW_D)) != 0) return(ret); ptr = fullpath + strlen(fullpath); /* point to end of fullpath */ *ptr++ = '/'; *ptr = 0; if ((dp = opendir(fullpath)) == NULL) /* can't read directory */ return(func(fullpath, &statbuf, FTW_DNR)); while ((dirp = readdir(dp)) != NULL) { if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) continue; /* ignore dot and dot-dot */ strcpy(ptr, dirp->d_name); /* append name after slash */ if ((ret = dopath(func)) != 0) /* recursive */ break; /* time to leave */ } ptr[-1] = 0; /* erase everything from slash onwards */ if (closedir(dp) < 0) err_ret("can't close directory %s", fullpath); return(ret); } static int myfunc(const char *pathname, const struct stat *statptr, int type)//两个参数 { switch (type) { case FTW_F: switch (statptr->st_mode & S_IFMT) { // case S_IFREG: nreg++; break; case S_IFREG: {nreg++; if(statptr->st_size<4096) nreg0++; } case S_IFBLK: nblk++; break; case S_IFCHR: nchr++; break; case S_IFIFO: nfifo++; break; case S_IFLNK: nslink++; break; case S_IFSOCK: nsock++; break; case S_IFDIR: err_dump("for S_IFDIR for %s", pathname); /* directories should have type = FTW_D */ } break; case FTW_D: ndir++; break; case FTW_DNR: err_ret("can't read directory %s", pathname); break; case FTW_NS: err_ret("stat error for %s", pathname); break; default: err_dump("unknown type %d for pathname %s", type, pathname); } return(0); } static int myfunc1(const char *pathname, const struct stat *statptr, int type)//四个参数 { i=0; char *p; switch (type) { case FTW_F: { //if(statptr->st_size==f_le){ fo=open(pathname,O_RDWR); fo_le=lseek(fo,0,SEEK_END); now=lseek(fo,0,SEEK_SET); if(fo_le==f_le) { focontd=(char *)malloc(sizeof(char)*fo_le); now=read(fo,focontd,fo_le); p=fcontd; for(i=0;i<fo_le;i++) { p++; focontd++; if(*p!=*focontd) break; } if(i>=fo_le) printf("path is %s\n",pathname); } } case FTW_D: ndir++; break; case FTW_DNR: err_ret("can't read directory %s", pathname); break; case FTW_NS: err_ret("stat error for %s", pathname); break; default: err_dump("unknown type %d for pathname %s", type, pathname); } return(0); } static int myfunc2(const char *pathname, const struct stat *statptr, int type)//大于四个参数 { // printf("asdf"); char *q=NULL; q=pathname; int leng=0; switch (type) { case FTW_F: switch (statptr->st_mode & S_IFMT) { // case S_IFREG: nreg++; break; case S_IFREG: { /* directories should have type = FTW_D */ for(i=0;i<num;i++) { leng=strlen(pathname); q=q+leng; while(*q!='/') q--; q++; if(0==strcmp(argv0[i],q)) printf("path is %s\n",pathname); } } break; } case FTW_D: ndir++; break; case FTW_DNR: err_ret("can't read directory %s", pathname); break; case FTW_NS: err_ret("stat error for %s", pathname); break; default: err_dump("unknown type %d for pathname %s", type, pathname); } return(0); }
四.实验结果
说明:
Ftw4.c 为c源程序
Pathalloc.c pathalloc函数源程序
Abc.txt 为搜索条件(文件名)
home/cs09/cs094180/expmt//3/ 搜索路径
Ftw4 编译后的程序
运行结果详见上面的截图