fuse-archive
fuse-archive copied to clipboard
Hard links not mounted
Hard links produce an error and are not mounted. The issue is likely related to how libarchive handles hard links.
How to reproduce:
- Creating a tar.gz archive with two hard linked files
$ echo "testing fs-archive with hard links" > file1
$ ln file1 file2
$ stat file1 file2
File: file1
Size: 35 Blocks: 8 IO Block: 4096 regular file
Device: 254,0 Inode: 794969 Links: 2
Access: (0644/-rw-r--r--) Uid: ( 1000/ eugene) Gid: ( 1000/ eugene)
Access: 2023-07-31 16:12:00.330384852 +0200
Modify: 2023-07-31 16:12:00.330384852 +0200
Change: 2023-07-31 16:12:07.123700568 +0200
Birth: 2023-07-31 16:12:00.330384852 +0200
File: file2
Size: 35 Blocks: 8 IO Block: 4096 regular file
Device: 254,0 Inode: 794969 Links: 2
Access: (0644/-rw-r--r--) Uid: ( 1000/ eugene) Gid: ( 1000/ eugene)
Access: 2023-07-31 16:12:00.330384852 +0200
Modify: 2023-07-31 16:12:00.330384852 +0200
Change: 2023-07-31 16:12:07.123700568 +0200
Birth: 2023-07-31 16:12:00.330384852 +0200
$ tar cvaf test_fuse_archive_hard_links.tar.gz file1 file2
file1
file2
- Mounting with latest fuse-archive fails:
$ git clone https://github.com/google/fuse-archive.git -b v0.1.14
$ cd fuse-archive
$ make all
$ ./out/fuse-archive ~/test_fuse_archive_hard_links.tar.gz /mnt/tmp
fuse-archive: irregular non-link file in /home/eugene/test_fuse_archive_hard_links.tar.gz: /file2
$ ls /mnt/tmp
file1
- Re-extracting the tar.gz works properly and hard links are preserved:
$ mkdir ~/out && tar xvaf ~/test_fuse_archive_hard_links.tar.gz -C ~/out
$ stat ~/out/file1 ~/out/file2
File: /home/eugene/out/file1
Size: 35 Blocks: 8 IO Block: 4096 regular file
Device: 254,0 Inode: 15874535 Links: 2
Access: (0644/-rw-r--r--) Uid: ( 1000/ eugene) Gid: ( 1000/ eugene)
Access: 2023-07-31 16:49:52.049826264 +0200
Modify: 2023-07-31 16:12:00.000000000 +0200
Change: 2023-07-31 16:49:52.049826264 +0200
Birth: 2023-07-31 16:49:52.049826264 +0200
File: /home/eugene/out/file2
Size: 35 Blocks: 8 IO Block: 4096 regular file
Device: 254,0 Inode: 15874535 Links: 2
Access: (0644/-rw-r--r--) Uid: ( 1000/ eugene) Gid: ( 1000/ eugene)
Access: 2023-07-31 16:49:52.049826264 +0200
Modify: 2023-07-31 16:12:00.000000000 +0200
Change: 2023-07-31 16:49:52.049826264 +0200
Birth: 2023-07-31 16:49:52.049826264 +0200
- By debugging further, it is clear that the
"regular"bit flag is not set for the second file.
diff --git a/src/main.cc b/src/main.cc
index 6afb15f..6c77912 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -1130,6 +1130,8 @@ insert_leaf(struct archive* a,
std::string symlink;
mode_t mode = archive_entry_mode(e);
+ mode_t filetype = archive_entry_filetype(e);
+ syslog(LOG_INFO, "AE_IFREG: 0x%04x, file: %s, mode 0x%04x, filetype: 0x%04x\n", AE_IFREG, redact(pathname.c_str()), mode, filetype);
if (S_ISLNK(mode)) {
const char* s = archive_entry_symlink_utf8(e);
if (!s) {
./out/fuse-archive ~/test_fuse_archive_hard_links.tar.gz /mnt/tmp 130
fuse-archive: AE_IFREG: 0x8000, file: /file1, mode 0x81a4, filetype: 0x8000
fuse-archive: AE_IFREG: 0x8000, file: /file2, mode 0x01a4, filetype: 0x0000
fuse-archive: irregular non-link file in /home/eugene/test_fuse_archive_hard_links.tar.gz: /file2
A possible solution has already been submitted in PR #11.
Thanks Matteo for your detailed bug report.
I confirm that hard links are not properly handled by fuse-archive.
The proposed pull request #11 does not solve the issue, at least not just by itself. I tried it. When I apply it, I get two files, but the second one is empty:
$ ls -lh mnt
total 0
-r--r--r-- 1 fdegros primarygroup 35 Aug 4 10:33 file1
-r--r--r-- 1 fdegros primarygroup 0 Aug 4 10:33 file2
In order to fully handle hard links, fuse-archive would require further modifications.