[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1070042: libarchive: archive_entry_stat returns zero size on mips64el with _FILE_OFFSET_BITS=64



Source: libarchive
Version: 3.7.2-2
Severity: normal
X-Debbugs-Cc: debian-mips@lists.debian.org, tytso@mit.edu
Control: affects -1 src:e2fsprogs

Hi,

the upload of e2fsprogs 1.47.1~rc1-1 to unstable yesterday uses a new
feature where libarchive is used to create filesystem images from
tarballs. This works on all architectures (main as well as ports) except
on mips64el:

https://buildd.debian.org/status/package.php?p=e2fsprogs

I attached a minimal reproducer. It includes an embedded gzipped tarball with a
single file called "myfilename" of size 10. It works fine if _FILE_OFFSET_BITS
is not set but with it, it reports a wrong archive member size of zero on
mips64el:

    $ gcc -Wall -g -O0 libarchivetest.c -larchive -D_FILE_OFFSET_BITS=64
    $ ./a.out
    myfilename: 0

Since the reproducer only makes use of libarchive, I'm filing this as a
libarchive bug. Since this problem is mips64el specific, I'm putting the
porter-list in X-Debbugs-Cc.

The problem can also be reproduced on bookworm.

gdb can show what is going on (thanks to Theodore Ts'o for the initial
debugging):

(gdb) run
[...]
Breakpoint 1, main () at test.c:49
49			st = archive_entry_stat(entry);
(gdb) next
50			fprintf(stderr, "%s: %ld\n", archive_entry_pathname(entry), st->st_size);
(gdb) p *st
$2 = {st_dev = 1, st_pad1 = {0, 0, 0}, st_ino = 1, st_mode = 33188, st_nlink = 0, 
  st_uid = 1000, st_gid = 1000, st_rdev = 0, st_pad2 = {0, 0, 10}, st_size = 0, 
  st_atim = {tv_sec = 0, tv_nsec = 0}, st_mtim = {tv_sec = 1714375615, tv_nsec = 0}, 
  st_ctim = {tv_sec = 0, tv_nsec = 0}, st_blksize = 0, st_pad4 = 0, st_blocks = 0, 
  st_pad5 = {0 <repeats 14 times>}}

As one can see, the size "10" is not in st_size but in the padding before the
st_size member. This only happens when _FILE_OFFSET_BITS=64 and only on
mips64el.

Any idea what is going on with mips64el?

Thanks!

cheers, josch
#include <stdio.h>
#include <archive.h>
#include <archive_entry.h>

// gzipped tarball created with xxd --include
unsigned char archive_tar_gz[] = {
  0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xed, 0xce,
  0x41, 0x0a, 0xc2, 0x30, 0x10, 0x85, 0xe1, 0x59, 0x7b, 0x8a, 0x1c, 0x21,
  0xa3, 0xd3, 0xe4, 0x3c, 0xa5, 0x44, 0xb4, 0x98, 0x14, 0xda, 0xb8, 0xe8,
  0xed, 0xad, 0xb8, 0xd0, 0x95, 0xd2, 0x45, 0x29, 0xc2, 0xff, 0x6d, 0x1e,
  0xc3, 0x9b, 0xc5, 0xcb, 0xf3, 0xf9, 0x7a, 0x4b, 0xa5, 0xcd, 0x49, 0x36,
  0xe3, 0x17, 0xc1, 0xec, 0x99, 0x1a, 0x1b, 0xff, 0x99, 0x2f, 0x7a, 0x14,
  0xb5, 0xa0, 0xa7, 0x60, 0x4d, 0x88, 0x51, 0x96, 0x5b, 0x4d, 0xc5, 0xf9,
  0xed, 0x26, 0xbd, 0xdd, 0xa7, 0xda, 0x8e, 0xce, 0x49, 0x3f, 0x4c, 0xdd,
  0xe5, 0xcb, 0xdf, 0xaf, 0xfe, 0x4f, 0xe5, 0xb9, 0x1b, 0x4a, 0x4d, 0xa5,
  0x1e, 0xf6, 0x5e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0xe3, 0x01, 0x16, 0x64, 0x3c, 0x30,
  0x00, 0x28, 0x00, 0x00
};
unsigned int archive_tar_gz_len = 136;

int main() {
	int ret;
	struct archive_entry *entry;
	const struct stat *st;

	struct archive *a = archive_read_new();
	if (a == NULL) {
		fprintf(stderr, "archive_read_new\n");
		return 1;
	}
	archive_read_support_filter_all(a);
	archive_read_support_format_all(a);
	ret = archive_read_open_memory(a, archive_tar_gz, archive_tar_gz_len);
	if (ret != ARCHIVE_OK) {
		fprintf(stderr, "archive_read_open_memory\n");
		return 1;
	}
	for (;;) {
		ret = archive_read_next_header(a, &entry);
		if (ret == ARCHIVE_EOF) {
			break;
		}
		if (ret != ARCHIVE_OK) {
			fprintf(stderr, "archive_read_next_header\n");
			return 1;
		}
		st = archive_entry_stat(entry);
		fprintf(stderr, "%s: %ld\n", archive_entry_pathname(entry), st->st_size);
	}
	archive_read_close(a);
	archive_read_free(a);
	return 0;
}

Reply to: