diff --git a/TODO b/TODO index cac06a4..9ee75c7 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,3 @@ -- New style scripts - Internal gunzip (via lib) to speed up stuff, and avoid threads - mmap() if possible for reading diff --git a/src/apk_package.h b/src/apk_package.h index c3649fd..68e63e1 100644 --- a/src/apk_package.h +++ b/src/apk_package.h @@ -18,12 +18,14 @@ struct apk_database; struct apk_name; -#define APK_SCRIPT_PRE_INSTALL 0 -#define APK_SCRIPT_POST_INSTALL 1 -#define APK_SCRIPT_PRE_DEINSTALL 2 -#define APK_SCRIPT_POST_DEINSTALL 3 -#define APK_SCRIPT_PRE_UPGRADE 4 -#define APK_SCRIPT_POST_UPGRADE 5 +#define APK_SCRIPT_INVALID -1 +#define APK_SCRIPT_GENERIC 0 +#define APK_SCRIPT_PRE_INSTALL 1 +#define APK_SCRIPT_POST_INSTALL 2 +#define APK_SCRIPT_PRE_DEINSTALL 3 +#define APK_SCRIPT_POST_DEINSTALL 4 +#define APK_SCRIPT_PRE_UPGRADE 5 +#define APK_SCRIPT_POST_UPGRADE 6 struct apk_script { struct hlist_node script_list; diff --git a/src/database.c b/src/database.c index 168df04..6b32255 100644 --- a/src/database.c +++ b/src/database.c @@ -673,12 +673,16 @@ static int apk_db_install_archive_entry(struct apk_archive_entry *ae, struct apk_db_dir *dir; struct apk_db_file *file; const char *p; - int r = 0, type; + int r = 0, type = APK_SCRIPT_INVALID; - if (strcmp(ae->name, ".PKGINFO") == 0) - return 0; - - if (strncmp(ae->name, "var/db/apk/", 11) == 0) { + /* Package metainfo and script processing */ + if (ae->name[0] == '.') { + /* APK 2.0 format */ + if (strcmp(ae->name, ".INSTALL") != 0) + return 0; + type = APK_SCRIPT_GENERIC; + } else if (strncmp(ae->name, "var/db/apk/", 11) == 0) { + /* APK 1.0 format */ p = &ae->name[11]; if (strncmp(p, pkg->name->name, strlen(pkg->name->name)) != 0) return 0; @@ -688,13 +692,17 @@ static int apk_db_install_archive_entry(struct apk_archive_entry *ae, p += strlen(pkg->version) + 1; type = apk_script_type(p); - if (type < 0) + if (type != APK_SCRIPT_INVALID) return 0; + } + /* Handle script */ + if (type != APK_SCRIPT_INVALID) { ae->size -= apk_pkg_add_script(pkg, ae->read_fd, type, ae->size); - if (type == ctx->script) { + if (type == APK_SCRIPT_GENERIC || + type == ctx->script) { r = apk_pkg_run_script(pkg, db->root_fd, type); if (r != 0) apk_error("%s-%s: Failed to execute pre-install/upgrade script", @@ -704,6 +712,7 @@ static int apk_db_install_archive_entry(struct apk_archive_entry *ae, return r; } + /* Installable entry */ if (ctx->file_pkg_node == NULL) ctx->file_pkg_node = hlist_tail_ptr(&pkg->owned_files); diff --git a/src/package.c b/src/package.c index bc517ad..1cbf203 100644 --- a/src/package.c +++ b/src/package.c @@ -49,15 +49,15 @@ int apk_pkg_parse_name(apk_blob_t apkname, return 0; } -static char *trim(apk_blob_t str) +static apk_blob_t trim(apk_blob_t str) { if (str.ptr == NULL || str.len < 1) - return NULL; + return str; if (str.ptr[str.len-2] == '\n') - str.ptr[str.len-2] = 0; + return APK_BLOB_PTR_LEN(str.ptr, str.len-1); - return str.ptr; + return str; } static void parse_depend(struct apk_database *db, @@ -154,6 +154,15 @@ static const char *script_types[] = { [APK_SCRIPT_POST_UPGRADE] = "post-upgrade", }; +static const char *script_types2[] = { + [APK_SCRIPT_PRE_INSTALL] = "pre_install", + [APK_SCRIPT_POST_INSTALL] = "post_install", + [APK_SCRIPT_PRE_DEINSTALL] = "pre_deinstall", + [APK_SCRIPT_POST_DEINSTALL] = "post_deinstall", + [APK_SCRIPT_PRE_UPGRADE] = "pre_upgrade", + [APK_SCRIPT_POST_UPGRADE] = "post_upgrade", +}; + int apk_script_type(const char *name) { int i; @@ -247,59 +256,69 @@ static int read_info_line(void *ctx, apk_blob_t line) static int read_info_entry(struct apk_archive_entry *ae, void *ctx) { + static struct { + const char *str; + char field; + } fields[] = { + { "DESC", 'T' }, + { "WW", 'U' }, + { "LICENSE", 'L' }, + { "DEPEND", 'D' }, + }; struct read_info_ctx *ri = (struct read_info_ctx *) ctx; struct apk_database *db = ri->db; struct apk_package *pkg = ri->pkg; const int bsize = 4 * 1024; apk_blob_t name, version; char *slash, *str; + int i; - if (strcmp(ae->name, ".PKGINFO") == 0) { - apk_blob_t blob = apk_archive_entry_read(ae); - apk_blob_for_each_segment(blob, "\n", read_info_line, ctx); - free(blob.ptr); - return 0; - } - - if (strncmp(ae->name, "var/db/apk/", 11) != 0) { - pkg->installed_size += (ae->size + bsize - 1) & ~(bsize - 1); - return 0; - } - - if (!S_ISREG(ae->mode)) - return 0; - - slash = strchr(&ae->name[11], '/'); - if (slash == NULL) - return 0; - - if (apk_pkg_parse_name(APK_BLOB_PTR_PTR(&ae->name[11], slash-1), - &name, &version) < 0) - return -1; - - if (pkg->name == NULL) { - str = apk_blob_cstr(name); - pkg->name = apk_db_get_name(db, str); - free(str); - } - if (pkg->version == NULL) - pkg->version = apk_blob_cstr(version); - - if (strcmp(slash, "/DEPEND") == 0) { - apk_blob_t blob = apk_archive_entry_read(ae); - if (blob.ptr) { - apk_deps_parse(db, &pkg->depends, blob); + /* Meta info and scripts */ + if (ae->name[0] == '.') { + /* APK 2.0 format */ + if (strcmp(ae->name, ".PKGINFO") == 0) { + apk_blob_t blob = apk_archive_entry_read(ae); + apk_blob_for_each_segment(blob, "\n", read_info_line, ctx); free(blob.ptr); + /* FIXME: all done after checking if .INSTALL exists */ + return 0; } - } else if (strcmp(slash, "/DESC") == 0) { - pkg->description = trim(apk_archive_entry_read(ae)); - } else if (strcmp(slash, "/WWW") == 0) { - pkg->url = trim(apk_archive_entry_read(ae)); - } else if (strcmp(slash, "/LICENSE") == 0) { - pkg->license = trim(apk_archive_entry_read(ae)); - } else if (apk_script_type(slash+1) == APK_SCRIPT_POST_INSTALL || - apk_script_type(slash+1) == APK_SCRIPT_PRE_INSTALL) - ri->has_install = 1; + } else if (strncmp(ae->name, "var/db/apk/", 11) == 0) { + /* APK 1.0 format */ + if (!S_ISREG(ae->mode)) + return 0; + + slash = strchr(&ae->name[11], '/'); + if (slash == NULL) + return 0; + + if (apk_pkg_parse_name(APK_BLOB_PTR_PTR(&ae->name[11], slash-1), + &name, &version) < 0) + return -1; + + if (pkg->name == NULL) { + str = apk_blob_cstr(name); + pkg->name = apk_db_get_name(db, str); + free(str); + } + if (pkg->version == NULL) + pkg->version = apk_blob_cstr(version); + + for (i = 0; i < ARRAY_SIZE(fields); i++) { + if (strcmp(fields[i].str, slash+1) == 0) { + apk_blob_t blob = apk_archive_entry_read(ae); + add_info(ri->db, ri->pkg, fields[i].field, + trim(blob)); + free(blob.ptr); + break; + } + } + if (apk_script_type(slash+1) == APK_SCRIPT_POST_INSTALL || + apk_script_type(slash+1) == APK_SCRIPT_PRE_INSTALL) + ri->has_install = 1; + } else { + pkg->installed_size += (ae->size + bsize - 1) & ~(bsize - 1); + } return 0; } @@ -420,13 +439,14 @@ int apk_pkg_run_script(struct apk_package *pkg, int root_fd, fchdir(root_fd); hlist_for_each_entry(script, c, &pkg->scripts, script_list) { - if (script->type != type) + if (script->type != type && + script->type != APK_SCRIPT_GENERIC) continue; snprintf(fn, sizeof(fn), "tmp/%s-%s.%s", pkg->name->name, pkg->version, - script_types[script->type]); + script_types[type]); fd = creat(fn, 0777); if (fd < 0) return fd; @@ -441,13 +461,17 @@ int apk_pkg_run_script(struct apk_package *pkg, int root_fd, if (pid == 0) { if (chroot(".") < 0) { apk_error("chroot: %s", strerror(errno)); - } else - execle(fn, script_types[script->type], + } else if (script->type == APK_SCRIPT_GENERIC) { + execle(fn, "INSTALL", script_types2[type], pkg->version, "", NULL, environment); + } else { + execle(fn, script_types[type], + pkg->version, "", NULL, environment); + } exit(1); } waitpid(pid, &status, 0); - //unlink(fn); + unlink(fn); if (WIFEXITED(status)) return WEXITSTATUS(status); return -1;