From e9dba420c3813da7c8b68ba58ed75b6f9344b2de Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Sat, 4 Jul 2020 17:36:18 -0700 Subject: [PATCH 1/2] Write GNU tar files, supporting long names. Fixes #8452 --- src/cargo/ops/cargo_package.rs | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/src/cargo/ops/cargo_package.rs b/src/cargo/ops/cargo_package.rs index 4b59afdae1e..fc98f5de66a 100644 --- a/src/cargo/ops/cargo_package.rs +++ b/src/cargo/ops/cargo_package.rs @@ -501,28 +501,7 @@ fn tar( config .shell() .verbose(|shell| shell.status("Archiving", &rel_str))?; - // The `tar::Builder` type by default will build GNU archives, but - // unfortunately we force it here to use UStar archives instead. The - // UStar format has more limitations on the length of path name that it - // can encode, so it's not quite as nice to use. - // - // Older cargos, however, had a bug where GNU archives were interpreted - // as UStar archives. This bug means that if we publish a GNU archive - // which has fully filled out metadata it'll be corrupt when unpacked by - // older cargos. - // - // Hopefully in the future after enough cargos have been running around - // with the bugfixed tar-rs library we'll be able to switch this over to - // GNU archives, but for now we'll just say that you can't encode paths - // in archives that are *too* long. - // - // For an instance of this in the wild, use the tar-rs 0.3.3 library to - // unpack the selectors 0.4.0 crate on crates.io. Either that or take a - // look at rust-lang/cargo#2326. - let mut header = Header::new_ustar(); - header - .set_path(&ar_path) - .chain_err(|| format!("failed to add to archive: `{}`", rel_str))?; + let mut header = Header::new_gnu(); match contents { FileContents::OnDisk(disk_path) => { let mut file = File::open(&disk_path).chain_err(|| { @@ -533,9 +512,10 @@ fn tar( })?; header.set_metadata(&metadata); header.set_cksum(); - ar.append(&header, &mut file).chain_err(|| { - format!("could not archive source file `{}`", disk_path.display()) - })?; + ar.append_data(&mut header, &ar_path, &mut file) + .chain_err(|| { + format!("could not archive source file `{}`", disk_path.display()) + })?; } FileContents::Generated(generated_kind) => { let contents = match generated_kind { @@ -553,7 +533,7 @@ fn tar( ); header.set_size(contents.len() as u64); header.set_cksum(); - ar.append(&header, contents.as_bytes()) + ar.append_data(&mut header, &ar_path, contents.as_bytes()) .chain_err(|| format!("could not archive source file `{}`", rel_str))?; } } From 0dfd4a88fd88aba6aa27a9f7c552a23f414b6f70 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Sat, 4 Jul 2020 17:52:02 -0700 Subject: [PATCH 2/2] Add test for packaging long file names --- tests/testsuite/package.rs | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs index 46dc42de85a..907b8a7ed00 100644 --- a/tests/testsuite/package.rs +++ b/tests/testsuite/package.rs @@ -1845,3 +1845,47 @@ dependency `bar` does not specify a version. ) .run(); } + +#[cargo_test] +fn long_file_names() { + // Filenames over 100 characters require a GNU extension tarfile. + // See #8453. + + registry::init(); + let long_name = concat!( + "012345678901234567890123456789012345678901234567890123456789", + "012345678901234567890123456789012345678901234567890123456789", + "012345678901234567890123456789012345678901234567890123456789" + ); + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + license = "MIT" + description = "foo" + homepage = "foo" + + [dependencies] + "#, + ) + .file(long_name, "something") + .file("src/main.rs", "fn main() {}") + .build(); + + p.cargo("package").run(); + p.cargo("package --list") + .with_stdout(&format!( + "\ +{} +Cargo.lock +Cargo.toml +Cargo.toml.orig +src/main.rs +", + long_name + )) + .run(); +}