summaryrefslogtreecommitdiff
path: root/src/bootstrap/tar.c
diff options
context:
space:
mode:
authordzwdz2023-08-25 17:18:07 +0200
committerdzwdz2023-08-25 17:18:30 +0200
commiteff47b170a7b0ea24a7c6e3a538186faac758c23 (patch)
tree8d715835272aa4be0631d971c6608ba6885ad80c /src/bootstrap/tar.c
parenta767724386c9fe175c2fe4311511c0a402339c37 (diff)
bootstrap: support hardlinks in initrd
required for the binutils port
Diffstat (limited to 'src/bootstrap/tar.c')
-rw-r--r--src/bootstrap/tar.c18
1 files changed, 14 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) {