Add hook routine archive_write_ar_finish() which writes the 'ar'

global header if nothing else has been written before the closing of
the archive. This will change the behaviour when creating archives
without members, i.e., instead of generating a 0-size archive file, an
archive with just the global header (8 bytes in total) will be created
and it is indeed a valid archive by the definition of libarchive, thus
subsequent operation on this archive will be accepted. This especially
solves the failure caused by following sequence: (several ports do)

% ar cru libfoo.a  	    # without specifying obj files
% ranlib libfoo.a

Reviewed by:	kientzle, jkoshy
Approved by:	kientzle
Approved by:	jkoshy	(mentor)
Reported by:	erwin
MFC after:	1 month
This commit is contained in:
kaiw 2008-01-31 08:11:01 +00:00
parent 213915cb49
commit e57ce2b6e6

View File

@ -75,6 +75,7 @@ static int archive_write_ar_header(struct archive_write *,
static ssize_t archive_write_ar_data(struct archive_write *,
const void *buff, size_t s);
static int archive_write_ar_destroy(struct archive_write *);
static int archive_write_ar_finish(struct archive_write *);
static int archive_write_ar_finish_entry(struct archive_write *);
static const char *ar_basename(const char *path);
static int format_octal(int64_t v, char *p, int s);
@ -126,7 +127,7 @@ archive_write_set_format_ar(struct archive_write *a)
a->format_write_header = archive_write_ar_header;
a->format_write_data = archive_write_ar_data;
a->format_finish = NULL;
a->format_finish = archive_write_ar_finish;
a->format_destroy = archive_write_ar_destroy;
a->format_finish_entry = archive_write_ar_finish_entry;
return (ARCHIVE_OK);
@ -397,6 +398,23 @@ archive_write_ar_destroy(struct archive_write *a)
return (ARCHIVE_OK);
}
static int
archive_write_ar_finish(struct archive_write *a)
{
int ret;
/*
* If we haven't written anything yet, we need to write
* the ar global header now to make it a valid ar archive.
*/
if (a->archive.file_position == 0) {
ret = (a->compressor.write)(a, "!<arch>\n", 8);
return (ret);
}
return (ARCHIVE_OK);
}
static int
archive_write_ar_finish_entry(struct archive_write *a)
{