make file install errors non-fatal, and xattr errors hidden
user xattrs on tmpfs are not supported no non-grsec kernels, and many times root fs is mounted without user_xattr. Thus to allow things to go smoothly on non-grsec kernels xattr unsupported errors are now hidden. xattrs can be fixed still now with "apk fix --xattrs"cute-signatures
parent
60867c47c5
commit
90e760339e
|
@ -91,6 +91,7 @@ struct apk_installed_package {
|
|||
unsigned run_all_triggers : 1;
|
||||
unsigned broken_files : 1;
|
||||
unsigned broken_script : 1;
|
||||
unsigned broken_xattr : 1;
|
||||
};
|
||||
|
||||
struct apk_package {
|
||||
|
|
131
src/archive.c
131
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 (r < 0) {
|
||||
apk_error("Failed to set ownership 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
} else {
|
||||
r = errno;
|
||||
}
|
||||
if (r) {
|
||||
apk_error("Failed to set xattrs on %s: %s",
|
||||
fn, strerror(r));
|
||||
return -r;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
apk_error("Failed to extract %s: %s", ae->name, strerror(errno));
|
||||
return -errno;
|
||||
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 file permissions "
|
||||
"on %s: %s",
|
||||
fn, strerror(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;
|
||||
if (r != -ENOTSUP) break;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
} else {
|
||||
r = -errno;
|
||||
}
|
||||
if (r) {
|
||||
if (r != -ENOTSUP)
|
||||
apk_error("Failed to set xattrs on %s: %s",
|
||||
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));
|
||||
if (!ret || ret == -ENOTSUP) ret = -errno;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -110,7 +110,8 @@ static int audit_file(struct audit_ctx *actx,
|
|||
if (dbf->csum.type != APK_CHECKSUM_NONE &&
|
||||
apk_checksum_compare(&fi.csum, &dbf->csum) != 0)
|
||||
rv = 'U';
|
||||
else if (apk_checksum_compare(&fi.xattr_csum, &dbf->acl->xattr_csum) != 0)
|
||||
else if (!dbf->diri->pkg->ipkg->broken_xattr &&
|
||||
apk_checksum_compare(&fi.xattr_csum, &dbf->acl->xattr_csum) != 0)
|
||||
rv = 'x';
|
||||
else if (S_ISLNK(fi.mode) && dbf->csum.type == APK_CHECKSUM_NONE)
|
||||
rv = 'U';
|
||||
|
|
|
@ -852,6 +852,7 @@ int apk_db_index_read(struct apk_database *db, struct apk_bstream *bs, int repo)
|
|||
switch (l.ptr[r]) {
|
||||
case 'f': ipkg->broken_files = 1; break;
|
||||
case 's': ipkg->broken_script = 1; break;
|
||||
case 'x': ipkg->broken_xattr = 1; break;
|
||||
default:
|
||||
if (!(apk_flags & APK_FORCE))
|
||||
goto old_apk_tools;
|
||||
|
@ -926,12 +927,14 @@ static int apk_db_write_fdb(struct apk_database *db, struct apk_ostream *os)
|
|||
apk_blob_push_blob(&bbuf, db->repo_tags[ipkg->repository_tag].plain_name);
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
|
||||
}
|
||||
if (ipkg->broken_files || ipkg->broken_script) {
|
||||
if (ipkg->broken_files || ipkg->broken_script || ipkg->broken_xattr) {
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("f:"));
|
||||
if (ipkg->broken_files)
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("f"));
|
||||
if (ipkg->broken_script)
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("s"));
|
||||
if (ipkg->broken_xattr)
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("x"));
|
||||
apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n"));
|
||||
}
|
||||
hlist_for_each_entry(diri, c1, &ipkg->owned_dirs, pkg_dirs_list) {
|
||||
|
@ -2366,35 +2369,44 @@ static int apk_db_install_archive_entry(void *_ctx,
|
|||
r = apk_archive_entry_extract(db->root_fd, ae, ".apk-new", is,
|
||||
extract_cb, ctx);
|
||||
|
||||
/* Hardlinks need special care for checksum */
|
||||
if (ae->csum.type == APK_CHECKSUM_NONE &&
|
||||
ae->link_target != NULL) {
|
||||
do {
|
||||
struct apk_db_file *lfile;
|
||||
struct apk_db_dir_instance *ldiri;
|
||||
struct hlist_node *n;
|
||||
switch (r) {
|
||||
case 0:
|
||||
/* Hardlinks need special care for checksum */
|
||||
if (ae->csum.type == APK_CHECKSUM_NONE &&
|
||||
ae->link_target != NULL) {
|
||||
do {
|
||||
struct apk_db_file *lfile;
|
||||
struct apk_db_dir_instance *ldiri;
|
||||
struct hlist_node *n;
|
||||
|
||||
if (!apk_blob_rsplit(APK_BLOB_STR(ae->link_target),
|
||||
'/', &bdir, &bfile))
|
||||
break;
|
||||
|
||||
ldiri = find_diri(ipkg, bdir, diri, NULL);
|
||||
if (ldiri == NULL)
|
||||
break;
|
||||
|
||||
hlist_for_each_entry(lfile, n, &ldiri->owned_files,
|
||||
diri_files_list) {
|
||||
if (apk_blob_compare(APK_BLOB_PTR_LEN(lfile->name, lfile->namelen),
|
||||
bfile) == 0) {
|
||||
memcpy(&file->csum, &lfile->csum,
|
||||
sizeof(file->csum));
|
||||
if (!apk_blob_rsplit(APK_BLOB_STR(ae->link_target),
|
||||
'/', &bdir, &bfile))
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
} else
|
||||
memcpy(&file->csum, &ae->csum, sizeof(file->csum));
|
||||
ldiri = find_diri(ipkg, bdir, diri, NULL);
|
||||
if (ldiri == NULL)
|
||||
break;
|
||||
|
||||
hlist_for_each_entry(lfile, n, &ldiri->owned_files,
|
||||
diri_files_list) {
|
||||
if (apk_blob_compare(APK_BLOB_PTR_LEN(lfile->name, lfile->namelen),
|
||||
bfile) == 0) {
|
||||
memcpy(&file->csum, &lfile->csum,
|
||||
sizeof(file->csum));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
} else
|
||||
memcpy(&file->csum, &ae->csum, sizeof(file->csum));
|
||||
break;
|
||||
case -ENOTSUP:
|
||||
ipkg->broken_xattr = 1;
|
||||
break;
|
||||
default:
|
||||
ipkg->broken_files = 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (apk_verbosity >= 3)
|
||||
apk_message("%s (dir)", ae->name);
|
||||
|
@ -2408,7 +2420,7 @@ static int apk_db_install_archive_entry(void *_ctx,
|
|||
}
|
||||
ctx->installed_size += ctx->current_file_size;
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void apk_db_purge_pkg(struct apk_database *db,
|
||||
|
@ -2659,6 +2671,7 @@ int apk_db_install_pkg(struct apk_database *db, struct apk_package *oldpkg,
|
|||
ipkg->run_all_triggers = 1;
|
||||
ipkg->broken_script = 0;
|
||||
ipkg->broken_files = 0;
|
||||
ipkg->broken_xattr = 0;
|
||||
if (ipkg->triggers->num != 0) {
|
||||
list_del(&ipkg->trigger_pkgs_list);
|
||||
list_init(&ipkg->trigger_pkgs_list);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
struct fix_ctx {
|
||||
unsigned short solver_flags;
|
||||
int fix_depends : 1;
|
||||
int fix_xattrs : 1;
|
||||
int fix_directory_permissions : 1;
|
||||
int errors;
|
||||
};
|
||||
|
@ -30,6 +31,9 @@ static int option_parse_applet(void *pctx, struct apk_db_options *dbopts, int op
|
|||
case 'd':
|
||||
ctx->fix_depends = 1;
|
||||
break;
|
||||
case 'x':
|
||||
ctx->fix_xattrs = 1;
|
||||
break;
|
||||
case 'u':
|
||||
ctx->solver_flags |= APK_SOLVERF_UPGRADE;
|
||||
break;
|
||||
|
@ -49,6 +53,7 @@ static const struct apk_option options_applet[] = {
|
|||
{ 'd', "depends", "Fix all dependencies too" },
|
||||
{ 'r', "reinstall", "Reinstall the package (default)" },
|
||||
{ 'u', "upgrade", "Prefer to upgrade package" },
|
||||
{ 'x', "xattr", "Fix packages with broken xattrs" },
|
||||
{ 0x10000, "directory-permissions", "Reset all directory permissions" },
|
||||
};
|
||||
|
||||
|
@ -95,7 +100,8 @@ static int fix_main(void *pctx, struct apk_database *db, struct apk_string_array
|
|||
|
||||
if (args->num == 0) {
|
||||
list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
|
||||
if (ipkg->broken_files || ipkg->broken_script)
|
||||
if (ipkg->broken_files || ipkg->broken_script ||
|
||||
(ipkg->broken_xattr && ctx->fix_xattrs))
|
||||
mark_fix(ctx, ipkg->pkg->name);
|
||||
}
|
||||
} else
|
||||
|
|
Loading…
Reference in New Issue