summaryrefslogtreecommitdiff
path: root/src/user
diff options
context:
space:
mode:
Diffstat (limited to 'src/user')
-rw-r--r--src/user/app/find/find.c60
-rw-r--r--src/user/lib/dirent.c55
-rw-r--r--src/user/lib/include/dirent.h20
-rw-r--r--src/user/lib/stdio/file.c7
-rw-r--r--src/user/lib/string/string.c2
5 files changed, 93 insertions, 51 deletions
diff --git a/src/user/app/find/find.c b/src/user/app/find/find.c
index 529b54e..d473b82 100644
--- a/src/user/app/find/find.c
+++ b/src/user/app/find/find.c
@@ -1,55 +1,43 @@
#include <camellia/path.h>
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#define eprintf(fmt, ...) fprintf(stderr, "find: "fmt"\n" __VA_OPT__(,) __VA_ARGS__)
-
void recurse(char *path) {
- FILE *f = fopen(path, "r");
- const int buf_len = 4096;
- char *buf;
-
- if (!f) {
- eprintf("couldn't open %s", path);
+ DIR *d = opendir(path);
+ if (!d) {
+ warn("couldn't open %s", path);
return;
}
-
- buf = malloc(buf_len);
for (;;) {
- int len = fread(buf, 1, buf_len, f);
- int pos = 0;
- if (len <= 0) break;
- while (pos < len) {
- if (buf[pos] == '\0') {
- eprintf("%s has an empty entry, bailing", path);
- break;
- }
- const char *end = memchr(buf + pos, 0, len - pos);
- if (!end) {
- eprintf("buf overflowed, unimplemented"); // TODO
- break;
+ struct dirent *dent;
+ errno = 0;
+ dent = readdir(d);
+ if (!dent) {
+ if (errno) {
+ warn("when reading %s", path);
}
- printf("%s%s\n", path, buf + pos);
-
- size_t entrylen = end - (buf + pos) + 1;
- if (end[-1] == '/') {
- // append onto end of the current path
- // TODO no overflow check
- char *pend = path + strlen(path);
- memcpy(pend, buf + pos, entrylen);
- recurse(path);
- *pend = '\0';
- }
- pos += entrylen;
+ break;
+ }
+ printf("%s%s\n", path, dent->d_name);
+ /* if the string ends with '/' */
+ if (strchr(dent->d_name, '\0')[-1] == '/') {
+ // TODO no overflow check
+ char *pend = strchr(path, '\0');
+ strcpy(pend, dent->d_name);
+ recurse(path);
+ *pend = '\0';
}
}
- fclose(f);
- free(buf);
+ closedir(d);
}
void find(const char *path) {
// TODO bound checking
+ // TODO or just implement asprintf()
char *buf = malloc(PATH_MAX);
memcpy(buf, path, strlen(path)+1);
recurse(buf);
diff --git a/src/user/lib/dirent.c b/src/user/lib/dirent.c
new file mode 100644
index 0000000..c2d1b9c
--- /dev/null
+++ b/src/user/lib/dirent.c
@@ -0,0 +1,55 @@
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+DIR *opendir(const char *name) {
+ FILE *fp = NULL;
+ DIR *dir = NULL;
+ fp = fopen(name, "r");
+ if (!fp) {
+ goto err;
+ }
+ dir = calloc(1, sizeof *dir);
+ if (!dir) {
+ goto err;
+ }
+ dir->fp = fp;
+ return dir;
+err:
+ if (fp) fclose(fp);
+ free(dir);
+ return NULL;
+}
+
+int closedir(DIR *dir) {
+ fclose(dir->fp);
+ free(dir);
+ return 0;
+}
+
+struct dirent *readdir(DIR *dir) {
+ int i = 0;
+ char *buf = dir->dent.d_name;
+ for (;;) {
+ int c = fgetc(dir->fp);
+ if (c == EOF) {
+ if (i == 0) return NULL;
+ else break;
+ }
+ if (c == '\0') {
+ break;
+ }
+ if (i == sizeof(dir->dent.d_name)-1) {
+ /* overflow */
+ for (;;) {
+ c = fgetc(dir->fp);
+ if (c == EOF || c == '\0') break;
+ }
+ return errno = ENAMETOOLONG, NULL;
+ }
+ buf[i++] = c;
+ }
+ buf[i] = '\0';
+ return &dir->dent;
+}
diff --git a/src/user/lib/include/dirent.h b/src/user/lib/include/dirent.h
index 35ba1e9..7c419d7 100644
--- a/src/user/lib/include/dirent.h
+++ b/src/user/lib/include/dirent.h
@@ -1,20 +1,16 @@
#pragma once
-#include <bits/panic.h>
+#include <stdio.h>
-typedef struct DIR DIR;
struct dirent {
ino_t d_ino;
char d_name[256]; /* NAME_MAX + 1 */
};
-static inline DIR *opendir(const char *name) {
- __libc_panic("unimplemented");
-}
+typedef struct {
+ FILE *fp;
+ struct dirent dent;
+} DIR;
-static inline int closedir(DIR *dir) {
- __libc_panic("unimplemented");
-}
-
-static inline struct dirent *readdir(DIR *dir) {
- __libc_panic("unimplemented");
-}
+DIR *opendir(const char *name);
+int closedir(DIR *dir);
+struct dirent *readdir(DIR *dir);
diff --git a/src/user/lib/stdio/file.c b/src/user/lib/stdio/file.c
index cbacfdd..9a6e555 100644
--- a/src/user/lib/stdio/file.c
+++ b/src/user/lib/stdio/file.c
@@ -155,8 +155,9 @@ size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict f) {
errno = EBADF;
return 0;
}
- if (size == 0)
+ if (size == 0) {
return 0;
+ }
while (pos < total) {
long res = _sys_read(f->fd, buf + pos, total - pos, f->pos);
@@ -207,6 +208,7 @@ int fputs(const char *s, FILE *f) {
return fprintf(f, "%s\n", s);
}
+// TODO! c file buffering
char *fgets(char *buf, int size, FILE *f) {
char c = '\0';
long pos = 0;
@@ -221,7 +223,8 @@ char *fgets(char *buf, int size, FILE *f) {
int fgetc(FILE *f) {
char c;
- return fread(&c, 1, 1, f) ? c : EOF;
+ size_t ret = fread(&c, 1, 1, f);
+ return ret ? c : EOF;
}
int getc(FILE *f) { return fgetc(f); }
diff --git a/src/user/lib/string/string.c b/src/user/lib/string/string.c
index 68c4826..c65d7c5 100644
--- a/src/user/lib/string/string.c
+++ b/src/user/lib/string/string.c
@@ -5,7 +5,7 @@
#include <strings.h>
char *strchr(const char *s, int c) {
- for (; *s; s++) {
+ for (; *s || c == 0; s++) {
if (*s == c) return (char *)s;
}
return NULL;