Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add support for long link names #2

Merged
merged 1 commit into from
Sep 10, 2024
Merged

Conversation

Xynnn007
Copy link

Before this commit, if a hard link with name length more than 100 chars, the original name will be truncated to 100 chars. This commit will help to support long link names files unpacking.

src/entry.rs Outdated Show resolved Hide resolved
src/pax.rs Outdated Show resolved Hide resolved
Before this commit, if a hard link with name length more than 100 chars,
the original name will be truncated to 100 chars. This commit will help
to support long link names files unpacking.

Signed-off-by: Xynnn007 <[email protected]>
@pmores
Copy link

pmores commented Aug 26, 2024

Cool, thanks a lot @Xynnn007 , looks good to me!

@Xynnn007
Copy link
Author

Hi @pmores Do you have any plan to get this fix into another release?

@pmores
Copy link

pmores commented Sep 5, 2024

@Xynnn007 I'm not a project member and don't have commit rights. I just did a review.

@JakubLedworowski
Copy link

Hi @azenla, do you have any update on this PR?

@azenla
Copy link
Member

azenla commented Sep 9, 2024

Hi! I will review this in the next day! Thank you!

Copy link
Member

@azenla azenla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@azenla azenla merged commit 7e2ae9a into edera-dev:edera Sep 10, 2024
@burgerdev
Copy link

Hi @Xynnn007 @pmores @azenla,

I think this fix may be incomplete, because I can still reproduce what I believe to be the original issue that sent @Xynnn007 here (confidential-containers/guest-components#689).

Preparing a pax tarball with long hard link names

touch 81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d83cc92d70554b2fc82ec28e4ef52f924a2.1
ln 81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d83cc92d70554b2fc82ec28e4ef52f924a2.1 81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d83cc92d70554b2fc82ec28e4ef52f924a2.2
tar --format pax -cf /tmp/pax.tar 81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d83cc92d70554b2fc82ec28e4ef52f924a2*

Inspecting with the raw_list example program

-------------------------- Entry 0
path: ./PaxHeaders/81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d8
size: 222
entry size: 222
link name: None
file type: 0x78
mode: 0o644
uid: 0
gid: 0
mtime: 1739182325
username: Some("")
groupname: Some("")
kind: UStar
pax extensions:
	"path" = "81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d83cc92d70554b2fc82ec28e4ef52f924a2.1"
	"mtime" = "1739182325.217698115"
	"atime" = "1739182325.217698115"
	"ctime" = "1739187780.888853019"
-------------------------- Entry 1
path: 81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d83cc92d70554b2
size: 0
entry size: 0
link name: None
file type: 0x30
mode: 0o644
uid: 1001
gid: 1000
mtime: 1739182325
username: Some("burger")
groupname: Some("burger")
kind: UStar
-------------------------- Entry 2
path: ./PaxHeaders/81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d8
size: 358
entry size: 358
link name: None
file type: 0x78
mode: 0o644
uid: 0
gid: 0
mtime: 1739182325
username: Some("")
groupname: Some("")
kind: UStar
pax extensions:
	"linkpath" = "81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d83cc92d70554b2fc82ec28e4ef52f924a2.1"
	"path" = "81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d83cc92d70554b2fc82ec28e4ef52f924a2.2"
	"mtime" = "1739182325.217698115"
	"atime" = "1739182325.217698115"
	"ctime" = "1739187780.888853019"
-------------------------- Entry 3
path: 81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d83cc92d70554b2
size: 0
entry size: 0
link name: Some("81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d83cc92d70554b2")
file type: 0x31
mode: 0o644
uid: 1001
gid: 1000
mtime: 1739182325
username: Some("burger")
groupname: Some("burger")
kind: UStar

Trying to unpack

This is more or less the list example, but with an unpacking step.

fn main() {
    tokio::runtime::Runtime::new().unwrap().block_on(async {
        let mut ar = Archive::new(stdin());
        let mut entries = ar.entries().unwrap();
        while let Some(file) = entries.next().await {
            let mut f = file.unwrap();
            let _ = f.unpack_in(std::env::args_os().nth(1).unwrap()).await.unwrap();
        }
    });
}

Note the truncated filename (should end in .2).

thread 'main' panicked at examples/unpack.rs:18:76:
called `Result::unwrap()` on an `Err` value: Custom { kind: NotFound, error: TarError { desc: "failed to unpack `/tmp/tarout/81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d83cc92d70554b2`", io: Custom { kind: NotFound, error: "No such file or directory (os error 2) while canonicalizing /tmp/tarout/81ea4731d7e16961875695d35cc1b6fdcbcbb9f102fa532679c01d8698a7cca89f509a0803246b9cd6337d83cc92d70554b2" } } }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Analysis

I'm not too familiar with the async APIs used in this crate, but I believe the problem to lie somewhere around here:

tokio-tar/src/archive.rs

Lines 316 to 318 in 4ee3572

let mut ef = EntryFields::from(entry);
let val = ready_err!(Pin::new(&mut ef).poll_read_all(cx));
self.pax_extensions = Some(val);

Iiuc the pax_extensions field should be assigned the next polled val, but the poll returns early in my little test program, so the next entry is handled with the pax_extensions still None.

@Xynnn007
Copy link
Author

@burgerdev Yes. I can reproduce the behavior. You are right that

ready_err!(Pin::new(&mut ef).poll_read_all(cx)); 

would return a Poll::Pending and with make the function return early

@Xynnn007
Copy link
Author

Xynnn007 commented Feb 14, 2025

Commits astral-sh/tokio-tar@a393710 and astral-sh/tokio-tar@b002e0a will solve this and I test locally.

Coincidently that comes from another fork of this repository and which includes some more commits.

As a downstream user, we still try our best to hope that the upstream is an active warehouse. With this in mind, one choice for us might be to consider using the fork -- if no more time is had to focus on maintaining this repository from @azenla @pmores

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants