Linux---Ls命令 初级实现
By xxx0624
Done:
ls
ls -a
ls -l
ls /tmp
ls -R
ls -t
FileName color
FileName output
1 /* 2 By xxx0624 3 Done: 4 ls 5 ls -a 6 ls -l 7 ls /tmp 8 ls -R 9 ls -t 10 FileName color 11 FileName output 12 */ 13 14 #include<stdio.h> 15 #include<string.h> 16 #include<stdlib.h> 17 #include<sys/types.h> 18 #include<sys/stat.h> 19 #include<sys/ioctl.h> 20 #include<dirent.h> 21 #include<pwd.h> 22 #include<grp.h> 23 #include<unistd.h> 24 /*head file*/ 25 26 27 #define LenOfName 256 28 #define maxN 1005 29 #define maxM 505 30 #define maxL 105 31 #define LenOfPath 256<<4 32 #define LS 0 //ls 33 #define LS_A 1 //ls -a 34 #define LS_L 2 //ls -l 35 #define LS_TMP 3 //ls /tmp 36 #define LS_R 4 //ls -R 37 #define LS_T 5 //ls -t 38 /*define file*/ 39 40 41 void do_ls( int,char [] ); 42 void dostat( char * ); 43 void show_file_info( char *,struct stat * ); 44 void mode_to_letters( int,char [] ); 45 char *uid_to_name( uid_t ); 46 char *gid_to_name( gid_t ); 47 void getcolor( char * ); 48 int get_file_type( char * ); 49 int get_modify_time( char * ); 50 void getWidth(); 51 void display_R( char * ); 52 int cmp1( const void * ,const void * ); 53 int cmp2( const void * ,const void * ); 54 int cmp3( const void * ,const void * ); 55 56 57 struct outputFile{ 58 char FileName[ LenOfName ]; 59 int modify_time ; 60 int file_type ; 61 }Output[ maxN ],OutputPoint[ maxM ],Temp[ maxN+maxM ]; 62 int colormode,foreground,background; 63 int terminalWidth ; 64 65 66 void dostat( char *filename ){ 67 struct stat info; 68 if( stat( filename,&info )==-1 ){ 69 perror( filename ); 70 } 71 else{ 72 getcolor( filename ); 73 show_file_info( filename,&info ); 74 } 75 return ; 76 } 77 /*get file info*/ 78 79 80 void mode_to_letters( int mode,char str[] ){ 81 strcpy( str,"----------" ); 82 83 if( S_ISDIR( mode ) ) str[0] = 'd'; 84 if( S_ISCHR( mode ) ) str[0] = 'c'; 85 if( S_ISBLK( mode ) ) str[0] = 'b'; 86 87 if( mode&S_IRUSR ) str[1] = 'r'; 88 if( mode&S_IWUSR ) str[2] = 'w'; 89 if( mode&S_IXUSR ) str[3] = 'x'; 90 91 if( mode&S_IRGRP ) str[4] = 'r'; 92 if( mode&S_IWGRP ) str[5] = 'w'; 93 if( mode&S_IXGRP ) str[6] = 'x'; 94 95 if( mode&S_IROTH ) str[7] = 'r'; 96 if( mode&S_IWOTH ) str[8] = 'w'; 97 if( mode&S_IXOTH ) str[9] = 'x'; 98 99 return ; 100 } 101 102 103 char *uid_to_name( uid_t uid ){ 104 struct passwd *pw_ptr; 105 static char numstr[ 10 ]; 106 if( (pw_ptr = getpwuid( uid ) )==NULL ){ 107 sprintf(numstr,"%d",uid); 108 return numstr; 109 } 110 else{ 111 return pw_ptr->pw_name; 112 } 113 } 114 char *gid_to_name( gid_t gid ){ 115 struct group *grp_ptr; 116 static char numstr[ 10 ]; 117 if( (grp_ptr = getgrgid( gid ) )==NULL ){ 118 sprintf(numstr,"%d",gid); 119 return numstr; 120 } 121 else{ 122 return grp_ptr->gr_name; 123 } 124 } 125 /*get userid & groupid*/ 126 127 128 int get_file_type( char *filename ){ 129 struct stat info; 130 stat( filename,&info ); 131 int file_type = 0; 132 file_type = info.st_mode & S_IFMT; 133 return file_type; 134 } 135 /*get file type*/ 136 137 138 int get_modify_time( char *filename ){ 139 struct stat info; 140 stat( filename,&info ); 141 int modify_time = 0; 142 modify_time = info.st_mtime; 143 return modify_time; 144 } 145 /*get file last modify time*/ 146 147 148 int isadir(char *str) 149 { 150 struct stat info; 151 152 return ( lstat(str,&info) != -1 && S_ISDIR(info.st_mode) ); 153 } 154 /*judge the file is or not a dir*/ 155 156 157 void display_R( char *filename ){ 158 char fullpath[ LenOfPath ]; 159 struct outputFile Output2[ maxN ]; 160 getcolor( filename ); 161 printf("\033[%d;%d;%dm%s\033[0m :\n",colormode,foreground,background,filename); 162 DIR * dir_ptr ; 163 struct dirent *direntp; 164 int cntTemp = 0; 165 int i ; 166 if( (dir_ptr = opendir( filename ) )==NULL ){ 167 fprintf( stderr,"myls:cannot open %s\n",filename ); 168 closedir( dir_ptr ); 169 return ; 170 } 171 else { 172 while( (direntp = readdir( dir_ptr ))!=NULL ){ 173 if( strcmp( direntp->d_name,"." )==0||strcmp( direntp->d_name,".." )==0 ) 174 continue; 175 strcpy( Output2[ cntTemp ].FileName,direntp->d_name ); 176 strcpy( Output[ cntTemp ].FileName,direntp->d_name ); 177 cntTemp ++ ; 178 } 179 closedir( dir_ptr ); 180 if( cntTemp>1 ){ 181 qsort( Output2,cntTemp,sizeof( Output2[0] ),cmp1 ); 182 qsort( Output,cntTemp,sizeof( Output[0] ),cmp1 ); 183 } 184 display_Ls( cntTemp ); 185 for( i=0;i<cntTemp;i++ ){ 186 memset( fullpath,'\0',sizeof( fullpath ) ); 187 strcpy( fullpath,filename ); 188 strcat( fullpath,"/" ); 189 strcat( fullpath,Output2[ i ].FileName ); 190 if( isadir( fullpath ) ) 191 display_R( fullpath ); 192 } 193 } 194 return ; 195 } 196 /*active ls -R && Output */ 197 198 199 void getWidth(){ 200 char *tp; 201 struct winsize wbuf; 202 terminalWidth = 80; 203 if( isatty(STDOUT_FILENO) ){ 204 if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &wbuf) == -1 || wbuf.ws_col == 0){ 205 if( tp = getenv("COLUMNS") ) 206 terminalWidth = atoi( tp ); 207 } 208 else 209 terminalWidth = wbuf.ws_col; 210 } 211 return ; 212 } 213 /****************************************************************** 214 得出终端的宽度,默认宽度为80,如果获取失败,将激活-1选项 215 *******************************************************************/ 216 217 218 219 int cmp1( const void *p ,const void *q ){ 220 char T1[ LenOfName ],T2[ LenOfName ]; 221 strcpy( T1,(*(struct outputFile *)p).FileName ); 222 strcpy( T2,(*(struct outputFile *)q).FileName ); 223 int len1 = strlen( T1 ); 224 int i ; 225 for( i=0;i<len1;i++ ){ 226 if( T1[ i ]>='A' && T1[ i ]<='Z' ){ 227 T1[ i ] = T1[ i ] - 'A' + 'a'; 228 } 229 } 230 int len2 = strlen( T2 ); 231 for( i=0;i<len2;i++ ){ 232 if( T2[ i ]>='A' && T2[ i ]<='Z' ){ 233 T2[ i ] = T2[ i ] - 'A' + 'a'; 234 } 235 } 236 return strcmp( T1,T2 ); 237 } 238 /******************************************************** 239 文件名排序 cmp1 240 *********************************************************/ 241 242 243 244 int cmp2( const void *p,const void *q ){ 245 return (*(struct outputFile *)p).file_type < (*(struct outputFile *)q).file_type ; 246 } 247 /******************************************************** 248 文件类型排序 cmp2 249 *********************************************************/ 250 251 252 253 int cmp3( const void *p,const void *q ){ 254 return (*(struct outputFile *)p).modify_time < (*(struct outputFile *)q).modify_time ; 255 } 256 /******************************************************** 257 文件修改时间排序 cmp3 258 *********************************************************/ 259 260 261 262 void show_file_info( char *filename,struct stat * info_p ){ 263 char modestr[ 12 ]; 264 265 mode_to_letters( info_p->st_mode,modestr ); 266 267 printf("%s",modestr); 268 printf("%4d ",(int)info_p->st_nlink); 269 printf("%-8s ",uid_to_name(info_p->st_uid)); 270 printf("%-8s ",gid_to_name(info_p->st_gid)); 271 printf("%8ld ",(long)info_p->st_size); 272 printf("%.12s ",4+ctime(&info_p->st_mtime)); 273 printf("\033[%d;%d;%dm%s\033[0m\n",colormode,foreground,background,filename); 274 return ; 275 } 276 /******************************************************* 277 ls -l 的输出 278 ********************************************************/ 279 280 281 282 void getcolor( char *filename ){ 283 struct stat info; 284 stat( filename,&info ); 285 foreground = 37; 286 background = 1; 287 colormode = 0; 288 switch ( (info.st_mode & S_IFMT) ){ 289 case S_IFREG: /*regular 普通文件 , 白色*/ 290 foreground = 37; 291 break; 292 case S_IFLNK: /*symbolic link 链接文件 , 青蓝色*/ 293 foreground = 36; 294 colormode = 1; 295 break; 296 case S_IFSOCK: /*紫红色*/ 297 foreground = 35; 298 colormode = 1; 299 break; 300 case S_IFDIR: /*directory 目录文件 , 蓝色*/ 301 foreground = 34; 302 break; 303 case S_IFBLK: /*block special 块设备文件 , 黄色*/ 304 foreground = 33; 305 colormode = 1; 306 break; 307 case S_IFCHR: /*character special 字符设备文件 , 黄色*/ 308 foreground = 33; 309 colormode = 1; 310 break; 311 case S_IFIFO: /*fifo 绿色*/ 312 foreground = 32; 313 colormode = 1; 314 break; 315 } 316 } 317 /******************************************************* 318 给文件添加颜色 319 ********************************************************/ 320 321 322 323 void display_Ls( int cnt ){ 324 int wordLenMax = 0;//the LenMax word 325 int wordRowNum = 0;//the amount of one row 326 int wordColNum = 0;//the amount of one col 327 int i , j; 328 for( i=0;i<cnt;i++ ){ 329 if( i==0 ) wordLenMax = strlen( Output[ i ].FileName ); 330 else wordLenMax = wordLenMax>strlen( Output[ i ].FileName )?wordLenMax:strlen( Output[ i ].FileName ); 331 } 332 wordLenMax += 2; 333 wordRowNum = terminalWidth / wordLenMax; 334 if( cnt%wordRowNum==0 ) wordColNum = cnt / wordRowNum; 335 else wordColNum = cnt / wordRowNum + 1; 336 for( i=0;i<wordColNum;i++ ){ 337 j = i; 338 while( j<cnt ){ 339 getcolor( Output[ j ].FileName ); 340 printf("\033[%d;%d;%dm%-15s\033[0m ",colormode,foreground,background,Output[ j ].FileName); 341 j += wordColNum; 342 } 343 printf("\n"); 344 } 345 return ; 346 } 347 /********************************************************** 348 ls的分栏输出 349 ***********************************************************/ 350 351 352 353 void display_Ls_a( int cntPoint,int cnt ){ 354 int CNT = 0; 355 int wordLenMax = 0;//the LenMax word 356 int wordRowNum = 0;//the amount of one row 357 int wordColNum = 0;//the amount of one col 358 int i , j; 359 for( i=0;i<cntPoint;i++ ){ 360 strcpy( Temp[ CNT ].FileName,OutputPoint[ i ].FileName ); 361 Temp[ CNT ].file_type = OutputPoint[ i ].file_type; 362 Temp[ CNT ].modify_time = OutputPoint[ i ].modify_time; 363 CNT ++; 364 wordLenMax = wordLenMax>strlen( OutputPoint[ i ].FileName )?wordLenMax:strlen( OutputPoint[ i ].FileName ); 365 } 366 for( i=0;i<cnt;i++ ){ 367 strcpy( Temp[ CNT ].FileName,Output[ i ].FileName ); 368 Temp[ CNT ].file_type = Output[ i ].file_type; 369 Temp[ CNT ].modify_time = Output[ i ].modify_time; 370 CNT ++; 371 wordLenMax = wordLenMax>strlen( Output[ i ].FileName )?wordLenMax:strlen( Output[ i ].FileName ); 372 } 373 wordLenMax += 2; 374 wordRowNum = terminalWidth / wordLenMax; 375 if( CNT%wordRowNum==0 ) wordColNum = CNT / wordRowNum; 376 else wordColNum = CNT / wordRowNum + 1; 377 for( i=0;i<wordColNum;i++ ){ 378 j = i; 379 while( j<CNT ){ 380 getcolor( Temp[ j ].FileName ); 381 printf("\033[%d;%d;%dm%-15s\033[0m ",colormode,foreground,background,Temp[ j ].FileName); 382 j += wordColNum; 383 } 384 printf("\n"); 385 } 386 return ; 387 } 388 /********************************************************** 389 ls -a 的分栏输出 390 ***********************************************************/ 391 392 393 394 void display_Ls_tmp( int cnt ){ 395 display_Ls( cnt ); 396 return ; 397 } 398 /********************************************************** 399 ls /tmp 的分栏输出 400 ***********************************************************/ 401 402 403 404 void display_Ls_R( char *filename ){ 405 char fullpath[ LenOfPath ]; 406 strcpy( fullpath,get_current_dir_name() ); 407 strcat( fullpath,"/" ); 408 strcat( fullpath,filename ); 409 display_R( fullpath ); 410 return ; 411 } 412 /********************************************************** 413 ls -R 的分栏输出 414 ***********************************************************/ 415 416 417 418 void do_ls( int myJudge,char myOrder[] ){ 419 if( myJudge==LS_R ){ 420 display_Ls_R( "." ); 421 return ; 422 } 423 /********************************************************** 424 ls -R 425 ***********************************************************/ 426 char dirname[ maxL ]; 427 if( myJudge!=LS_TMP ){ 428 strcpy( dirname,"." ); 429 } 430 else { 431 strcpy( dirname,myOrder ); 432 } 433 DIR * dir_ptr; 434 struct dirent *direntp; 435 int cntOutput = 0; 436 int cntOutputPoint = 0; 437 if( ( dir_ptr = opendir( dirname ) )==NULL ){ 438 fprintf( stderr,"myls:cannot open %s\n",dirname ); 439 } 440 else{ 441 while( (direntp = readdir( dir_ptr ) )!=NULL ){ 442 if( direntp->d_name[ 0 ]=='.' ) { 443 strcpy( OutputPoint[ cntOutputPoint ].FileName,direntp->d_name ); 444 OutputPoint[ cntOutputPoint ].file_type = get_file_type( OutputPoint[ cntOutputPoint ].FileName ); 445 OutputPoint[ cntOutputPoint ].modify_time = get_modify_time( OutputPoint[ cntOutputPoint ].FileName ); 446 cntOutputPoint ++; 447 } 448 else { 449 strcpy( Output[ cntOutput ].FileName,direntp->d_name ); 450 Output[ cntOutput ].file_type = get_file_type( Output[ cntOutput ].FileName ); 451 Output[ cntOutput ].modify_time = get_modify_time( Output[ cntOutput ].FileName ); 452 cntOutput ++; 453 } 454 } 455 456 if( myJudge==LS_T ){ 457 qsort( OutputPoint,cntOutputPoint,sizeof( OutputPoint[0] ),cmp3 ); 458 qsort( Output,cntOutput,sizeof( Output[0] ),cmp3 ); 459 } 460 else { 461 qsort( OutputPoint,cntOutputPoint,sizeof( OutputPoint[0] ),cmp1 ); 462 qsort( Output,cntOutput,sizeof( Output[0] ),cmp1 ); 463 } 464 /********************************************************** 465 预处理输出 466 ***********************************************************/ 467 if( myJudge==LS||myJudge==LS_T ){ 468 display_Ls( cntOutput ); 469 closedir( dir_ptr ); 470 } 471 /********************************************************** 472 ls && ls -t 473 ***********************************************************/ 474 else if( myJudge==LS_A ){ 475 display_Ls_a( cntOutputPoint,cntOutput ); 476 closedir( dir_ptr ); 477 } 478 /********************************************************** 479 ls -a 480 ***********************************************************/ 481 else if( myJudge==LS_L ){ 482 int i; 483 for( i=0;i<cntOutput;i++ ) 484 dostat( Output[ i ].FileName ); 485 closedir( dir_ptr ); 486 } 487 /********************************************************** 488 ls -l 489 ***********************************************************/ 490 else { 491 display_Ls_tmp( cntOutput ); 492 closedir( dir_ptr ); 493 } 494 /********************************************************** 495 ls /tmp 496 ***********************************************************/ 497 } 498 return ; 499 }/*sovle*/ 500 501 502 int main( int argc, char *argv[] ){ 503 getWidth( ); 504 int i ; 505 if( argc==1 ){ 506 do_ls( LS,"ls" ); 507 } 508 else{ 509 int ord; 510 while( (ord = getopt(argc,argv,":laRt"))!=-1 ){ 511 switch( ord ){ 512 case 'a': 513 do_ls( LS_A,"ls-a" ); 514 break; 515 case 'l': 516 do_ls( LS_L,"ls-l" ); 517 break; 518 case 'R': 519 do_ls( LS_R,"ls-R" ); 520 break; 521 case 't': 522 do_ls( LS_T,"ls-t" ); 523 break; 524 default : 525 break; 526 } 527 } 528 for( i=1;i<argc;i++ ){ 529 if( argv[ i ][ 0 ]=='-' ) continue; 530 printf("%s:\n",argv[ i ]); 531 do_ls( LS_TMP,argv[ i ] ); 532 } 533 } 534 return 0; 535 } 536 /*main*/
keep moving...