为什么要写这个呢...是因为要出一些恶意的代码片段,有一个遍历文件夹的需求。按照要求,所有的恶意行为只能写在一个函数中,且不能有注释。本来不想自己写,可是google到的遍历文件夹的代码全是递归写的。虽然gcc也支持内部函数的编译,但是这样感觉不太优雅,于是稍微修改一下,就有了下面的代码。
实现思路其实很简单,其实就是链表啦,不过上次写链表还是13年吧,真太菜了。
用一个结构体保存 1. 当前文件夹的path的地址2.下一个结构体的地址(初始化为NULL)。
遍历时,创建两个结构体指针,folderfirst和folderlast。用folderfirst遍历指定文件夹(如/home)的时候,如果出现新的文件夹,就用创建新的结构体,用folderlast来增加到链表中。当前文件夹遍历完成,修改folderfirst指向下一个结构体。循环结束的条件就是,folderfirst为NULL。
PS:这么实现貌似算广度优先搜索?貌似搜索文件夹BFS比DFS要快, 和OS有关系。忘了出处了,感兴趣的可以搜索一下。
1806191523 bug:scan根目录的时候,猜测由于部分文件没有读权限,因此程序就停了。此外,有替代工具,命令"du -h"。暂时没时间改了,有空参考一下du的源码实现吧。ftp://ftp.gnu.org/gnu/coreutils/
如果有人有兴趣修改,欢迎留言讨论。
最新以及历史版本放在:https://gist.github.com/thinkycx/a6359201f79ffdf4e97a111c5fe4cf01
代码:
/* date: 20180619 author: thinkycx usage: gcc scanfolder.c -o scanfolder ./scanfolder [foldername] ./scscanfolderan /home Only support to scan folder and regular file.Maybe support symbolic etc in future... */ #include <stdio.h> #include <dirent.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <fcntl.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/stat.h> #include <regex.h> void f(char *path){ #define SEARCH_PATH "/home" struct foldernode{ char *path; // point to foldername or filename path struct foldernode *next; }; DIR *dir; struct stat statbuf; struct dirent *ptr; char *filename; char *filepath; char *data; char *foldername ; char *folderpath ; struct foldernode folderstart; folderstart.path = path; folderstart.next = NULL; struct foldernode * folderfirst; // use to search folderfirst = &folderstart; struct foldernode * folderlast; // use to add foldernode folderlast = &folderstart; while(folderfirst != NULL){ dir = opendir(folderfirst->path); if (dir) { while ((ptr = readdir(dir)) != NULL) { if(strcmp(ptr->d_name, ".")==0 || strcmp(ptr->d_name, "..")==0) continue; else if(ptr->d_type == 8){ //file filename = malloc(0x100); filepath = malloc(0x1000); memset(filename, 0x100, 0); memset(filepath, 0x100, 0); strcpy(filename, ptr->d_name); sprintf(filepath, "%s/%s", folderfirst->path, filename); printf("[*]FILE %s\n",filepath); free(filename); free(filepath); } else if(ptr->d_type == 4){ //folder foldername = malloc(0x100); folderpath = malloc(0x1000); memset(foldername, 0x100, 0); memset(folderpath, 0x1000, 0); strcpy(foldername, ptr->d_name); sprintf(folderpath, "%s/%s", folderfirst->path , foldername); printf("[*]FOLDER %s\n",folderpath); struct foldernode *foldernew; foldernew = malloc(sizeof(struct foldernode)); foldernew->path = malloc(strlen(folderpath)+1); strcpy(foldernew->path, folderpath); foldernew->next = NULL; folderlast->next = foldernew; folderlast = foldernew; free(foldername); free(folderpath); } } }else{ return; } folderfirst = folderfirst->next; // change folderfirst point to next foldernode closedir(dir); } } int main(int argc,char **argv, char **env) { if(argc == 2){ f(argv[1]); }else{ printf("Usage: scanfolder [foldername]\n\tscanfolder /home\n"); } }