bin/xbps-create: better error handling for writing archives
This fixes issues where if xbps-create creates a new archive on a full disk, it will write an incomplete archive and then later fails to be read by xbps-rindex.
This commit is contained in:
parent
7b66a2885b
commit
04d5554ed2
@ -51,11 +51,6 @@
|
|||||||
|
|
||||||
#define _PROGNAME "xbps-create"
|
#define _PROGNAME "xbps-create"
|
||||||
|
|
||||||
/* libarchive 2.x compat */
|
|
||||||
#if ARCHIVE_VERSION_NUMBER >= 3000000
|
|
||||||
# define archive_write_finish(x) archive_write_free(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct xentry {
|
struct xentry {
|
||||||
TAILQ_ENTRY(xentry) entries;
|
TAILQ_ENTRY(xentry) entries;
|
||||||
uint64_t mtime;
|
uint64_t mtime;
|
||||||
@ -136,6 +131,19 @@ die(const char *fmt, ...)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __attribute__((noreturn))
|
||||||
|
die_archive(struct archive *ar, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
fprintf(stderr, "%s: ERROR: ", _PROGNAME);
|
||||||
|
vfprintf(stderr, fmt, ap);
|
||||||
|
fprintf(stderr, " %s\n", archive_error_string(ar));
|
||||||
|
va_end(ap);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_array(const char *key, const char *val)
|
process_array(const char *key, const char *val)
|
||||||
{
|
{
|
||||||
@ -627,19 +635,16 @@ process_destdir(const char *mutable_files)
|
|||||||
static void
|
static void
|
||||||
write_entry(struct archive *ar, struct archive_entry *entry)
|
write_entry(struct archive *ar, struct archive_entry *entry)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name, *target;
|
||||||
int fd;
|
int fd;
|
||||||
char buf[65536];
|
char buf[65536];
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
if (archive_entry_pathname(entry) == NULL)
|
if ((target = archive_entry_pathname(entry)) == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (archive_write_header(ar, entry)) {
|
if (archive_write_header(ar, entry))
|
||||||
die("cannot write %s to archive: %s",
|
die_archive(ar, "cannot write %s to archive:", target);
|
||||||
archive_entry_pathname(entry),
|
|
||||||
archive_error_string(ar));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only regular files can have data. */
|
/* Only regular files can have data. */
|
||||||
if (archive_entry_filetype(entry) != AE_IFREG ||
|
if (archive_entry_filetype(entry) != AE_IFREG ||
|
||||||
@ -653,7 +658,8 @@ write_entry(struct archive *ar, struct archive_entry *entry)
|
|||||||
if ((fd = open(name, O_RDONLY)) < 0)
|
if ((fd = open(name, O_RDONLY)) < 0)
|
||||||
die("cannot open %s file", name);
|
die("cannot open %s file", name);
|
||||||
while ((len = read(fd, buf, sizeof(buf))) > 0)
|
while ((len = read(fd, buf, sizeof(buf))) > 0)
|
||||||
archive_write_data(ar, buf, len);
|
if (archive_write_data(ar, buf, len) != len)
|
||||||
|
die_archive(ar, "cannot write %s to archive:", target);
|
||||||
(void)close(fd);
|
(void)close(fd);
|
||||||
|
|
||||||
if(len < 0)
|
if(len < 0)
|
||||||
@ -684,7 +690,9 @@ process_entry_file(struct archive *ar,
|
|||||||
die("failed to add entry (fstat) %s to archive:", xe->file);
|
die("failed to add entry (fstat) %s to archive:", xe->file);
|
||||||
|
|
||||||
entry = archive_entry_new();
|
entry = archive_entry_new();
|
||||||
assert(entry);
|
if (entry == NULL)
|
||||||
|
die("failed to add entry %s to archive:", xe->file);
|
||||||
|
|
||||||
archive_entry_set_pathname(entry, xe->file);
|
archive_entry_set_pathname(entry, xe->file);
|
||||||
if (st.st_uid == geteuid())
|
if (st.st_uid == geteuid())
|
||||||
st.st_uid = 0;
|
st.st_uid = 0;
|
||||||
@ -700,7 +708,8 @@ process_entry_file(struct archive *ar,
|
|||||||
|
|
||||||
if (S_ISLNK(st.st_mode)) {
|
if (S_ISLNK(st.st_mode)) {
|
||||||
buf = malloc(st.st_size+1);
|
buf = malloc(st.st_size+1);
|
||||||
assert(buf);
|
if (buf == NULL)
|
||||||
|
die("failed to allocate readlink buffer", xe->file);
|
||||||
len = readlink(p, buf, st.st_size+1);
|
len = readlink(p, buf, st.st_size+1);
|
||||||
if (len < 0 || len > st.st_size)
|
if (len < 0 || len > st.st_size)
|
||||||
die("failed to add entry %s (readlink) to archive:",
|
die("failed to add entry %s (readlink) to archive:",
|
||||||
@ -1030,7 +1039,8 @@ main(int argc, char **argv)
|
|||||||
* Process the binary package's archive (ustar compressed with xz).
|
* Process the binary package's archive (ustar compressed with xz).
|
||||||
*/
|
*/
|
||||||
ar = archive_write_new();
|
ar = archive_write_new();
|
||||||
assert(ar);
|
if (ar == NULL)
|
||||||
|
die("cannot create new archive");
|
||||||
/*
|
/*
|
||||||
* Set compression format, xz if unset.
|
* Set compression format, xz if unset.
|
||||||
*/
|
*/
|
||||||
@ -1060,7 +1070,7 @@ main(int argc, char **argv)
|
|||||||
archive_entry_linkresolver_set_strategy(resolver,
|
archive_entry_linkresolver_set_strategy(resolver,
|
||||||
archive_format(ar));
|
archive_format(ar));
|
||||||
|
|
||||||
if (archive_write_open_fd(ar, pkg_fd) != 0)
|
if (archive_write_open_fd(ar, pkg_fd) != ARCHIVE_OK)
|
||||||
die("Failed to open %s fd for writing:", tname);
|
die("Failed to open %s fd for writing:", tname);
|
||||||
|
|
||||||
process_archive(ar, resolver, pkgver, quiet);
|
process_archive(ar, resolver, pkgver, quiet);
|
||||||
@ -1073,8 +1083,11 @@ main(int argc, char **argv)
|
|||||||
archive_entry_linkify(resolver, &entry, &sparse_entry);
|
archive_entry_linkify(resolver, &entry, &sparse_entry);
|
||||||
}
|
}
|
||||||
archive_entry_linkresolver_free(resolver);
|
archive_entry_linkresolver_free(resolver);
|
||||||
/* close and free archive */
|
|
||||||
archive_write_finish(ar);
|
if (archive_write_close(ar) != ARCHIVE_OK)
|
||||||
|
die_archive(ar, "Failed to write archive %s:", tname);
|
||||||
|
if (archive_write_free(ar) != ARCHIVE_OK)
|
||||||
|
die_archive(ar, "Failed to close archive");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Archive was created successfully; flush data to storage,
|
* Archive was created successfully; flush data to storage,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user