Newer
Older
apk_db_file_change_owner(db, file, diri,
&ctx->file_diri_node);
}
if ((diri->dir->flags & APK_DBDIRF_PROTECTED) &&
csum_valid(file->csum) &&
apk_file_get_info(ae->name, &fi) == 0 &&
memcmp(file->csum, fi.csum, sizeof(csum_t)) != 0) {
/* Protected file, which is modified locally.
* Extract to separate place */
snprintf(alt_name, sizeof(alt_name),
"%s/%s.apk-new",
diri->dir->dirname, file->filename);
r = apk_archive_entry_extract(ae, is, alt_name,
extract_cb, ctx);
r = apk_archive_entry_extract(ae, is, NULL,
extract_cb, ctx);
}
memcpy(file->csum, ae->csum, sizeof(csum_t));
} else {
if (name.ptr[name.len-1] == '/')
name.len--;
if (ctx->diri_node == NULL)
ctx->diri_node = hlist_tail_ptr(&pkg->owned_dirs);
ctx->diri = diri = apk_db_diri_new(db, pkg, name,
&ctx->diri_node);
ctx->file_diri_node = hlist_tail_ptr(&diri->owned_files);
apk_db_diri_set(diri, ae->mode & 0777, ae->uid, ae->gid);
}
ctx->installed_size += ctx->current_file_size;
return r;
}
static void apk_db_purge_pkg(struct apk_database *db,
struct apk_package *pkg)
{
struct apk_db_file *file;
struct apk_db_file_hash_key key;
struct hlist_node *dc, *dn, *fc, *fn;
char name[1024];
hlist_for_each_entry_safe(diri, dc, dn, &pkg->owned_dirs, pkg_dirs_list) {
hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files, diri_files_list) {
snprintf(name, sizeof(name), "%s/%s",
diri->dir->dirname,
file->filename);
key = (struct apk_db_file_hash_key) {
.dirname = APK_BLOB_STR(diri->dir->dirname),
.filename = APK_BLOB_STR(file->filename),
};
apk_hash_delete(&db->installed.files,
APK_BLOB_BUF(&key));
unlink(name);
__hlist_del(fc, &diri->owned_files.first);
db->installed.stats.files--;
}
apk_db_dir_unref(db, diri->dir);
__hlist_del(dc, &pkg->owned_dirs.first);
}
apk_pkg_set_state(db, pkg, APK_STATE_NO_INSTALL);
}
int apk_db_install_pkg(struct apk_database *db,
struct apk_package *oldpkg,
struct apk_package *newpkg,
apk_progress_cb cb, void *cb_ctx)
{
struct install_ctx ctx;
csum_t csum;
char file[256];
return errno;
/* Just purging? */
if (oldpkg != NULL && newpkg == NULL) {
r = apk_pkg_run_script(oldpkg, db->root_fd,
APK_SCRIPT_PRE_DEINSTALL);
if (r != 0)
return r;
apk_db_purge_pkg(db, oldpkg);
r = apk_pkg_run_script(oldpkg, db->root_fd,
APK_SCRIPT_POST_DEINSTALL);
return r;
}
/* Install the new stuff */
if (newpkg->filename == NULL) {
for (i = 0; i < APK_MAX_REPOS; i++)
if (newpkg->repos & BIT(i))
break;
if (i >= APK_MAX_REPOS) {
apk_error("%s-%s: not present in any repository",
newpkg->name->name, newpkg->version);
return -1;
}
snprintf(file, sizeof(file),
"%s/%s-%s.apk",
db->repos[i].url,
newpkg->name->name, newpkg->version);
bs = apk_bstream_from_file(newpkg->filename);
apk_error("%s: %s", file, strerror(errno));
return errno;
ctx = (struct install_ctx) {
.db = db,
.pkg = newpkg,
.script = (oldpkg == NULL) ?
APK_SCRIPT_PRE_INSTALL : APK_SCRIPT_PRE_UPGRADE,
.cb = cb,
.cb_ctx = cb_ctx,
};
if (apk_parse_tar_gz(bs, apk_db_install_archive_entry, &ctx) != 0)
goto err_close;
apk_pkg_set_state(db, newpkg, APK_STATE_INSTALL);
if (memcmp(csum, newpkg->csum, sizeof(csum)) != 0)
apk_warning("%s-%s: checksum does not match",
newpkg->name->name, newpkg->version);
if (oldpkg != NULL)
apk_db_purge_pkg(db, oldpkg);
r = apk_pkg_run_script(newpkg, db->root_fd,
(oldpkg == NULL) ?
APK_SCRIPT_POST_INSTALL : APK_SCRIPT_POST_UPGRADE);
apk_error("%s-%s: Failed to execute post-install/upgrade script",
newpkg->name->name, newpkg->version);
return r;
err_close:
return -1;
}