enum
{
DT_UNKNOWN = 0,
#define DT_UNKNOWN DT_UNKNOWN //未知的类型
DT_FIFO = 1,
#define DT_FIFO DT_FIFO //命名管道或FIFO
DT_CHR = 2,
#define DT_CHR DT_CHR //字符设备文件
DT_DIR = 4,
#define DT_DIR DT_DIR //普通目录
DT_BLK = 6,
#define DT_BLK DT_BLK //块设备文件
DT_REG = 8,
#define DT_REG DT_REG //普通文件
DT_LNK = 10,
#define DT_LNK DT_LNK //快捷方式
DT_SOCK = 12,
#define DT_SOCK DT_SOCK //本地套接口
DT_WHT = 14
#define DT_WHT DT_WHT //whiteout
};
/*
whiteout 概念存在于联合文件系统(UnionFS)中,代表某一类占位符形态的特殊文件,
当用户文件夹与系统文件夹的共通部分联合到一个目录时(例如 bin 目录),
用户可删除归属于自己的某些系统文件副本,但归属于系统级的原件仍存留于同一个联合目录中,
此时系统将产生一份 whiteout 文件,表示该文件在当前用户目录中已删除,但系统目录中仍然保留。
*/
可以这些写一个类似于Linux中Tree类似功能的程序,而且貌似st_mode比dtype要判断的精确,误差更小。
stat 返回lnk所指向的文件信息
lstat 返回lnk的信息
其他都一样
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#define PATH_LENGTH 2000
#define FILE_MAXN 1000
#define NAME_LENGTH 255
struct OPT
{
int Show_Hidden_File;
int Show_File;
};
void Print_TAB(int Dep)
{
for (int i = 1; i < Dep; i++)
printf("| ");
printf("|-- ");
}
int Is_Hidden_File(const char * Str)
{
if (Str[0] == '.')
return 1;
return 0;
}
//int Reg = 0, Chr = 0, Blk = 0, Sock = 0, Fifo = 0;
int Is_File(char * File_Path)
{
struct stat S_Buf;
if (lstat(File_Path, &S_Buf) < 0)
return 1;
#if 0
if (S_ISREG(S_Buf.st_mode))
Reg++;
if (S_ISCHR(S_Buf.st_mode))
Chr++;
if (S_ISBLK(S_Buf.st_mode))
Blk++;
if (S_ISSOCK(S_Buf.st_mode))
Sock++;
if (S_ISFIFO(S_Buf.st_mode))
Fifo++;
#endif
if (S_ISREG(S_Buf.st_mode) || S_ISCHR(S_Buf.st_mode) || S_ISBLK(S_Buf.st_mode) || S_ISFIFO(S_Buf.st_mode) || S_ISSOCK(S_Buf.st_mode))
return 1;
if (S_ISLNK(S_Buf.st_mode))
{
if (stat(File_Path, &S_Buf) < 0)
return 1;
#if 0
if (S_ISREG(S_Buf.st_mode))
Reg++;
if (S_ISCHR(S_Buf.st_mode))
Chr++;
if (S_ISBLK(S_Buf.st_mode))
Blk++;
if (S_ISSOCK(S_Buf.st_mode))
Sock++;
if (S_ISFIFO(S_Buf.st_mode))
Fifo++;
#endif
if (S_ISREG(S_Buf.st_mode) || S_ISCHR(S_Buf.st_mode) || S_ISBLK(S_Buf.st_mode) || S_ISFIFO(S_Buf.st_mode) || S_ISSOCK(S_Buf.st_mode))
return 1;
}
return 0;
}
int Is_Dir(char * File_Path)
{
struct stat S_Buf;
stat(File_Path, &S_Buf);
if (S_ISDIR(S_Buf.st_mode) || S_ISSOCK(S_Buf.st_mode))
return 1;
return 0;
}
int Is_Lnk(char * File_Path)
{
struct stat S_Buf;
lstat(File_Path, &S_Buf);
//!! use lstat
if (S_ISLNK(S_Buf.st_mode))
return 1;
return 0;
}
int Cmp(const char * Str1, const char * Str2)
{
for (int i = 0; Str1[i] && Str2[i]; i++)
{
if (Str1[i] > Str2[i])
return 1;
if (Str1[i] < Str2[i])
return 0;
}
return 1;
}
/*
用stat之后结果会准确很多,但是在/proc/self/task这个文件夹下面有个fd的文件夹和一个fdinfo的文件夹,
里面分别有两个软连接,tree只会打开其中一个,我的两个无法打开
*/
void Tree_Maker(const char * Cur_Path, int Depth, OPT Opt, int * Dir_Num, int * File_Num)
{
DIR *dir;
struct dirent *node;
if ((dir = opendir(Cur_Path)) == NULL)
return;
/*
char File[FILE_MAXN][NAME_LENGTH];
int Cnt = 0;
while ((node = readdir(dir)) != NULL)
strcpy(File[++Cnt], node->d_name);
closedir(dir);
for (int i = 1; i <= Cnt; i++)
for (int j = i + 1; j <= Cnt; j++)
if (Cmp(File[i], File[j]))
{
char Tmp[PATH_LENGTH];
strcpy(Tmp, File[i]);
strcpy(File[i], File[j]);
strcpy(File[j], Tmp);
}
*/
while ((node = readdir(dir)) != NULL)
{
char File_Path[PATH_LENGTH];
strcpy(File_Path, Cur_Path);
strcat(File_Path, "/");
strcat(File_Path, node->d_name);
int Sym_File = Is_File(File_Path);
if (strcmp(node->d_name, ".") == 0 || strcmp(node->d_name, "..") == 0)
continue;
//Ignore dot and dot-dot
if (Is_Hidden_File(node->d_name) && !Opt.Show_Hidden_File)
continue;
if (Sym_File && !Opt.Show_File)
continue;
Print_TAB(Depth);
printf("%s", node->d_name);
if (Sym_File)
(*File_Num)++;
else
{
(*Dir_Num)++;
//printf("!!!");
}
putchar('\n');
if (Is_Dir(File_Path) && !Is_Lnk(File_Path))
Tree_Maker(File_Path, Depth + 1, Opt, Dir_Num, File_Num);
}
closedir(dir);
}
int main(int argc, char* argv[])
{
if (argc > 3)
{
puts("参数过多");
return -1;
}
OPT Opt = { 0,1 };
char Path[PATH_LENGTH] = ".";
if (argc == 2)
{
if (argv[1][0] == '-')
{
if (strcmp(argv[1], "-a") == 0)
Opt.Show_Hidden_File = 1;
if (strcmp(argv[1], "-d") == 0)
Opt.Show_File = 0;
}
else
strcpy(Path, argv[1]);
}
if (argc == 3)
{
if (strcmp(argv[1], "-a") == 0)
Opt.Show_Hidden_File = 1;
if (strcmp(argv[1], "-d") == 0)
Opt.Show_File = 0;
strcpy(Path, argv[2]);
}
int Dir_Num = 0, File_Num = 0;
puts(Path);
Tree_Maker(Path, 1, Opt, &Dir_Num, &File_Num);
printf("\n%d directories, %d files\n", Dir_Num, File_Num);
//printf("Reg: %d Chr: %d Blk: %d Sock: %d Fifo: %d\n", Reg, Chr, Blk, Sock, Fifo);
return 0;
}