summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2013-05-29 14:37:42 +0300
committerTimo Teräs <timo.teras@iki.fi>2013-05-29 14:37:42 +0300
commit035da870362494bcb4ed092e27278c290b204410 (patch)
treebd5ceffb0dfeff9debceb423bf0c97a93342f1d9
parent6a761c72e203cbc58a4963df9c1c12a233cf5b0a (diff)
downloadapk-tools-035da870362494bcb4ed092e27278c290b204410.tar.gz
apk-tools-035da870362494bcb4ed092e27278c290b204410.tar.bz2
apk-tools-035da870362494bcb4ed092e27278c290b204410.tar.xz
apk-tools-035da870362494bcb4ed092e27278c290b204410.zip
db, info: allow packages to install files/symlinks to root
fixes #1578
-rw-r--r--src/apk_database.h3
-rw-r--r--src/database.c60
-rw-r--r--src/info.c2
3 files changed, 44 insertions, 21 deletions
diff --git a/src/apk_database.h b/src/apk_database.h
index 4628c23..4ede631 100644
--- a/src/apk_database.h
+++ b/src/apk_database.h
@@ -71,6 +71,9 @@ struct apk_db_dir {
char name[];
};
+#define PKG_FILE_FMT "%s%s%s"
+#define PKG_FILE_PRINTF(dir,file) (dir)->name, (dir)->namelen ? "/" : "", (file)->name
+
struct apk_db_dir_instance {
struct hlist_node pkg_dirs_list;
struct hlist_head owned_files;
diff --git a/src/database.c b/src/database.c
index 1fe4eae..d97b504 100644
--- a/src/database.c
+++ b/src/database.c
@@ -263,7 +263,8 @@ void apk_db_dir_unref(struct apk_database *db, struct apk_db_dir *dir, int allow
dir->uid = (uid_t) -1;
dir->gid = (gid_t) -1;
- unlinkat(db->root_fd, dir->name, AT_REMOVEDIR);
+ if (dir->namelen)
+ unlinkat(db->root_fd, dir->name, AT_REMOVEDIR);
} else if (dir->recalc_mode) {
/* Directory permissions need a reset. */
apk_db_dir_mkdir(db, dir);
@@ -1847,8 +1848,10 @@ struct apk_package *apk_db_get_file_owner(struct apk_database *db,
if (filename.len && filename.ptr[0] == '/')
filename.len--, filename.ptr++;
- if (!apk_blob_rsplit(filename, '/', &key.dirname, &key.filename))
- return NULL;
+ if (!apk_blob_rsplit(filename, '/', &key.dirname, &key.filename)) {
+ key.dirname = APK_BLOB_NULL;
+ key.filename = filename;
+ }
dbf = (struct apk_db_file *) apk_hash_get(&db->installed.files,
APK_BLOB_BUF(&key));
@@ -2161,6 +2164,21 @@ static int read_info_line(void *_ctx, apk_blob_t line)
return 0;
}
+static struct apk_db_dir_instance *apk_db_install_directory_entry(struct install_ctx * ctx, apk_blob_t dir)
+{
+ struct apk_database *db = ctx->db;
+ struct apk_package *pkg = ctx->pkg;
+ struct apk_installed_package *ipkg = pkg->ipkg;
+ struct apk_db_dir_instance *diri;
+
+ if (ctx->diri_node == NULL)
+ ctx->diri_node = hlist_tail_ptr(&ipkg->owned_dirs);
+ ctx->diri = diri = apk_db_diri_new(db, pkg, dir, &ctx->diri_node);
+ ctx->file_diri_node = hlist_tail_ptr(&diri->owned_files);
+
+ return diri;
+}
+
static int apk_db_install_archive_entry(void *_ctx,
const struct apk_file_info *ae,
struct apk_istream *is)
@@ -2215,8 +2233,10 @@ static int apk_db_install_archive_entry(void *_ctx,
/* Installable entry */
ctx->current_file_size = apk_calc_installed_size(ae->size);
if (!S_ISDIR(ae->mode)) {
- if (!apk_blob_rsplit(name, '/', &bdir, &bfile))
- return 0;
+ if (!apk_blob_rsplit(name, '/', &bdir, &bfile)) {
+ bdir = APK_BLOB_NULL;
+ bfile = name;
+ }
if (bfile.len > 6 && memcmp(bfile.ptr, ".keep_", 6) == 0)
return 0;
@@ -2224,9 +2244,12 @@ static int apk_db_install_archive_entry(void *_ctx,
/* Make sure the file is part of the cached directory tree */
diri = find_diri(ipkg, bdir, diri, &ctx->file_diri_node);
if (diri == NULL) {
- apk_error("%s: File '%*s' entry without directory entry.\n",
- pkg->name->name, name.len, name.ptr);
- return -1;
+ if (!APK_BLOB_IS_NULL(bdir)) {
+ apk_error("%s: File '%*s' entry without directory entry.\n",
+ pkg->name->name, name.len, name.ptr);
+ return -1;
+ }
+ diri = apk_db_install_directory_entry(ctx, bdir);
}
opkg = NULL;
@@ -2329,12 +2352,7 @@ static int apk_db_install_archive_entry(void *_ctx,
if (name.ptr[name.len-1] == '/')
name.len--;
- if (ctx->diri_node == NULL)
- ctx->diri_node = hlist_tail_ptr(&ipkg->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);
-
+ diri = apk_db_install_directory_entry(ctx, name);
apk_db_diri_set(diri, ae->mode, ae->uid, ae->gid);
apk_db_dir_mkdir(db, diri->dir);
}
@@ -2360,8 +2378,10 @@ static void apk_db_purge_pkg(struct apk_database *db,
diri->dir->modified = 1;
hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files, diri_files_list) {
- snprintf(name, sizeof(name), "%s/%s%s",
- diri->dir->name, file->name, exten ?: "");
+ snprintf(name, sizeof(name),
+ PKG_FILE_FMT "%s",
+ PKG_FILE_PRINTF(diri->dir, file),
+ exten ?: "");
key = (struct apk_db_file_hash_key) {
.dirname = APK_BLOB_PTR_LEN(diri->dir->name, diri->dir->namelen),
@@ -2406,10 +2426,10 @@ static void apk_db_migrate_files(struct apk_database *db,
dir->modified = 1;
hlist_for_each_entry_safe(file, fc, fn, &diri->owned_files, diri_files_list) {
- snprintf(name, sizeof(name), "%s/%s",
- diri->dir->name, file->name);
- snprintf(tmpname, sizeof(tmpname), "%s/%s.apk-new",
- diri->dir->name, file->name);
+ snprintf(name, sizeof(name), PKG_FILE_FMT,
+ PKG_FILE_PRINTF(diri->dir, file));
+ snprintf(tmpname, sizeof(tmpname), PKG_FILE_FMT ".apk-new",
+ PKG_FILE_PRINTF(diri->dir, file));
key = (struct apk_db_file_hash_key) {
.dirname = APK_BLOB_PTR_LEN(dir->name, dir->namelen),
diff --git a/src/info.c b/src/info.c
index 9b37f38..f643df2 100644
--- a/src/info.c
+++ b/src/info.c
@@ -314,7 +314,7 @@ static void info_print_contents(struct apk_database *db, struct apk_package *pkg
diri_files_list) {
if (apk_verbosity > 1)
printf("%s: ", pkg->name->name);
- printf("%s/%s\n", diri->dir->name, file->name);
+ printf(PKG_FILE_FMT "\n", PKG_FILE_PRINTF(diri->dir, file));
}
}
}