From 8ef4c2587ac0041049c67befed281a70cf240769 Mon Sep 17 00:00:00 2001 From: Justin Klaassen Date: Wed, 21 Feb 2024 22:49:32 +0000 Subject: [PATCH] sys: use "Auto-Installed" field for packagelist A change to the build scripts (openwrt/openwrt#14428) removed the "user" flag from all installed packages in the rootfs. This caused problems for tools like "auc" which rely on the rpcd packagelist command to determine which packages to request when building a new image. This change modifies the packagelist implementation to use the "Auto-Installed" field rather than the "user" flag in order to filter dependencies from the returned list of packages. The resulting package list is identical without relying on the semantics of the "user" flag which is typically used to indicate which packages have been interactively installed by the user. Signed-off-by: Justin Klaassen [use 'bool' instead of 'int' type for booleans] Signed-off-by: Daniel Golle --- sys.c | 122 +++++++++++++++++++++++++++------------------------------- 1 file changed, 57 insertions(+), 65 deletions(-) diff --git a/sys.c b/sys.c index 42a2fc6..da3508e 100644 --- a/sys.c +++ b/sys.c @@ -16,6 +16,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include @@ -164,16 +165,31 @@ rpc_cgi_password_set(struct ubus_context *ctx, struct ubus_object *obj, } } +static bool +is_field(const char *type, const char *line) +{ + return strncmp(line, type, strlen(type)) == 0; +} + +static bool +is_blank(const char *line) +{ + for (; *line; line++) + if (!isspace(*line)) + return false; + return true; +} + static int rpc_sys_packagelist(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { struct blob_attr *tb[__RPC_PACKAGELIST_MAX]; - int all = false; + bool all = false, installed = false, auto_installed = false; struct blob_buf buf = { 0 }; - char var[256], pkg[128] = { 0 }, ver[128] = { 0 }; - char *tmp, *p1, *p2, *p3; + char line[256], tmp[128], pkg[128], ver[128]; + char *pkg_abi; void *tbl; blobmsg_parse(rpc_packagelist_policy, __RPC_PACKAGELIST_MAX, tb, @@ -190,68 +206,44 @@ rpc_sys_packagelist(struct ubus_context *ctx, struct ubus_object *obj, tbl = blobmsg_open_table(&buf, "packages"); pkg[0] = ver[0] = '\0'; - while(fgets(var, sizeof(var), f)) { - p1 = strchr(var, ' '); - p2 = p3 = NULL; - if (!p1) - goto procstr; - - *p1++ = '\0'; - p2 = strchr(p1, ' '); - if (!p2) { - tmp = strchr(p1, '\n'); - if (tmp) - *tmp = '\0'; - goto procstr; - } - - *p2++ = '\0'; - p3 = strchr(p2, ' '); - if (!p3) { - tmp = strchr(p2, '\n'); - if (tmp) - *tmp = '\0'; - goto procstr; - } - - *p3++ = '\0'; - tmp = strchr(p3, '\n'); - if (tmp) - *tmp = '\0'; - -procstr: - if (!p1) - continue; - - if (!strcmp(var, "Package:")) { - strncpy(pkg, p1, sizeof(pkg) - 1); - continue; - } - - /* If there is ABIVersion, remove that suffix */ - if (!strcmp(var, "ABIVersion:")) { - if (strlen(pkg) <= strlen(p1)) - continue; - tmp = &pkg[strlen(pkg) - strlen(p1)]; - if (strncmp(p1, tmp, strlen(p1))) - continue; - - *tmp = '\0'; - continue; - } - - if (!strcmp(var, "Version:")) { - strncpy(ver, p1, sizeof(ver) - 1); - continue; - } - - if (p2 && p3 && - !strcmp(var, "Status:") && - !strcmp(p1, "install") && - (all || strstr(p2, "user")) && - !strcmp(p3, "installed") && pkg[0] && ver[0]) { - blobmsg_add_string(&buf, pkg, ver); - pkg[0] = ver[0] = '\0'; + while (fgets(line, sizeof(line), f)) { + switch (line[0]) { + case 'A': + if (is_field("ABIVersion", line)) { + /* if there is ABIVersion, remove that suffix */ + if (sscanf(line, "ABIVersion: %127s", tmp) == 1 + && strlen(tmp) < strlen(pkg)) { + pkg_abi = pkg + (strlen(pkg) - strlen(tmp)); + if (strncmp(pkg_abi, tmp, strlen(tmp)) == 0) + pkg_abi[0] = '\0'; + } + } else if (is_field("Auto-Installed", line)) + if (sscanf(line, "Auto-Installed: %63s", tmp) == 1) + auto_installed = (strcmp(tmp, "yes") == 0); + break; + case 'P': + if (is_field("Package", line)) + if (sscanf(line, "Package: %127s", pkg) != 1) + pkg[0] = '\0'; + break; + case 'V': + if (is_field("Version", line)) + if (sscanf(line, "Version: %127s", ver) != 1) + ver[0] = '\0'; + break; + case 'S': + if (is_field("Status", line)) + if (sscanf(line, "Status: install %63s installed", tmp) == 1) + installed = true; + break; + default: + if (is_blank(line)) { + if (installed && (all || !auto_installed) && pkg[0] && ver[0]) + blobmsg_add_string(&buf, pkg, ver); + pkg[0] = ver[0] = '\0'; + installed = auto_installed = false; + } + break; } } -- 2.30.2