ls is used to list the contents of the directory. To achieve this function, there is no doubt that you need to read the directory, involving two APIs:
Opendir: DIR *opendir(const char *name), pass file name, return a pointer, point to directory sequence
Readdir: struct dirent *readdir(DIR *dirp). Pass the return value of opendir to a structure
struct dirent { ino_t d_ino; /* inode number */ off_t d_off; /* not an offset; see NOTES */ unsigned short d_reclen; /* length of this record */ unsigned char d_type; /* type of file; not supported by all filesystem types */ char d_name[256]; /* filename */ };
With these two APIs, you can implement a simple ls function
1 /*================================================================ 2 * Copyright (C) 2018 . All rights reserved. 3 * 4 * File name: myls.c 5 * Creator: ghostwu (Wu Hua) 6 * Date of establishment: January 9, 2018 7 * Description: ls command 8 * 9 ================================================================*/ 10 11 #include <stdio.h> 12 #include <sys/types.h> 13 #include <dirent.h> 14 #include <stdlib.h> 15 16 void do_ls( char [] ); 17 18 int main(int argc, char *argv[]) 19 { 20 if( argc == 1 ) { 21 do_ls( "." ); 22 }else { 23 while( --argc ) { 24 printf( "arg=%s\n", * ++argv ); 25 do_ls( *argv ); 26 } 27 } 28 return 0; 29 } 30 31 void do_ls( char dir_entry[] ) { 32 DIR* pDir; 33 struct dirent* pCurDir; 34 if( ( pDir = opendir( dir_entry ) ) == NULL ){ 35 perror( "read dir" ); 36 exit( -1 ); 37 }else { 38 while( ( pCurDir = readdir( pDir ) ) != NULL ) { 39 printf( "%s\n", pCurDir->d_name ); 40 } 41 } 42 }
This simple ls function lists all files (including hidden ones), but a lot of information is incomplete, such as permissions, users and groups, modification time, file size, number of links, etc. stat api can obtain these information of files
stat: get file status information
Prototype: int stat(const char *pathname, struct stat *buf), the first parameter: file name, the second parameter: the structure to save the file status information (man 2 stat has the description of the structure)
1. Get file size
1 /*================================================================ 2 * Copyright (C) 2018 . All rights reserved. 3 * 4 * File name: stat.c 5 * Creator: ghostwu (Wu Hua) 6 * Date of establishment: January 9, 2018 7 * Description: 8 * 9 ================================================================*/ 10 11 #include <stdio.h> 12 #include <sys/stat.h> 13 14 #define FILENAME "/etc/passwd" 15 16 int main(int argc, char *argv[]) 17 { 18 struct stat filestat; 19 20 if( -1 == stat( FILENAME, &filestat ) ) { 21 perror( "file stat" ); 22 return -1; 23 }else { 24 printf( "the size of %s is %ld\n",FILENAME, filestat.st_size ); 25 } 26 27 return 0; 28 }
2. Read file st mode, user id, group id, modification time, number of links
1 /*================================================================ 2 * Copyright (C) 2018 . All rights reserved. 3 * 4 * File name: stat2.c 5 * Creator: ghostwu (Wu Hua) 6 * Date of establishment: January 9, 2018 7 * Description: 8 * 9 ================================================================*/ 10 11 #include <stdio.h> 12 #include <sys/stat.h> 13 #include <string.h> 14 #include <time.h> 15 16 void show_info( char *file, struct stat* statinfo ); 17 void show_time( time_t filetime ); 18 char* format_time( char* dsttime, const char* srctime ); 19 20 int main(int argc, char *argv[]) 21 { 22 struct stat fileinfo; 23 if( argc > 1 ) { 24 /*debug information 25 printf( "%s\n", argv[1] ); 26 int res = stat( argv[1], &fileinfo ); 27 printf( "%d\n", res ); 28 */ 29 if( stat( argv[1], &fileinfo ) != -1 ) { 30 show_info( argv[1], &fileinfo ); 31 } 32 }else { 33 perror( "get args from terminal" ); 34 } 35 36 return 0; 37 } 38 39 void show_info( char* file, struct stat* statinfo ){ 40 printf( "%s The file information is as follows:\n", file ); 41 printf( "st_mode = %d\n", statinfo->st_mode ); 42 printf( "links = %ld\n", statinfo->st_nlink ); 43 printf( "uid = %d\n", statinfo->st_uid ); 44 printf( "gid = %d\n", statinfo->st_gid ); 45 printf( "file size = %ld\n", statinfo->st_size ); 46 show_time( statinfo->st_mtime ); 47 } 48 49 void show_time( time_t filetime ) { 50 struct tm* ptm; 51 ptm = localtime( &filetime ); 52 53 int month = ptm->tm_mon + 1; 54 int day = ptm->tm_mday; 55 int hour = ptm->tm_hour; 56 int min = ptm->tm_min; 57 58 char srchour[3] = "0"; 59 char srcmin[3] = "0"; 60 char dsthour[3] = "0"; 61 char dstmin[3] = "0"; 62 sprintf( srchour, "%d", hour ); 63 sprintf( srcmin, "%d", min ); 64 format_time( dsthour, srchour ); 65 format_time( dstmin, srcmin ); 66 67 printf( "File last modified: %d month\t%d\t%s:%s\n", month, day, dsthour, dstmin ); 68 } 69 70 char* format_time( char* dsttime, const char* srctime ) { 71 if( strlen( srctime ) < 2 ) { 72 return strcat( dsttime, srctime ); 73 } 74 return strcpy( dsttime, srctime ); 75 }
3. Permission st mode to character permission bit (for example: - rwxrwxrwx), user id and group id to user name and group name, determine file type
1 /*================================================================ 2 * Copyright (C) 2018 . All rights reserved. 3 * 4 * File name: stat3.c 5 * Creator: ghostwu (Wu Hua) 6 * Date of establishment: January 9, 2018 7 * Description: file type and permission bit 8 * 9 ================================================================*/ 10 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <sys/stat.h> 14 #include <string.h> 15 #include <sys/types.h> 16 #include <pwd.h> 17 #include <grp.h> 18 19 void do_ls( char* filename ); 20 void show_filetype( char* filename, int filemode ); 21 void show_filetype2( char* filename, int filemode ); 22 void mode_to_letters( int filemode, char str[] ); 23 //user id Transfer name 24 char* uid_to_name( uid_t uid ); 25 //group id Transfer name 26 char* gid_to_name( gid_t gid ); 27 28 int main(int argc, char *argv[]) 29 { 30 if( argc < 2 ) { 31 printf( "usage:%s file\n", argv[0] ); 32 return -1; 33 }else { 34 do_ls( argv[1] ); 35 } 36 return 0; 37 } 38 39 char* uid_to_name( uid_t uid ){ 40 return getpwuid( uid )->pw_name; 41 } 42 43 char* gid_to_name( gid_t gid ){ 44 return getgrgid( gid )->gr_name; 45 } 46 47 void do_ls( char* filename ) { 48 struct stat fileinfo; 49 if( stat( filename, &fileinfo ) == -1 ) { 50 printf( "%s open failure\n", filename ); 51 exit( -1 ); 52 } 53 //printf( "st_mode = %d\n", fileinfo.st_mode ); 54 show_filetype( filename, fileinfo.st_mode ); 55 show_filetype2( filename, fileinfo.st_mode ); 56 char file_permission[10]; 57 mode_to_letters( fileinfo.st_mode, file_permission ); 58 printf( "%s\n", file_permission ); 59 printf( "user:%s\n", uid_to_name( fileinfo.st_uid ) ); 60 printf( "group:%s\n", gid_to_name( fileinfo.st_gid ) ); 61 } 62 63 //Mask to determine file type 64 void show_filetype( char* filename, int filemode ){ 65 //use st_mode The result of the mask phase sum of Judge document type 66 if ( ( filemode & 0170000 ) == 0100000 ){ 67 printf( "%s It's a regular file\n", filename ); 68 }else if( ( filemode & 0170000 ) == 0040000 ){ 69 printf( "%s Is the catalog\n", filename ); 70 }else if ( ( filemode & S_IFMT ) == S_IFLNK ){ 71 printf( "%s Is a symbolic link\n", filename ); 72 } 73 } 74 75 //Using macro to judge file type 76 void show_filetype2( char* filename, int filemode ){ 77 if( S_ISREG( filemode ) ) { 78 printf( "%s It's a regular file\n", filename ); 79 }else if( S_ISDIR( filemode ) ) { 80 printf( "%s Is the catalog\n", filename ); 81 }else if( S_ISLNK( filemode ) ){ 82 printf( "%s Is a symbolic link\n", filename ); 83 } 84 } 85 86 //Decode numbers into alphanumeric permission bits 87 void mode_to_letters( int filemode, char str[] ) { 88 strcpy( str, "----------" ); 89 if( S_ISREG( filemode ) ) str[0] = '-'; 90 if( S_ISDIR( filemode ) ) str[0] = 'd'; 91 if( S_ISLNK( filemode ) ) str[0] = 'l'; 92 93 //User permission bit 94 if( filemode & S_IRUSR ) str[1] = 'r'; 95 if( filemode & S_IWUSR ) str[2] = 'w'; 96 if( filemode & S_IXUSR ) str[3] = 'x'; 97 98 //Group permission bit 99 if( filemode & S_IRGRP ) str[4] = 'r'; 100 if( filemode & S_IWGRP ) str[5] = 'w'; 101 if( filemode & S_IXGRP ) str[6] = 'x'; 102 103 //Other group permission bits 104 if( filemode & S_IROTH ) str[7] = 'r'; 105 if( filemode & S_IWOTH ) str[8] = 'w'; 106 if( filemode & S_IXOTH ) str[9] = 'x'; 107 }
Based on the above three small examples, a well formatted version of ls command can be obtained:
1 /*================================================================ 2 * Copyright (C) 2018 . All rights reserved. 3 * 4 * File name: myls2.c 5 * Creator: ghostwu (Wu Hua) 6 * Date of establishment: January 9, 2018 7 * Description: ls command (version 1.2) 8 * 9 ================================================================*/ 10 11 #include <stdio.h> 12 #include <sys/types.h> 13 #include <dirent.h> 14 #include <stdlib.h> 15 #include <sys/types.h> 16 #include <sys/stat.h> 17 #include <unistd.h> 18 #include <string.h> 19 #include <sys/types.h> 20 #include <pwd.h> 21 #include <grp.h> 22 #include <time.h> 23 24 void do_ls( char [] ); 25 void do_stat( char* filename ); 26 void show_list( char* filename, struct stat* statinfo ); 27 void mode_to_letters( mode_t filemode, char str[] ); 28 void show_time( time_t filetime ); 29 char* format_time( char* dsttime, const char* srctime ); 30 31 //user id Transfer name 32 char* uid_to_name( uid_t uid ); 33 //group id Transfer name 34 char* gid_to_name( gid_t gid ); 35 36 int main(int argc, char *argv[]) 37 { 38 if( argc == 1 ) { 39 do_ls( "." ); 40 }else { 41 while( --argc ) { 42 printf( "arg=%s\n", * ++argv ); 43 do_ls( *argv ); 44 } 45 } 46 return 0; 47 } 48 49 void do_ls( char dir_entry[] ) { 50 DIR* pDir; 51 struct dirent* pCurDir; 52 if( ( pDir = opendir( dir_entry ) ) == NULL ){ 53 perror( "read dir" ); 54 exit( -1 ); 55 }else { 56 while( ( pCurDir = readdir( pDir ) ) != NULL ) { 57 do_stat( pCurDir->d_name ); 58 } 59 closedir( pDir ); 60 } 61 } 62 63 //Get file information 64 void do_stat( char* filename ){ 65 struct stat statinfo; 66 if ( stat( filename, &statinfo ) == -1 ) { 67 printf( "open%s fail\n", filename ); 68 exit( -1 ); 69 }else { 70 show_list( filename, &statinfo ); 71 } 72 } 73 74 //Show file list 75 void show_list( char* filename, struct stat* statinfo ) { 76 mode_t st_mode = statinfo->st_mode; 77 78 char str[10]; 79 mode_to_letters( st_mode, str ); 80 printf( "%s\t", str ); 81 82 printf( "%ld\t", statinfo->st_nlink ); //Symbolic link 83 printf( "%s\t\t", uid_to_name( statinfo->st_uid ) ); //user name 84 printf( "%s\t", gid_to_name( statinfo->st_gid ) ); //Group name 85 printf( "%10ld", statinfo->st_size ); //file size 86 show_time( statinfo->st_mtime ); //Last modification time 87 printf( "\t%s", filename ); 88 89 printf( "\n" ); 90 } 91 92 char* uid_to_name( uid_t uid ){ 93 return getpwuid( uid )->pw_name; 94 } 95 96 char* gid_to_name( gid_t gid ){ 97 return getgrgid( gid )->gr_name; 98 } 99 100 void mode_to_letters( mode_t filemode, char str[] ) { 101 102 strcpy( str, "----------" ); 103 if( S_ISREG( filemode ) ) str[0] = '-'; 104 if( S_ISDIR( filemode ) ) str[0] = 'd'; 105 if( S_ISLNK( filemode ) ) str[0] = 'l'; 106 107 //User permission bit 108 if( filemode & S_IRUSR ) str[1] = 'r'; 109 if( filemode & S_IWUSR ) str[2] = 'w'; 110 if( filemode & S_IXUSR ) str[3] = 'x'; 111 112 //Group permission bit 113 if( filemode & S_IRGRP ) str[4] = 'r'; 114 if( filemode & S_IWGRP ) str[5] = 'w'; 115 if( filemode & S_IXGRP ) str[6] = 'x'; 116 117 //Other group permission bits 118 if( filemode & S_IROTH ) str[7] = 'r'; 119 if( filemode & S_IWOTH ) str[8] = 'w'; 120 if( filemode & S_IXOTH ) str[9] = 'x'; 121 } 122 123 void show_time( time_t filetime ) { 124 struct tm* ptm; 125 ptm = localtime( &filetime ); 126 127 int month = ptm->tm_mon + 1; 128 int day = ptm->tm_mday; 129 int hour = ptm->tm_hour; 130 int min = ptm->tm_min; 131 132 char srchour[3] = "0"; 133 char srcmin[3] = "0"; 134 char dsthour[3] = "0"; 135 char dstmin[3] = "0"; 136 sprintf( srchour, "%d", hour ); 137 sprintf( srcmin, "%d", min ); 138 format_time( dsthour, srchour ); 139 format_time( dstmin, srcmin ); 140 141 printf( "%4d month%4d%4s:%2s", month, day, dsthour, dstmin ); 142 } 143 144 char* format_time( char* dsttime, const char* srctime ) { 145 if( strlen( srctime ) < 2 ) { 146 return strcat( dsttime, srctime ); 147 } 148 return strcpy( dsttime, srctime ); 149 }
Summary:
1) The usage of opendir and readdir
2) Application of struct direct
3) Usage of stat