#include <pakfire/file.h>
#include <pakfire/hex.h>
#include <pakfire/logging.h>
+#include <pakfire/path.h>
#include <pakfire/string.h>
// libelf
// Otherwise we assume the binary being stripped
return 1;
}
+
+/*
+ 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
+
+int pakfire_elf_foreach_source_file(struct pakfire_elf* self,
+ pakfire_elf_foreach_source_file_callback callback, void* data) {
+ const char* filename = NULL;
+ char basename[PATH_MAX];
+ char path[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;
+ int r;
+
+ // Read DWARF information
+ dwarf = dwarf_begin(self->fd, 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(self->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(self->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);
+
+ // Copy to the stack
+ r = pakfire_string_set(path, filename);
+ if (r < 0)
+ goto ERROR;
+
+ // Normalize the path
+ r = pakfire_path_normalize(path);
+ if (r < 0)
+ goto ERROR;
+
+ // 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(self->ctx, "Found source file: %s\n", path);
+
+ // Call the callback
+ r = callback(self->ctx, self, path, data);
+ if (r)
+ goto ERROR;
+ }
+
+ offset = next_offset;
+ }
+
+ERROR:
+ if (dwarf)
+ dwarf_end(dwarf);
+
+ return r;
+}
#############################################################################*/
#include <errno.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
-// libdw
-#include <elfutils/libdw.h>
-#include <elfutils/libdwelf.h>
-
#include <pakfire/elf.h>
#include <pakfire/filelist.h>
#include <pakfire/hex.h>
// Filelist
struct pakfire_filelist* filelist;
+
+ // Source Directory
+ int sourcesfd;
};
+static int pakfire_stripper_open_sources(struct pakfire_stripper* stripper) {
+ // Open the source directory
+ stripper->sourcesfd = pakfire_openat(stripper->pakfire, BUILD_SRC_DIR, O_DIRECTORY|O_PATH);
+ if (stripper->sourcesfd < 0) {
+ switch (errno) {
+ case ENOENT:
+ break;
+
+ default:
+ ERROR(stripper->ctx, "Could not open %s: %m\n", BUILD_SRC_DIR);
+ return -errno;
+ }
+ }
+
+ return 0;
+}
+
int pakfire_stripper_create(struct pakfire_stripper** stripper,
struct pakfire* pakfire, struct pakfire_jail* jail, const char* path) {
struct pakfire_stripper* s = NULL;
// Initialize the reference counter
s->nrefs = 1;
+ // Initialize file descriptors
+ s->sourcesfd = -EBADF;
+
// Store the path
r = pakfire_string_set(s->path, path);
if (r < 0)
if (r < 0)
goto ERROR;
+ // Open the source directory
+ r = pakfire_stripper_open_sources(s);
+ if (r < 0)
+ goto ERROR;
+
// Return the pointer
*stripper = pakfire_stripper_ref(s);
}
static void pakfire_stripper_free(struct pakfire_stripper* stripper) {
+ if (stripper->sourcesfd)
+ close(stripper->sourcesfd);
if (stripper->filelist)
pakfire_filelist_unref(stripper->filelist);
if (stripper->pakfire)
}
static int pakfire_stripper_copy_source_file(
- struct pakfire_stripper* stripper, const char* filename) {
- char srcpath[PATH_MAX];
- char dstpath[PATH_MAX];
+ struct pakfire_ctx* ctx, struct pakfire_elf* elf, const char* filename, void* data) {
+ struct pakfire_stripper* stripper = data;
+ char path[PATH_MAX];
struct stat st = {};
- int r;
-
- FILE* src = NULL;
FILE* dst = NULL;
+ int fd = -EBADF;
+ int r;
- // Make the source path absolute
- r = pakfire_path(stripper->pakfire, srcpath, "%s", filename);
- if (r < 0)
- goto ERROR;
+ // If the source file is not in the right path, we ignore it
+ if (!pakfire_string_startswith(filename, DEBUG_SRC_DIR))
+ return 0;
// Remove the original source path
- r = pakfire_path_relative(dstpath, BUILD_SRC_DIR, filename);
- if (r < 0)
- goto ERROR;
-
- // Add the debug directory source path
- r = pakfire_path_append(dstpath, DEBUG_SRC_DIR, dstpath);
- if (r < 0)
- goto ERROR;
-
- // Add the buildroot
- r = pakfire_path_append(dstpath, stripper->path, dstpath);
+ r = pakfire_path_relative(path, DEBUG_SRC_DIR, filename);
if (r < 0)
goto ERROR;
// Open the source file
- src = fopen(srcpath, "r");
- if (!src) {
+ fd = openat(stripper->sourcesfd, path, O_RDONLY);
+ if (fd < 0) {
switch (errno) {
// If the source file does not exist, we cannot copy anything
- case ENOENT:
- goto ERROR;
+ //case ENOENT:
+ // goto ERROR;
default:
- ERROR(stripper->ctx, "Could not open %s: %m\n", filename);
+ ERROR(stripper->ctx, "Could not open %s: %m\n", path);
r = -errno;
goto ERROR;
}
}
// Stat the source file
- r = fstat(fileno(src), &st);
+ r = fstat(fd, &st);
if (r < 0) {
- ERROR(stripper->ctx, "Could not stat %s: %m\n", filename);
+ ERROR(stripper->ctx, "Could not stat %s: %m\n", path);
r = -errno;
goto ERROR;
}
+ // Add the buildroot
+ r = pakfire_path_append(path, stripper->path, filename);
+ if (r < 0)
+ goto ERROR;
+
// Create all directories
- r = pakfire_mkparentdir(dstpath, 0755);
+ r = pakfire_mkparentdir(path, 0755);
if (r < 0)
goto ERROR;
// Open the destination file
- dst = fopen(dstpath, "wx");
+ dst = fopen(path, "wx");
if (!dst) {
switch (errno) {
// If the file exist already, we are done
goto ERROR;
default:
- ERROR(stripper->ctx, "Could not open %s: %m\n", dstpath);
+ ERROR(stripper->ctx, "Could not open %s: %m\n", path);
r = -errno;
goto ERROR;
}
}
// Copy all content
- ssize_t bytes_written = sendfile(fileno(dst), fileno(src), 0, st.st_size);
+ ssize_t bytes_written = sendfile(fileno(dst), fd, 0, st.st_size);
if (bytes_written < st.st_size) {
ERROR(stripper->ctx, "Failed to copy source file %s: %m\n", filename);
r = -errno;
// Change permissions
r = fchmod(fileno(dst), 0444);
if (r < 0) {
- ERROR(stripper->ctx, "Could not change permissions of %s: %m\n", dstpath);
+ ERROR(stripper->ctx, "Could not change permissions of %s: %m\n", path);
r = -errno;
goto ERROR;
}
ERROR:
if (dst)
fclose(dst);
- if (src)
- fclose(src);
-
- return r;
-}
-
-/*
- 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_stripper* stripper, struct pakfire_file* file, int fd) {
- 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;
- int r;
-
- // Read DWARF information
- dwarf = dwarf_begin(fd, 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(stripper->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(stripper->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(stripper->ctx, "Found source file: %s\n", filename);
-
- // Copy the file
- r = pakfire_stripper_copy_source_file(stripper, filename);
- if (r < 0) {
- ERROR(stripper->ctx, "Could not copy source file %s: %s\n", filename, strerror(-r));
- goto ERROR;
- }
- }
-
- offset = next_offset;
- }
-
-ERROR:
- if (dwarf)
- dwarf_end(dwarf);
+ if (fd >= 0)
+ close(fd);
return r;
}
// The command returned an error
} else if (r > 0) {
- ERROR(stripper->ctx, "Could not extract debug sections from %s\n",
- pakfire_file_get_path(file));
+ ERROR(stripper->ctx, "Could not extract debug sections from %s: %d\n",
+ pakfire_file_get_path(file), r);
return -ENOTSUP;
}
struct pakfire_ctx* ctx, struct pakfire_file* file, void* data) {
struct pakfire_stripper* stripper = data;
struct pakfire_elf* elf = NULL;
- int fd = -EBADF;
int r;
- // Open the file
- fd = pakfire_file_open(file, 0);
- if (fd < 0) {
- r = -errno;
- goto ERROR;
- }
-
// Open the ELF file
r = pakfire_elf_open_file(&elf, stripper->ctx, file);
if (r < 0)
// Only strip if there is actually some debug information
if (!pakfire_elf_is_stripped(elf)) {
// Copy sources
- r = pakfire_stripper_copy_sources(stripper, file, fd);
+ r = pakfire_elf_foreach_source_file(elf,
+ pakfire_stripper_copy_source_file, stripper);
if (r < 0)
goto ERROR;
ERROR:
if (elf)
pakfire_elf_unref(elf);
- if (fd >= 0)
- close(fd);
return r;
}