#include <stdlib.h>
#include <string.h>
#include <sys/capability.h>
+#include <sys/mman.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/types.h>
return f;
}
-int pakfire_file_payload_matches(struct pakfire_file* file,
- const void* needle, const size_t length) {
- char buffer[1024 * 1024];
- FILE* f = NULL;
- void* p = NULL;
+/*
+ Opens the file and returns a mapping of the payload in memory
+*/
+static int pakfire_file_mmap(struct pakfire_file* file, char** data, size_t* length) {
+ struct stat st = {};
+ char* buffer = NULL;
+ int fd = -EBADF;
+ int r;
+
+ // Open the file
+ fd = r = pakfire_file_open(file, O_RDONLY);
+ if (fd < 0)
+ goto ERROR;
+
+ // Stat the file
+ r = fstat(fd, &st);
+ if (r < 0) {
+ ERROR(file->ctx, "Could not stat %s: %m\n", pakfire_file_get_path(file));
+ r = -errno;
+ goto ERROR;
+ }
+
+ // Map the data
+ buffer = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (buffer == MAP_FAILED) {
+ ERROR(file->ctx, "Could not map %s: %m\n", pakfire_file_get_path(file));
+ r = -errno;
+ goto ERROR;
+ }
+
+ // Return the values
+ *data = buffer;
+ *length = st.st_size;
+
+ERROR:
+ if (fd >= 0)
+ close(fd);
+
+ return r;
+}
+
+int pakfire_file_contains(struct pakfire_file* file, const char* needle, ssize_t length) {
+ char* haystack = NULL;
+ size_t l = 0;
+ int pos;
int r;
+ // Check inputs
+ if (!needle)
+ return -EINVAL;
+
const mode_t mode = pakfire_file_get_mode(file);
// Only run for regular files
if (!S_ISREG(mode))
return 0;
- const size_t size = pakfire_file_get_size(file);
-
- // Skip empty files
- if (!size)
- return 0;
-
- // Open the file
- f = pakfire_file_fopen(file, "r");
- if (!f) {
- r = 1;
+ // Map the file into memory
+ r = pakfire_file_mmap(file, &haystack, &l);
+ if (r < 0)
goto ERROR;
- }
- while (!feof(f)) {
- size_t bytes_read = fread(buffer, 1, sizeof(buffer), f);
+ // Perform the search
+ pos = pakfire_string_search(haystack, l, needle, length);
- // Raise any reading errors
- if (ferror(f)) {
- r = 1;
- goto ERROR;
- }
+ // No match found
+ if (pos == -1)
+ r = 0;
- // Search for the needle
- p = memmem(buffer, bytes_read, needle, length);
- if (p) {
- r = 1;
- goto ERROR;
- }
- }
+ // Match found
+ else if (pos >= 0)
+ r = pos;
- // No match
- r = 0;
+ // Error
+ else if (pos < 0)
+ r = pos;
ERROR:
- if (f)
- fclose(f);
+ if (haystack)
+ munmap(haystack, l);
return r;
}
int pakfire_file_open(struct pakfire_file* file, int flags);
FILE* pakfire_file_fopen(struct pakfire_file* file, const char* mode);
-int pakfire_file_payload_matches(struct pakfire_file* file,
- const void* needle, const size_t length);
+int pakfire_file_contains(struct pakfire_file* file, const char* needle, ssize_t length);
int pakfire_file_compute_digests(struct pakfire_file* file, const int types);