return r;
}
+static int find_dependency(char** haystack, const char* needle) {
+ if (!needle) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (!haystack)
+ return 0;
+
+ for (char** element = haystack; *element; element++) {
+ if (strcmp(needle, *element) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int pakfire_build_find_dependencies(Pakfire pakfire,
+ PakfirePackage pkg, PakfireFilelist filelist, const char* buildroot) {
+ char** provides = NULL;
+ char** requires = NULL;
+ char path[PATH_MAX];
+
+ // Allocate path to write the filelist to
+ int r = pakfire_make_path(pakfire, path, "tmp/.pakfire-filelist.XXXXXX");
+ if (r < 0)
+ return 1;
+
+ // Create a temporary file
+ FILE* f = pakfire_mktemp(path);
+ if (!f)
+ goto ERROR;
+
+ // Write filelist to the temporary file
+ r = pakfire_filelist_export(filelist, f);
+ fclose(f);
+ if (r) {
+ ERROR(pakfire, "Could not export filelist: %s\n", strerror(errno));
+ goto ERROR;
+ }
+
+ const char* root = pakfire_get_path(pakfire);
+
+ // Pass buildroot and the filelist as arguments
+ const char* args[] = {
+ buildroot, pakfire_path_relpath(root, path), NULL
+ };
+
+ // Find all provides
+ r = pakfire_build_run_script(pakfire, "find-provides", args,
+ pakfire_execute_capture_stdout_to_array, &provides);
+ if (r) {
+ ERROR(pakfire, "find-provides returned with error %d\n", r);
+ goto ERROR;
+ }
+
+ // Find all requires
+ r = pakfire_build_run_script(pakfire, "find-requires", args,
+ pakfire_execute_capture_stdout_to_array, &requires);
+ if (r) {
+ ERROR(pakfire, "find-requires returned with error %d\n", r);
+ goto ERROR;
+ }
+
+ // Add all provides to the package
+ if (provides) {
+ for (char** element = provides; *element; element++) {
+ DEBUG(pakfire, "Adding provides: %s\n", *element);
+ pakfire_package_add_provides(pkg, *element);
+ }
+ }
+
+ // Add all requires to the package
+ if (requires) {
+ for (char** element = requires; *element; element++) {
+ // Skip adding this requirement if also provided by this package
+ if (find_dependency(provides, *element))
+ continue;
+
+ DEBUG(pakfire, "Adding requires: %s\n", *element);
+ pakfire_package_add_requires(pkg, *element);
+ }
+ }
+
+ // Success
+ r = 0;
+
+ERROR:
+ if (provides) {
+ for (char** element = provides; *element; element++)
+ free(*element);
+ free(provides);
+ }
+ if (requires) {
+ for (char** element = requires; *element; element++)
+ free(*element);
+ free(requires);
+ }
+ unlink(path);
+
+ return r;
+}
+
static int append_to_array(const char*** array, const char* s) {
unsigned int length = 0;
}
static int pakfire_build_package_add_files(Pakfire pakfire, PakfireParser makefile,
- const char* namespace, struct pakfire_packager* packager) {
+ const char* buildroot, const char* namespace, PakfirePackage pkg,
+ struct pakfire_packager* packager) {
PakfireFilelist filelist = NULL;
char path[PATH_MAX];
int r = 1;
if (!files)
return 0;
- // Fetch buildroot
- char* buildroot = pakfire_parser_get(makefile, NULL, "BUILDROOT");
- if (!buildroot)
- goto ERROR;
-
// Convert to absolute path
pakfire_make_path(pakfire, path, buildroot);
const size_t length = pakfire_filelist_size(filelist);
DEBUG(pakfire, "%zu file(s) found\n", length);
+ // Find dependencies
+ r = pakfire_build_find_dependencies(pakfire, pkg, filelist, buildroot);
+ if (r) {
+ ERROR(pakfire, "Finding dependencies failed: %s\n", strerror(errno));
+ goto ERROR;
+ }
+
// Add all files to the package
for (unsigned int i = 0; i < length; i++) {
PakfireFile file = pakfire_filelist_get(filelist, i);
free(includes);
if (excludes)
free(excludes);
- if (buildroot)
- free(buildroot);
return r;
}
static int pakfire_build_package(Pakfire pakfire, PakfireParser makefile,
- const char* namespace, const char* target) {
+ const char* buildroot, const char* namespace, const char* target) {
PakfireRepo repo = NULL;
PakfirePackage pkg = NULL;
struct pakfire_packager* packager = NULL;
goto ERROR;
// Add files
- r = pakfire_build_package_add_files(pakfire, makefile, namespace, packager);
+ r = pakfire_build_package_add_files(pakfire, makefile, buildroot, namespace,
+ pkg, packager);
if (r)
goto ERROR;
return r;
}
-static int pakfire_build_packages(Pakfire pakfire, PakfireParser makefile, const char* target) {
+static int pakfire_build_packages(Pakfire pakfire, PakfireParser makefile,
+ const char* buildroot, const char* target) {
DEBUG(pakfire, "Creating packages...");
int r = 1;
// Build packages in reverse order
for (int i = num_packages - 1; i >= 0; i--) {
- r = pakfire_build_package(pakfire, makefile, packages[i], target);
+ r = pakfire_build_package(pakfire, makefile, buildroot, packages[i], target);
if (r)
goto ERROR;
}
goto ERROR;
// Create the packages
- r = pakfire_build_packages(pakfire, makefile, target);
+ r = pakfire_build_packages(pakfire, makefile, buildroot_rel, target);
if (r) {
ERROR(pakfire, "Could not create packages: %s\n", strerror(errno));
goto ERROR;
return 0;
}
+int pakfire_execute_capture_stdout(Pakfire pakfire, void* data, int priority,
+ const char* line, size_t length) {
+ char** output = (char**)data;
+
+ // Append everything from stdout to a buffer
+ if (priority == LOG_INFO) {
+ int r = asprintf(output, "%s%s", (output && *output) ? *output : "", line);
+ if (r)
+ return 1;
+ }
+
+ // Send everything else to the default logger
+ return default_logging_callback(pakfire, NULL, priority, line, length);
+}
+
+int pakfire_execute_capture_stdout_to_array(Pakfire pakfire, void* data, int priority,
+ const char* line, size_t length) {
+ char*** array = (char***)data;
+
+ // Append everything from stdout to an array
+ if (priority == LOG_INFO) {
+ unsigned int length = 0;
+
+ // Determine the length of the existing array
+ if (*array) {
+ for (char** element = *array; *element; element++)
+ length++;
+ }
+
+ // Allocate space
+ *array = reallocarray(*array, length + 2, sizeof(**array));
+ if (!*array)
+ return 1;
+
+ // Append line and terminate the array
+ (*array)[length] = strdup(line);
+ (*array)[length + 1] = NULL;
+
+ return 0;
+ }
+
+ // Send everything else to the default logger
+ return default_logging_callback(pakfire, NULL, priority, line, length);
+}
+
static int find_environ(struct pakfire_execute* env, const char* key) {
if (!key) {
errno = EINVAL;
return 0;
}
+
+int pakfire_filelist_export(PakfireFilelist list, FILE* f) {
+ for (unsigned int i = 0; i < list->size; i++) {
+ PakfireFile file = list->elements[i];
+
+ const char* path = pakfire_file_get_path(file);
+ if (!path)
+ return 1;
+
+ int r = fprintf(f, "%s\n", path);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
#ifdef PAKFIRE_PRIVATE
+int pakfire_execute_capture_stdout(Pakfire pakfire, void* data, int priority,
+ const char* line, size_t length);
+int pakfire_execute_capture_stdout_to_array(Pakfire pakfire, void* data, int priority,
+ const char* line, size_t length);
int pakfire_execute_ldconfig(Pakfire pakfire);
#endif
const char** includes, const char** excludes);
int pakfire_filelist_contains(PakfireFilelist list, const char* pattern);
+int pakfire_filelist_export(PakfireFilelist list, FILE* f);
#endif
#!/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/>. #
+# #
+###############################################################################
-# Include functions.
-BASEDIR=$(dirname ${0})
-source ${BASEDIR}/find-common
-
-BUILDROOT=${1}
-FILELIST=${2}
-
-binary_files=
-perl_files=
-pkgconfig_files=
-
-# Walk through all file files and see what we have got here.
-while read file; do
- case "${file}" in
- */usr/lib/debug/*|*/usr/src/debug/*)
- # Skip all debuginfo files.
- continue
- ;;
- */usr/lib*/python*/*.so*)
- # Do not show python shared objects in provides list.
- ;;
- */usr/lib*/gconv/*)
- # Skip gconv files.
- continue
- ;;
- *.so*)
- # Skip symlinks for performance reasons.
- [ -L "${file}" ] && continue
-
- file_is_elf ${file} >/dev/null 2>&1 && \
- binary_files="${binary_files} ${file}"
- ;;
- *.pm)
- # This file is a perl module. We check them later.
- perl_files="${perl_files} ${file}"
- ;;
- *.pc)
- pkgconfig_files="${pkgconfig_files} ${file}"
- ;;
- esac
-done < ${FILELIST}
-
-# Search for SONAMEs in all binary files.
-for file in ${binary_files}; do
- soname=$(file_get_soname ${file})
-
- # If the files does not have a SONAME, we will
- # simply use the basename.
+error() {
+ echo "${0#/}: $@" >&2
+}
+
+FILTER_WEAK_PROVIDES='BEGIN { START=0; }
+ /Version definitions:/ { START=1; }
+ /^[0-9]/ && (START==1) { print $4; }
+ /^$/ { START=0; }'
+
+pkgconfig_provides() {
+ local file="${1}"
+
+ local n r v
+ while read -r n r v; do
+ echo "pkgconfig(${n}) ${r} ${v}"
+ done < <(pkg-config --print-provides "${file}" 2>/dev/null)
+
+ return 0
+}
+
+shared_object_provides() {
+ local file="${1}"
+
+ # Get SONAME
+ local soname="$(objdump -p "${file}" 2>/dev/null | awk '/SONAME/ { print $2 }')"
+
+ # If the files does not have a SONAME, we will simply use the basename
if [ -z "${soname}" ]; then
- if [ -L ${file} ]; then
- continue
- fi
- soname=$(basename ${file})
+ soname="$(basename "${file}")"
fi
- if file_is_64bit ${file}; then
- is_64=true
- echo "${soname}${mark64}"
+ local suffix
+
+ # Is this a 64 bit file?
+ if file -L "${file}" 2>/dev/null | grep -q "ELF 64-bit"; then
+ suffix="(64bit)"
+
+ echo "${soname}()${suffix}"
else
- is_64=false
echo "${soname}"
fi
- # Find weak symbol provides.
- objdump -p ${file} 2>/dev/null | awk '
- BEGIN { START=0 ; }
- /Version definitions:/ { START=1; }
- /^[0-9]/ && (START==1) { print $4; }
- /^$/ { START=0; }' | \
- while read symbol ; do
- echo "${soname}(${symbol})$(${is_64} && echo ${mark64} | sed 's/()//')"
- done
-done
-
-# Search for perl provides.
-if [ -n "${perl_files}" ] && [ -x /usr/bin/perl ]; then
- perl ${BASEDIR}/perl.prov ${perl_files} | sort -u
-fi
-
-# pkg-config files.
-pkgconfig=$(which pkg-config)
-
-if [ -n "${pkgconfig}" -a -x "${pkgconfig}" ]; then
- for file in ${pkgconfig_files}; do
- # Query the dependencies of the package.
- ${pkgconfig} --print-provides "${file}" 2> /dev/null | while read n r v ; do
- # We have a dependency. Make a note that we need the pkgconfig
- # tool for this package.
- echo "pkgconfig(${n}) ${r} ${v}"
- done
- done | sort -u
-fi
-
-exit 0
+ # Find weak symbol provides
+ while read -r symbol; do
+ echo "${soname}(${symbol})${suffix}"
+ done < <(objdump -p "${file}" 2>/dev/null | awk "${FILTER_WEAK_PROVIDES}")
+
+ return 0
+}
+
+main() {
+ local buildroot="${1}"
+ local filelist="${2}"
+
+ # Check if BUILDROOT exists
+ if [ ! -d "${buildroot}" ]; then
+ error "BUILDROOT does not exist"
+ return 1
+ fi
+
+ # Check if the filelist exists
+ if [ ! -r "${filelist}" ]; then
+ error "Cannot read filelist '${filelist}'"
+ return 1
+ fi
+
+ local file
+ while read -r file; do
+ # Filter out what we don't need
+ case "${file}" in
+ # Debug files
+ /usr/lib/debug/*|/usr/src/debug/*)
+ continue
+ ;;
+
+ # Skip shared objects in Python directories
+ /usr/lib*/python*/*.so*)
+ continue
+ ;;
+
+ # Skip gconv
+ /usr/lib*/gconv/*)
+ continue
+ ;;
+ esac
+
+ # Make the full path
+ local path="${buildroot}${file}"
+
+ # Process special files
+ case "${file}" in
+ # pkg-config
+ *.pc)
+ # Query provides of the package
+ pkgconfig_provides "${path}"
+ ;;
+
+ # Perl
+ *.pm)
+ # TODO
+ ;;
+
+ # Shared objects
+ *.so.*)
+ # Skip symlinks
+ if [ -L "${path}" ]; then
+ continue
+ fi
+
+ shared_object_provides "${path}"
+ ;;
+ esac
+ done < "${filelist}" | sort -u
+
+ return 0
+}
+
+main "$@" || exit $?
#!/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/>. #
+# #
+###############################################################################
+
+error() {
+ echo "${0#/}: $@" >&2
+}
+
+pkgconfig_requires() {
+ local file="${1}"
+
+ # Require the pkgconfig package
+ echo "pkgconfig"
+
+ local n r v
+ while read -r n r v; do
+ echo "pkgconfig(${n}) ${r} ${v}"
+ done < <(pkg-config --print-requires --print-requires-private "${file}" 2>/dev/null)
+
+ return 0
+}
+
+is_file_on_filelist() {
+ local file="${1}"
+ local filelist="${2}"
+
+ local line
+ while read -r line; do
+ if [ "${file}" = "${line}" ]; then
+ return 0
+ fi
+ done < "${filelist}"
-# Include functions.
-BASEDIR=$(dirname ${0})
-source ${BASEDIR}/find-common
-
-# BUILDROOT is the first argument.
-BUILDROOT=${1}
-FILELIST=${2}
-
-# Determine libdir.
-if [ "$(uname -m)" = "x86_64" ]; then
- libdir=/usr/lib64
-else
- libdir=/usr/lib
-fi
-
-binary_files=
-perl_files=
-script_files=
-pkgconfig_files=
-
-# Walk through all file files and see what we have got here.
-while read file; do
- case "${file}" in
- */usr/lib/debug/*|*/usr/src/debug/*)
- # Skip all debuginfo files.
- continue
- ;;
- */usr/lib*/gconv/*)
- # Skip all gconv files.
- continue
- ;;
- *.ko)
- # Skip all kernel modules because they do not
- # require anything at all.
- continue
- ;;
- *.pc)
- # Find all pkg-config files.
- pkgconfig_files="${pkgconfig_files} ${file}"
- continue
- ;;
- *.pm)
- # Find all perl modules.
- if [ -r "${file}" ]; then
- perl_files="${perl_files} ${file}"
- continue
- fi
- ;;
+ # Nothing found
+ return 1
+}
- # Python
- */usr/lib*/python*/*)
- # Sort out all python files.
- # Directories are processed bewlow.
- ;;
- */usr/lib/python*|*/usr/lib64/python*)
- # This will only get the python directory.
- file=$(basename ${file})
+find_elf_interpreter() {
+ local file="${1}"
+ local filelist="${2}"
- # Strip the python version from the string.
- python_version="${file#python}"
+ local interpreter="$(readelf -l "${file}" 2>/dev/null | \
+ grep "program interpreter" | tr -d "]" | awk '{ print $NF }')"
- if [ -n "${python_version}" ]; then
- echo "python-abi = ${python_version}"
- fi
- continue
- ;;
- esac
+ # Only add interpreter if it isn't part of this package
+ if [ -n "${interpreter}" ] && ! is_file_on_filelist "${interpreter}" "${filelist}"; then
+ echo "${interpreter}"
+ fi
- # Unresolved symlinks.
- if [ -L "${file}" ]; then
- # Get destination.
- link=$(readlink -m ${file})
+ return 0
+}
- # If destination does not exist, make
- # a dependency for it.
- if ! [ -e "${link}" ]; then
- echo "${link#${BUILDROOT}}"
- fi
+find_weak_symbols() {
+ local file="${1}"
- # Don't search for anything else, because
- # symlinks do not require anything but the target file.
- continue
- fi
+ local suffix
- # Search for all binary files.
- if file_is_elf ${file}; then
- binary_files="${binary_files} ${file}"
- continue
+ # Is this a 64 bit file?
+ if file -L "${file}" 2>/dev/null | grep -q "ELF 64-bit"; then
+ suffix="(64bit)"
fi
- # Search for script files.
- if file_is_script ${file}; then
- script_files="${script_files} ${file}"
+ # List all weak symbol versions
+ objdump -p "${file}" 2>/dev/null | \
+ awk \
+ 'BEGIN { START=0; LIBNAME=""; }
+ /^$/ { START=0; }
+ /^Dynamic Section:$/ { START=1; }
+ (START==1) && /NEEDED/ {
+ if ("'${suffix}'" != "") {
+ sub(/$/, "()'${suffix}'", $2);
+ }
+ print $2;
+ }
+ (START==2) && /^[A-Za-z]/ { START=3; }
+ /^Version References:$/ { START=2; }
+ (START==2) && /required from/ {
+ sub(/:/, "", $3);
+ LIBNAME=$3;
+ }
+ (START==2) && (LIBNAME!="") && ($4!="") {
+ print LIBNAME "(" $4 ")'${suffix}'";
+ }'
+
+ return 0
+}
+
+find_script_interpreter() {
+ local file="${1}"
+
+ local first_line="$(grep -q "^#!" "${file}" && head -n1 "${file}")"
+
+ # Skip files that are not scripts
+ if [ "${first_line:0:2}" != "#!" ]; then
continue
fi
-done < ${FILELIST}
-# Process script files.
-interpreters=
-for file in ${script_files}; do
- [ -r ${file} -a -x ${file} ] || continue
+ local interpreter="${first_line:2}"
- interp=$(file_get_script_interpreter ${file})
- interpreters="${interpreters} ${interp}"
-
- # Collect all perl files.
- case "${interp}" in
+ case "${interpreter}" in
*/perl)
- perl_files="${perl_files} ${file}"
+ # XXX process perl files here
;;
esac
-done
-
-# Output the list of needed interpreters.
-[ -n "${interpreters}" ] && { echo ${interpreters} | tr '[:blank:]' \\n | sort -u ; }
-
-# Search for binary interpreters.
-for file in ${binary_files}; do
- # Get the interpreter.
- interp=$(file_get_elf_interpreter ${file})
-
- # Skip the interpreter if it is provided by this
- # package.
- [ -e "${BUILDROOT}${interp}" ] && continue
-
- # Print the interpreter.
- echo "${interp}"
-done | sort -u
-
-# Weak symbol versions (from glibc).
-[ -n "${mark64}" ] && mark64="(64bit)"
-for file in ${binary_files}; do
- [ -r ${file} ] || continue
-
- lib64=$(if file_is_64bit ${file}; then echo "${mark64}"; fi)
- objdump -p ${file} 2>/dev/null | awk 'BEGIN { START=0; LIBNAME=""; }
- /^$/ { START=0; }
- /^Dynamic Section:$/ { START=1; }
- (START==1) && /NEEDED/ {
- if ("'${lib64}'" != "") {
- sub(/$/, "()'${lib64}'", $2);
- }
- print $2;
- }
- (START==2) && /^[A-Za-z]/ { START=3; }
- /^Version References:$/ { START=2; }
- (START==2) && /required from/ {
- sub(/:/, "", $3);
- LIBNAME=$3;
- }
- (START==2) && (LIBNAME!="") && ($4!="") {
- print LIBNAME "(" $4 ")'${lib64}'";
- }'
-done | sort -u
-
-# Search for perl requires.
-if [ -n "${perl_files}" ] && [ -x /usr/bin/perl ]; then
- perl ${BASEDIR}/perl.req ${perl_files} | sort -u
-fi
-
-# Search for pkg-config requires.
-pkgconfig=$(which pkg-config)
-if [ -n "${pkgconfig}" -a -x "${pkgconfig}" ]; then
- for file in ${pkgconfig_files}; do
- # The dependency for the pkgconfig package itself.
- echo "pkgconfig"
-
- ${pkgconfig} --print-requires --print-requires-private "${file}" 2> /dev/null | while read n r v ; do
- echo "pkgconfig(${n})" "${r}" "${v}"
- done
- done
-fi
-
-exit 0
+
+ echo "${interpreter}"
+ return 0
+}
+
+set -x
+
+main() {
+ local buildroot="${1}"
+ local filelist="${2}"
+
+ # Check if BUILDROOT exists
+ if [ ! -d "${buildroot}" ]; then
+ error "BUILDROOT does not exist"
+ return 1
+ fi
+
+ # Check if the filelist exists
+ if [ ! -r "${filelist}" ]; then
+ error "Cannot read filelist '${filelist}'"
+ return 1
+ fi
+
+ local file
+ while read -r file; do
+ # Filter out what we don't need
+ case "${file}" in
+ # Debug files
+ /usr/lib/debug/*|/usr/src/debug/*)
+ continue
+ ;;
+
+ # Skip gconv
+ /usr/lib*/gconv/*)
+ continue
+ ;;
+
+ # Skip all kernel modules
+ *.ko)
+ continue
+ ;;
+ esac
+
+ # Make the full path
+ local path="${buildroot}${file}"
+
+ # Process unresolvable symlinks
+ if [ -L "${path}" ]; then
+ local link="$(readlink -m "${path}")"
+
+ # Make link relative to buildroot
+ link="${link#${BUILDROOT}}"
+
+ # If the destination is not in this package, we create a dependency for it
+ if ! is_file_on_filelist "${link}" "${filelist}"; then
+ echo "${link}"
+ fi
+
+ # We do not process symlinks any further
+ continue
+ fi
+
+ # Process special files
+ case "${file}" in
+ # pkg-config
+ *.pc)
+ # Query requires of the package
+ pkgconfig_requires "${path}"
+ ;;
+
+ # Perl
+ *.pm)
+ # XXX TODO
+ continue
+ ;;
+
+ # Python
+ /usr/lib*/python*/*)
+ # Fall through for all python files
+ ;;
+
+ # Catch the module directory
+ /usr/lib*/python*)
+ # This will only get the python directory
+ file="$(basename "${file}")"
+
+ # Strip the python version from the string
+ python_version="${file#python}"
+
+ if [ -n "${python_version}" ]; then
+ echo "python-abi = ${python_version}"
+ fi
+ ;;
+ esac
+
+ # Is this an ELF file?
+ if file -L "${path}" 2>/dev/null | grep -q "ELF"; then
+ # Find the ELF interpreter
+ if ! find_elf_interpreter "${path}" "${filelist}"; then
+ return 1
+ fi
+
+ # Find weak symbols
+ if ! find_weak_symbols "${path}"; then
+ return 1
+ fi
+
+ continue
+ fi
+
+ # Add script interpreters
+ if ! find_script_interpreter "${path}"; then
+ return 1
+ fi
+ done < "${filelist}" | sort -u
+
+ return 0
+}
+
+main "$@" || exit $?