【Linux C】遍历 指定文件夹(home)的所有文件 (非递归实现)

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

}


猜你喜欢

转载自blog.csdn.net/think_ycx/article/details/80732353