Skip to content

Commit 0b04cc4

Browse files
committed
tar/export: Fix error with zero-sized hardlinked files
In the case where we already emitted an object into the tar stream, we wouldn't previously set the file type and size into the tar header structure that we passed into the hardlink emission function. This would cause an error when accessing the (logically) uninitialized `size()`. Fix the writer function to always set the file type and size unconditionally, and also rework the consumer side to make the logic even clearer. Signed-off-by: Colin Walters <[email protected]>
1 parent 4c523b4 commit 0b04cc4

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

ostree-ext/src/tar/export.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,11 @@ impl<'a, W: std::io::Write> OstreeTarWriter<'a, W> {
430430
let mode = meta.attribute_uint32("unix::mode");
431431
h.set_mode(self.filter_mode(mode));
432432
if instream.is_some() {
433+
h.set_entry_type(tar::EntryType::Regular);
433434
h.set_size(meta.size() as u64);
435+
} else {
436+
h.set_entry_type(tar::EntryType::Symlink);
437+
h.set_size(0);
434438
}
435439
if !self.wrote_content.contains(checksum) {
436440
let inserted = self.wrote_content.insert(checksum.to_string());
@@ -445,8 +449,6 @@ impl<'a, W: std::io::Write> OstreeTarWriter<'a, W> {
445449
if let Some(instream) = instream {
446450
ensure!(meta.file_type() == gio::FileType::Regular);
447451

448-
h.set_entry_type(tar::EntryType::Regular);
449-
h.set_size(meta.size() as u64);
450452
let mut instream = BufReader::with_capacity(BUF_CAPACITY, instream.into_read());
451453
self.out
452454
.append_data(&mut h, &path, &mut instream)
@@ -461,8 +463,6 @@ impl<'a, W: std::io::Write> OstreeTarWriter<'a, W> {
461463
.to_str()
462464
.ok_or_else(|| anyhow!("Invalid UTF-8 symlink target: {target:?}"))?;
463465
let context = || format!("Writing content symlink: {}", checksum);
464-
h.set_entry_type(tar::EntryType::Symlink);
465-
h.set_size(0);
466466
// Handle //chkconfig, see above
467467
if symlink_is_denormal(target) {
468468
h.set_link_name_literal(target).with_context(context)?;
@@ -501,15 +501,20 @@ impl<'a, W: std::io::Write> OstreeTarWriter<'a, W> {
501501
mut h: tar::Header,
502502
dest: &Utf8Path,
503503
) -> Result<()> {
504-
// Query the original size first
505-
let size = h.size().context("Querying size for hardlink append")?;
506504
// Don't create hardlinks to zero-sized files, it's much more likely
507505
// to result in generated tar streams from container builds resulting
508506
// in a modified linked-to file in /sysroot, which we don't currently handle.
509507
// And in the case where the input is *not* zero sized, we still output
510508
// a hardlink of size zero, as this is what is normal.
509+
let is_regular_zerosized = if h.entry_type() == tar::EntryType::Regular {
510+
let size = h.size().context("Querying size for hardlink append")?;
511+
size == 0
512+
} else {
513+
false
514+
};
515+
// Link sizes shoud always be zero
511516
h.set_size(0);
512-
if h.entry_type() == tar::EntryType::Regular && size == 0 {
517+
if is_regular_zerosized {
513518
self.out.append_data(&mut h, dest, &mut std::io::empty())?;
514519
} else {
515520
h.set_entry_type(tar::EntryType::Link);

0 commit comments

Comments
 (0)