diff options
author | dzwdz | 2023-08-25 17:18:07 +0200 |
---|---|---|
committer | dzwdz | 2023-08-25 17:18:30 +0200 |
commit | eff47b170a7b0ea24a7c6e3a538186faac758c23 (patch) | |
tree | 8d715835272aa4be0631d971c6608ba6885ad80c | |
parent | a767724386c9fe175c2fe4311511c0a402339c37 (diff) |
bootstrap: support hardlinks in initrd
required for the binutils port
-rw-r--r-- | src/bootstrap/tar.c | 18 | ||||
-rw-r--r-- | src/libc/include/string.h | 2 | ||||
-rw-r--r-- | src/libc/string/string.c | 9 |
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); |