return r;
}
-struct pakfire_build_send_scriptlet_state {
- struct pakfire_scriptlet* scriptlet;
+static int pakfire_build_extract_command(
+ char* command, size_t lcommand, const char* line, const size_t lline) {
+ const char* s = NULL;
+ const char* e = NULL;
- const char* p;
- size_t l;
-};
+ // Line must at least have a certain length
+ if (lline <= strlen("executable()"))
+ return -EINVAL;
-static ssize_t pakfire_build_send_scriptlet(
- struct pakfire_ctx* ctx, void* data, char* buffer, size_t length) {
- struct pakfire_build_send_scriptlet_state* state = data;
-
- // Fetch the scriptlet unless already done
- if (!state->p) {
- state->p = pakfire_scriptlet_get_data(state->scriptlet, &state->l);
- if (!state->p) {
- ERROR(ctx, "Could not fetch scriptlet: %m\n");
- return -errno;
+ // Check if we begin with "executable("
+ if (!pakfire_string_startswith(line, "executable("))
+ return -EINVAL;
+
+ // Find the closing bracket
+ e = memrchr(line, ')', lline);
+ if (!e)
+ return -EINVAL;
+
+ // Find the opening bracket
+ s = memchr(line, '(', lline);
+ if (!s)
+ return -EINVAL;
+
+ // Skip the opening bracket
+ s++;
+
+ // Check if we have seen the opening bracket first and then the closing bracket
+ ssize_t l = e - s;
+ if (l <= 0)
+ return -EINVAL;
+
+ // Copy the text to the buffer
+ return __pakfire_string_setn(command, lcommand, s, l);
+}
+
+static int pakfire_build_process_scriptlet_dep(
+ struct pakfire_ctx* ctx, void* data, const char* line, const size_t length) {
+ struct pakfire_find_deps_ctx* deps = data;
+ char command[PATH_MAX];
+ char path[PATH_MAX];
+ int r;
+
+ // Try to extract the command
+ r = pakfire_build_extract_command(command, sizeof(command), line, length);
+ if (r < 0) {
+ switch (-r) {
+ // Ignore if the string was presumed to be invalid (some other format)
+ case EINVAL:
+ DEBUG(ctx, "Ignoring invalid line %.*s\n", (int)length, line);
+
+ // Consume the entire line
+ return length;
+
+ default:
+ return r;
}
}
- // Return if we have nothing left to send
- if (state->l == 0)
- return 0;
+ DEBUG(ctx, "Found '%s' as a dependency of the scriptlet\n", command);
- // Cap the buffer to the maximum size of the scriptlet
- if (state->l < length)
- length = state->l;
+ // Add absolute paths just like that
+ if (pakfire_path_is_absolute(command)) {
+ r = pakfire_package_add_dep(deps->pkg, PAKFIRE_PKG_PREREQUIRES, "%s", command);
+ if (r < 0)
+ return r;
- // Copy the scriptlet into the buffer
- memcpy(buffer, state->p, length);
+ // Otherwise, we will have to resolve the command
+ } else {
+ r = pakfire_which(deps->build->pakfire, path, command);
+ if (r < 0)
+ return r;
- // Forward the pointer by how much we have written
- state->p += length;
- state->l -= length;
+ // If we could resolve the command, we add the full path
+ if (*path) {
+ r = pakfire_package_add_dep(deps->pkg, PAKFIRE_PKG_PREREQUIRES, "%s", path);
+ if (r < 0)
+ return r;
+ }
+ }
+ // Consume the entire line
return length;
}
static int pakfire_build_add_scriptlet_requires(struct pakfire_build* build,
struct pakfire_package* pkg, struct pakfire_scriptlet* scriptlet) {
+ struct pakfire_pty_buffer buffer = {};
int r;
- struct pakfire_build_send_scriptlet_state send_scriptlet_state = {
- .scriptlet = scriptlet,
- };
-
struct pakfire_find_deps_ctx ctx = {
- .build = build,
- .pkg = pkg,
- .dep = PAKFIRE_PKG_PREREQUIRES,
+ .build = build,
+ .pkg = pkg,
};
- // Find all pre-requires
- r = pakfire_build_run_script(build, "find-prerequires", NULL,
- pakfire_build_send_scriptlet, &send_scriptlet_state, pakfire_build_process_deps, &ctx);
- if (r)
- goto ERROR;
+ // Fetch the scriptlet data
+ buffer.data = pakfire_scriptlet_get_data(scriptlet, &buffer.length);
+ if (!buffer.data)
+ return -errno;
-ERROR:
- return r;
+ // To execute the scriptlet we require /bin/bash
+ r = pakfire_package_add_dep(pkg, PAKFIRE_PKG_PREREQUIRES, "/bin/sh");
+ if (r < 0)
+ return r;
+
+ // We pass /dev/stdin as a script name to prevent bash from running in interactive mode
+ const char* argv[] = {
+ "bash", "--rpm-requires", "/dev/stdin", NULL,
+ };
+
+ return pakfire_jail_communicate(build->jail, argv, NULL, 0,
+ pakfire_pty_send_buffer, &buffer, pakfire_build_process_scriptlet_dep, &ctx);
}
static int pakfire_build_package_add_scriptlet(struct pakfire_build* build,
+++ /dev/null
-#!/bin/bash
-###############################################################################
-# #
-# Pakfire - The IPFire package management system #
-# Copyright (C) 2021 Pakfire development team #
-# #
-# This program is free software: you can redistribute it and/or modify #
-# it under the terms of the GNU General Public License as published by #
-# the Free Software Foundation, either version 3 of the License, or #
-# (at your option) any later version. #
-# #
-# This program is distributed in the hope that it will be useful, #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
-# GNU General Public License for more details. #
-# #
-# You should have received a copy of the GNU General Public License #
-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
-# #
-###############################################################################
-
-main() {
- # We require a shell
- echo "/bin/sh"
-
- local req
- while read -r req; do
- case "${req}" in
- /*)
- echo "${req}"
- ;;
- *)
- which "${req}" 2>/dev/null
- ;;
- esac
- done < <(bash --rpm-requires | sed -e "s/^.*(//;s/)$//" | sort -u)
-
- return 0
-}
-
-main "$@" || exit $?