代码改变世界

实现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;