#include "package_db.h" #include "util.h" #include #include #include #include #include #include #define PKG_INFO_CMD "./scripts/get_pkg_attrs.sh" // note: fixed location of package database for now const char pkg_db[] = "./var/snag/packages"; const size_t pkg_db_len = sizeof(pkg_db) - 1; bool load_package_info(char* pkgid, package_info_t* info) { 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) { print("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", 3); info->script_path[script_path_len] = '\0'; free(pkg_dir); if (access(info->script_path, F_OK) != 0) { print("Package '%s' broken, doesn't have description script\n", pkgid); free(info->script_path); return false; } } // PIPE and FORK to run pkg attrs script int pipefds[2] = {0}; if (pipe(pipefds) < 0) die("failed to pipe: %s", strerror(errno)); pid_t pid = fork(); if (pid < 0) die("failed to fork: %s", strerror(errno)); if (pid == 0) { // child proc // connect my stdout to 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); // what are you still doing here? die("CHILD - execve to %s failed: %s", PKG_INFO_CMD, strerror(errno)); } else { // parent proc, close write end of pipe close(pipefds[1]); } // wait for child to finish int wstatus; if (waitpid(pid, &wstatus, 0) < 0) die("waitpid failed: %s", strerror(errno)); if (WEXITSTATUS(wstatus) != 0) die("the child failed to execute get_pkg_attr script: %d", WEXITSTATUS(wstatus)); // read all bytes from pipe into attr buffer ssize_t bytes_read = read(pipefds[0], info->attrs.buffer, sizeof(info->attrs.buffer)); if (bytes_read < 0) die("failed to read from pipe: %s", strerror(errno)); close(pipefds[0]); // read attributes from attr buffer // attribute format: type (char), data value (null terminated str) // todo(jqj): switch over to dynamically allocated buffer for (int i = 0; i < bytes_read;) { char atype = info->attrs.buffer[i]; i++; switch (atype) { case 'i': info->attrs.id = &info->attrs.buffer[i]; break; case 'n': info->attrs.name = &info->attrs.buffer[i]; break; case 'd': info->attrs.desc = &info->attrs.buffer[i]; break; case 'w': info->attrs.webpage = &info->attrs.buffer[i]; break; case 'l': info->attrs.license = &info->attrs.buffer[i]; break; case 'v': info->attrs.version = &info->attrs.buffer[i]; break; case 'u': info->attrs.source_url = &info->attrs.buffer[i]; break; case 'c': info->attrs.source_checksum = &info->attrs.buffer[i]; break; } for(;info->attrs.buffer[i] && i < bytes_read; i++); i++; } return true; }