20 int main(int argc, char *argv[]);
21 void ShowUsage(char *ProgName);
22 void ParseArguments(int argc, char *argv[]);
24 void DisplayFile(char *Filename);
29 int gbShowImplicit = 0;
30 int gbViewExtended = 0;
31 int gbViewHumanReadable = 0;
33 char *gsDirectory = NULL;
34 // --- Working Set ---
39 * \fn int main(int argc, char *argv[])
42 int main(int argc, char *argv[])
51 ParseArguments(argc, argv);
54 fd = _SysOpen(gsDirectory, OPENFLAG_READ|OPENFLAG_EXEC);
56 printf("Unable to open '%s' for reading\n", gsDirectory);
60 // Check that it is a directory
61 _SysFInfo(fd, &info, 0);
62 if( !(info.flags & FILEFLAG_DIRECTORY) ) {
63 fprintf(stderr, "'%s' is not a directory\n", gsDirectory);
68 // Check if we should include the implicit . and ..
72 gFileList = malloc(space*sizeof(char*));
73 gFileList[giNumFiles++] = ".";
74 gFileList[giNumFiles++] = "..";
78 while( (tmp = _SysReadDir(fd, buf)) > 0 )
87 if(space == giNumFiles)
90 gFileList = realloc(gFileList, space*sizeof(char*));
91 if(gFileList == NULL) {
96 gFileList[giNumFiles++] = strdup(buf);
99 // Sort File List according to rules passed
102 // Show the file list
103 for( i = 0; i < giNumFiles; i ++ )
105 DisplayFile( gFileList[i] );
115 * \fn void ShowUsage(char *ProgName)
117 void ShowUsage(char *ProgName)
119 fprintf(stderr, "Usage: %s [options] [<directory>]\n", ProgName);
120 fprintf(stderr, "\n");
124 * \fn void ParseArguments(int argc, char *argv[])
125 * \brief Parse the command line arguments
127 void ParseArguments(int argc, char *argv[])
131 for( i = 1; i < argc; i ++ )
147 case 'a': gbShowAll = 1; gbShowImplicit = 1; continue;
149 case 'A': gbShowAll = 1; gbShowImplicit = 0; continue;
151 case 'l': gbViewExtended = 1; continue;
152 // Human readable sizes
153 case 'h': gbViewHumanReadable = 1; continue;
155 fprintf(stderr, "%s: Unknown option '%c'\n", argv[0], *str);
163 if(gsDirectory == NULL) {
164 gsDirectory = argv[i];
169 if(!gsDirectory) gsDirectory = ".";
173 * \fn int strcmpp(void *p1, void *p2)
174 * \brief Compares two strings given pointers to their pointers
176 int strcmpp(const void *p1, const void *p2)
178 return strcmp( *(char **)p1, *(char **)p2 );
182 * \fn void SortFileList()
183 * \brief Sorts the filled file list
187 qsort(gFileList, giNumFiles, sizeof(char*), strcmpp);
191 * \fn void DisplayFile(char *Filename)
192 * \brief Prints out the information for a file
194 void DisplayFile(char *Filename)
200 int dirLen = strlen(gsDirectory);
201 int type = FTYPE_NORMAL, perms = 0;
203 int owner = 0, group = 0;
205 // Check if we should skip this file
206 if(!gbShowAll && Filename[0] == '.') return;
209 path = malloc(dirLen+1+strlen(Filename)+1);
211 fprintf(stderr, "heap exhausted\n");
216 strcpy(path, gsDirectory);
218 strcpy(&path[dirLen+1], Filename);
221 fd = _SysOpen(path, 0);
223 fprintf(stderr, "Unable to open '%s'\n", path);
227 _SysFInfo(fd, &info, 0);
229 if(info.flags & FILEFLAG_DIRECTORY) {
232 else if(info.flags & FILEFLAG_SYMLINK) {
233 type = FTYPE_SYMLINK;
240 // Get Owner and Group
246 acl.object = info.uid;
247 _SysGetACL(fd, &acl);
248 if(acl.perms & 1) perms |= 0400; // R
249 if(acl.perms & 2) perms |= 0200; // W
250 if(acl.perms & 8) perms |= 0100; // X
252 acl.object = info.gid | 0x80000000;
253 _SysGetACL(fd, &acl);
254 if(acl.perms & 1) perms |= 0040; // R
255 if(acl.perms & 2) perms |= 0020; // W
256 if(acl.perms & 8) perms |= 0010; // X
258 acl.object = 0xFFFFFFFF;
259 _SysGetACL(fd, &acl);
260 if(acl.perms & 1) perms |= 0004; // R
261 if(acl.perms & 2) perms |= 0002; // W
262 if(acl.perms & 8) perms |= 0001; // X
267 free(path); // We're finished with it
272 char permStr[11] = " ---------";
273 if(type == FTYPE_DIR) permStr[0] = 'd';
274 if(perms & 0400) permStr[1] = 'r';
275 if(perms & 0200) permStr[2] = 'w';
276 if(perms & 0100) permStr[3] = 'x';
277 if(perms & 0040) permStr[4] = 'r';
278 if(perms & 0020) permStr[5] = 'w';
279 if(perms & 0010) permStr[6] = 'x';
280 if(perms & 0004) permStr[7] = 'r';
281 if(perms & 0002) permStr[8] = 'w';
282 if(perms & 0001) permStr[9] = 'x';
283 printf("%s %4i %4i ", permStr, owner, group);
284 if(gbViewHumanReadable && type != FTYPE_DIR) {
285 if(size < 2048) { // < 2 KiB
286 printf("%4lli B ", size);
288 else if(size < 2048*1024) { // < 2 MiB
289 printf("%4lli KiB ", size>>10);
291 else if(size < (uint64_t)2048*1024*1024) { // < 2 GiB
292 printf("%4lli MiB ", size>>20);
294 else if(size < (uint64_t)2048*1024*1024*1024) { // < 2 TiB
295 printf("%4lli GiB ", size>>30);
297 else { // Greater than 2 TiB (if your files are larger than this, you are Doing It Wrong [TM])
298 printf("%4lli TiB ", size>>40);
301 printf("%8lli ", size);
307 case FTYPE_DIR: printf("\x1B[32m"); break; // Green
308 case FTYPE_SYMLINK: printf("\x1B[34m"); break; // Blue
309 case FTYPE_NORMAL: break;
311 printf("%s%s\n", Filename, (type==FTYPE_DIR?"/":""));
312 printf("\x1B[00m"); // Reset