PatchworkOS  3984a1d
A non-POSIX operating system.
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1#define __STDC_WANT_LIB_EXT1__ 1
2#include <errno.h>
3#include <stdbool.h>
4#include <stdint.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <sys/io.h>
9
10static bool showAll = false;
11static bool showFlags = false;
12
14{
16 printf("\033[999C\033[6n");
18 char buffer[MAX_NAME] = {0};
19 for (uint32_t i = 0; i < sizeof(buffer) - 1; i++)
20 {
22 if (buffer[i] == 'R')
23 {
24 break;
25 }
26 }
27 int row;
28 int cols;
29 sscanf(buffer, "\033[%d;%dR", &row, &cols);
30
31 if (cols != 0)
32 {
34 }
35
36 printf("\r");
38 return terminalWidth;
39}
40
41static int dirent_cmp(const void* a, const void* b)
42{
43 const dirent_t* da = (const dirent_t*)a;
44 const dirent_t* db = (const dirent_t*)b;
45 return strcmp(da->path, db->path);
46}
47
48static uint64_t print_dir(const char* path)
49{
50 fd_t fd = open(path);
51 if (fd == ERR)
52 {
53 fprintf(stderr, "ls: can't open directory %s (%s)\n", path, strerror(errno));
54 return ERR;
55 }
56
57 uint64_t capacity = 16;
58 uint64_t count = 0;
59 dirent_t* entries = malloc(sizeof(dirent_t) * capacity);
60 if (entries == NULL)
61 {
62 close(fd);
63 fprintf(stderr, "ls: memory allocation failed\n");
64 return ERR;
65 }
66
67 while (true)
68 {
69 if (count == capacity)
70 {
71 capacity *= 2;
72 dirent_t* newEntries = realloc(entries, sizeof(dirent_t) * capacity);
73 if (newEntries == NULL)
74 {
76 close(fd);
77 fprintf(stderr, "ls: memory allocation failed\n");
78 return ERR;
79 }
81 }
82
83 uint64_t bytesRead = getdents(fd, &entries[count], sizeof(dirent_t) * (capacity - count));
84 if (bytesRead == ERR)
85 {
87 close(fd);
88 fprintf(stderr, "ls: can't read directory %s (%s)\n", path, strerror(errno));
89 return ERR;
90 }
91 if (bytesRead == 0)
92 {
93 break;
94 }
95
96 count += bytesRead / sizeof(dirent_t);
97 }
98 close(fd);
99
100 if (count == 0)
101 {
102 free(entries);
103 return 0;
104 }
105
106 if (!showAll)
107 {
108 uint64_t newCount = 0;
109 for (uint64_t i = 0; i < count; i++)
110 {
111 if (entries[i].path[0] != '.' && strstr(entries[i].path, "/.") == NULL)
112 {
113 if (i != newCount)
114 {
116 }
117 newCount++;
118 }
119 }
120 count = newCount;
121 if (count == 0)
122 {
123 free(entries);
124 return 0;
125 }
126 }
127
129
130 uint64_t maxLen = 0;
131 for (uint64_t i = 0; i < count; i++)
132 {
133 uint64_t len = strlen(entries[i].path);
134 if (entries[i].type == INODE_DIR || entries[i].type == INODE_SYMLINK)
135 {
136 len++;
137 }
138 if (showFlags)
139 {
140 len += strlen(entries[i].mode);
141 }
142 if (len > maxLen)
143 {
144 maxLen = len;
145 }
146 }
147
149 uint32_t colWidth = maxLen + 2;
150 if (colWidth > termWidth)
151 {
153 }
154
156 if (numCols == 0)
157 {
158 numCols = 1;
159 }
160
162
163 for (uint32_t r = 0; r < numRows; r++)
164 {
165 for (uint32_t c = 0; c < numCols; c++)
166 {
167 uint32_t index = c * numRows + r;
168 if (index >= count)
169 {
170 continue;
171 }
172
173 const dirent_t* ent = &entries[index];
174 const char* name = ent->path;
175 int len = strlen(name);
176 const char* modifier = (ent->flags & DIRENT_MOUNTED) ? "\033[4m" : "";
177
178 if (ent->type == INODE_DIR)
179 {
180 printf("%s\033[34m%s%s\033[0m/", modifier, name, showFlags ? ent->mode : "");
181 len++;
182 }
183 else if (ent->type == INODE_SYMLINK)
184 {
185 printf("%s\033[36m%s%s\033[0m@", modifier, name, showFlags ? ent->mode : "");
186 len++;
187 }
188 else
189 {
190 printf("%s%s%s\033[0m", modifier, name, showFlags ? ent->mode : "");
191 }
192
193 if (showFlags)
194 {
195 len += strlen(ent->mode);
196 }
197
198 if (c < numCols - 1)
199 {
200 for (uint64_t i = len; i < colWidth; i++)
201 {
202 putchar(' ');
203 }
204 }
205 }
206 printf("\n");
207 }
208
209 free(entries);
210 return 0;
211}
212
213int main(int argc, char** argv)
214{
215 int i = 1;
216 for (; i < argc; i++)
217 {
218 if (argv[i][0] != '-')
219 {
220 break;
221 }
222
223 for (int j = 1; argv[i][j] != '\0'; j++)
224 {
225 if (argv[i][j] == 'a')
226 {
227 showAll = true;
228 }
229 else if (argv[i][j] == 'f')
230 {
231 showFlags = true;
232 }
233 else
234 {
235 fprintf(stderr, "ls: invalid option -- '%c'\n", argv[i][j]);
236 return EXIT_FAILURE;
237 }
238 }
239 }
240
241 if (i >= argc)
242 {
243 if (print_dir(".") == ERR)
244 {
245 return EXIT_FAILURE;
246 }
247 }
248 else
249 {
250 for (; i < argc; i++)
251 {
252 if (print_dir(argv[i]) == ERR)
253 {
254 return EXIT_FAILURE;
255 }
256 }
257 }
258
259 return EXIT_SUCCESS;
260}
#define MAX_NAME
Maximum length of names.
Definition MAX_NAME.h:11
int main(void)
Definition main.c:5
int64_t y
Definition main.c:153
#define errno
Error number variable.
Definition errno.h:27
size_t getdents(fd_t fd, dirent_t *buffer, uint64_t count)
System call for reading directory entires.
Definition getdents.c:8
fd_t open(const char *path)
System call for opening files.
Definition open.c:8
uint64_t close(fd_t fd)
System call for closing files.
Definition close.c:8
size_t read(fd_t fd, void *buffer, size_t count)
System call for reading from files.
Definition read.c:8
#define STDIN_FILENO
Standard input file descriptor.
Definition io.h:34
@ DIRENT_MOUNTED
The directory entry is a mountpoint.
Definition io.h:435
@ INODE_DIR
Is a directory.
Definition io.h:343
@ INODE_SYMLINK
Is a symbolic link.
Definition io.h:344
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
__UINT64_TYPE__ fd_t
A file descriptor.
Definition fd_t.h:12
EFI_PHYSICAL_ADDRESS buffer
Definition mem.c:15
static uint64_t terminal_columns_get(void)
Definition main.c:13
static int dirent_cmp(const void *a, const void *b)
Definition main.c:41
static uint64_t print_dir(const char *path)
Definition main.c:48
static bool showFlags
Definition main.c:11
static bool showAll
Definition main.c:10
static atomic_long count
Definition main.c:11
static start_entry_t entries[START_ENTRY_MAX]
Definition start_menu.c:22
__UINT32_TYPE__ uint32_t
Definition stdint.h:15
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
_PUBLIC int sscanf(const char *_RESTRICT s, const char *_RESTRICT format,...)
Definition sscanf.c:4
_PUBLIC int putchar(int c)
Definition putchar.c:7
_PUBLIC int fflush(FILE *stream)
Definition fflush.c:5
_PUBLIC int printf(const char *_RESTRICT format,...)
Definition printf.c:3
FILE * stdout
Definition std_streams.c:18
FILE * stderr
Definition std_streams.c:19
_PUBLIC int fprintf(FILE *_RESTRICT stream, const char *_RESTRICT format,...)
Definition fprintf.c:3
_PUBLIC void * realloc(void *ptr, size_t size)
Definition realloc.c:13
_PUBLIC void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))
Definition qsort.c:47
#define EXIT_SUCCESS
Definition stdlib.h:46
#define EXIT_FAILURE
Definition stdlib.h:47
_PUBLIC void * malloc(size_t size)
Definition malloc.c:5
_PUBLIC void free(void *ptr)
Definition free.c:11
_PUBLIC char * strerror(int errnum)
Definition strerror.c:6
_PUBLIC char * strstr(const char *s1, const char *s2)
Definition strstr.c:3
_PUBLIC size_t strlen(const char *s)
Definition strlen.c:3
_PUBLIC int strcmp(const char *s1, const char *s2)
Definition strcmp.c:3
Directory entry struct.
Definition io.h:443
const char * path
Definition start_menu.c:18