Skip to content

Commit a2ee63a

Browse files
committed
lib: more error handling for xbps_archive_get_file
1 parent 0b1bd28 commit a2ee63a

File tree

1 file changed

+39
-10
lines changed

1 file changed

+39
-10
lines changed

lib/archive.c

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,54 @@
3838
char HIDDEN *
3939
xbps_archive_get_file(struct archive *ar, struct archive_entry *entry)
4040
{
41-
size_t buflen;
42-
ssize_t nbytes = -1;
41+
size_t used = 0;
42+
size_t len;
4343
char *buf;
44+
int r;
4445

4546
assert(ar != NULL);
4647
assert(entry != NULL);
4748

48-
buflen = (size_t)archive_entry_size(entry);
49-
buf = malloc(buflen+1);
50-
if (buf == NULL)
51-
return NULL;
49+
len = archive_entry_size(entry);
5250

53-
nbytes = archive_read_data(ar, buf, buflen);
54-
if ((size_t)nbytes != buflen) {
55-
free(buf);
51+
buf = malloc(len + 1);
52+
if (!buf) {
53+
xbps_error_printf("out of memory\n");
54+
errno = ENOMEM;
5655
return NULL;
5756
}
58-
buf[buflen] = '\0';
57+
58+
for (;;) {
59+
ssize_t rd = archive_read_data(ar, buf + used, len - used);
60+
if (rd == ARCHIVE_FATAL || rd == ARCHIVE_WARN) {
61+
r = -archive_errno(ar);
62+
xbps_error_printf(
63+
"failed to ready archive entry: %s: %s\n",
64+
archive_entry_pathname(entry),
65+
archive_error_string(ar));
66+
goto err;
67+
} else if (rd == ARCHIVE_RETRY) {
68+
continue;
69+
}
70+
used += rd;
71+
if (rd == 0 || used == len)
72+
break;
73+
}
74+
if (used < len) {
75+
r = -EIO;
76+
xbps_error_printf(
77+
"failed to read archive entry: %s: could not read enough "
78+
"data: %s\n",
79+
archive_entry_pathname(entry), strerror(-r));
80+
goto err;
81+
}
82+
83+
buf[len] = '\0';
5984
return buf;
85+
err:
86+
free(buf);
87+
errno = -r;
88+
return NULL;
6089
}
6190

6291
xbps_dictionary_t HIDDEN

0 commit comments

Comments
 (0)