--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2024 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/>. #
+# #
+#############################################################################*/
+
+#ifndef PAKFIRE_STRIPPER_H
+#define PAKFIRE_STRIPPER_H
+
+#ifdef PAKFIRE_PRIVATE
+
+#define BUILD_SRC_DIR "/build/source"
+#define DEBUG_SRC_DIR "/usr/src/debug"
+
+struct pakfire_stripper;
+
+int pakfire_stripper_create(struct pakfire_stripper** stripper,
+ struct pakfire* pakfire, const char* path);
+
+struct pakfire_stripper* pakfire_stripper_ref(struct pakfire_stripper* stripper);
+struct pakfire_stripper* pakfire_stripper_unref(struct pakfire_stripper* stripper);
+
+int pakfire_stripper_run(struct pakfire_stripper* stripper);
+
+#endif /* PAKFIRE_PRIVATE */
+#endif /* PAKFIRE_STRIPPER_H */
--- /dev/null
+/*#############################################################################
+# #
+# Pakfire - The IPFire package management system #
+# Copyright (C) 2023 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 <errno.h>
+#include <stdlib.h>
+
+// libdw
+#include <elfutils/libdw.h>
+
+#include <pakfire/filelist.h>
+#include <pakfire/pakfire.h>
+#include <pakfire/path.h>
+#include <pakfire/string.h>
+#include <pakfire/stripper.h>
+
+struct pakfire_stripper {
+ struct pakfire_ctx* ctx;
+ int nrefs;
+
+ // Pakfire
+ struct pakfire* pakfire;
+
+ // Path
+ char path[PATH_MAX];
+
+ // Filelist
+ struct pakfire_filelist* filelist;
+};
+
+int pakfire_stripper_create(struct pakfire_stripper** stripper,
+ struct pakfire* pakfire, const char* path) {
+ struct pakfire_stripper* s = NULL;
+ int r;
+
+ // Allocate a new object
+ s = calloc(1, sizeof(*s));
+ if (!s)
+ return -errno;
+
+ // Store a reference to the context
+ s->ctx = pakfire_ctx(pakfire);
+
+ // Store a reference to Pakfire
+ s->pakfire = pakfire_ref(pakfire);
+
+ // Initialize the reference counter
+ s->nrefs = 1;
+
+ // Store the path
+ r = pakfire_string_set(s->path, path);
+ if (r < 0)
+ goto ERROR;
+
+ // Create a filelist
+ r = pakfire_filelist_create(&s->filelist, s->pakfire);
+ if (r < 0)
+ goto ERROR;
+
+ // Return the pointer
+ *stripper = pakfire_stripper_ref(s);
+
+ERROR:
+ if (s)
+ pakfire_stripper_unref(s);
+
+ return r;
+}
+
+static void pakfire_stripper_free(struct pakfire_stripper* stripper) {
+ if (stripper->filelist)
+ pakfire_filelist_unref(stripper->filelist);
+ if (stripper->pakfire)
+ pakfire_unref(stripper->pakfire);
+ if (stripper->ctx)
+ pakfire_ctx_unref(stripper->ctx);
+ free(stripper);
+}
+
+struct pakfire_stripper* pakfire_stripper_ref(struct pakfire_stripper* stripper) {
+ ++stripper->nrefs;
+
+ return stripper;
+}
+
+struct pakfire_stripper* pakfire_stripper_unref(struct pakfire_stripper* stripper) {
+ if (--stripper->nrefs > 0)
+ return stripper;
+
+ pakfire_stripper_free(stripper);
+ return NULL;
+}
+
+static int pakfire_stripper_find_elf(
+ struct pakfire_ctx* ctx, struct pakfire_file* file, void* data) {
+ struct pakfire_stripper* stripper = data;
+ int r;
+
+ // Add ELF files to the filelist
+ if (pakfire_file_matches_class(file, PAKFIRE_FILE_ELF)) {
+ r = pakfire_filelist_add(stripper->filelist, file);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+/*
+ Scan all files in path and identify ELF files
+*/
+static int pakfire_stripper_scan(struct pakfire_stripper* stripper) {
+ struct pakfire_filelist* filelist = NULL;
+ int r;
+
+ // Create a new filelist
+ r = pakfire_filelist_create(&filelist, stripper->pakfire);
+ if (r < 0)
+ goto ERROR;
+
+ // Scan path for all files
+ r = pakfire_filelist_scan(filelist, stripper->path, NULL, NULL, 0);
+ if (r < 0)
+ goto ERROR;
+
+ // Walk through all files to find ELF files
+ r = pakfire_filelist_walk(filelist, pakfire_stripper_find_elf, stripper, 0);
+ if (r < 0)
+ goto ERROR;
+
+ERROR:
+ if (filelist)
+ pakfire_filelist_unref(filelist);
+
+ return r;
+}
+
+static int pakfire_stripper_copy_source_file(
+ struct pakfire_stripper* stripper, const char* filename) {
+ printf("FILENAME = %s\n", filename);
+
+ return 0;
+}
+
+/*
+ libdw does not seem to export the error codes in their header files,
+ although there is a function to retrieve them...
+*/
+#ifndef DWARF_E_NO_DWARF
+#define DWARF_E_NO_DWARF 6
+#endif
+
+static int pakfire_stripper_copy_sources(
+ struct pakfire_ctx* ctx, struct pakfire_file* file, void* data) {
+ struct pakfire_stripper* stripper = data;
+ const char* filename = NULL;
+ char basename[PATH_MAX];
+ Dwarf* dwarf = NULL;
+ Dwarf_Files* files = NULL;
+ Dwarf_Die* die = NULL;
+ Dwarf_Off offset = 0;
+ Dwarf_Off next_offset;
+ size_t cu_header_length;
+ Dwarf_Die die_mem;
+ size_t count;
+ FILE* f = NULL;
+ int r;
+
+ // Open the file
+ f = pakfire_file_open(file);
+ if (!f) {
+ r = -errno;
+ goto ERROR;
+ }
+
+ // Read DWARF information
+ dwarf = dwarf_begin(fileno(f), DWARF_C_READ);
+ if (!dwarf) {
+ switch (dwarf_errno()) {
+ // If we don't have any DWARF information there is nothing to do
+ case DWARF_E_NO_DWARF:
+ r = 0;
+ goto ERROR;
+
+ default:
+ ERROR(ctx, "Could not initialize DWARF context: %s\n", dwarf_errmsg(-1));
+ r = -errno;
+ goto ERROR;
+ }
+ }
+
+ for (;;) {
+ // Fetch the next compilation unit
+ r = dwarf_nextcu(dwarf, offset, &next_offset, &cu_header_length, NULL, NULL, NULL);
+ if (r < 0)
+ goto ERROR;
+
+ // Fetch the Debug Information Entry
+ die = dwarf_offdie(dwarf, offset + cu_header_length, &die_mem);
+ if (!die)
+ break;
+
+ // Fetch the source files
+ r = dwarf_getsrcfiles(die, &files, &count);
+ if (r < 0) {
+ ERROR(ctx, "Could not fetch the source files: %s\n", dwarf_errmsg(-1));
+ r = -errno;
+ goto ERROR;
+ }
+
+ // Iterate over all files...
+ for (unsigned int i = 0; i < count; i++) {
+ // Fetch the filename
+ filename = dwarf_filesrc(files, i, NULL, NULL);
+
+ // If the source file is not in the right path, we ignore it
+ if (!pakfire_string_startswith(filename, BUILD_SRC_DIR))
+ continue;
+
+ // Determine the basename
+ r = pakfire_path_basename(basename, filename);
+ if (r < 0)
+ goto ERROR;
+
+ // Ignore things like <artificial> or <built-in>
+ if (pakfire_string_startswith(basename, "<") && pakfire_string_endswith(basename, ">"))
+ continue;
+
+ DEBUG(ctx, "Found source file: %s\n", filename);
+
+ // Copy the file
+ r = pakfire_stripper_copy_source_file(stripper, filename);
+ if (r < 0) {
+ ERROR(ctx, "Could not copy source file %s: %s\n", filename, strerror(-r));
+ goto ERROR;
+ }
+ }
+
+ offset = next_offset;
+ }
+
+ERROR:
+ if (f)
+ fclose(f);
+ if (dwarf)
+ dwarf_end(dwarf);
+
+ return r;
+}
+
+int pakfire_stripper_run(struct pakfire_stripper* stripper) {
+ int r;
+
+ // Scan for all ELF files in path
+ r = pakfire_stripper_scan(stripper);
+ if (r < 0)
+ return r;
+
+ // If the filelist is empty, there is nothing to do
+ if (pakfire_filelist_is_empty(stripper->filelist))
+ return 0;
+
+ // Copy sources
+ r = pakfire_filelist_walk(stripper->filelist, pakfire_stripper_copy_sources, stripper, 0);
+ if (r < 0)
+ return r;
+
+ return 0;
+}