#include <errno.h>
#include <stdlib.h>
+#include <sys/mman.h>
#include <sys/queue.h>
// libarchive
linter->result_data = data;
}
+static int pakfire_linter_read_file(
+ struct pakfire_linter* linter, struct pakfire_file* file, struct archive* a) {
+ int fd = -EBADF;
+ int r;
+
+ // Fetch path
+ const char* path = pakfire_file_get_path(file);
+
+ // Allocate a new buffer
+ fd = memfd_create(path, MFD_CLOEXEC);
+ if (fd < 0) {
+ CTX_ERROR(linter->ctx, "memfd_create() failed: %m\n");
+ r = -errno;
+ goto ERROR;
+ }
+
+ // Fetch file size
+ size_t size = pakfire_file_get_size(file);
+
+ // Tell the kernel how large the file would be
+ r = ftruncate(fd, size);
+ if (r < 0) {
+ CTX_ERROR(linter->ctx, "fallocate() failed: %m\n");
+ r = -errno;
+ goto ERROR;
+ }
+
+ // Read the payload into the file descriptor
+ r = archive_read_data_into_fd(a, fd);
+ if (r) {
+ CTX_ERROR(linter->ctx, "Could not read %s: %s\n", path, archive_error_string(a));
+ r = -errno;
+ goto ERROR;
+ }
+
+ // Check how much data we have read
+ off_t offset = lseek(fd, 0, SEEK_CUR);
+ if (offset < 0) {
+ CTX_ERROR(linter->ctx, "lseek() failed: %m\n");
+ r = -errno;
+ goto ERROR;
+ }
+
+ CTX_DEBUG(linter->ctx, "Read %jd byte(s)\n", offset);
+
+ // Check if we didn't read too little data
+ if ((size_t)offset < size) {
+ r = pakfire_linter_error(linter, "%s is actually smaller than %zu byte(s)", path, size);
+ if (r < 0)
+ goto ERROR;
+
+ // Check if we have not read more data
+ } else if ((size_t)offset > size) {
+ r = pakfire_linter_error(linter, "/%s is actually larger than %zu byte(s)", path, size);
+ if (r < 0)
+ goto ERROR;
+ }
+
+ // Rewind
+ offset = lseek(fd, 0, SEEK_SET);
+ if (offset) {
+ CTX_ERROR(linter->ctx, "Could not rewind: %m\n");
+ r = -errno;
+ goto ERROR;
+ }
+
+ return fd;
+
+ERROR:
+ if (fd >= 0)
+ close(fd);
+
+ return r;
+}
+
+static int pakfire_linter_payload(
+ struct pakfire_linter* linter, struct pakfire_file* file, struct archive* a) {
+ int fd = -EBADF;
+ int r;
+
+ // Fetch path
+ const char* path = pakfire_file_get_path(file);
+
+ CTX_DEBUG(linter->ctx, "Checking payload of %s\n", path);
+
+ // Read the file
+ fd = pakfire_linter_read_file(linter, file, a);
+ if (fd < 0) {
+ r = fd;
+ goto ERROR;
+ }
+
+ r = 0;
+
+ERROR:
+ if (fd >= 0)
+ close(fd);
+
+ return r;
+}
+
static int pakfire_linter_name(struct pakfire_linter* linter) {
int r;
return 0;
}
-static int pakfire_linter_payload(struct pakfire_archive* archive,
+static int pakfire_linter_file(struct pakfire_archive* archive,
struct archive* a, struct archive_entry* e, void* data) {
struct pakfire_linter* linter = data;
struct pakfire_file* file = NULL;
goto ERROR;
}
+ // Lint the payload for regular files
+ if (pakfire_file_has_payload(file)) {
+ r = pakfire_linter_payload(linter, file, a);
+ if (r < 0)
+ goto ERROR;
+ }
+
ERROR:
if (file)
pakfire_file_unref(file);
return r;
// Lint the payload
- r = pakfire_archive_walk_payload(linter->archive, pakfire_linter_payload, linter);
+ r = pakfire_archive_walk_payload(linter->archive, pakfire_linter_file, linter);
if (r < 0)
return r;