#include "pkg_db.h" #include "util.h" #include #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)); size_t pkgid_len = strlen(pkgid); // construct package description directory path and ensure it exists // pkg_dir = "PKG_DB/pkgid" size_t pkg_dir_len = PKG_DB_LEN + pkgid_len + 1; char* pkg_dir = emalloc(pkg_dir_len + 1, "pkg_dir"); { memcpy(pkg_dir, PKG_DB, PKG_DB_LEN); pkg_dir[PKG_DB_LEN] = '/'; memcpy(pkg_dir + PKG_DB_LEN + 1, pkgid, pkgid_len); pkg_dir[pkg_dir_len] = '\0'; if (access(pkg_dir, F_OK) != 0) { eprintf("Package '%s' not found\n", pkgid); free(pkg_dir); return false; } } // construct package description script path and ensure it exists // script_path = "pkg_dir/pkgid.sh" size_t script_path_len = pkg_dir_len + pkgid_len + 4; info->script_path = emalloc(script_path_len + 1, "info->script_path"); { 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) { eprintf("Package '%s' broken, doesn't have description script\n", pkgid); free(info->script_path); return false; } } // PIPE and FORK to run get pkg attrs script int pipefds[2] = {0}; if (pipe(pipefds) < 0) error_out("failed to pipe: %s", strerror(errno)); pid_t pid = fork(); if (pid < 0) error_out("failed to fork: %s", strerror(errno)); // child proc if (pid == 0) { // write my stdout the the pipe close(pipefds[0]); dup2(pipefds[1], STDOUT_FILENO); close(pipefds[1]); // exec into get attr script char* argv[] = { PKG_INFO_CMD, info->script_path, NULL }; char* envp[] = { NULL }; execve(PKG_INFO_CMD, argv, envp); error_out("execve failed"); } // wait for child to finish int wstatus; if (waitpid(pid, &wstatus, 0) < 0) error_out("waitpid failed: %s", strerror(errno)); if (WEXITSTATUS(wstatus) != 0) error_out("failed to execute get pkg attr script"); // read all bytes from pipe ssize_t bytes_read = read(pipefds[0], info->package_attrs, sizeof(info->package_attrs)); if (bytes_read < 0) error_out("Failed to read from pipe"); // read attributes from pipe data 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; }