summaryrefslogtreecommitdiff
path: root/src/archive.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/archive.c')
-rw-r--r--src/archive.c111
1 files changed, 58 insertions, 53 deletions
diff --git a/src/archive.c b/src/archive.c
index 3062c43..63eb48f 100644
--- a/src/archive.c
+++ b/src/archive.c
@@ -397,7 +397,7 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
{
struct apk_xattr *xattr;
char *fn = ae->name;
- int fd, r = -1, atflags = 0;
+ int fd, r = -1, atflags = 0, ret = 0;
if (suffix != NULL) {
fn = alloca(PATH_MAX);
@@ -413,8 +413,8 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
switch (ae->mode & S_IFMT) {
case S_IFDIR:
r = mkdirat(atfd, fn, ae->mode & 07777);
- if (r < 0 && errno == EEXIST)
- r = 0;
+ if (r < 0 && errno != EEXIST)
+ ret = -errno;
break;
case S_IFREG:
if (ae->link_target == NULL) {
@@ -422,11 +422,11 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
fd = openat(atfd, fn, flags, ae->mode & 07777);
if (fd < 0) {
- r = -1;
+ ret = -errno;
break;
}
- if (apk_istream_splice(is, fd, ae->size, cb, cb_ctx) == ae->size)
- r = 0;
+ r = apk_istream_splice(is, fd, ae->size, cb, cb_ctx);
+ if (r != ae->size) ret = r < 0 ? r : -ENOSPC;
close(fd);
} else {
char *link_target = ae->link_target;
@@ -436,10 +436,12 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
ae->link_target, suffix);
}
r = linkat(atfd, link_target, atfd, fn, 0);
+ if (r < 0) ret = -errno;
}
break;
case S_IFLNK:
r = symlinkat(ae->link_target, atfd, fn);
+ if (r < 0) ret = -errno;
atflags |= AT_SYMLINK_NOFOLLOW;
break;
case S_IFSOCK:
@@ -447,65 +449,68 @@ int apk_archive_entry_extract(int atfd, const struct apk_file_info *ae,
case S_IFCHR:
case S_IFIFO:
r = mknodat(atfd, fn, ae->mode & 07777, ae->device);
+ if (r < 0) ret = -errno;
break;
}
- if (r == 0) {
- r = fchownat(atfd, fn, ae->uid, ae->gid, atflags);
+ if (ret) {
+ apk_error("Failed to create %s: %s", ae->name, strerror(-ret));
+ return ret;
+ }
+
+ r = fchownat(atfd, fn, ae->uid, ae->gid, atflags);
+ if (r < 0) {
+ apk_error("Failed to set ownership on %s: %s",
+ fn, strerror(errno));
+ if (!ret) ret = -errno;
+ }
+
+ /* chown resets suid bit so we need set it again */
+ if (ae->mode & 07000) {
+ r = fchmodat(atfd, fn, ae->mode & 07777, atflags);
if (r < 0) {
- apk_error("Failed to set ownership on %s: %s",
+ apk_error("Failed to set file permissions "
+ "on %s: %s",
fn, strerror(errno));
- return -errno;
- }
-
- /* chown resets suid bit so we need set it again */
- if (ae->mode & 07000) {
- r = fchmodat(atfd, fn, ae->mode & 07777, atflags);
- if (r < 0) {
- apk_error("Failed to set file permissions "
- "on %s: %s",
- fn, strerror(errno));
- return -errno;
- }
+ if (!ret) ret = -errno;
}
+ }
- /* extract xattrs */
- if (ae->xattrs && ae->xattrs->num) {
- r = 0;
- fd = openat(atfd, fn, O_RDWR);
- if (fd >= 0) {
- foreach_array_item(xattr, ae->xattrs) {
- if (fsetxattr(fd, xattr->name, xattr->value.ptr, xattr->value.len, 0) < 0) {
- r = errno;
- break;
- }
+ /* extract xattrs */
+ if (ae->xattrs && ae->xattrs->num) {
+ r = 0;
+ fd = openat(atfd, fn, O_RDWR);
+ if (fd >= 0) {
+ foreach_array_item(xattr, ae->xattrs) {
+ if (fsetxattr(fd, xattr->name, xattr->value.ptr, xattr->value.len, 0) < 0) {
+ r = -errno;
+ if (r != -ENOTSUP) break;
}
- close(fd);
- } else {
- r = errno;
}
- if (r) {
+ close(fd);
+ } else {
+ r = -errno;
+ }
+ if (r) {
+ if (r != -ENOTSUP)
apk_error("Failed to set xattrs on %s: %s",
- fn, strerror(r));
- return -r;
- }
+ fn, strerror(-r));
+ if (!ret) ret = -errno;
}
+ }
- if (!S_ISLNK(ae->mode)) {
- /* preserve modification time */
- struct timespec times[2];
-
- times[0].tv_sec = times[1].tv_sec = ae->mtime;
- times[0].tv_nsec = times[1].tv_nsec = 0;
- r = utimensat(atfd, fn, times, atflags);
- if (r < 0) {
- apk_error("Failed to preserve modification time on %s: %s",
- fn, strerror(errno));
- return -errno;
- }
+ if (!S_ISLNK(ae->mode)) {
+ /* preserve modification time */
+ struct timespec times[2];
+
+ times[0].tv_sec = times[1].tv_sec = ae->mtime;
+ times[0].tv_nsec = times[1].tv_nsec = 0;
+ r = utimensat(atfd, fn, times, atflags);
+ if (r < 0) {
+ apk_error("Failed to preserve modification time on %s: %s",
+ fn, strerror(errno));
+ if (!ret || ret == -ENOTSUP) ret = -errno;
}
- } else {
- apk_error("Failed to extract %s: %s", ae->name, strerror(errno));
- return -errno;
}
+
return 0;
}