-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhw3.cpp
301 lines (280 loc) · 8.45 KB
/
hw3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
/**
* 实现“ls -l”的基本功能,至少能输出文件类型、9个权限位信息、文件大小、文件名称
*
* first line: the total space occupied of file
* Field: file attribute 10 words
* 1: File type: '-' ordinary file, 'd' dirtectory, 'l' link, 'b' block, 'c' character, 'p' command pipeline
* File permission: r read, w write, x execute
* 2: If isn't a dirtectory, Number of hard links; Is a directory, Number of subdirtectories
* 3: file owner
* 4: file owner group
* 5: file size (bits)
* 6: Last visited (modified) time. MM-DD mm:ss
* 7: file name
*
* struct stat
* {
* dev_t st_dev; ID of device containing file -文件所在设备的ID
* ino_t st_ino; inode number -inode节点号
* mode_t st_mode; File mode
* nlink_t st_nlink; number of hard links -链向此文件的连接数(硬连接)
* uid_t st_uid; user ID of owner -user id
* gid_t st_gid; group ID of owner - group id
* dev_t st_rdev; device ID (if special file) -设备号,针对设备文件
* off_t st_size; total size, in bytes -文件大小,字节为单位
* blksize_t st_blksize; blocksize for filesystem I/O -系统块的大小
* blkcnt_t st_blocks; number of blocks allocated -文件所占块数
* time_t st_atime; time of last access -最近存取时间
* time_t st_mtime; time of last modification -最近修改时间
* time_t st_ctime; time of last status change - 文件状态改变时间
* }
*
*/
#include <dirent.h>
#include <grp.h>
#include <iostream>
#include <pwd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define RECURSION_DEPTH 3 /*定义递归深度*/
#define MAX_D_NAME_LENGTH 256 /*最大路径字符长度*/
#define yearsecs (60 * 60 * 24 * 365) /*seconds in a year*/
bool showDirecoryList(char *path);
char *getFileModeFlag(int mode); //get char file mode
char *uidToName(uid_t uid);
char *gidToName(gid_t gid);
int counterSubdirtectory(char *path);
int fileCounter(char *path);
/**
* @brief 文件路径递归调用
*
* @param path 需要读取的文件夹路径
* @param depth 递归深度
* @return true 成功
* @return false 文件未知类型错误,文件路径无法打开
*/
bool showDirecoryList(char *path)
{
DIR *dir; //目录流对象的数据类型指针
struct stat stat_buf; //文件属性
struct dirent *ptr; //目录项结构体指针
char curr_path[MAX_D_NAME_LENGTH]; //扫描的当前目录项,方便打开目录
dir = opendir(path); //打开当前文件夹
/*文件路径错误判断*/
if (dir == NULL)
{
std::cout << "can't open this directory" << std::endl;
return false;
}
std::cout << "count:" << fileCounter(path) << std::endl;
// 循环读取当前文件夹内的目录项
while ((ptr = readdir(dir)) != NULL)
{
if (ptr->d_name[0] == '.')
{
//剔除隐藏文件和文件自身,保证文件隐藏和打印效果
continue;
}
stat(ptr->d_name, &stat_buf); // 获取文件信息,把信息放到s_buf中
memcpy(curr_path, path, strlen(path) + 1); // 获取当前文件路径
/* 判断是不是文件夹 */
if (S_ISDIR(stat_buf.st_mode)) //是一个文件夹
{
/* 手动处理文件夹路径 */
strcat(curr_path, "/");
strcat(curr_path, ptr->d_name);
std::cout
<< getFileModeFlag(stat_buf.st_mode)
<< ' ' << counterSubdirtectory(curr_path) //number of subdirtectories
<< ' ' << uidToName(stat_buf.st_uid)
<< ' ' << gidToName(stat_buf.st_gid)
<< ' ' << stat_buf.st_size
<< '\t' << (stat_buf.st_mtim.tv_sec / yearsecs) + 1970
<< ' ' << ptr->d_name << std::endl; //打印当前文件
}
else if (!S_ISDIR(stat_buf.st_mode)) // 不是个文件夹
{
std::cout
<< getFileModeFlag(stat_buf.st_mode)
<< ' ' << stat_buf.st_nlink
<< ' ' << uidToName(stat_buf.st_uid)
<< ' ' << gidToName(stat_buf.st_gid)
<< ' ' << stat_buf.st_size
<< '\t' << (stat_buf.st_mtim.tv_sec / yearsecs) + 1970
<< ' ' << ptr->d_name << std::endl; //打印当前文件
}
else
{
std::cout << "file mode error!" << std::endl;
return false;
}
}
closedir(dir); //关闭当前文件夹,节省资源
return true;
}
int fileCounter(char *path)
{
int count = 0;
DIR *dir; //目录流对象的数据类型指针
struct dirent *ptr; //目录项结构体指针开目录
dir = opendir(path); //打开当前文件夹
while ((ptr = readdir(dir)) != NULL)
count++;
return count;
}
/**
* @brief get number of subdirtectory
*
* @param path diretectory path
* @return number of subdirtectory
*/
int counterSubdirtectory(char *path)
{
int counter = 1;
DIR *dir; //目录流对象的数据类型指针
struct stat stat_buf; //文件属性
struct dirent *ptr; //目录项结构体指针
char curr_path[MAX_D_NAME_LENGTH]; //扫描的当前目录项,方便打开目录
dir = opendir(path); //打开当前文件夹
/*文件路径错误判断*/
if (dir == NULL)
{
std::cout << "can't open this directory" << std::endl;
return false;
}
// 循环读取当前文件夹内的目录项
while ((ptr = readdir(dir)) != NULL)
{
if (ptr->d_name[0] == '.')
{
//剔除隐藏文件和文件自身,保证文件隐藏和打印效果
continue;
}
stat(ptr->d_name, &stat_buf); // 获取文件信息,把信息放到s_buf中
memcpy(curr_path, path, strlen(path) + 1); // 获取当前文件路径
/* 判断是不是文件夹 */
if (S_ISDIR(stat_buf.st_mode)) //是一个文件夹
{
counter++;
}
}
closedir(dir); //关闭当前文件夹,节省资源
return counter;
}
/**
* @brief Get the File Mode Flag object
*
* @param mode file mode
* @return Flag char
*/
char *getFileModeFlag(int mode)
{
static char ptr[11] = "----------"; //Field: file attribute 10 words
// File type
if (S_ISREG(mode))
ptr[0] = '-';
else if (S_ISDIR(mode))
ptr[0] = 'd';
else if (S_ISCHR(mode))
ptr[0] = 'c';
else if (S_ISBLK(mode))
ptr[0] = 'b';
else if (S_ISFIFO(mode))
ptr[0] = 'f';
else if (S_ISLNK(mode))
ptr[0] = 'l';
else if (S_ISSOCK(mode))
ptr[0] = 's';
else
ptr[0] = '?';
//print field of file attribute
if (mode & S_IRUSR)
{
ptr[1] = 'r';
}
if (mode & S_IWUSR)
{
ptr[2] = 'w';
}
if (mode & S_IXUSR)
{
ptr[3] = 'x';
}
if (mode & S_IRGRP)
{
ptr[4] = 'r';
}
if (mode & S_IWGRP)
{
ptr[5] = 'w';
}
if (mode & S_IXGRP)
{
ptr[6] = 'x';
}
if (mode & S_IROTH)
{
ptr[7] = 'r';
}
if (mode & S_IWOTH)
{
ptr[8] = 'w';
}
if (mode & S_IXOTH)
{
ptr[9] = 'x';
}
return (char *)ptr;
}
/**
* @brief Find the username corresponding to uid
*
* @param uid
* @return user name
*/
char *uidToName(uid_t uid)
{
struct passwd *pw_ptr;
static char numstr[10];
if ((pw_ptr = getpwuid(uid)) == NULL)
{
sprintf(numstr, "%d", uid);
return numstr;
}
else
return pw_ptr->pw_name;
}
/**
* @brief Find the groupname corresponding to gid
*
* @param gid
* @return groupname
*/
char *gidToName(gid_t gid)
{
struct group *grp_ptr;
static char numstr[10];
if ((grp_ptr = getgrgid(gid)) == NULL)
{
sprintf(numstr, "%d", gid);
return numstr;
}
else
return grp_ptr->gr_name;
}
int main(int argc, char *argv[])
{
// 规定只填入路径作为参数
if (argc != 2)
{
std::cout << "pleas input the file path to be printed." << std::endl;
return -1;
}
/*传入的第一个参数作为路径*/
char *path = argv[1];
path = argv[1];
showDirecoryList(path); //开始文件夹递归打印
return 0;
}