为什么要写这个呢...是因为要出一些恶意的代码片段,有一个遍历文件夹的需求。按照要求,所有的恶意行为只能写在一个函数中,且不能有注释。本来不想自己写,可是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");
}
}