From ca85bcb7bd3fccbf361e7e97c0dc3df12e4b5943 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Fri, 11 Mar 2011 08:34:42 +0000 Subject: url: try wget from $PATH first and fallback to busybox wget If GNU wget is available, then we want use it as it gives the user possibility to set misc options, such as bandwidth limit in wgetrc. It might also be that busybox is not available in case bootstrapping alpine from other distros (think debian vserver host creating an alpine guest) In any case we, fall back to busybox wget in case wget libs are getting upgraded. (see http://redmine.alpinelinux.org/issues/347) --- src/url.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/url.c b/src/url.c index d007860..0a17a7a 100644 --- a/src/url.c +++ b/src/url.c @@ -70,6 +70,10 @@ static int fork_wget(const char *url, pid_t *ppid) close(fds[0]); dup2(open("/dev/null", O_RDONLY), STDIN_FILENO); dup2(fds[1], STDOUT_FILENO); + execlp("wget", "wget", "-q", "-O", "-", url, NULL); + /* fall back to busybox wget + * See http://redmine.alpinelinux.org/issues/347 + */ execlp("busybox", "wget", "-q", "-O", "-", url, NULL); exit(0); } -- cgit v1.2.3 From 15badbfd975b2a898acaacfc943e4df2cb1c7864 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Wed, 16 Mar 2011 13:18:54 +0200 Subject: db: detect tmpfs better Use statfs() filesystem type, instead of the device IDs. --- src/database.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/database.c b/src/database.c index 53a18c7..eea852a 100644 --- a/src/database.c +++ b/src/database.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -1061,6 +1062,7 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) struct apk_repository_list *repo = NULL; struct apk_bstream *bs; struct stat64 st; + struct statfs stfs; apk_blob_t blob; int r, rr = 0; @@ -1096,7 +1098,8 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) msg = "Unable to open root"; goto ret_errno; } - if (fstat64(db->root_fd, &st) != 0 || major(st.st_dev) == 0) + if (fstatfs(db->root_fd, &stfs) == 0 && + stfs.f_type == 0x01021994 /* TMPFS_MAGIC */) db->permanent = 0; if (fstatat64(db->root_fd, apk_linked_cache_dir, &st, 0) == 0 && -- cgit v1.2.3 From 1e17da9d704097523e337b64d2b0e424caa4a9ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Wed, 16 Mar 2011 14:51:44 +0200 Subject: db: handle arch similarly to stable branch if package arch is not set, do not append anything to repository. if arch is set, it is appended to repository. --- src/apk_database.h | 2 +- src/cache.c | 3 ++- src/database.c | 37 +++++++++++++++++++++++-------------- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/apk_database.h b/src/apk_database.h index b79253d..64c4fed 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -183,7 +183,7 @@ int apk_repository_update(struct apk_database *db, struct apk_repository *repo); int apk_db_cache_active(struct apk_database *db); void apk_cache_format_index(apk_blob_t to, struct apk_repository *repo); -int apk_cache_download(struct apk_database *db, const char *url, +int apk_cache_download(struct apk_database *db, const char *url, apk_blob_t *arch, const char *item, const char *cache_item, int verify); int apk_db_install_pkg(struct apk_database *db, diff --git a/src/cache.c b/src/cache.c index 60c7aeb..f827cc1 100644 --- a/src/cache.c +++ b/src/cache.c @@ -58,7 +58,8 @@ static int cache_download(struct apk_database *db) continue; apk_pkg_format_plain(pkg, APK_BLOB_BUF(item)); - apk_cache_download(db, repo->url, item, cacheitem, + apk_cache_download(db, repo->url, pkg->arch, + item, cacheitem, APK_SIGN_VERIFY_IDENTITY); } diff --git a/src/database.c b/src/database.c index eea852a..4531eeb 100644 --- a/src/database.c +++ b/src/database.c @@ -428,9 +428,7 @@ struct apk_package *apk_db_pkg_add(struct apk_database *db, struct apk_package * struct apk_package *idb; if (pkg->license == NULL) - pkg->license = apk_blob_atomize(APK_BLOB_NULL); - if (pkg->arch == NULL) - pkg->arch = apk_blob_atomize(APK_BLOB_STR(APK_DEFAULT_ARCH)); + pkg->license = apk_blob_atomize(APK_BLOB_NULL); idb = apk_hash_get(&db->available.packages, APK_BLOB_CSUM(pkg->csum)); if (idb == NULL) { @@ -464,15 +462,20 @@ void apk_cache_format_index(apk_blob_t to, struct apk_repository *repo) apk_blob_push_blob(&to, APK_BLOB_PTR_LEN("", 1)); } -int apk_cache_download(struct apk_database *db, const char *url, +int apk_cache_download(struct apk_database *db, const char *url, apk_blob_t *arch, const char *item, const char *cacheitem, int verify) { char fullurl[PATH_MAX]; int r; - snprintf(fullurl, sizeof(fullurl), "%s%s" BLOB_FMT "/%s", - url, url[strlen(url)-1] == '/' ? "" : "/", - BLOB_PRINTF(*db->arch), item); + if (arch != NULL) + snprintf(fullurl, sizeof(fullurl), "%s%s" BLOB_FMT "/%s", + url, url[strlen(url)-1] == '/' ? "" : "/", + BLOB_PRINTF(*arch), item); + else + snprintf(fullurl, sizeof(fullurl), "%s%s/%s", + url, url[strlen(url)-1] == '/' ? "" : "/", + item); apk_message("fetch %s", fullurl); if (apk_flags & APK_SIMULATE) @@ -1432,15 +1435,20 @@ static int apk_repo_is_remote(struct apk_repository *repo) } static struct apk_bstream *apk_repo_file_open(struct apk_repository *repo, - apk_blob_t arch, + apk_blob_t *arch, const char *file, char *buf, int buflen) { const char *url = repo->url; - snprintf(buf, buflen, "%s%s" BLOB_FMT "/%s", - url, url[strlen(url)-1] == '/' ? "" : "/", - BLOB_PRINTF(arch), file); + if (arch != NULL) + snprintf(buf, buflen, "%s%s" BLOB_FMT "/%s", + url, url[strlen(url)-1] == '/' ? "" : "/", + BLOB_PRINTF(*arch), file); + else + snprintf(buf, buflen, "%s%s/%s", + url, url[strlen(url)-1] == '/' ? "" : "/", + file); if ((apk_flags & APK_NO_NETWORK) && apk_repo_is_remote(repo)) return NULL; @@ -1500,7 +1508,7 @@ int apk_repository_update(struct apk_database *db, struct apk_repository *repo) return 0; apk_cache_format_index(APK_BLOB_BUF(cacheitem), repo); - r = apk_cache_download(db, repo->url, apkindex_tar_gz, cacheitem, + r = apk_cache_download(db, repo->url, db->arch, apkindex_tar_gz, cacheitem, (apk_flags & APK_ALLOW_UNTRUSTED) ? APK_SIGN_NONE : APK_SIGN_VERIFY); if (r != 0) @@ -1608,7 +1616,7 @@ int apk_db_add_repository(apk_database_t _db, apk_blob_t repository) bs = apk_bstream_from_file(db->cache_fd, buf); } else { db->local_repos |= BIT(r); - bs = apk_repo_file_open(repo, *db->arch, apkindex_tar_gz, buf, sizeof(buf)); + bs = apk_repo_file_open(repo, db->arch, apkindex_tar_gz, buf, sizeof(buf)); } if (bs == NULL) { apk_warning("%s: index failed to open", buf); @@ -2018,7 +2026,8 @@ static int apk_db_unpack_pkg(struct apk_database *db, if (bs == NULL) { apk_pkg_format_plain(pkg, APK_BLOB_BUF(item)); - bs = apk_repo_file_open(repo, *(pkg->arch ?: db->arch), item, file, sizeof(file)); + bs = apk_repo_file_open(repo, pkg->arch, + item, file, sizeof(file)); if (apk_repo_is_remote(repo)) need_copy = TRUE; } -- cgit v1.2.3 From 415e230a7f0874206d4bbe2662c9f9cbf7e4c307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Wed, 16 Mar 2011 14:55:08 +0200 Subject: db, cache: automatically remount cache read-write when needed .. and back to read-only after finishing with modifications. fixes #512 --- src/apk_database.h | 3 ++ src/cache.c | 2 +- src/database.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 104 insertions(+), 14 deletions(-) diff --git a/src/apk_database.h b/src/apk_database.h index 64c4fed..988a668 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -105,9 +105,11 @@ struct apk_database { int root_fd, lock_fd, cache_fd, cachetmp_fd, keys_fd; unsigned name_id, num_repos; const char *cache_dir; + char *cache_remount_dir; apk_blob_t *arch; unsigned int local_repos; int permanent : 1; + int ro_cache : 1; int compat_newfeatures : 1; int compat_notinstallable : 1; @@ -155,6 +157,7 @@ struct apk_db_file *apk_db_file_query(struct apk_database *db, #define APK_OPENF_NO_WORLD 0x0040 #define APK_OPENF_NO_SYS_REPOS 0x0100 #define APK_OPENF_NO_INSTALLED_REPO 0x0200 +#define APK_OPENF_CACHE_WRITE 0x0400 #define APK_OPENF_NO_REPOS (APK_OPENF_NO_SYS_REPOS | \ APK_OPENF_NO_INSTALLED_REPO) diff --git a/src/cache.c b/src/cache.c index f827cc1..8cee1e4 100644 --- a/src/cache.c +++ b/src/cache.c @@ -172,7 +172,7 @@ static struct apk_applet apk_cache = { "making /etc/apk/cache a symlink to the directory (on boot " "media) that will be used as package cache.", .arguments = "sync | clean | download", - .open_flags = APK_OPENF_READ|APK_OPENF_NO_SCRIPTS|APK_OPENF_NO_INSTALLED, + .open_flags = APK_OPENF_READ|APK_OPENF_NO_SCRIPTS|APK_OPENF_NO_INSTALLED|APK_OPENF_CACHE_WRITE, .main = cache_main, }; diff --git a/src/database.c b/src/database.c index 4531eeb..f2cd3b7 100644 --- a/src/database.c +++ b/src/database.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -21,7 +22,9 @@ #include #include #include +#include #include +#include #include "apk_defines.h" #include "apk_package.h" @@ -503,8 +506,10 @@ int apk_cache_download(struct apk_database *db, const char *url, apk_blob_t *arc } } - if (renameat(db->cachetmp_fd, cacheitem, db->cache_fd, cacheitem) < 0) - return -errno; + if (db->cachetmp_fd != db->cache_fd) { + if (renameat(db->cachetmp_fd, cacheitem, db->cache_fd, cacheitem) < 0) + return -errno; + } return 0; } @@ -1059,15 +1064,65 @@ static void handle_alarm(int sig) { } +static char *find_mountpoint(int atfd, const char *rel_path) +{ + struct mntent *me; + struct stat64 st; + FILE *f; + char *ret = NULL; + dev_t dev; + + if (fstatat64(atfd, rel_path, &st, 0) != 0) + return NULL; + dev = st.st_dev; + + f = setmntent("/proc/mounts", "r"); + if (f == NULL) + return NULL; + while ((me = getmntent(f)) != NULL) { + if (strcmp(me->mnt_fsname, "rootfs") == 0) + continue; + if (fstatat64(atfd, me->mnt_dir, &st, 0) == 0 && + st.st_dev == dev) { + ret = strdup(me->mnt_dir); + break; + } + } + endmntent(f); + + return ret; +} + +static int do_remount(const char *path, const char *option) +{ + pid_t pid; + int status; + + pid = fork(); + if (pid < 0) + return -errno; + + if (pid == 0) { + execl("/bin/mount", "mount", "-o", "remount", "-o", + option, path, NULL); + return 1; + } + + waitpid(pid, &status, 0); + if (!WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); +} + int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) { const char *msg = NULL; struct apk_repository_list *repo = NULL; struct apk_bstream *bs; - struct stat64 st; struct statfs stfs; apk_blob_t blob; - int r, rr = 0; + int r, fd, rr = 0; memset(db, 0, sizeof(*db)); if (apk_flags & APK_SIMULATE) { @@ -1088,7 +1143,6 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) list_init(&db->installed.triggers); apk_dependency_array_init(&db->world); apk_string_array_init(&db->protected_paths); - db->cache_dir = apk_static_cache_dir; db->permanent = 1; db->root = strdup(dbopts->root ?: "/"); @@ -1105,10 +1159,6 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) stfs.f_type == 0x01021994 /* TMPFS_MAGIC */) db->permanent = 0; - if (fstatat64(db->root_fd, apk_linked_cache_dir, &st, 0) == 0 && - S_ISDIR(st.st_mode) && major(st.st_dev) != 0) - db->cache_dir = apk_linked_cache_dir; - apk_id_cache_init(&db->id_cache, db->root_fd); if (dbopts->open_flags & APK_OPENF_WRITE) { @@ -1150,10 +1200,26 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) blob = APK_BLOB_STR("etc:*etc/init.d"); apk_blob_for_each_segment(blob, ":", add_protected_path, db); + /* figure out where to have the cache */ + fd = openat(db->root_fd, apk_linked_cache_dir, O_RDONLY | O_CLOEXEC); + if (fd >= 0 && fstatfs(fd, &stfs) == 0 /*&& stfs.f_type != 0x01021994*/ /* TMPFS_MAGIC */) { + struct statvfs stvfs; + + db->cache_dir = apk_linked_cache_dir; + db->cache_fd = fd; + mkdirat(db->cache_fd, "tmp", 0644); + db->cachetmp_fd = openat(db->cache_fd, "tmp", O_RDONLY | O_CLOEXEC); + if (fstatvfs(fd, &stvfs) == 0 && (stvfs.f_flag & ST_RDONLY) != 0) + db->ro_cache = 1; + } else { + if (fd >= 0) + close(fd); + db->cache_dir = apk_static_cache_dir; + db->cache_fd = openat(db->root_fd, db->cache_dir, O_RDONLY | O_CLOEXEC); + db->cachetmp_fd = db->cache_fd; + } + db->arch = apk_blob_atomize(APK_BLOB_STR(apk_arch)); - db->cache_fd = openat(db->root_fd, db->cache_dir, O_RDONLY | O_CLOEXEC); - mkdirat(db->cache_fd, "tmp", 0644); - db->cachetmp_fd = openat(db->cache_fd, "tmp", O_RDONLY | O_CLOEXEC); db->keys_fd = openat(db->root_fd, dbopts->keys_dir ?: "etc/apk/keys", O_RDONLY | O_CLOEXEC); @@ -1217,6 +1283,21 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) "might not function properly"); } + if ((dbopts->open_flags & (APK_OPENF_WRITE | APK_OPENF_CACHE_WRITE)) && + db->ro_cache) { + /* remount cache read-write */ + db->cache_remount_dir = find_mountpoint(db->root_fd, db->cache_dir); + if (db->cache_remount_dir == NULL) { + apk_warning("Unable to find cache directory mount point"); + } else if (do_remount(db->cache_remount_dir, "rw") != 0) { + free(db->cache_remount_dir); + db->cache_remount_dir = NULL; + apk_error("Unable to remount cache read-write"); + r = EROFS; + goto ret_r; + } + } + return rr; ret_errno: @@ -1306,6 +1387,12 @@ void apk_db_close(struct apk_database *db) struct hlist_node *dc, *dn; int i; + if (db->cache_remount_dir) { + do_remount(db->cache_remount_dir, "ro"); + free(db->cache_remount_dir); + db->cache_remount_dir = NULL; + } + apk_id_cache_free(&db->id_cache); list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) { @@ -1329,7 +1416,7 @@ void apk_db_close(struct apk_database *db) if (db->keys_fd) close(db->keys_fd); - if (db->cachetmp_fd) + if (db->cachetmp_fd && db->cachetmp_fd != db->cache_fd) close(db->cachetmp_fd); if (db->cache_fd) close(db->cache_fd); -- cgit v1.2.3 From 5d64bc5d8c7cdd2759e970f848e948fac9cc9577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Wed, 16 Mar 2011 15:21:41 +0200 Subject: db: fix cache tmpfs detection comment out the code that was out for testing. duh. --- src/database.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/database.c b/src/database.c index f2cd3b7..21b266b 100644 --- a/src/database.c +++ b/src/database.c @@ -1202,7 +1202,7 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) /* figure out where to have the cache */ fd = openat(db->root_fd, apk_linked_cache_dir, O_RDONLY | O_CLOEXEC); - if (fd >= 0 && fstatfs(fd, &stfs) == 0 /*&& stfs.f_type != 0x01021994*/ /* TMPFS_MAGIC */) { + if (fd >= 0 && fstatfs(fd, &stfs) == 0 && stfs.f_type != 0x01021994 /* TMPFS_MAGIC */) { struct statvfs stvfs; db->cache_dir = apk_linked_cache_dir; -- cgit v1.2.3 From 20775276b934418ba451f76c9c8a24418201fa66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Wed, 16 Mar 2011 15:22:05 +0200 Subject: apk: show progress bar by default for tty controlled runs and make the progress bar disappear on regular runs too. --- src/apk.c | 8 ++++++++ src/state.c | 11 ++++------- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/apk.c b/src/apk.c index 4b97be5..e8b8b12 100644 --- a/src/apk.c +++ b/src/apk.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,7 @@ static struct apk_option generic_options[] = { { 'f', "force", "Do what was asked even if it looks dangerous" }, { 'U', "update-cache", "Update the repository cache" }, { 0x101, "progress", "Show a progress bar" }, + { 0x110, "no-progress", "Disable progress bar even for TTYs" }, { 0x102, "clean-protected", "Do not create .apk-new files to " "configuration dirs" }, { 0x106, "purge", "Delete also modified configuration files on " @@ -256,6 +258,9 @@ int main(int argc, char **argv) apk_atom_init(); umask(0); + if (isatty(STDOUT_FILENO) && isatty(STDERR_FILENO) && isatty(STDIN_FILENO)) + apk_flags |= APK_PROGRESS; + applet = deduce_applet(argc, argv); num_options = ARRAY_SIZE(generic_options) + 1; if (applet != NULL) @@ -326,6 +331,9 @@ int main(int argc, char **argv) case 0x101: apk_flags |= APK_PROGRESS; break; + case 0x110: + apk_flags &= ~APK_PROGRESS; + break; case 0x102: apk_flags |= APK_CLEAN_PROTECTED; break; diff --git a/src/state.c b/src/state.c index 4a4641d..7991802 100644 --- a/src/state.c +++ b/src/state.c @@ -655,7 +655,7 @@ static void apk_count_change(struct apk_change *change, struct apk_stats *stats) stats->packages ++; } -static inline void apk_draw_progress(int percent, int last) +static inline void apk_draw_progress(int percent) { char tmp[128]; char reset[128]; @@ -666,10 +666,7 @@ static inline void apk_draw_progress(int percent, int last) tmp[2+i] = '#'; memset(reset, '\b', strlen(tmp)); fwrite(tmp, strlen(tmp), 1, stderr); - if (!last) - fwrite(reset, strlen(tmp), 1, stderr); - else if (apk_verbosity > 0) - fwrite("\n", 1, 1, stderr); + fwrite(reset, strlen(tmp), 1, stderr); fflush(stderr); } @@ -692,7 +689,7 @@ static void progress_cb(void *ctx, size_t progress) prog->total.bytes + prog->total.packages); if (prog->count != count) - apk_draw_progress(count, 0); + apk_draw_progress(count); prog->count = count; } @@ -961,7 +958,7 @@ int apk_state_commit(struct apk_state *state, apk_count_change(change, &prog.done); } if (apk_flags & APK_PROGRESS) - apk_draw_progress(100, 1); + apk_draw_progress(100); update_state: apk_db_run_triggers(db); -- cgit v1.2.3 From 2222a15eddad9c5fac8d032f51f65811c0947495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Wed, 16 Mar 2011 15:39:36 +0200 Subject: db: move lock file to /var/lock in accordance with FSH. this also to clear /var of apk related things as we might want to run /var as harddisk, but rest of system from ramdisk. --- src/database.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/database.c b/src/database.c index 21b266b..6f00aa1 100644 --- a/src/database.c +++ b/src/database.c @@ -54,6 +54,7 @@ const char *apk_arch = APK_DEFAULT_ARCH; const char * const apkindex_tar_gz = "APKINDEX.tar.gz"; static const char * const apk_static_cache_dir = "var/lib/apk"; static const char * const apk_linked_cache_dir = "etc/apk/cache"; +static const char * const apk_lock_file = "var/lock/apkdb"; struct install_ctx { struct apk_database *db; @@ -1051,6 +1052,7 @@ static int apk_db_create(struct apk_database *db) mkdirat(db->root_fd, "var/lib/apk", 0755); mkdirat(db->root_fd, "var/cache", 0755); mkdirat(db->root_fd, "var/cache/misc", 0755); + mkdirat(db->root_fd, "var/lock", 0755); fd = openat(db->root_fd, "var/lib/apk/world", O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0644); if (fd < 0) @@ -1162,7 +1164,7 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_id_cache_init(&db->id_cache, db->root_fd); if (dbopts->open_flags & APK_OPENF_WRITE) { - db->lock_fd = openat(db->root_fd, "var/lib/apk/lock", + db->lock_fd = openat(db->root_fd, apk_lock_file, O_CREAT | O_RDWR | O_CLOEXEC, 0400); if (db->lock_fd < 0 && errno == ENOENT && (dbopts->open_flags & APK_OPENF_CREATE)) { @@ -1171,7 +1173,7 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) msg = "Unable to create database"; goto ret_r; } - db->lock_fd = openat(db->root_fd, "var/lib/apk/lock", + db->lock_fd = openat(db->root_fd, apk_lock_file, O_CREAT | O_RDWR | O_CLOEXEC, 0400); } if (db->lock_fd < 0 || -- cgit v1.2.3 From 93eb38a31ae97f1cb470f18c6019ede19c5c314e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Wed, 16 Mar 2011 16:52:14 +0200 Subject: db: relocate from /var/lib/apk move all files therein to other places. this allows /var to be mounted from harddisk, but rest of system be run from ramdisk. this also removes support for historical version of the scripts database which was obsoleted in 2.0_pre16 (in July 2009). --- src/apk_io.h | 1 + src/database.c | 106 ++++++++++++++++++++++++++++++++------------------------- src/io.c | 31 +++++++++++++++++ 3 files changed, 91 insertions(+), 47 deletions(-) diff --git a/src/apk_io.h b/src/apk_io.h index 3845554..8cf24d8 100644 --- a/src/apk_io.h +++ b/src/apk_io.h @@ -110,6 +110,7 @@ apk_blob_t apk_blob_from_file(int atfd, const char *file); int apk_file_get_info(int atfd, const char *filename, unsigned int flags, struct apk_file_info *fi); +int apk_move_file(int atfd, const char *from, const char *to); int apk_url_download(const char *url, int atfd, const char *file); const char *apk_url_local_file(const char *url); diff --git a/src/database.c b/src/database.c index 6f00aa1..5d8cc38 100644 --- a/src/database.c +++ b/src/database.c @@ -52,10 +52,27 @@ unsigned int apk_flags = 0; const char *apk_arch = APK_DEFAULT_ARCH; const char * const apkindex_tar_gz = "APKINDEX.tar.gz"; -static const char * const apk_static_cache_dir = "var/lib/apk"; +static const char * const apk_static_cache_dir = "var/cache/apk"; static const char * const apk_linked_cache_dir = "etc/apk/cache"; + static const char * const apk_lock_file = "var/lock/apkdb"; +static const char * const apk_world_file = "etc/apk/world"; +static const char * const apk_world_file_tmp = "etc/apk/world.new"; +static const char * const apk_world_file_old = "var/lib/apk/world"; + +static const char * const apk_scripts_file = "lib/apk/db/scripts.tar"; +static const char * const apk_scripts_file_tmp = "lib/apk/db/scripts.tar.new"; +static const char * const apk_scripts_file_old = "var/lib/apk/scripts.tar"; + +static const char * const apk_triggers_file = "lib/apk/db/triggers"; +static const char * const apk_triggers_file_tmp = "lib/apk/db/triggers.new"; +static const char * const apk_triggers_file_old = "var/lib/apk/triggers"; + +static const char * const apk_installed_file = "lib/apk/db/installed"; +static const char * const apk_installed_file_tmp = "lib/apk/db/installed.new"; +static const char * const apk_installed_file_old = "var/lib/apk/installed"; + struct install_ctx { struct apk_database *db; struct apk_package *pkg; @@ -784,30 +801,6 @@ static int apk_db_scriptdb_write(struct apk_database *db, struct apk_ostream *os return apk_tar_write_entry(os, NULL, NULL); } -static int apk_db_scriptdb_read_v1(struct apk_database *db, struct apk_istream *is) -{ - struct apk_package *pkg; - struct { - unsigned char md5sum[16]; - unsigned int type; - unsigned int size; - } hdr; - struct apk_checksum csum; - - while (is->read(is, &hdr, sizeof(hdr)) == sizeof(hdr)) { - memcpy(csum.data, hdr.md5sum, sizeof(hdr.md5sum)); - csum.type = APK_CHECKSUM_MD5; - - pkg = apk_db_get_pkg(db, &csum); - if (pkg != NULL && pkg->ipkg != NULL) - apk_ipkg_add_script(pkg->ipkg, is, hdr.type, hdr.size); - else - apk_istream_skip(is, hdr.size); - } - - return 0; -} - static int apk_read_script_archive_entry(void *ctx, const struct apk_file_info *ae, struct apk_istream *is) @@ -920,7 +913,7 @@ static int apk_db_read_state(struct apk_database *db, int flags) * 6. script db */ if (!(flags & APK_OPENF_NO_WORLD)) { - blob = apk_blob_from_file(db->root_fd, "var/lib/apk/world"); + blob = apk_blob_from_file(db->root_fd, apk_world_file); if (APK_BLOB_IS_NULL(blob)) return -ENOENT; apk_deps_parse(db, &db->world, blob); @@ -931,7 +924,7 @@ static int apk_db_read_state(struct apk_database *db, int flags) } if (!(flags & APK_OPENF_NO_INSTALLED)) { - bs = apk_bstream_from_file(db->root_fd, "var/lib/apk/installed"); + bs = apk_bstream_from_file(db->root_fd, apk_installed_file); if (bs != NULL) { r = apk_db_index_read(db, bs, -1); bs->close(bs, NULL); @@ -939,7 +932,7 @@ static int apk_db_read_state(struct apk_database *db, int flags) return -1; } - bs = apk_bstream_from_file(db->root_fd, "var/lib/apk/triggers"); + bs = apk_bstream_from_file(db->root_fd, apk_triggers_file); if (bs != NULL) { apk_db_triggers_read(db, bs); bs->close(bs, NULL); @@ -947,17 +940,12 @@ static int apk_db_read_state(struct apk_database *db, int flags) } if (!(flags & APK_OPENF_NO_SCRIPTS)) { - is = apk_istream_from_file(db->root_fd, "var/lib/apk/scripts.tar"); + is = apk_istream_from_file(db->root_fd, apk_scripts_file); if (is != NULL) { apk_tar_parse(is, apk_read_script_archive_entry, db, FALSE, &db->id_cache); - } else { - is = apk_istream_from_file(db->root_fd, "var/lib/apk/scripts"); - if (is != NULL) - apk_db_scriptdb_read_v1(db, is); - } - if (is != NULL) is->close(is); + } } return 0; @@ -1047,14 +1035,18 @@ static int apk_db_create(struct apk_database *db) mkdirat(db->root_fd, "tmp", 01777); mkdirat(db->root_fd, "dev", 0755); mknodat(db->root_fd, "dev/null", 0666, makedev(1, 3)); + mkdirat(db->root_fd, "etc", 0755); + mkdirat(db->root_fd, "etc/apk", 0755); + mkdirat(db->root_fd, "lib", 0755); + mkdirat(db->root_fd, "lib/apk", 0755); + mkdirat(db->root_fd, "lib/apk/db", 0755); mkdirat(db->root_fd, "var", 0755); - mkdirat(db->root_fd, "var/lib", 0755); - mkdirat(db->root_fd, "var/lib/apk", 0755); mkdirat(db->root_fd, "var/cache", 0755); + mkdirat(db->root_fd, "var/cache/apk", 0755); mkdirat(db->root_fd, "var/cache/misc", 0755); mkdirat(db->root_fd, "var/lock", 0755); - fd = openat(db->root_fd, "var/lib/apk/world", O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0644); + fd = openat(db->root_fd, apk_world_file, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0644); if (fd < 0) return -errno; close(fd); @@ -1117,6 +1109,24 @@ static int do_remount(const char *path, const char *option) return WEXITSTATUS(status); } +static void relocate_database(struct apk_database *db) +{ + mkdirat(db->root_fd, "etc", 0755); + mkdirat(db->root_fd, "etc/apk", 0755); + mkdirat(db->root_fd, "lib", 0755); + mkdirat(db->root_fd, "lib/apk", 0755); + mkdirat(db->root_fd, "lib/apk/db", 0755); + mkdirat(db->root_fd, "var", 0755); + mkdirat(db->root_fd, "var/cache", 0755); + mkdirat(db->root_fd, "var/cache/apk", 0755); + mkdirat(db->root_fd, "var/cache/misc", 0755); + mkdirat(db->root_fd, "var/lock", 0755); + apk_move_file(db->root_fd, apk_world_file_old, apk_world_file); + apk_move_file(db->root_fd, apk_scripts_file_old, apk_scripts_file); + apk_move_file(db->root_fd, apk_triggers_file_old, apk_triggers_file); + apk_move_file(db->root_fd, apk_installed_file_old, apk_installed_file); +} + int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) { const char *msg = NULL; @@ -1164,6 +1174,9 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_id_cache_init(&db->id_cache, db->root_fd); if (dbopts->open_flags & APK_OPENF_WRITE) { + if (faccessat(db->root_fd, apk_installed_file_old, F_OK, 0) == 0) + relocate_database(db); + db->lock_fd = openat(db->root_fd, apk_lock_file, O_CREAT | O_RDWR | O_CLOEXEC, 0400); if (db->lock_fd < 0 && errno == ENOENT && @@ -1331,8 +1344,8 @@ int apk_db_write_config(struct apk_database *db) } os = apk_ostream_to_file(db->root_fd, - "var/lib/apk/world", - "var/lib/apk/world.new", + apk_world_file, + apk_world_file_tmp, 0644); if (os == NULL) return -1; @@ -1344,8 +1357,8 @@ int apk_db_write_config(struct apk_database *db) return r; os = apk_ostream_to_file(db->root_fd, - "var/lib/apk/installed", - "var/lib/apk/installed.new", + apk_installed_file, + apk_installed_file_tmp, 0644); if (os == NULL) return -1; @@ -1355,8 +1368,8 @@ int apk_db_write_config(struct apk_database *db) return r; os = apk_ostream_to_file(db->root_fd, - "var/lib/apk/scripts.tar", - "var/lib/apk/scripts.tar.new", + apk_scripts_file, + apk_scripts_file_tmp, 0644); if (os == NULL) return -1; @@ -1365,12 +1378,11 @@ int apk_db_write_config(struct apk_database *db) if (r < 0) return r; - unlinkat(db->root_fd, "var/lib/apk/scripts", 0); apk_db_index_write_nr_cache(db); os = apk_ostream_to_file(db->root_fd, - "var/lib/apk/triggers", - "var/lib/apk/triggers.new", + apk_triggers_file, + apk_triggers_file_tmp, 0644); if (os == NULL) return -1; diff --git a/src/io.c b/src/io.c index 7eecbf8..e4b3710 100644 --- a/src/io.c +++ b/src/io.c @@ -739,6 +739,37 @@ size_t apk_ostream_write_string(struct apk_ostream *os, const char *string) return len; } +int apk_move_file(int atfd, const char *from, const char *to) +{ + struct apk_istream *is; + struct stat64 st; + int rc, tofd; + + if (renameat(atfd, from, atfd, to) == 0) + return 0; + + if (fstatat64(atfd, from, &st, 0) != 0) + return -errno; + + is = apk_istream_from_file(atfd, from); + if (is == NULL) + return -ENOENT; + + tofd = openat(atfd, to, O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (tofd < 0) { + rc = -errno; + goto close_is; + } + + rc = apk_istream_splice(is, tofd, st.st_size, NULL, NULL); + close(tofd); + unlinkat(atfd, from, 0); +close_is: + is->close(is); + return rc; +} + struct cache_item { apk_hash_node hash_node; unsigned int genid; -- cgit v1.2.3 From 4e72075fbab32e9368d1305431924f10e78c0546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Sat, 19 Mar 2011 13:58:37 +0200 Subject: state: lock package late for names specified on command line This will fix certain scenarios where multiple packages are installed with full package files specified on command line and they depend on each other. --- src/state.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/state.c b/src/state.c index 7991802..005470c 100644 --- a/src/state.c +++ b/src/state.c @@ -420,10 +420,17 @@ static int apk_state_fix_package(struct apk_state *state, return 0; for (i = 0; i < pkg->depends->num; i++) { - r = apk_state_lock_dependency(state, - &pkg->depends->item[i]); - if (r != 0) - ret = -1; + if (pkg->name->flags & APK_NAME_TOPLEVEL_OVERRIDE) { + r = apk_state_prune_dependency(state, + &pkg->depends->item[i]); + if (r < 0) + ret = -1; + } else { + r = apk_state_lock_dependency(state, + &pkg->depends->item[i]); + if (r != 0) + ret = -1; + } } return ret; -- cgit v1.2.3 From 7b6e44b11b4b419a6af91555270b1ddc981c5a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Sat, 19 Mar 2011 14:21:58 +0200 Subject: upgrade: reset world dependencies during traversal This allows us to get apk-tools dependencies get reset at proper time in world. As a bonus, it reduces code amount. --- src/state.c | 18 ++++++++++++------ src/upgrade.c | 20 ++------------------ 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/src/state.c b/src/state.c index 005470c..3a8d3a6 100644 --- a/src/state.c +++ b/src/state.c @@ -138,14 +138,20 @@ static struct apk_name_choices *name_choices_new(struct apk_database *db, if (dep->name != name) continue; - for (j = 0; j < nc->num; ) { - if (apk_dep_is_satisfied(dep, nc->pkgs[j])) { - j++; - } else { - nc->pkgs[j] = nc->pkgs[nc->num - 1]; - nc->num--; + if (apk_flags & APK_PREFER_AVAILABLE) { + dep->version = apk_blob_atomize(APK_BLOB_NULL); + dep->result_mask = APK_DEPMASK_REQUIRE; + } else { + for (j = 0; j < nc->num; ) { + if (apk_dep_is_satisfied(dep, nc->pkgs[j])) { + j++; + } else { + nc->pkgs[j] = nc->pkgs[nc->num - 1]; + nc->num--; + } } } + break; } return nc; diff --git a/src/upgrade.c b/src/upgrade.c index 795e62f..eb51457 100644 --- a/src/upgrade.c +++ b/src/upgrade.c @@ -33,21 +33,10 @@ static int upgrade_parse(void *ctx, struct apk_db_options *dbopts, int apk_do_self_upgrade(struct apk_database *db, struct apk_state *state) { struct apk_dependency dep; - int r, i; + int r; apk_dep_from_blob(&dep, db, APK_BLOB_STR("apk-tools")); - if (apk_flags & APK_PREFER_AVAILABLE) { - for (i = 0; i < db->world->num; i++) { - struct apk_dependency *dep0 = &db->world->item[i]; - if (dep0->name != dep.name) - continue; - dep0->version = apk_blob_atomize(APK_BLOB_NULL); - dep0->result_mask = APK_DEPMASK_REQUIRE; - break; - } - } - r = apk_state_lock_dependency(state, &dep); if (r != 0 || state->num_changes == 0) return r; @@ -74,7 +63,6 @@ static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **arg { struct apk_state *state = NULL; struct apk_name_array *missing; - apk_blob_t *null_atom = apk_blob_atomize(APK_BLOB_NULL); int i, r = 0; apk_flags |= APK_UPGRADE; @@ -92,11 +80,7 @@ static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **arg for (i = 0; i < db->world->num; i++) { struct apk_dependency *dep = &db->world->item[i]; - if (dep->version != null_atom && - (apk_flags & APK_PREFER_AVAILABLE)) { - dep->result_mask = APK_DEPMASK_REQUIRE; - dep->version = null_atom; - } + if (dep->name->pkgs->num != 0) r |= apk_state_lock_dependency(state, dep); else -- cgit v1.2.3 From 116d9a0ea7a5e903a344f7e6044dd019349bc01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Sat, 19 Mar 2011 15:20:47 +0200 Subject: apk: improve progress bar * make it as wide as the screen * make sure it's drawn after package change * and draw it using ansi escapes in line buffered stderr --- src/apk.c | 20 +++++++++++++++++--- src/apk_defines.h | 1 + src/state.c | 20 +++++++++++--------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/apk.c b/src/apk.c index e8b8b12..55963b0 100644 --- a/src/apk.c +++ b/src/apk.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #ifndef OPENSSL_NO_ENGINE @@ -32,6 +33,7 @@ #include "apk_print.h" char **apk_argv; +int apk_screen_width; static struct apk_option generic_options[] = { { 'h', "help", "Show generic help or applet specific help" }, @@ -238,6 +240,20 @@ static void init_openssl(void) #endif } +static void setup_terminal(void) +{ + struct winsize w; + + setvbuf(stderr, NULL, _IOLBF, BUFSIZ); + if (ioctl(STDERR_FILENO,TIOCGWINSZ, &w) == 0) + apk_screen_width = w.ws_col; + else + apk_screen_width = 70; + if (isatty(STDOUT_FILENO) && isatty(STDERR_FILENO) && isatty(STDIN_FILENO)) + apk_flags |= APK_PROGRESS; + +} + int main(int argc, char **argv) { struct apk_applet *applet; @@ -257,9 +273,7 @@ int main(int argc, char **argv) list_init(&dbopts.repository_list); apk_atom_init(); umask(0); - - if (isatty(STDOUT_FILENO) && isatty(STDERR_FILENO) && isatty(STDIN_FILENO)) - apk_flags |= APK_PROGRESS; + setup_terminal(); applet = deduce_applet(argc, argv); num_options = ARRAY_SIZE(generic_options) + 1; diff --git a/src/apk_defines.h b/src/apk_defines.h index b11d181..b5ad12e 100644 --- a/src/apk_defines.h +++ b/src/apk_defines.h @@ -51,6 +51,7 @@ extern int apk_verbosity; extern unsigned int apk_flags; extern const char *apk_arch; extern char **apk_argv; +extern int apk_screen_width; #define APK_FORCE 0x0001 #define APK_SIMULATE 0x0002 diff --git a/src/state.c b/src/state.c index 3a8d3a6..cb6e5cc 100644 --- a/src/state.c +++ b/src/state.c @@ -668,19 +668,19 @@ static void apk_count_change(struct apk_change *change, struct apk_stats *stats) stats->packages ++; } -static inline void apk_draw_progress(int percent) +static void apk_draw_progress(int percent) { - char tmp[128]; - char reset[128]; + const int bar_width = (apk_screen_width - 15); int i; - snprintf(tmp, sizeof(tmp), "-[ ]- %3i%%", percent); - for (i = 0; (i < (percent/5)) && (i < (sizeof(tmp)-2)); i++) - tmp[2+i] = '#'; - memset(reset, '\b', strlen(tmp)); - fwrite(tmp, strlen(tmp), 1, stderr); - fwrite(reset, strlen(tmp), 1, stderr); + fputs("\e7-[", stderr); + for (i = 0; i < bar_width * percent / 100; i++) + fputc('#', stderr); + for (; i < bar_width; i++) + fputc(' ', stderr); + fprintf(stderr, "]- %3i%%", percent); fflush(stderr); + fputs("\e8\e[0K", stderr); } struct progress { @@ -950,6 +950,8 @@ int apk_state_commit(struct apk_state *state, list_for_each_entry(change, &state->change_list_head, change_list) { n++; apk_print_change(db, change->oldpkg, change->newpkg, n, state->num_changes); + if (apk_flags & APK_PROGRESS) + apk_draw_progress(prog.count); prog.pkg = change->newpkg; if (!(apk_flags & APK_SIMULATE)) { -- cgit v1.2.3 From 79b7123b09dc7f467e0a7f89d521fb75b616f574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Sun, 27 Mar 2011 02:50:48 +0200 Subject: state: fix late locking of packages commit 4e72075fbab introduced late locking for top level packages, but used the wrong package's top level flag for the check. this fixes a problem that dependencies might not get pulled in. --- src/state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/state.c b/src/state.c index cb6e5cc..6fa81f2 100644 --- a/src/state.c +++ b/src/state.c @@ -426,7 +426,7 @@ static int apk_state_fix_package(struct apk_state *state, return 0; for (i = 0; i < pkg->depends->num; i++) { - if (pkg->name->flags & APK_NAME_TOPLEVEL_OVERRIDE) { + if (pkg->depends->item[i].name->flags & APK_NAME_TOPLEVEL_OVERRIDE) { r = apk_state_prune_dependency(state, &pkg->depends->item[i]); if (r < 0) -- cgit v1.2.3 From 8e01be477762769b3f5bda4bd78b30bec699fb0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Sun, 27 Mar 2011 02:51:51 +0200 Subject: apk: fix gcc 4.6 warnings --- src/database.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/database.c b/src/database.c index 5d8cc38..8e9cb0d 100644 --- a/src/database.c +++ b/src/database.c @@ -563,7 +563,6 @@ int apk_db_read_overlay(struct apk_database *db, struct apk_bstream *bs) struct hlist_node **diri_node = NULL, **file_diri_node = NULL; struct apk_package *pkg; struct apk_installed_package *ipkg; - struct apk_db_file *file; apk_blob_t token = APK_BLOB_STR("\n"), line, bdir, bfile; pkg = apk_pkg_new(); @@ -589,7 +588,7 @@ int apk_db_read_overlay(struct apk_database *db, struct apk_bstream *bs) diri = apk_db_diri_new(db, pkg, bdir, &diri_node); file_diri_node = &diri->owned_files.first; } - file = apk_db_file_get(db, diri, bfile, &file_diri_node); + (void) apk_db_file_get(db, diri, bfile, &file_diri_node); } } -- cgit v1.2.3 From e783f20eff95a22452856eb3e33720d2d8c23a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Tue, 29 Mar 2011 13:09:45 +0300 Subject: fetch: fix package version print broke after making the version field an atom because the printf was not updated accordingly. --- src/fetch.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/fetch.c b/src/fetch.c index b67a189..0f39ecd 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -109,11 +109,12 @@ static int fetch_package(struct fetch_ctx *fctx, return 0; } - apk_message("Downloading %s-%s", pkg->name->name, pkg->version); + apk_message("Downloading %s-" BLOB_FMT, pkg->name->name, + BLOB_PRINTF(*pkg->version)); repo = apk_db_select_repo(db, pkg); if (repo == NULL) { - apk_error("%s-%s: package is not currently available", - pkg->name->name, pkg->version); + apk_error("%s-" BLOB_FMT ": package is not currently available", + pkg->name->name, BLOB_PRINTF(*pkg->version)); return -1; } -- cgit v1.2.3 From 9eeb95470b49529998d0518e3a89638400dca858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Tue, 29 Mar 2011 14:51:57 +0300 Subject: apk-tools-2.1.0_pre1 --- Makefile | 2 +- src/fetch.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 7499414..e70c8bf 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ -include config.mk PACKAGE := apk-tools -VERSION := 2.0.7 +VERSION := 2.1.0_pre1 ## # Default directories diff --git a/src/fetch.c b/src/fetch.c index 0f39ecd..09e3b9d 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -109,12 +109,11 @@ static int fetch_package(struct fetch_ctx *fctx, return 0; } - apk_message("Downloading %s-" BLOB_FMT, pkg->name->name, - BLOB_PRINTF(*pkg->version)); + apk_message("Downloading " PKG_VER_FMT, PKG_VER_PRINTF(pkg)); repo = apk_db_select_repo(db, pkg); if (repo == NULL) { - apk_error("%s-" BLOB_FMT ": package is not currently available", - pkg->name->name, BLOB_PRINTF(*pkg->version)); + apk_error(PKG_VER_FMT ": package is not currently available", + PKG_VER_PRINTF(pkg)); return -1; } -- cgit v1.2.3 From 0f6475b88466b6e4cd424f9807fa14eab0fafe96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Tue, 29 Mar 2011 16:36:10 +0300 Subject: state, info: implement install_if (fixes #443) Implement the logic for install_if lines. Update info applet to also display the install_if related fields. --- src/info.c | 80 +++++++++++++++++++++++++++-- src/state.c | 165 +++++++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 185 insertions(+), 60 deletions(-) diff --git a/src/info.c b/src/info.c index c9dc39c..3ae51f0 100644 --- a/src/info.c +++ b/src/info.c @@ -33,6 +33,8 @@ struct info_ctx { #define APK_INFO_RDEPENDS 0x10 #define APK_INFO_CONTENTS 0x20 #define APK_INFO_TRIGGERS 0x40 +#define APK_INFO_INSTALL_IF 0x80 +#define APK_INFO_RINSTALL_IF 0x100 static void verbose_print_pkg(struct apk_package *pkg, int minimal_verbosity) { @@ -168,15 +170,22 @@ static void info_print_size(struct apk_package *pkg) static void info_print_depends(struct apk_package *pkg) { + apk_blob_t separator = APK_BLOB_STR(apk_verbosity > 1 ? " " : "\n"); + char dep[256]; int i; - char *separator = apk_verbosity > 1 ? " " : "\n"; + if (apk_verbosity == 1) printf(PKG_VER_FMT " depends on:\n", PKG_VER_PRINTF(pkg)); if (apk_verbosity > 1) printf("%s: ", pkg->name->name); - for (i = 0; i < pkg->depends->num; i++) - printf("%s%s", pkg->depends->item[i].name->name, separator); + for (i = 0; i < pkg->depends->num; i++) { + apk_blob_t b = APK_BLOB_BUF(dep); + apk_blob_push_dep(&b, &pkg->depends->item[i]); + apk_blob_push_blob(&b, separator); + b = apk_blob_pushed(APK_BLOB_BUF(dep), b); + fwrite(b.ptr, b.len, 1, stdout); + } } static void info_print_required_by(struct apk_package *pkg) @@ -211,6 +220,58 @@ static void info_print_required_by(struct apk_package *pkg) } } +static void info_print_install_if(struct apk_package *pkg) +{ + apk_blob_t separator = APK_BLOB_STR(apk_verbosity > 1 ? " " : "\n"); + char dep[256]; + int i; + + if (apk_verbosity == 1) + printf(PKG_VER_FMT " has auto-install rule:\n", + PKG_VER_PRINTF(pkg)); + if (apk_verbosity > 1) + printf("%s: ", pkg->name->name); + for (i = 0; i < pkg->install_if->num; i++) { + apk_blob_t b = APK_BLOB_BUF(dep); + apk_blob_push_dep(&b, &pkg->install_if->item[i]); + apk_blob_push_blob(&b, separator); + b = apk_blob_pushed(APK_BLOB_BUF(dep), b); + fwrite(b.ptr, b.len, 1, stdout); + } +} + +static void info_print_rinstall_if(struct apk_package *pkg) +{ + int i, j, k; + char *separator = apk_verbosity > 1 ? " " : "\n"; + + if (apk_verbosity == 1) + printf(PKG_VER_FMT " affects auto-installation of:\n", + PKG_VER_PRINTF(pkg)); + if (apk_verbosity > 1) + printf("%s: ", pkg->name->name); + for (i = 0; i < pkg->name->rinstall_if->num; i++) { + struct apk_name *name0 = pkg->name->rinstall_if->item[i]; + + /* Check only the package that is installed, and that + * it actually has this package in install_if. */ + for (j = 0; j < name0->pkgs->num; j++) { + struct apk_package *pkg0 = name0->pkgs->item[j]; + + if (pkg0->ipkg == NULL) + continue; + for (k = 0; k < pkg0->install_if->num; k++) { + if (pkg0->install_if->item[k].name != pkg->name) + continue; + printf(PKG_VER_FMT "%s", + PKG_VER_PRINTF(pkg0), + separator); + break; + } + } + } +} + static void info_print_contents(struct apk_package *pkg) { struct apk_installed_package *ipkg = pkg->ipkg; @@ -260,9 +321,12 @@ static void info_subaction(struct info_ctx *ctx, struct apk_package *pkg) info_print_required_by, info_print_contents, info_print_triggers, + info_print_install_if, + info_print_rinstall_if, }; const int requireipkg = - APK_INFO_CONTENTS | APK_INFO_TRIGGERS | APK_INFO_RDEPENDS; + APK_INFO_CONTENTS | APK_INFO_TRIGGERS | APK_INFO_RDEPENDS | + APK_INFO_RINSTALL_IF; int i; for (i = 0; i < ARRAY_SIZE(subactions); i++) { @@ -317,6 +381,12 @@ static int info_parse(void *ctx, struct apk_db_options *dbopts, case 'r': ictx->subaction_mask |= APK_INFO_RDEPENDS; break; + case 'I': + ictx->subaction_mask |= APK_INFO_INSTALL_IF; + break; + case 'i': + ictx->subaction_mask |= APK_INFO_RINSTALL_IF; + break; case 's': ictx->subaction_mask |= APK_INFO_SIZE; break; @@ -354,6 +424,8 @@ static struct apk_option info_options[] = { { 'W', "who-owns", "Print the package owning the specified file" }, { 'R', "depends", "List packages that the PACKAGE depends on" }, { 'r', "rdepends", "List all packages depending on PACKAGE" }, + { 'i', "install-if", "List the PACKAGE's install-if rule" }, + { 'I', "rinstall-if", "List all packages having install-if referencing PACKAGE" }, { 'w', "webpage", "Show URL for more information about PACKAGE" }, { 's', "size", "Show installed size of PACKAGE" }, { 'd', "description", "Print description for PACKAGE" }, diff --git a/src/state.c b/src/state.c index 6fa81f2..fef1cbb 100644 --- a/src/state.c +++ b/src/state.c @@ -238,6 +238,50 @@ void apk_state_unref(struct apk_state *state) free(state); } +static struct apk_package *get_locked_or_installed_package( + struct apk_state *state, + struct apk_name *name) +{ + int i; + + if (ns_locked(state->name[name->id])) + return ns_to_pkg(state->name[name->id]); + + if (!ns_empty(state->name[name->id])) { + struct apk_name_choices *ns = + ns_to_choices(state->name[name->id]); + + for (i = 0; i < ns->num; i++) { + if (ns->pkgs[i]->ipkg != NULL) + return ns->pkgs[i]; + } + return NULL; + } + + for (i = 0; i < name->pkgs->num; i++) { + if (name->pkgs->item[i]->ipkg != NULL) + return name->pkgs->item[i]; + } + return NULL; +} + +static int check_dependency_array(struct apk_state *state, + struct apk_dependency_array *da) +{ + struct apk_package *pkg; + int i; + + for (i = 0; i < da->num; i++) { + pkg = get_locked_or_installed_package(state, da->item[i].name); + if (pkg == NULL && da->item[i].result_mask != APK_DEPMASK_CONFLICT) + return 0; + if (!apk_dep_is_satisfied(&da->item[i], pkg)) + return 0; + } + + return da->num; +} + static int apk_state_add_change(struct apk_state *state, struct apk_package *oldpkg, struct apk_package *newpkg) @@ -340,20 +384,22 @@ int apk_state_prune_dependency(struct apk_state *state, return c->num; } -int apk_state_lock_dependency(struct apk_state *state, - struct apk_dependency *dep) +int apk_state_autolock_name(struct apk_state *state, struct apk_name *name, + int install_if) { - struct apk_name *name = dep->name; struct apk_name_choices *c; - struct apk_package *installed = NULL, *latest = NULL, *use; - int i, r; - - r = apk_state_prune_dependency(state, dep); - if (r <= 0) - return r; + struct apk_package *installed = NULL, *latest = NULL, *use; + int i; if (ns_pending(state->name[name->id])) return apk_state_lock_name(state, name, ns_to_pkg(state->name[name->id])); + if (ns_locked(state->name[name->id])) + return 0; + if (ns_empty(state->name[name->id])) { + /* This name has not been visited yet. + * Construct list of candidates. */ + state->name[name->id] = ns_from_choices(name_choices_new(state->db, name)); + } c = ns_to_choices(state->name[name->id]); #if 1 @@ -361,6 +407,10 @@ int apk_state_lock_dependency(struct apk_state *state, for (i = 0; i < c->num; i++) { struct apk_package *pkg = c->pkgs[i]; + if (install_if && + !check_dependency_array(state, pkg->install_if)) + continue; + if (pkg->ipkg != NULL) installed = pkg; else if (!apk_state_pkg_available(state, pkg)) @@ -402,7 +452,7 @@ int apk_state_lock_dependency(struct apk_state *state, use = latest; } if (use == NULL) - return -1; + return -2; return apk_state_lock_name(state, name, use); #else @@ -417,6 +467,18 @@ int apk_state_lock_dependency(struct apk_state *state, #endif } +int apk_state_lock_dependency(struct apk_state *state, + struct apk_dependency *dep) +{ + int r; + + r = apk_state_prune_dependency(state, dep); + if (r <= 0) + return r; + + return apk_state_autolock_name(state, dep->name, FALSE); +} + static int apk_state_fix_package(struct apk_state *state, struct apk_package *pkg) { @@ -438,7 +500,6 @@ static int apk_state_fix_package(struct apk_state *state, ret = -1; } } - return ret; } @@ -480,48 +541,19 @@ static int for_each_broken_reverse_depency(struct apk_state *state, void *ctx) { struct apk_package *pkg0; - int i, j, r; + int i, r; for (i = 0; i < name->rdepends->num; i++) { struct apk_name *name0 = name->rdepends->item[i]; - if (ns_locked(state->name[name0->id])) { - pkg0 = ns_to_pkg(state->name[name0->id]); - if (pkg0 == NULL) - continue; - r = call_if_dependency_broke(state, pkg0, name, - cb, ctx); - if (r != 0) - return r; - } else if (!ns_empty(state->name[name0->id])) { - struct apk_name_choices *ns = - ns_to_choices(state->name[name0->id]); - - for (j = 0; j < ns->num; j++) { - if (ns->pkgs[j]->ipkg == NULL) - continue; - r = call_if_dependency_broke(state, - ns->pkgs[j], - name, cb, ctx); - if (r != 0) - return r; - break; - } - } else { - for (j = 0; j < name0->pkgs->num; j++) { - pkg0 = name0->pkgs->item[j]; - - if (pkg0->ipkg == NULL) - continue; + pkg0 = get_locked_or_installed_package(state, name0); + if (pkg0 == NULL) + continue; - r = call_if_dependency_broke(state, - name0->pkgs->item[j], - name, cb, ctx); - if (r != 0) - return r; - break; - } - } + r = call_if_dependency_broke(state, pkg0, name, + cb, ctx); + if (r != 0) + return r; } return 0; @@ -591,15 +623,19 @@ int apk_state_lock_name(struct apk_state *state, } /* If the chosen package is installed, all is done here */ - if (oldpkg == newpkg && - (newpkg == NULL || - !(newpkg->name->flags & APK_NAME_REINSTALL))) - return 0; + if ((oldpkg != newpkg) || + (newpkg != NULL && (newpkg->name->flags & APK_NAME_REINSTALL))) { + /* Track change */ + r = apk_state_add_change(state, oldpkg, newpkg); + if (r != 0) + return r; + } - /* Track change */ - r = apk_state_add_change(state, oldpkg, newpkg); - if (r != 0) - return r; + /* Check all reverse install_if's */ + if (newpkg != NULL) { + for (i = 0; i < newpkg->name->rinstall_if->num; i++) + apk_state_autolock_name(state, newpkg->name->rinstall_if->item[i], TRUE); + } return 0; } @@ -809,6 +845,23 @@ static int apk_state_autoclean(struct apk_state *state, return r; } } + + for (i = 0; i < pkg->name->rinstall_if->num; i++) { + struct apk_name *n = pkg->name->rinstall_if->item[i]; + + if (ns_locked(state->name[n->id])) + continue; + if (n->flags & APK_NAME_TOPLEVEL) + continue; + + r = apk_state_autolock_name(state, n, TRUE); + if (r == -2) { + r = apk_state_lock_name(state, n, NULL); + if (r != 0) + return r; + } + } + return 0; } -- cgit v1.2.3 From e43ec608749a44a305afec89f46bcb282ab93d10 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Mon, 21 Feb 2011 15:31:39 +0000 Subject: state: use db in own struc when committing The db parameter to apk_state_commit is not needed so we remove it. --- src/add.c | 2 +- src/apk_state.h | 2 +- src/del.c | 2 +- src/fix.c | 2 +- src/state.c | 4 ++-- src/upgrade.c | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/add.c b/src/add.c index 977c772..d63f61d 100644 --- a/src/add.c +++ b/src/add.c @@ -142,7 +142,7 @@ static int add_main(void *ctx, struct apk_database *db, int argc, char **argv) apk_state_print_errors(state); r = -1; } else { - r = apk_state_commit(state, db); + r = apk_state_commit(state); } if (state != NULL) apk_state_unref(state); diff --git a/src/apk_state.h b/src/apk_state.h index 1ac049a..e0df54e 100644 --- a/src/apk_state.h +++ b/src/apk_state.h @@ -37,7 +37,7 @@ struct apk_state *apk_state_dup(struct apk_state *state); void apk_state_unref(struct apk_state *state); void apk_state_print_errors(struct apk_state *state); -int apk_state_commit(struct apk_state *state, struct apk_database *db); +int apk_state_commit(struct apk_state *state); int apk_state_lock_dependency(struct apk_state *state, struct apk_dependency *dep); int apk_state_lock_name(struct apk_state *state, diff --git a/src/del.c b/src/del.c index 695785f..4c00ade 100644 --- a/src/del.c +++ b/src/del.c @@ -58,7 +58,7 @@ static int del_main(void *ctx, struct apk_database *db, int argc, char **argv) r |= apk_state_lock_dependency(state, &dep); } if (r == 0) - r = apk_state_commit(state, db); + r = apk_state_commit(state); else apk_state_print_errors(state); err: diff --git a/src/fix.c b/src/fix.c index 1bacce2..48cab9c 100644 --- a/src/fix.c +++ b/src/fix.c @@ -89,7 +89,7 @@ static int fix_main(void *pctx, struct apk_database *db, int argc, char **argv) r |= apk_state_lock_dependency(state, &deps[i]); if (r == 0 || (apk_flags & APK_FORCE)) - r = apk_state_commit(state, db); + r = apk_state_commit(state); else apk_state_print_errors(state); err: diff --git a/src/state.c b/src/state.c index fef1cbb..d63e1bf 100644 --- a/src/state.c +++ b/src/state.c @@ -937,11 +937,11 @@ void apk_state_print_errors(struct apk_state *state) printf("\n"); } -int apk_state_commit(struct apk_state *state, - struct apk_database *db) +int apk_state_commit(struct apk_state *state) { struct progress prog; struct apk_change *change; + struct apk_database *db = state->db; int n = 0, r = 0, size_diff = 0, toplevel = FALSE, deleteonly = TRUE; /* Count what needs to be done */ diff --git a/src/upgrade.c b/src/upgrade.c index eb51457..4db0c00 100644 --- a/src/upgrade.c +++ b/src/upgrade.c @@ -48,7 +48,7 @@ int apk_do_self_upgrade(struct apk_database *db, struct apk_state *state) apk_message("Uprading first to new apk-tools:"); state->print_ok = 0; - r = apk_state_commit(state, db); + r = apk_state_commit(state); apk_state_unref(state); apk_db_close(db); @@ -101,7 +101,7 @@ static int upgrade_main(void *ctx, struct apk_database *db, int argc, char **arg if (i != 0) printf("\n"); - r = apk_state_commit(state, db); + r = apk_state_commit(state); } else apk_state_print_errors(state); err: -- cgit v1.2.3 From dded261924dba3d86200a2c748443d0f3ec3247b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Thu, 31 Mar 2011 09:21:24 +0300 Subject: state: late locking for install_if package selection improves behaviour under certain corner case conditions. --- src/state.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/state.c b/src/state.c index d63e1bf..cbc0f25 100644 --- a/src/state.c +++ b/src/state.c @@ -454,6 +454,12 @@ int apk_state_autolock_name(struct apk_state *state, struct apk_name *name, if (use == NULL) return -2; + /* Install_if check did not result in package selection change: + * do not lock the package yet as the preferency might change + * later. */ + if (install_if && use->ipkg != NULL) + return 0; + return apk_state_lock_name(state, name, use); #else /* If any of the choices is installed, we are good. Otherwise, -- cgit v1.2.3 From 0cc2086e27a2109e13e8925b882d1014b5bab96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 4 Apr 2011 13:19:12 +0300 Subject: index: support rewriting of architecture Our build infra does not yet handle properly noarch, so for the time being we will rewrite them as native packages in index. This allows the package to be fetched from the proper URL. This feature will be removed once abuild and the build infra handle noarch properly. --- src/index.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/index.c b/src/index.c index d2b4b01..442e98a 100644 --- a/src/index.c +++ b/src/index.c @@ -25,6 +25,7 @@ struct index_ctx { const char *index; const char *output; const char *description; + apk_blob_t *rewrite_arch; time_t index_mtime; int method; }; @@ -44,6 +45,9 @@ static int index_parse(void *ctx, struct apk_db_options *dbopts, case 'd': ictx->description = optarg; break; + case 0x10000: + ictx->rewrite_arch = apk_blob_atomize(APK_BLOB_STR(optarg)); + break; default: return -1; } @@ -88,6 +92,7 @@ static int index_main(void *ctx, struct apk_database *db, int argc, char **argv) struct apk_file_info fi; int total, r, i, j, found, newpkgs = 0; struct index_ctx *ictx = (struct index_ctx *) ctx; + struct apk_package *pkg; if (isatty(STDOUT_FILENO) && ictx->output == NULL && !(apk_flags & APK_FORCE)) { @@ -139,12 +144,14 @@ static int index_main(void *ctx, struct apk_database *db, int argc, char **argv) break; for (j = 0; j < name->pkgs->num; j++) { - struct apk_package *pkg = name->pkgs->item[j]; + pkg = name->pkgs->item[j]; if (apk_blob_compare(bver, *pkg->version) != 0) continue; if (pkg->size != fi.size) continue; pkg->filename = strdup(argv[i]); + if (ictx->rewrite_arch != NULL) + pkg->arch = ictx->rewrite_arch; found = TRUE; break; } @@ -153,8 +160,10 @@ static int index_main(void *ctx, struct apk_database *db, int argc, char **argv) if (!found) { struct apk_sign_ctx sctx; apk_sign_ctx_init(&sctx, ictx->method, NULL, db->keys_fd); - if (apk_pkg_read(db, argv[i], &sctx, NULL) == 0) + if (apk_pkg_read(db, argv[i], &sctx, &pkg) == 0) newpkgs++; + if (ictx->rewrite_arch != NULL) + pkg->arch = ictx->rewrite_arch; apk_sign_ctx_free(&sctx); } } @@ -214,6 +223,8 @@ static struct apk_option index_options[] = { { 'd', "description", "Embed TEXT as description and version " "information of the repository index", required_argument, "TEXT" }, + { 0x10000, "rewrite-arch", "Use ARCH as architery for all packages", + required_argument, "ARCH" }, }; static struct apk_applet apk_index = { -- cgit v1.2.3 From 5a9d8323a088e370a5943071e78f9c3032aed261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Mon, 4 Apr 2011 14:05:52 +0300 Subject: pkg: add origin, maintainer, build_time and commit id to index Parse these fields from .PKGINFO, and write them to index. --- src/apk_package.h | 4 +++- src/package.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/apk_package.h b/src/apk_package.h index ed25bd4..9802dfa 100644 --- a/src/apk_package.h +++ b/src/apk_package.h @@ -83,10 +83,12 @@ struct apk_package { struct apk_name *name; struct apk_installed_package *ipkg; apk_blob_t *version, *arch, *license; - char *url, *description; + apk_blob_t *origin, *maintainer; + char *url, *description, *commit; char *filename; struct apk_dependency_array *depends, *install_if; size_t installed_size, size; + time_t build_time; unsigned repos; struct apk_checksum csum; }; diff --git a/src/package.c b/src/package.c index 1a5d502..2699420 100644 --- a/src/package.c +++ b/src/package.c @@ -659,6 +659,18 @@ int apk_pkg_add_info(struct apk_database *db, struct apk_package *pkg, case 'i': apk_deps_parse(db, &pkg->install_if, value); break; + case 'o': + pkg->origin = apk_blob_atomize_dup(value); + break; + case 'm': + pkg->maintainer = apk_blob_atomize_dup(value); + break; + case 't': + pkg->build_time = apk_blob_pull_uint(&value, 10); + break; + case 'c': + pkg->commit = apk_blob_cstr(value); + break; case 'F': case 'M': case 'R': case 'Z': /* installed db entries which are handled in database.c */ return 1; @@ -691,6 +703,10 @@ static int read_info_line(void *ctx, apk_blob_t line) { "arch", 'A' }, { "depend", 'D' }, { "install_if", 'i' }, + { "origin", 'o' }, + { "maintainer", 'm' }, + { "builddate", 't' }, + { "commit", 'c' }, }; struct read_info_ctx *ri = (struct read_info_ctx *) ctx; apk_blob_t l, r; @@ -800,6 +816,8 @@ void apk_pkg_free(struct apk_package *pkg) free(pkg->url); if (pkg->description) free(pkg->description); + if (pkg->commit) + free(pkg->commit); free(pkg); } @@ -968,6 +986,22 @@ int apk_pkg_write_index_entry(struct apk_package *info, apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->url)); apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nL:")); apk_blob_push_blob(&bbuf, *info->license); + if (info->origin) { + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\no:")); + apk_blob_push_blob(&bbuf, *info->origin); + } + if (info->maintainer) { + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nm:")); + apk_blob_push_blob(&bbuf, *info->maintainer); + } + if (info->build_time) { + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nt:")); + apk_blob_push_uint(&bbuf, info->build_time, 10); + } + if (info->commit) { + apk_blob_push_blob(&bbuf, APK_BLOB_STR("\nc:")); + apk_blob_push_blob(&bbuf, APK_BLOB_STR(info->commit)); + } apk_blob_push_blob(&bbuf, APK_BLOB_STR("\n")); if (APK_BLOB_IS_NULL(bbuf)) -- cgit v1.2.3 From 4a16ddbc1051c62e97e6a3332375051c8a06dc5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Wed, 6 Apr 2011 09:53:28 +0300 Subject: apk-tools-2.1.0_rc1 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e70c8bf..5bd6b66 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ -include config.mk PACKAGE := apk-tools -VERSION := 2.1.0_pre1 +VERSION := 2.1.0_rc1 ## # Default directories -- cgit v1.2.3 From 91c4cc6c188bc20eddcd40e9b9b30f20dc2f36cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Ter=C3=A4s?= Date: Thu, 7 Apr 2011 14:14:27 +0300 Subject: fetch: fix fetching of packages with arch --- src/apk_database.h | 3 +++ src/database.c | 36 ++++++++++++++++++++---------------- src/fetch.c | 4 +--- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/apk_database.h b/src/apk_database.h index 988a668..68bba08 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -183,6 +183,9 @@ int apk_db_add_repository(apk_database_t db, apk_blob_t repository); struct apk_repository *apk_db_select_repo(struct apk_database *db, struct apk_package *pkg); int apk_repository_update(struct apk_database *db, struct apk_repository *repo); +int apk_repo_format_filename(char *buf, size_t len, + const char *repourl, apk_blob_t *arch, + const char *pkgfile); int apk_db_cache_active(struct apk_database *db); void apk_cache_format_index(apk_blob_t to, struct apk_repository *repo); diff --git a/src/database.c b/src/database.c index 8e9cb0d..1376ec3 100644 --- a/src/database.c +++ b/src/database.c @@ -489,14 +489,7 @@ int apk_cache_download(struct apk_database *db, const char *url, apk_blob_t *arc char fullurl[PATH_MAX]; int r; - if (arch != NULL) - snprintf(fullurl, sizeof(fullurl), "%s%s" BLOB_FMT "/%s", - url, url[strlen(url)-1] == '/' ? "" : "/", - BLOB_PRINTF(*arch), item); - else - snprintf(fullurl, sizeof(fullurl), "%s%s/%s", - url, url[strlen(url)-1] == '/' ? "" : "/", - item); + apk_repo_format_filename(fullurl, sizeof(fullurl), url, arch, item); apk_message("fetch %s", fullurl); if (apk_flags & APK_SIMULATE) @@ -1529,6 +1522,24 @@ struct apk_package *apk_db_get_file_owner(struct apk_database *db, return dbf->diri->pkg; } +int apk_repo_format_filename(char *buf, size_t len, + const char *repourl, apk_blob_t *arch, + const char *item) +{ + int n; + + if (arch != NULL) + n = snprintf(buf, len, "%s%s" BLOB_FMT "/%s", + repourl, repourl[strlen(repourl)-1] == '/' ? "" : "/", + BLOB_PRINTF(*arch), item); + else + n = snprintf(buf, len, "%s%s%s", + repourl, repourl[strlen(repourl)-1] == '/' ? "" : "/", + item); + + return n; +} + static int apk_repo_is_remote(struct apk_repository *repo) { return repo->csum.type != APK_CHECKSUM_NONE; @@ -1541,14 +1552,7 @@ static struct apk_bstream *apk_repo_file_open(struct apk_repository *repo, { const char *url = repo->url; - if (arch != NULL) - snprintf(buf, buflen, "%s%s" BLOB_FMT "/%s", - url, url[strlen(url)-1] == '/' ? "" : "/", - BLOB_PRINTF(*arch), file); - else - snprintf(buf, buflen, "%s%s/%s", - url, url[strlen(url)-1] == '/' ? "" : "/", - file); + apk_repo_format_filename(buf, buflen, url, arch, file); if ((apk_flags & APK_NO_NETWORK) && apk_repo_is_remote(repo)) return NULL; diff --git a/src/fetch.c b/src/fetch.c index 09e3b9d..72b481d 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -120,9 +120,7 @@ static int fetch_package(struct fetch_ctx *fctx, if (apk_flags & APK_SIMULATE) return 0; - snprintf(url, sizeof(url), "%s%s%s", repo->url, - repo->url[strlen(repo->url)-1] == '/' ? "" : "/", - pkgfile); + apk_repo_format_filename(url, sizeof(url), repo->url, pkg->arch, pkgfile); if (fctx->flags & FETCH_STDOUT) { fd = STDOUT_FILENO; -- cgit v1.2.3 From 2911d0cad2a2aceda8f617754d5290f6f3ae96f4 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 9 Apr 2011 08:05:49 -0500 Subject: upgrade: Improve english messages on apk-tools/baselibs upgrade transaction. --- src/upgrade.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/upgrade.c b/src/upgrade.c index 4db0c00..ec0dc91 100644 --- a/src/upgrade.c +++ b/src/upgrade.c @@ -46,13 +46,13 @@ int apk_do_self_upgrade(struct apk_database *db, struct apk_state *state) return 0; } - apk_message("Uprading first to new apk-tools:"); + apk_message("Upgrading critical system libraries and apk-tools:"); state->print_ok = 0; r = apk_state_commit(state); apk_state_unref(state); apk_db_close(db); - apk_message("Performing rest of the operation:"); + apk_message("Continuing the upgrade transaction with new apk-tools:"); execvp(apk_argv[0], apk_argv); apk_error("PANIC! Failed to re-execute new apk-tools!"); -- cgit v1.2.3 From 762e0c717bcae8c2d0f46ba4f35232b773ac8419 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 9 Apr 2011 08:16:46 -0500 Subject: state: make the progress bar look nice --- src/state.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/state.c b/src/state.c index cbc0f25..6de3629 100644 --- a/src/state.c +++ b/src/state.c @@ -712,15 +712,15 @@ static void apk_count_change(struct apk_change *change, struct apk_stats *stats) static void apk_draw_progress(int percent) { - const int bar_width = (apk_screen_width - 15); + const int bar_width = (apk_screen_width - 7); int i; - fputs("\e7-[", stderr); + fprintf(stderr, "\e7%3i%% [", percent); for (i = 0; i < bar_width * percent / 100; i++) fputc('#', stderr); for (; i < bar_width; i++) fputc(' ', stderr); - fprintf(stderr, "]- %3i%%", percent); + fputc(']', stderr); fflush(stderr); fputs("\e8\e[0K", stderr); } -- cgit v1.2.3 From cd95304c838eee7fcd042869e49fd973f85439d6 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Thu, 14 Apr 2011 21:48:49 +0200 Subject: db: Allow override arch when using --root This is so we can do x86 --root installs on x86_64 hosts. Using --arch without --root can make great damage so we only enable it if --root is used. --- src/apk.c | 5 +++++ src/apk_database.h | 1 + src/database.c | 7 +++++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/apk.c b/src/apk.c index 55963b0..c40cc20 100644 --- a/src/apk.c +++ b/src/apk.c @@ -66,6 +66,8 @@ static struct apk_option generic_options[] = { required_argument, "REPOFILE" }, { 0x109, "no-network", "Do not use network (cache is still used)" }, { 0x111, "overlay-from-stdin", "Read list of overlay files from stdin" }, + { 0x112, "arch", "Use architecture with --root", + required_argument, "ARCH" }, }; static int version(void) @@ -369,6 +371,9 @@ int main(int argc, char **argv) case 0x111: apk_flags |= APK_OVERLAY_FROM_STDIN; break; + case 0x112: + dbopts.arch = optarg; + break; default: if (applet == NULL || applet->parse == NULL || applet->parse(ctx, &dbopts, r, diff --git a/src/apk_database.h b/src/apk_database.h index 68bba08..9b032e7 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -95,6 +95,7 @@ struct apk_db_options { int lock_wait; unsigned long open_flags; char *root; + char *arch; char *keys_dir; char *repositories_file; struct list_head repository_list; diff --git a/src/database.c b/src/database.c index 1376ec3..45960d2 100644 --- a/src/database.c +++ b/src/database.c @@ -49,7 +49,6 @@ enum { int apk_verbosity = 1; unsigned int apk_flags = 0; -const char *apk_arch = APK_DEFAULT_ARCH; const char * const apkindex_tar_gz = "APKINDEX.tar.gz"; static const char * const apk_static_cache_dir = "var/cache/apk"; @@ -1149,6 +1148,11 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_string_array_init(&db->protected_paths); db->permanent = 1; + if (dbopts->root && dbopts->arch) { + db->arch = apk_blob_atomize(APK_BLOB_STR(dbopts->arch)); + } else { + db->arch = apk_blob_atomize(APK_BLOB_STR(APK_DEFAULT_ARCH)); + } db->root = strdup(dbopts->root ?: "/"); db->root_fd = openat(AT_FDCWD, db->root, O_RDONLY | O_CLOEXEC); if (db->root_fd < 0 && (dbopts->open_flags & APK_OPENF_CREATE)) { @@ -1226,7 +1230,6 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) db->cachetmp_fd = db->cache_fd; } - db->arch = apk_blob_atomize(APK_BLOB_STR(apk_arch)); db->keys_fd = openat(db->root_fd, dbopts->keys_dir ?: "etc/apk/keys", O_RDONLY | O_CLOEXEC); -- cgit v1.2.3 From cec1fa2b0f414e980c4dc56a5cc4dc9ff48bddb8 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Thu, 14 Apr 2011 21:48:49 +0200 Subject: db: Allow override arch when using --root This is so we can do x86 --root installs on x86_64 hosts. Using --arch without --root can make great damage so we only enable it if --root is used. --- src/apk.c | 5 +++++ src/apk_database.h | 1 + src/database.c | 7 +++++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/apk.c b/src/apk.c index 55963b0..c40cc20 100644 --- a/src/apk.c +++ b/src/apk.c @@ -66,6 +66,8 @@ static struct apk_option generic_options[] = { required_argument, "REPOFILE" }, { 0x109, "no-network", "Do not use network (cache is still used)" }, { 0x111, "overlay-from-stdin", "Read list of overlay files from stdin" }, + { 0x112, "arch", "Use architecture with --root", + required_argument, "ARCH" }, }; static int version(void) @@ -369,6 +371,9 @@ int main(int argc, char **argv) case 0x111: apk_flags |= APK_OVERLAY_FROM_STDIN; break; + case 0x112: + dbopts.arch = optarg; + break; default: if (applet == NULL || applet->parse == NULL || applet->parse(ctx, &dbopts, r, diff --git a/src/apk_database.h b/src/apk_database.h index 68bba08..9b032e7 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -95,6 +95,7 @@ struct apk_db_options { int lock_wait; unsigned long open_flags; char *root; + char *arch; char *keys_dir; char *repositories_file; struct list_head repository_list; diff --git a/src/database.c b/src/database.c index 1376ec3..45960d2 100644 --- a/src/database.c +++ b/src/database.c @@ -49,7 +49,6 @@ enum { int apk_verbosity = 1; unsigned int apk_flags = 0; -const char *apk_arch = APK_DEFAULT_ARCH; const char * const apkindex_tar_gz = "APKINDEX.tar.gz"; static const char * const apk_static_cache_dir = "var/cache/apk"; @@ -1149,6 +1148,11 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) apk_string_array_init(&db->protected_paths); db->permanent = 1; + if (dbopts->root && dbopts->arch) { + db->arch = apk_blob_atomize(APK_BLOB_STR(dbopts->arch)); + } else { + db->arch = apk_blob_atomize(APK_BLOB_STR(APK_DEFAULT_ARCH)); + } db->root = strdup(dbopts->root ?: "/"); db->root_fd = openat(AT_FDCWD, db->root, O_RDONLY | O_CLOEXEC); if (db->root_fd < 0 && (dbopts->open_flags & APK_OPENF_CREATE)) { @@ -1226,7 +1230,6 @@ int apk_db_open(struct apk_database *db, struct apk_db_options *dbopts) db->cachetmp_fd = db->cache_fd; } - db->arch = apk_blob_atomize(APK_BLOB_STR(apk_arch)); db->keys_fd = openat(db->root_fd, dbopts->keys_dir ?: "etc/apk/keys", O_RDONLY | O_CLOEXEC); -- cgit v1.2.3 From bdd1f40af0168679b5d0808152ab53d758289938 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Fri, 15 Oct 2010 21:04:40 +0000 Subject: Makefile: fix installation of lib and apk module --- src/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index c9cda6a..6af23d1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,7 +9,7 @@ apk.so-objs := lua-apk.o CFLAGS_lua-apk.o := -DAPK_VERSION=\"$(FULL_VERSION)\" LIBS_apk.so := -L$(obj) -lapk LUA_LIB-y := $(obj)/apk.so -install-LUA_LIB-y := $(INSTALLDIR) $(DESTDIR)$(LUA_LIBDIR) \ +install-LUA_LIB-y := $(INSTALLDIR) $(DESTDIR)$(LUA_LIBDIR); \ $(INSTALL) $(LUA_LIB-y) $(DESTDIR)$(LUA_LIBDIR) endif @@ -35,7 +35,7 @@ endif ifneq ($(LIBAPK),) shlibs-y += libapk.so LIBAPK-y := $(obj)/libapk.so -install-LIBAPK-y := $(INSTALLDIR) $(DESTDIR)$(LIBDIR) \ +install-LIBAPK-y := $(INSTALLDIR) $(DESTDIR)$(LIBDIR); \ $(INSTALL) $(LIBAPK-y) $(DESTDIR)$(LIBDIR) endif -- cgit v1.2.3 From 66dee4809cbbc67ecf8da2f358c172cfb4cecfad Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Fri, 15 Oct 2010 21:06:36 +0000 Subject: lua: initial db_open so far we just parse the db options --- src/lua-apk.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/src/lua-apk.c b/src/lua-apk.c index efd7c3e..4bb5796 100644 --- a/src/lua-apk.c +++ b/src/lua-apk.c @@ -5,12 +5,34 @@ #include "apk_defines.h" #include "apk_version.h" #include "apk_blob.h" +#include "apk_database.h" #define LIBNAME "apk" int apk_verbosity; unsigned int apk_flags; +struct flagmap { + const char *name; + int flag; +}; + +struct flagmap opendb_flagmap[] = { + {"read", APK_OPENF_READ}, + {"write", APK_OPENF_WRITE}, + {"create", APK_OPENF_CREATE}, + {"no_installed", APK_OPENF_NO_INSTALLED}, + {"no_scripts", APK_OPENF_NO_SCRIPTS}, + {"no_world", APK_OPENF_NO_WORLD}, + {"no_sys_repos", APK_OPENF_NO_SYS_REPOS}, + {"no_installed_repo", APK_OPENF_NO_INSTALLED_REPO}, + {"no_repos", APK_OPENF_NO_REPOS}, + {"no_state", APK_OPENF_NO_STATE}, + {"no_scripts", APK_OPENF_NO_SCRIPTS}, + {"no_world", APK_OPENF_NO_WORLD}, + {NULL, 0} +}; + /* version_validate(verstr) */ /* returns boolean */ static int Pversion_validate(lua_State *L) @@ -45,11 +67,63 @@ static int Pversion_is_less(lua_State *L) return 1; } +//static getfield(lua_State *L, const char *key) +//{ +static const char *get_opt_string_field(lua_State *L, int index, + const char *key, const char *def) +{ + const char *value; + lua_getfield(L, index, key); + value = luaL_optstring(L, -1, def); + lua_pop(L, 1); + return value; +} + +static int get_opt_int_field(lua_State *L, int index, const char *key, int def) +{ + int value; + lua_getfield(L, index, key); + value = luaL_optinteger(L, -1, def); + lua_pop(L, 1); + return value; +} + +static int get_boolean_field(lua_State *L, int index, const char *key) +{ + int value; + lua_getfield(L, index, key); + value = lua_toboolean(L, -1); + lua_pop(L, 1); + return value; +} + +static int get_dbopts(lua_State *L, int i, struct apk_db_options *o) +{ + struct flagmap *f; + o->root = (char *)get_opt_string_field(L, i, "root", NULL); + o->repositories_file = (char *)get_opt_string_field(L, i, "repositories_file", NULL); + o->keys_dir = (char *)get_opt_string_field(L, i, "keys_dir", NULL); + o->lock_wait = get_opt_int_field(L, i, "lock_wait", 0); + for (f = opendb_flagmap; f->name != NULL; f++) + if (get_boolean_field(L, i, f->name)) + o->open_flags |= f->flag; + return 0; +} + +static int Papk_db_open(lua_State *L) +{ + struct apk_db_options opts; + memset(&opts, 0, sizeof(opts)); + if (lua_istable(L, 1)) + get_dbopts(L, 1, &opts); + return 0; +} static const luaL_reg R[] = { {"version_validate", Pversion_validate}, {"version_compare", Pversion_compare}, {"version_is_less", Pversion_is_less}, + {"db_open", Papk_db_open}, {NULL, NULL} }; -- cgit v1.2.3 From 5dcc480acdd07a48291194d7b95672d125d75c1d Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Fri, 15 Oct 2010 22:16:22 +0000 Subject: lua: open and close db --- src/lua-apk.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/lua-apk.c b/src/lua-apk.c index 4bb5796..24962ce 100644 --- a/src/lua-apk.c +++ b/src/lua-apk.c @@ -8,6 +8,7 @@ #include "apk_database.h" #define LIBNAME "apk" +#define APKDB_META "apk_database" int apk_verbosity; unsigned int apk_flags; @@ -110,16 +111,46 @@ static int get_dbopts(lua_State *L, int i, struct apk_db_options *o) return 0; } +static struct apk_database *checkdb(lua_State *L, int index) +{ + struct apk_database *db; + luaL_checktype(L, index, LUA_TUSERDATA); + db = (struct apk_database *) luaL_checkudata(L, index, APKDB_META); + if (db == NULL) + luaL_typerror(L, index, APKDB_META); + return db; +} + static int Papk_db_open(lua_State *L) { struct apk_db_options opts; + struct apk_database *db; + int r; + memset(&opts, 0, sizeof(opts)); + list_init(&opts.repository_list); if (lua_istable(L, 1)) get_dbopts(L, 1, &opts); + + db = lua_newuserdata(L, sizeof(struct apk_database)); + luaL_getmetatable(L, APKDB_META); + lua_setmetatable(L, -2); + + r = apk_db_open(db, &opts); + if (r != 0) + luaL_error(L, "apk_db_open() failed"); + return 1; +} + +static int Papk_db_close(lua_State *L) +{ + struct apk_database *db = checkdb(L, 1); + apk_db_close(db); return 0; } -static const luaL_reg R[] = { + +static const luaL_reg reg_apk_methods[] = { {"version_validate", Pversion_validate}, {"version_compare", Pversion_compare}, {"version_is_less", Pversion_is_less}, @@ -127,12 +158,29 @@ static const luaL_reg R[] = { {NULL, NULL} }; +static const luaL_reg reg_apk_db_meta_methods[] = { + {"__gc", Papk_db_close}, + {NULL, NULL} +}; + LUALIB_API int luaopen_apk(lua_State *L) { - luaL_register(L, LIBNAME, R); + luaL_register(L, LIBNAME, reg_apk_methods); lua_pushliteral(L, "version"); lua_pushliteral(L, APK_VERSION); lua_settable(L, -3); + + luaL_newmetatable(L, APKDB_META); + luaL_register(L, NULL, reg_apk_db_meta_methods); + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -3); + lua_rawset(L, -3); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, -3); + lua_rawset(L, -3); + lua_pop(L, 1); + return 1; } -- cgit v1.2.3 From d9efda7c01146eba207b7b4039c7457ec25e6b91 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Wed, 15 Dec 2010 10:09:35 +0000 Subject: lua: implement who_owns --- src/lua-apk.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/lua-apk.c b/src/lua-apk.c index 24962ce..6128718 100644 --- a/src/lua-apk.c +++ b/src/lua-apk.c @@ -80,6 +80,14 @@ static const char *get_opt_string_field(lua_State *L, int index, return value; } +static void set_string_field(lua_State *L, int index, const char *key, + const char *value) +{ + lua_pushstring(L, key); + lua_pushstring(L, value); + lua_settable(L, index); +} + static int get_opt_int_field(lua_State *L, int index, const char *key, int def) { int value; @@ -89,6 +97,13 @@ static int get_opt_int_field(lua_State *L, int index, const char *key, int def) return value; } +static void set_int_field(lua_State *L, int index, const char *key, int value) +{ + lua_pushstring(L, key); + lua_pushinteger(L, value); + lua_settable(L, index); +} + static int get_boolean_field(lua_State *L, int index, const char *key) { int value; @@ -150,11 +165,36 @@ static int Papk_db_close(lua_State *L) } +static int push_package(lua_State *L, struct apk_package *pkg) +{ + if (pkg == NULL) { + lua_pushnil(L); + return 1; + } + lua_newtable(L); + set_string_field(L, -3, "name", pkg->name->name); + set_string_field(L, -3, "version", pkg->version); + set_string_field(L, -3, "url", pkg->url); + set_string_field(L, -3, "license", pkg->license); + set_string_field(L, -3, "description", pkg->description); + set_string_field(L, -3, "filename", pkg->filename); + set_int_field(L, -3, "size", pkg->size); + return 1; +} +static int Papk_who_owns(lua_State *L) +{ + struct apk_database *db = checkdb(L, 1); + const char *path = luaL_checkstring(L, 2); + struct apk_package *pkg = apk_db_get_file_owner(db, APK_BLOB_STR(path)); + return push_package(L, pkg); +} + static const luaL_reg reg_apk_methods[] = { {"version_validate", Pversion_validate}, {"version_compare", Pversion_compare}, {"version_is_less", Pversion_is_less}, {"db_open", Papk_db_open}, + {"who_owns", Papk_who_owns}, {NULL, NULL} }; -- cgit v1.2.3 From 02c1f5b4b90fffbba2115cdf0bb1c17c520a2817 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Fri, 28 Jan 2011 03:24:51 +0000 Subject: lua-apk: fix compile warnings --- src/lua-apk.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/lua-apk.c b/src/lua-apk.c index 6128718..7a04dc6 100644 --- a/src/lua-apk.c +++ b/src/lua-apk.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -39,7 +40,7 @@ struct flagmap opendb_flagmap[] = { static int Pversion_validate(lua_State *L) { apk_blob_t ver; - ver.ptr = (char *)luaL_checklstring(L, 1, &ver.len); + ver.ptr = (char *)luaL_checklstring(L, 1, (size_t *)&ver.len); lua_pushboolean(L, apk_version_validate(ver)); return 1; } @@ -50,8 +51,8 @@ static int Pversion_validate(lua_State *L) static int Pversion_compare(lua_State *L) { apk_blob_t a, b; - a.ptr = (char *)luaL_checklstring(L, 1, &a.len); - b.ptr = (char *)luaL_checklstring(L, 2, &b.len); + a.ptr = (char *)luaL_checklstring(L, 1, (size_t *)&a.len); + b.ptr = (char *)luaL_checklstring(L, 2, (size_t *)&b.len); lua_pushstring(L, apk_version_op_string(apk_version_compare_blob(a, b))); return 1; } @@ -62,8 +63,8 @@ static int Pversion_compare(lua_State *L) static int Pversion_is_less(lua_State *L) { apk_blob_t a, b; - a.ptr = (char *)luaL_checklstring(L, 1, &a.len); - b.ptr = (char *)luaL_checklstring(L, 2, &b.len); + a.ptr = (char *)luaL_checklstring(L, 1, (size_t *)&a.len); + b.ptr = (char *)luaL_checklstring(L, 2, (size_t *)&b.len); lua_pushboolean(L, apk_version_compare_blob(a, b) == APK_VERSION_LESS); return 1; } @@ -173,9 +174,9 @@ static int push_package(lua_State *L, struct apk_package *pkg) } lua_newtable(L); set_string_field(L, -3, "name", pkg->name->name); - set_string_field(L, -3, "version", pkg->version); + set_string_field(L, -3, "version", apk_blob_cstr(*pkg->version)); set_string_field(L, -3, "url", pkg->url); - set_string_field(L, -3, "license", pkg->license); + set_string_field(L, -3, "license", apk_blob_cstr(*pkg->license)); set_string_field(L, -3, "description", pkg->description); set_string_field(L, -3, "filename", pkg->filename); set_int_field(L, -3, "size", pkg->size); -- cgit v1.2.3 From a9d594683a12c2935a43898dfc7132ac536be362 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Sat, 19 Feb 2011 04:25:05 +0000 Subject: lua: init fixes - call apk_atom_init() - if no open flag is specified, then default to read-only. --- src/lua-apk.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lua-apk.c b/src/lua-apk.c index 7a04dc6..835d379 100644 --- a/src/lua-apk.c +++ b/src/lua-apk.c @@ -145,8 +145,11 @@ static int Papk_db_open(lua_State *L) memset(&opts, 0, sizeof(opts)); list_init(&opts.repository_list); + apk_atom_init(); if (lua_istable(L, 1)) get_dbopts(L, 1, &opts); + else + opts.open_flags |= APK_OPENF_READ; db = lua_newuserdata(L, sizeof(struct apk_database)); luaL_getmetatable(L, APKDB_META); -- cgit v1.2.3 From 2804d01d89ca79082f15e217e46269d6ef7e5c1f Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Sat, 19 Feb 2011 09:41:15 +0000 Subject: lua: implement exists/is_installed Tests whether given package string is installed --- src/lua-apk.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/lua-apk.c b/src/lua-apk.c index 835d379..779dfd1 100644 --- a/src/lua-apk.c +++ b/src/lua-apk.c @@ -193,12 +193,45 @@ static int Papk_who_owns(lua_State *L) return push_package(L, pkg); } +static int Papk_exists(lua_State *L) +{ + struct apk_database *db = checkdb(L, 1); + const char *depstr = luaL_checkstring(L, 2); + struct apk_dependency dep; + struct apk_name *name; + struct apk_package *pkg; + int i, r; + + r = apk_dep_from_blob(&dep, db, APK_BLOB_STR(depstr)); + if (r != 0) + goto ret_nil; + + name = dep.name; + for (i = 0; i < name->pkgs->num; i++) { + pkg = name->pkgs->item[i]; + if (pkg->ipkg != NULL) + break; + } + if (i >= name->pkgs->num) + goto ret_nil; + + if (!apk_dep_is_satisfied(&dep, pkg)) + goto ret_nil; + + return push_package(L, pkg); +ret_nil: + lua_pushnil(L); + return 1; +} + static const luaL_reg reg_apk_methods[] = { {"version_validate", Pversion_validate}, {"version_compare", Pversion_compare}, {"version_is_less", Pversion_is_less}, {"db_open", Papk_db_open}, {"who_owns", Papk_who_owns}, + {"exists", Papk_exists}, + {"is_installed", Papk_exists}, {NULL, NULL} }; -- cgit v1.2.3 From 35bba3de1f4d6464dc03ffc60b6a6b6ec25ef6b0 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Mon, 21 Feb 2011 14:35:00 +0000 Subject: lua: implement iterator with installed packages --- src/lua-apk.c | 48 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/src/lua-apk.c b/src/lua-apk.c index 779dfd1..07cbc1c 100644 --- a/src/lua-apk.c +++ b/src/lua-apk.c @@ -9,7 +9,8 @@ #include "apk_database.h" #define LIBNAME "apk" -#define APKDB_META "apk_database" +#define APK_DB_META "apk_database" +#define APK_IPKG_META "apk_installed_package" int apk_verbosity; unsigned int apk_flags; @@ -131,9 +132,9 @@ static struct apk_database *checkdb(lua_State *L, int index) { struct apk_database *db; luaL_checktype(L, index, LUA_TUSERDATA); - db = (struct apk_database *) luaL_checkudata(L, index, APKDB_META); + db = (struct apk_database *) luaL_checkudata(L, index, APK_DB_META); if (db == NULL) - luaL_typerror(L, index, APKDB_META); + luaL_typerror(L, index, APK_DB_META); return db; } @@ -152,7 +153,7 @@ static int Papk_db_open(lua_State *L) opts.open_flags |= APK_OPENF_READ; db = lua_newuserdata(L, sizeof(struct apk_database)); - luaL_getmetatable(L, APKDB_META); + luaL_getmetatable(L, APK_DB_META); lua_setmetatable(L, -2); r = apk_db_open(db, &opts); @@ -224,6 +225,42 @@ ret_nil: return 1; } +// Iterator of all installed packages +struct apk_installed_package_iterator { + struct list_head *end; + struct apk_installed_package *node; +}; + +static int iterate_installed(lua_State *L) +{ + struct apk_installed_package_iterator *i; + struct apk_installed_package *ipkg; + i = (struct apk_installed_package_iterator *)lua_touserdata(L, lua_upvalueindex(1)); + ipkg = i->node; + + if (&ipkg->installed_pkgs_list == i->end) + return 0; + + i->node = list_entry(ipkg->installed_pkgs_list.next, + typeof(*ipkg), installed_pkgs_list); + return push_package(L, ipkg->pkg); + +} +static int Pinstalled(lua_State *L) +{ + struct apk_database *db = checkdb(L, 1); + struct apk_installed_package_iterator *i; + + i = (struct apk_installed_package_iterator *) lua_newuserdata(L, sizeof(*i)); + i->end = &db->installed.packages; + i->node = list_entry((&db->installed.packages)->next, + struct apk_installed_package, + installed_pkgs_list); + + lua_pushcclosure(L, iterate_installed, 1); + return 1; +} + static const luaL_reg reg_apk_methods[] = { {"version_validate", Pversion_validate}, {"version_compare", Pversion_compare}, @@ -232,6 +269,7 @@ static const luaL_reg reg_apk_methods[] = { {"who_owns", Papk_who_owns}, {"exists", Papk_exists}, {"is_installed", Papk_exists}, + {"installed", Pinstalled}, {NULL, NULL} }; @@ -247,7 +285,7 @@ LUALIB_API int luaopen_apk(lua_State *L) lua_pushliteral(L, APK_VERSION); lua_settable(L, -3); - luaL_newmetatable(L, APKDB_META); + luaL_newmetatable(L, APK_DB_META); luaL_register(L, NULL, reg_apk_db_meta_methods); lua_pushliteral(L, "__index"); lua_pushvalue(L, -3); -- cgit v1.2.3