-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathls.c
482 lines (468 loc) · 11.4 KB
/
ls.c
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
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <grp.h>
#include <pwd.h>
#include <sys/types.h>
#include <stddef.h>
#include <time.h>
#include <locale.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <wchar.h>
#define INITNUMBER 4
//各个数据的宽度
unsigned int w_nlink,w_uid,w_gid,w_size,w_time,w_name;
//是否为长输出
unsigned int isLong = 0;
//块总占用数
unsigned long total = 0;
//是否显示隐藏文件
unsigned int f_printAll = 0;
//是否反向排序
unsigned int isReverse = 0;
//储存文件数量
int fileNum = 0;
struct Filelist
{
char *name;
int isLink;
char *linkTo;
char mtime[128];
unsigned int column;
struct stat* buf;
char *path;
};
//用于储存数据的结构体组的指针files
struct Filelist **files = NULL;
//当前能存储的最大文件数量
int maxNum = INITNUMBER;
//处理参数
int dealArgv(int ,char *[]);
//读取文件夹的文件
int readFile(const char *);
//结构体排序所用参数函数
int mycmp(const void *,const void *);
//文件夹名字排序
int dir_cmp(const void *,const void *);
//计算名字宽度
int name_width(char * const );
//计算长输出的各个宽度
int width_for_long(struct Filelist **,int );
//输出权限
int print_per(struct Filelist *);
//输出nlink
int print_nlink(struct Filelist *);
//输出UId和GId
int print_Ids(struct Filelist *);
//输出文件大小
int print_size(struct Filelist *);
//输出mtime
int print_mtime(struct Filelist *);
//输出名字
int print_name(struct Filelist *);
//输出软链接目标文件
int print_link_to(struct Filelist *);
//长输出
int long_print(struct Filelist **,int );
//短输出
int short_print(struct Filelist **,int );
//主函数
int main(int argc,char *argv[])
{
setlocale(LC_ALL,"");
dealArgv(argc,argv);
return 0;
}
int dealArgv(int argc,char *argv[])
{
int i,fiNum=0,dirNum=0;
char **fiList = (char**)malloc(argc*sizeof(char*));
char **dirList = (char**)malloc(argc*sizeof(char*));
struct stat info;
int len=0;
for( i=1 ; i<argc ; ++i )
{
if(strcmp(argv[i],"-l")==0)
{
isLong = 1;
continue;
}
if(strcmp(argv[i],"-r")==0)
{
isReverse = 1;
continue;
}
if( strcmp(argv[i],"-a")==0 )
{
f_printAll = 1;
continue;
}
if(stat(argv[i],&info)==0)
{
if(S_ISDIR(info.st_mode))
{
len = strlen(argv[i]);
dirList[dirNum] = (char *)malloc(sizeof(char)*(len+1));
dirList[dirNum][len] = '\0';
strncpy(dirList[dirNum],argv[i],len+1);
dirNum++;
}
else
{
len = strlen(argv[i]);
fiList[fiNum] = (char *)malloc(sizeof(char)*(len+1));
fiList[fiNum][len] = '\0';
strncpy(fiList[fiNum],argv[i],len+1);
fiNum++;
}
}
else
printf("\"%s\" No such file or directory!\n",argv[i]);
}
if( fiNum+dirNum==0 )
{
//初始化结构体组指针的内存空间
files = (struct Filelist **)malloc(sizeof(struct Filelist*)*INITNUMBER);
readFile(".");
if(isLong)
{
printf("total:%lu\n",total);
long_print(files,fileNum);
}
else short_print(files,fileNum);
//释放结构体组指针所占的内存空间
free(files);
}
else
{
unsigned int temLen;
if( fiNum )
{
//初始化结构体组指针的内存空间
struct Filelist **temList = (struct Filelist **)malloc(sizeof(struct Filelist*)*fiNum);
for( i=0 ; i<fiNum ; ++i )
{
temLen = strlen(fiList[i]);
temList[i] = (struct Filelist *)malloc(sizeof(struct Filelist));
temList[i]->name = (char *)malloc(sizeof(char)*(temLen+1));
temList[i]->name[temLen] = '\0';
strncpy(temList[i]->name,fiList[i],temLen);
temList[i]->column = name_width(temList[i]->name);
//更新最大文件名长度
if( temList[i]->column > w_name )
w_name = temList[i]->column;
if( isLong )
{
temList[i]->buf = (struct stat*)malloc(sizeof(struct stat));
temList[i]->path = (char*)malloc(sizeof(char)*(temLen+1));
temList[i]->path[temLen] = '\0';
lstat(temList[i]->name,temList[i]->buf);
strncpy(temList[i]->path,fiList[i],temLen);
}
//释放内存
free(fiList[i]);
}
//文件夹名字排序
qsort(temList,fiNum,sizeof(temList[0]),mycmp);
//输出
if(isLong)
{
width_for_long(temList,fiNum);
long_print(temList,fiNum);
}
else
short_print(temList,fiNum);
free(temList);
//初始化
w_nlink=w_uid=w_gid=w_size=w_time=w_name=total=0;
printf("\n");
}
if( dirNum )
{
qsort(dirList,dirNum,sizeof(dirList[0]),dir_cmp);
for( i=0 ; i<dirNum ; ++i )
{
//初始化结构体组指针的内存空间
files = (struct Filelist **)malloc(sizeof(struct Filelist*)*INITNUMBER);
//读取数据
readFile(dirList[i]);
//输出
if(fiNum+dirNum>1)
printf("%s:\n",dirList[i]);
if(isLong)
{
printf("total:%lu\n",total);
long_print(files,fileNum);
}
else
short_print(files,fileNum);
free(files);
free(dirList[i]);
//初始化
w_nlink=w_uid=w_gid=w_size=w_time=w_name=total=0;
printf("\n");
}
}
}
free(fiList);
free(dirList);
return 0;
}
size_t length;
unsigned int temColumn;
int readFile(const char *path)
{
DIR *dir = NULL;
struct dirent *ptr = NULL;
dir = opendir(path);
maxNum = INITNUMBER;
fileNum=0;
while((ptr=readdir(dir)) != NULL)
{
if(ptr->d_name[0] == '.' && !f_printAll)
continue;
//使结构体组指针内存空间翻倍
if( fileNum == maxNum )
{
maxNum *= 2;
files = (struct Filelist**)realloc(files,sizeof(struct Filelist*)*maxNum);
}
//开辟内存空间储存名字和路径
length = strlen(ptr->d_name);
files[fileNum]=(struct Filelist*)malloc(sizeof(struct Filelist));
files[fileNum]->mtime[127] = '\0';
files[fileNum]->name = (char*)malloc((length+1)*sizeof(char));
files[fileNum]->name[length] = '\0';
strncpy(files[fileNum]->name,ptr->d_name,length);
files[fileNum]->column = name_width(ptr->d_name);
//更新最大文件名长度
if( files[fileNum]->column > w_name )
w_name = files[fileNum]->column;
//如果是长输出
if(isLong)
{
files[fileNum]->buf = (struct stat*)malloc(sizeof(struct stat));
if(strcmp(path,".")==0)
{
files[fileNum]->path = (char *)malloc(sizeof(char)*2);
strcpy(files[fileNum]->path,".");
lstat(files[fileNum]->name,files[fileNum]->buf);
}
else
{
files[fileNum]->path = (char *)malloc(sizeof(char)*(strlen(files[fileNum]->name)+strlen(path)+3));
files[fileNum]->path[0] = '\0';
strcpy(files[fileNum]->path,path);
strcat(files[fileNum]->path,"/");
strcat(files[fileNum]->path,files[fileNum]->name);
lstat(files[fileNum]->path,files[fileNum]->buf);
}
}
++fileNum;
}
if(isLong)
width_for_long(files,fileNum);
//按文件名升序排序
qsort(files,fileNum,sizeof(files[0]),mycmp);
closedir(dir);
return 0;
}
//结构体排序
int mycmp(const void *a,const void *b)
{
if (isReverse == 0)
return strcasecmp((*(struct Filelist**)a)->name,(*(struct Filelist**)b)->name);
else
return strcasecmp((*(struct Filelist**)b)->name,(*(struct Filelist**)a)->name);
}
//文件夹排序
int dir_cmp(const void *a,const void *b)
{
if (isReverse == 0)
return strcasecmp((char *)a,(char *)b);
else
return strcasecmp((char *)b,(char *)a);
}
//名字显示宽度
wchar_t temp[256];
int name_width(char * const name)
{
if( mbstowcs(temp,name,256*sizeof(wchar_t))!=(size_t)-1 )
return wcswidth(temp,sizeof(wchar_t)*256);
printf("mbstowcs error!\n");
return -1;
}
//计算长输出的各个宽度
unsigned int tempLen=0;
struct passwd *data1 = NULL;
struct group *data2 = NULL;
struct tm *mtm = NULL;
int width_for_long(struct Filelist ** list,int num)
{
int i=0;
for( ; i<num ; i++ )
{
//n_link的宽度
tempLen = snprintf(NULL,0,"%lu",list[i]->buf->st_nlink);
if(tempLen > w_nlink) w_nlink = tempLen;
//文件大小的宽度
tempLen = snprintf(NULL,0,"%ld",list[i]->buf->st_size);
if(tempLen > w_size) w_size = tempLen;
//UId和GId的宽度
data1 = getpwuid(list[i]->buf->st_uid);
data2 = getgrgid(list[i]->buf->st_gid);
if(strlen(data1->pw_name) > w_uid) w_uid = strlen(data1->pw_name);
if(strlen(data2->gr_name) > w_gid) w_gid = strlen(data2->gr_name);
//mtime宽度
mtm = localtime(&list[i]->buf->st_mtime);
strftime(list[i]->mtime,128,"%b %e %R",mtm);
if(strlen(list[i]->mtime) > w_time) w_time = strlen(list[i]->mtime);
//total
total += list[i]->buf->st_blocks;
}
return 0;
}
//输出权限
int print_per(struct Filelist * file)
{
file->isLink = 0;
if(S_ISCHR(file->buf->st_mode))
putchar('c');
else if(S_ISBLK(file->buf->st_mode))
putchar('b');
else if(S_ISLNK(file->buf->st_mode))
{
file->isLink = 1;
putchar('l');
}
else if(S_ISSOCK(file->buf->st_mode))
putchar('s');
else if(S_ISDIR(file->buf->st_mode))
putchar('d');
else if(S_ISREG(file->buf->st_mode))
putchar('-');
else
putchar('p');
if(file->buf->st_mode & S_IRUSR) putchar('r');
else putchar('-');
if(file->buf->st_mode & S_IWUSR) putchar('w');
else putchar('-');
if(file->buf->st_mode & S_ISUID) putchar('s');
else if(file->buf->st_mode & S_IXUSR) putchar('x');
else putchar('-');
if(file->buf->st_mode & S_IRGRP) putchar('r');
else putchar('-');
if(file->buf->st_mode & S_IWGRP) putchar('w');
else putchar('-');
if(file->buf->st_mode & S_ISGID) putchar('s');
else if(file->buf->st_mode & S_IXGRP) putchar('x');
else putchar('-');
if(file->buf->st_mode & S_IROTH) putchar('r');
else putchar('-');
if(file->buf->st_mode & S_IWOTH) putchar('w');
else putchar('-');
if(file->buf->st_mode & S_ISVTX) putchar('t');
else if(file->buf->st_mode & S_IXOTH) putchar('x');
else putchar('-');
putchar(' ');
return 0;
}
//输出nlink
int print_nlink(struct Filelist * file)
{
printf("%*lu ",w_nlink,file->buf->st_nlink);
return 0;
}
//输出UId和GId
int print_Ids(struct Filelist * file)
{
printf("%*s %*s ",w_uid,getpwuid(file->buf->st_uid)->pw_name,
w_gid,getgrgid(file->buf->st_gid)->gr_name);
return 0;
}
//输出文件大小
int print_size(struct Filelist * file)
{
printf("%*ld ",w_size,file->buf->st_size);
return 0;
}
//输出mtime
int print_mtime(struct Filelist * file)
{
printf("%*s ",w_time,file->mtime);
return 0;
}
//输出名字
int print_name(struct Filelist * file)
{
if( isLong )
printf("%-s ",file->name);
else
printf("%-s%*s",file->name,w_name-(file->column)+2,"");
free(file->name);
return 0;
}
//输出软链接目标文件
unsigned int sz;
int print_link_to(struct Filelist * file)
{
file->linkTo = (char*)malloc(file->buf->st_size+1);
sz = readlink(file->path,file->linkTo,file->buf->st_size+1);
file->linkTo[sz] = '\0';
printf("-> %-s",file->linkTo);
free(file->linkTo);
return 0;
}
//长输出
int long_print(struct Filelist ** list,int num)
{
int i=0;
for( ; i<num ; ++i )
{
print_per(list[i]);
print_nlink(list[i]);
print_Ids(list[i]);
print_size(list[i]);
print_mtime(list[i]);
print_name(list[i]);
if( list[i]->isLink )
print_link_to(list[i]);
free(list[i]->path);
free(list[i]->buf);
free(list[i]);
printf("\n");
}
return 0;
}
//短输出
int short_print(struct Filelist ** list,int num)
{
struct winsize size;
ioctl(STDIN_FILENO,TIOCGWINSZ,&size);
size.ws_col = size.ws_col;
int colNum = size.ws_col / (w_name+2);
int rowNum = (num+colNum-1) / colNum;
int r,c;
int temp;
for( r=0 ; r<rowNum ; ++r )
{
for( c=0 ; c<colNum ; ++c )
{
temp = c*rowNum+r;
if(temp<num)
{
print_name(list[temp]);
free(list[temp]);
}
else
printf("%-*s",w_name,"");
}
printf("\n");
}
return 0;
}