summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/tar.c18
-rw-r--r--src/libc/include/string.h2
-rw-r--r--src/libc/string/string.c9
3 files changed, 25 insertions, 4 deletions
diff --git a/src/bootstrap/tar.c b/src/bootstrap/tar.c
index 2020fe0..678f54f 100644
--- a/src/bootstrap/tar.c
+++ b/src/bootstrap/tar.c
@@ -60,18 +60,28 @@ static char tar_type(void *meta) {
return *(char*)(meta + 156);
}
+#include <stdio.h>
static void *tar_open(const char *path, int len, void *base, size_t base_len) {
+ void *res;
if (len <= 0) return NULL;
- path += 1; // skip the leading slash
- len -= 1;
+ if (*path == '/') {
+ path += 1; // skip the leading slash
+ len -= 1;
+ }
/* TAR archives don't (seem to) contain an entry for the root dir, so i'm
* returning a fake one. this isn't a full entry because i'm currently too
* lazy to create a full one - thus, it has to be special cased in tar_read */
- if (len == 0)
+ if (len == 0) {
return (void*)root_fakemeta;
+ }
- return tar_find(path, len, base, base_len);
+ res = tar_find(path, len, base, base_len);
+ if (res && tar_type(res) == '1') { /* hard link */
+ _klogf("hard link to %s", res+157);
+ res = tar_find(res + 157, strnlen(res + 157, 100), base, base_len);
+ }
+ return res;
}
static void tar_dirbuild(struct dirbuild *db, const char *meta, void *base, size_t base_len) {
diff --git a/src/libc/include/string.h b/src/libc/include/string.h
index d9d2b74..8b04b39 100644
--- a/src/libc/include/string.h
+++ b/src/libc/include/string.h
@@ -24,4 +24,6 @@ char *strncat(char *restrict dst, const char *restrict src, size_t n);
char *stpncpy(char *restrict dst, const char *restrict src, size_t n);
char *strdup(const char *s);
+size_t strnlen(const char *s, size_t len);
+
char *strerror(int errnum);
diff --git a/src/libc/string/string.c b/src/libc/string/string.c
index ac1c757..014be4a 100644
--- a/src/libc/string/string.c
+++ b/src/libc/string/string.c
@@ -115,6 +115,15 @@ char *strdup(const char *s) {
return buf;
}
+size_t strnlen(const char *s, size_t len) {
+ for (size_t i = 0; i < len; i++) {
+ if (!s[i]) {
+ return i;
+ }
+ }
+ return len;
+}
+
/* strings.h */
int strcasecmp(const char *s1, const char *s2) {
return strncasecmp(s1, s2, ~0);