实现Linux下的ls -l命令
2015-03-31 22:29 微尘_无名 阅读(477) 评论(0) 编辑 收藏 举报基本实现了Linux下的ls -l命令,对于不同的文件显示不同的颜色和显示符号链接暂时没有实现:
1 /************************************************************************* 2 > File Name: dirwalk.c 3 > Author: 4 > Mail: 5 > Created Time: Tue 31 Mar 2015 11:56:38 AM CST 6 ************************************************************************/ 7 8 #include<stdio.h> 9 #include <sys/types.h> 10 #include <sys/stat.h> 11 #include <fcntl.h> 12 #include <unistd.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <dirent.h> 16 #include <time.h> 17 18 #define MAX_PATH 1024 19 #define MODE_LEN 10 20 #define TIME_LEN 20 21 #define NAME_LEN 30 22 23 unsigned long ugo_mode[9] = {S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH}; 24 char* rwx[3] = {"r", "w", "x"}; 25 char* userpath = "/etc/passwd"; 26 char* grouppath = "/etc/group"; 27 28 /*dirwalk: apply fcn to all files in dir */ 29 void dirwalk(char* dir, void(*fcn)(char*)) 30 { 31 struct dirent *dp; 32 DIR* dfd; 33 34 char name[MAX_PATH]; 35 if((dfd = opendir(dir)) == NULL) 36 { 37 fprintf(stderr, "dirwalk: can't open %s\n", dir); 38 return; 39 } 40 41 while((dp = readdir(dfd)) != NULL) 42 { 43 if(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) 44 { 45 continue; 46 } 47 48 if(strlen(dir) + strlen(dp->d_name) + 2 > sizeof(name)) 49 { 50 fprintf(stderr, "%s/%s too long\n", dir, dp->d_name); 51 }else 52 { 53 sprintf(name, "%s/%s", dir, dp->d_name); 54 (*fcn)(name); 55 } 56 } 57 closedir(dfd); 58 } 59 60 /*getname: get the name of the user and the name of the group name */ 61 void getname(char* path, int id, char* name) 62 { 63 64 int fd, save_fd; 65 if((fd = open(path, O_RDONLY)) < 0) 66 { 67 perror("open \n"); 68 exit(1); 69 } 70 71 save_fd = dup(STDIN_FILENO); 72 dup2(fd, STDIN_FILENO); 73 close(fd); 74 char p[MAX_PATH]; 75 char usrid[20]; 76 sprintf(usrid, "%d", id); 77 char* puid; 78 while((scanf("%s", p)) != EOF) 79 { 80 if((puid = strstr(p, usrid)) != NULL) 81 { 82 char* pFlag; 83 char* pResult; 84 if((pFlag = strstr(p, ":")) != NULL) 85 { 86 pResult = pFlag; 87 pFlag = strstr(pFlag + 1, ":"); 88 } 89 if(pFlag != NULL) 90 { 91 if((memcmp(pFlag + 1, puid, strlen(usrid))) == 0) 92 { 93 *pResult = '\0'; 94 strcpy(name, p); 95 } 96 } 97 //printf("%s\n", puid); 98 } 99 } 100 101 dup2(save_fd, STDIN_FILENO); 102 close(save_fd); 103 } 104 105 /*getmode: get the mode of a file in string format by st_mode */ 106 void getmode(unsigned long st_mode, char* mode) 107 { 108 switch(st_mode & S_IFMT) 109 { 110 case S_IFDIR: 111 mode[0] = 'd'; 112 break; 113 case S_IFIFO: 114 mode[0] = 'p'; 115 break; 116 case S_IFBLK: 117 mode[0] = 'b'; 118 break; 119 case S_IFCHR: 120 mode[0] = 'c'; 121 break; 122 case S_IFREG: 123 mode[0] = '-'; 124 break; 125 case S_IFLNK: 126 mode[0] = 'l'; 127 break; 128 case S_IFSOCK: 129 mode[0] = 's'; 130 break; 131 default: 132 mode[0] = 'u'; 133 break; 134 } 135 136 int i; 137 for(i = 0; i < 9; ++i) 138 { 139 if(st_mode & ugo_mode[i]) 140 { 141 strcat(mode, rwx[i % 3]); 142 }else 143 { 144 strcat(mode, "-"); 145 } 146 } 147 } 148 149 150 /*gettime: get the time in string format */ 151 void gettime(const time_t ct, char* time) 152 { 153 char* tmp = ctime(&ct); 154 time[0] = tmp[4]; 155 time[1] = tmp[5]; 156 time[2] = tmp[6]; 157 time[3] = ' '; 158 159 struct tm* tm_buf = gmtime(&ct); 160 char last[20]; 161 sprintf(last, "%02d %02d:%02d", tm_buf->tm_mday, tm_buf->tm_hour, tm_buf->tm_min); 162 strcat(time, last); 163 } 164 165 /* print the file name and the size of the "name" */ 166 void fsize(char* name) 167 { 168 struct stat st_buf; 169 if(stat(name, &st_buf) < 0) 170 { 171 fprintf(stderr, "fsize: can't access %s\n", name); 172 return; 173 } 174 175 176 177 if((st_buf.st_mode & S_IFMT) == S_IFDIR) 178 { 179 dirwalk(name, fsize); 180 } 181 char* time = (char*)malloc(sizeof(char) * TIME_LEN); 182 memset(time, 0, TIME_LEN); 183 gettime(st_buf.st_atime, time); 184 185 char* mode = (char*)malloc(sizeof(char) * MODE_LEN); 186 memset(mode, 0, MODE_LEN); 187 getmode(st_buf.st_mode, mode); 188 189 190 char* username = (char*)malloc(sizeof(char) * NAME_LEN); 191 memset(username, 0, NAME_LEN); 192 getname(userpath, st_buf.st_uid, username); 193 194 char* groupname = (char*)malloc(sizeof(char) * NAME_LEN); 195 memset(groupname, 0, NAME_LEN); 196 getname(grouppath, st_buf.st_gid, groupname); 197 198 printf("%s %d %s %s %4ld %s %s\n", mode, (int)st_buf.st_nlink, username, groupname, st_buf.st_size, time, name); 199 free(groupname); 200 free(username); 201 free(mode); 202 free(time); 203 } 204 205 int main(int argc, char* argv[]) 206 { 207 if(argc == 1) 208 fsize("."); 209 while(--argc) 210 fsize(*++argv); 211 return 0;