#include "pkg_db.h" #include #include #include #include #include #define PKG_DB "../packages" #define PKG_DB_LEN (sizeof(PKG_DB) - 1) #define PKG_INFO_CMD "./get_pkg_attrs.sh" bool load_package_info(package_info_t* info, char* pkgid) { memset(info, 0, sizeof(*info)); // construct package description directory path and ensure it exists size_t pkgid_len = strlen(pkgid); size_t pkg_dir_len = PKG_DB_LEN + pkgid_len + 1; char* pkg_dir = malloc(pkg_dir_len + 1); if (!pkg_dir) { fprintf(stderr, "Failed to alloc pkg_dir\n"); exit(1); } // pkg_dir = "PKG_DB/pkgid" memcpy(pkg_dir, PKG_DB, PKG_DB_LEN); pkg_dir[PKG_DB_LEN] = '/'; memcpy(&pkg_dir[PKG_DB_LEN + 1], pkgid, pkgid_len + 1); if (access(pkg_dir, F_OK) != 0) { fprintf(stderr, "Package '%s' not found\n", pkgid); free(pkg_dir); return false; } // construct package description script path and ensure it exists size_t script_path_len = pkg_dir_len + pkgid_len + 4; info->script_path = malloc(script_path_len + 1); if (!info->script_path) { fprintf(stderr, "Failed to alloc info->script_path\n"); exit(1); } memcpy(info->script_path, pkg_dir, pkg_dir_len); info->script_path[pkg_dir_len] = '/'; memcpy(&info->script_path[pkg_dir_len + 1], pkgid, pkgid_len); memcpy(&info->script_path[script_path_len - 3], ".sh", 4); free(pkg_dir); if (access(info->script_path, F_OK) != 0) { fprintf(stderr, "Package '%s' broken, doesn't have description script\n", pkgid); free(info->script_path); return false; } int pipefds[2] = {0}; if (pipe(pipefds) < 0) { fprintf(stderr, "Failed to create pipe\n"); exit(1); } pid_t pid = fork(); if (pid < 0) { fprintf(stderr, "Failed to create child process\n"); exit(1); } if (pid == 0) { close(pipefds[0]); dup2(pipefds[1], STDOUT_FILENO); close(pipefds[1]); char* argv[] = { PKG_INFO_CMD, info->script_path, NULL }; char* envp[] = { NULL }; execve(PKG_INFO_CMD, argv, envp); fprintf(stderr, "execve failed\n"); exit(127); } int wstatus; if (waitpid(pid, &wstatus, 0) < 0) { fprintf(stderr, "waitpid failed\n"); exit(1); } if (WEXITSTATUS(wstatus) == 127) { exit(1); } ssize_t bytes_read = read(pipefds[0], info->package_attrs, sizeof(info->package_attrs)); if (bytes_read < 0) { fprintf(stderr, "Failed to read from pipe\n"); exit(1); } free(info->script_path); for (int i = 0; i < bytes_read;) { char atype = info->package_attrs[i]; i++; switch (atype) { case 'i': info->attrs.id = &info->package_attrs[i]; break; case 'n': info->attrs.name = &info->package_attrs[i]; break; case 'd': info->attrs.desc = &info->package_attrs[i]; break; } for(;info->package_attrs[i] && i < bytes_read; i++); i++; } return true; }