fc99a4052bf173bd24f88bc8d60008a72dd73980
[tpg/acess2.git] / Usermode / Applications / ls_src / main.c
1 /*
2  * Acess2 LS command
3  */
4 #include <acess/sys.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8
9 #define BUF_SIZE        1024
10
11 // === CONSTANTS ===
12 enum eFileTypes {
13         FTYPE_NORMAL,
14         FTYPE_EXEC,
15         FTYPE_DIR,
16         FTYPE_SYMLINK
17 };
18
19 // === PROTOTYPES ===
20  int    main(int argc, char *argv[]);
21 void    ShowUsage(char *ProgName);
22 void    ParseArguments(int argc, char *argv[]);
23 void    SortFileList();
24 void    DisplayFile(char *Filename);
25
26 // === GLOBALS ===
27 // --- Flags ---
28  int    gbShowAll = 0;
29  int    gbShowImplicit = 0;
30  int    gbViewExtended = 0;
31  int    gbViewHumanReadable = 0;
32 // --- Parameters ---
33 char    *gsDirectory = NULL;
34 // --- Working Set ---
35 char    **gFileList;
36  int    giNumFiles = 0;
37
38 /**
39  * \fn int main(int argc, char *argv[])
40  * \brief Entrypoint
41  */
42 int main(int argc, char *argv[])
43 {
44          int    fd, tmp;
45          int    i;
46         char    buf[BUF_SIZE+1];
47         t_sysFInfo      info;
48          int    space = 0;
49
50         // Arguments Check
51         ParseArguments(argc, argv);
52
53         // Open Directory
54         fd = open(gsDirectory, OPENFLAG_READ|OPENFLAG_EXEC);
55         if(fd == -1) {
56                 printf("Unable to open '%s' for reading\n", gsDirectory);
57                 return EXIT_FAILURE;
58         }
59
60         // Check that it is a directory
61         finfo(fd, &info, 0);
62         if( !(info.flags & FILEFLAG_DIRECTORY) ) {
63                 fprintf(stderr, "'%s' is a directory\n", gsDirectory);
64                 close(fd);
65                 return EXIT_FAILURE;
66         }
67
68         // Check if we should include the implicit . and ..
69         if(gbShowImplicit)
70         {
71                 space = 16;
72                 gFileList = malloc(space*sizeof(char*));
73                 gFileList[giNumFiles++] = ".";
74                 gFileList[giNumFiles++] = "..";
75         }
76
77         // Traverse Directory
78         while( (tmp = readdir(fd, buf)) )
79         {
80                 // Error check
81                 if(tmp < 0) {
82                         close(fd);
83                         return EXIT_FAILURE;
84                 }
85                 
86                 // Allocate Space
87                 if(space == giNumFiles)
88                 {
89                         space += 16;
90                         gFileList = realloc(gFileList, space*sizeof(char*));
91                         if(gFileList == NULL) {
92                                 close(fd);
93                                 return EXIT_FAILURE;
94                         }
95                 }
96                 gFileList[giNumFiles++] = strdup(buf);
97         }
98
99         // Sort File List according to rules passed
100         SortFileList();
101
102         // Show the file list
103         for( i = 0; i < giNumFiles; i ++ )
104         {
105                 DisplayFile( gFileList[i] );
106         }
107
108         close(fd);
109         printf("\n");
110
111         return EXIT_SUCCESS;
112 }
113
114 /**
115  * \fn void ShowUsage(char *ProgName)
116  */
117 void ShowUsage(char *ProgName)
118 {
119         fprintf(stderr, "Usage: %s [options] [<directory>]\n", ProgName);
120         fprintf(stderr, "\n");
121 }
122
123 /**
124  * \fn void ParseArguments(int argc, char *argv[])
125  * \brief Parse the command line arguments
126  */
127 void ParseArguments(int argc, char *argv[])
128 {
129          int    i;
130         char    *str;
131         for( i = 1; i < argc; i ++ )
132         {
133                 str = argv[i];
134                 // Flags
135                 if(str[0] == '-')
136                 {
137                         if(str[1] == '-')
138                         {
139                                 continue;
140                         }
141                         str = &str[1];
142                         for( ; *str; str++ )
143                         {
144                                 switch(*str)
145                                 {
146                                 // Show All
147                                 case 'a':       gbShowAll = 1;  gbShowImplicit = 1;     continue;
148                                 // Almost All
149                                 case 'A':       gbShowAll = 1;  gbShowImplicit = 0;     continue;
150                                 // Extended List
151                                 case 'l':       gbViewExtended = 1;     continue;
152                                 // Human readable sizes
153                                 case 'h':       gbViewHumanReadable = 1;        continue;
154                                 default:
155                                         fprintf(stderr, "%s: Unknown option '%c'\n", *str);
156                                         ShowUsage(argv[0]);
157                                         exit(EXIT_FAILURE);
158                                 }
159                         }
160                         continue;
161                 }
162                 
163                 if(gsDirectory == NULL) {
164                         gsDirectory = argv[i];
165                 }
166         }
167         
168         // Apply Defaults
169         if(!gsDirectory)        gsDirectory = ".";
170         
171         printf("gsDirectory = '%s'\n", gsDirectory);
172 }
173
174 /**
175  * \fn int strcmpp(void *p1, void *p2)
176  * \brief Compares two strings given pointers to their pointers
177  */
178 int strcmpp(const void *p1, const void *p2)
179 {
180         return strcmp( *(char **)p1, *(char **)p2 );
181 }
182
183 /**
184  * \fn void SortFileList()
185  * \brief Sorts the filled file list
186  */
187 void SortFileList()
188 {
189         qsort(gFileList, giNumFiles, sizeof(char*), strcmpp);
190 }
191
192 /**
193  * \fn void DisplayFile(char *Filename)
194  * \brief Prints out the information for a file
195  */
196 void DisplayFile(char *Filename)
197 {
198         t_sysFInfo      info;
199         t_sysACL        acl;
200         char    *path;
201          int    fd;
202          int    dirLen = strlen(gsDirectory);
203          int    type = FTYPE_NORMAL, perms = 0;
204         uint64_t        size = 0;
205          int    owner = 0, group = 0;
206         
207         // Check if we should skip this file
208         if(!gbShowAll && Filename[0] == '.')    return;
209         
210         // Allocate path
211         path = malloc(dirLen+1+strlen(Filename)+1);
212         if(!path) {
213                 fprintf(stderr, "heap exhausted\n");
214                 exit(EXIT_FAILURE);
215         }
216         
217         // Create path
218         strcpy(path, gsDirectory);
219         path[dirLen] = '/';
220         strcpy(&path[dirLen+1], Filename);
221         
222         // Get file type
223         fd = open(path, 0);
224         if(fd == -1) {
225                 fprintf(stderr, "Unable to open '%s'\n", path);
226         }
227         else {
228                 // Get Info
229                 finfo(fd, &info, 0);
230                 // Get Type
231                 if(info.flags & FILEFLAG_DIRECTORY) {
232                         type = FTYPE_DIR;
233                 }
234                 else if(info.flags & FILEFLAG_SYMLINK) {
235                         type = FTYPE_SYMLINK;
236                 }
237                 else {
238                         type = FTYPE_NORMAL;
239                 }
240                 // Get Size
241                 size = info.size;
242                 // Get Owner and Group
243                 owner = info.uid;
244                 group = info.gid;
245                 
246                 // Get Permissions
247                 // - Owner
248                 acl.group = 0;  acl.id = info.uid;
249                 _SysGetACL(fd, &acl);
250                 if(acl.perms & 1)       perms |= 0400;  // R
251                 if(acl.perms & 2)       perms |= 0200;  // W
252                 if(acl.perms & 8)       perms |= 0100;  // X
253                 // - Group
254                 acl.group = 1;  acl.id = info.gid;
255                 _SysGetACL(fd, &acl);
256                 if(acl.perms & 1)       perms |= 0040;  // R
257                 if(acl.perms & 2)       perms |= 0020;  // W
258                 if(acl.perms & 8)       perms |= 0010;  // X
259                 // - World
260                 acl.group = 1;  acl.id = -1;
261                 _SysGetACL(fd, &acl);
262                 if(acl.perms & 1)       perms |= 0004;  // R
263                 if(acl.perms & 2)       perms |= 0002;  // W
264                 if(acl.perms & 8)       perms |= 0001;  // X
265         }
266         free(path);     // We're finished with it
267         
268         // Extended view?
269         if(gbViewExtended)
270         {
271                 char    permStr[11] = " ---------";
272                 if(type == FTYPE_DIR)   permStr[0] = 'd';
273                 if(perms & 0400)        permStr[1] = 'r';
274                 if(perms & 0200)        permStr[2] = 'w';
275                 if(perms & 0100)        permStr[3] = 'x';
276                 if(perms & 0040)        permStr[4] = 'r';
277                 if(perms & 0020)        permStr[5] = 'w';
278                 if(perms & 0010)        permStr[6] = 'x';
279                 if(perms & 0004)        permStr[7] = 'r';
280                 if(perms & 0002)        permStr[8] = 'w';
281                 if(perms & 0001)        permStr[9] = 'x';
282                 printf("%s %4i %4i ", permStr, owner, group);
283                 if(gbViewHumanReadable) {
284                         if(size < 2048) {       // < 2 KiB
285                                 printf("%8lli B   ", size);
286                         }
287                         else if(size < 2048*1024) {     // < 2 MiB
288                                 printf("%8lli KiB ", size>>10);
289                         }
290                         else if(size < (uint64_t)2048*1024*1024) {      // < 2 GiB
291                                 printf("%8lli MiB ", size>>20);
292                         }
293                         else if(size < (uint64_t)2048*1024*1024*1024) { // < 2 TiB
294                                 printf("%8lli GiB ", size>>30);
295                         }
296                         else {  // Greater than 2 TiB
297                                 printf("%8i TiB ", size>>40);
298                         }
299                 } else {
300                         printf("%8i ", size);
301                 }
302         }
303         
304         printf("%s\n", Filename);
305 }

UCC git Repository :: git.ucc.asn.au