struct pakfire* pakfire;
int nrefs;
- // The relative path
- char path[PATH_MAX];
-
- // The absolute path in the file system
- char abspath[PATH_MAX];
-
- // File Ownership
- char uname[LOGIN_NAME_MAX];
- char gname[LOGIN_NAME_MAX];
-
- // Stat
- struct stat st;
+ // Use the libarchive entry to store common attributes
+ struct archive_entry* entry;
// Capabilities
cap_t caps;
// Flags
int flags;
- // Link destinations
- char hardlink[PATH_MAX];
- char symlink[PATH_MAX];
-
// Digests
struct pakfire_digests digests;
#ifdef ENABLE_DEBUG
char* text = cap_to_text(file->caps, NULL);
if (text) {
- DEBUG(file->pakfire, "%s: Capabilities %s\n", file->path, text);
+ DEBUG(file->pakfire, "%s: Capabilities %s\n", pakfire_file_get_path(file), text);
cap_free(text);
}
#endif
static int pakfire_file_from_archive_entry(struct pakfire_file* file, struct archive_entry* entry) {
char* buffer = NULL;
- const char* path = NULL;
const char* attr = NULL;
const void* value = NULL;
size_t size = 0;
int r = 0;
- // Set abspath
- path = archive_entry_sourcepath(entry);
- if (path) {
- // Make path absolute
- path = pakfire_path_abspath(path);
- if (!path) {
- r = 1;
- goto ERROR;
- }
-
- // Set
- r = pakfire_file_set_abspath(file, path);
- if (r) {
- ERROR(file->pakfire, "Could not set abspath: %m\n");
- goto ERROR;
- }
- }
-
- // Set path
- path = archive_entry_pathname(entry);
- if (path) {
- r = pakfire_file_set_path(file, path);
- if (r) {
- ERROR(file->pakfire, "Could not set path: %m\n");
- goto ERROR;
- }
- }
+ // Remove the existing entry
+ if (file->entry)
+ archive_entry_free(file->entry);
- // Set links
- pakfire_file_set_hardlink(file, archive_entry_hardlink(entry));
- pakfire_file_set_symlink(file, archive_entry_symlink(entry));
-
- pakfire_file_set_nlink(file, archive_entry_nlink(entry));
- pakfire_file_set_inode(file, archive_entry_ino64(entry));
- pakfire_file_set_dev(file, archive_entry_dev(entry));
-
- // Set size
- pakfire_file_set_size(file, archive_entry_size(entry));
-
- // Set mode
- pakfire_file_set_mode(file, archive_entry_mode(entry));
-
- // Set dev type
- if (archive_entry_dev_is_set(entry))
- pakfire_file_set_dev(file, archive_entry_dev(entry));
-
- // Set uname
- pakfire_file_set_uname(file, archive_entry_uname(entry));
-
- // Set gname
- pakfire_file_set_gname(file, archive_entry_gname(entry));
-
- // Set times
- pakfire_file_set_ctime(file, archive_entry_ctime(entry));
- pakfire_file_set_mtime(file, archive_entry_mtime(entry));
+ // Clone the given entry
+ file->entry = archive_entry_clone(entry);
+ if (!file->entry)
+ return -ENOMEM;
// Reset iterating over extended attributes
- archive_entry_xattr_reset(entry);
+ archive_entry_xattr_reset(file->entry);
// Read any extended attributes
while (archive_entry_xattr_next(entry, &attr, &value, &size) == ARCHIVE_OK) {
// Initialize reference counter
f->nrefs = 1;
+ // Create a new archive entry
+ f->entry = archive_entry_new();
+ if (!f->entry)
+ return -ENOMEM;
+
*file = f;
return 0;
}
-int pakfire_file_create_from_path(struct pakfire_file** file,
- struct pakfire* pakfire, const char* path) {
- struct archive* reader = NULL;
- struct archive_entry* entry = NULL;
- int r = 1;
-
- // Allocate a reader
- reader = pakfire_make_archive_disk_reader(pakfire, 0);
- if (!reader)
- goto ERROR;
+int pakfire_file_read(struct pakfire_file* file, struct archive* reader, const char* path) {
+ int r;
- // Allocate a new archive entry
- entry = archive_entry_new();
- if (!entry)
- goto ERROR;
+ // Check inputs
+ if (!reader || !path)
+ return -EINVAL;
- // Set source path
- archive_entry_copy_sourcepath(entry, path);
+ // Set abspath
+ r = pakfire_file_set_abspath(file, path);
+ if (r)
+ return r;
- // Read all file attributes from disk
- r = archive_read_disk_entry_from_file(reader, entry, -1, NULL);
+ // Read everything
+ r = archive_read_disk_entry_from_file(reader, file->entry, -1, NULL);
if (r) {
- ERROR(pakfire, "Could not read from %s: %m\n", path);
- goto ERROR;
+ ERROR(file->pakfire, "Could not read %s: %s\n", path, archive_error_string(reader));
+ return 1;
}
- // Create file
- r = pakfire_file_create_from_archive_entry(file, pakfire, entry);
- if (r)
- goto ERROR;
-
-ERROR:
- if (r)
- ERROR(pakfire, "Could not create file from path %s: %m\n", path);
- if (entry)
- archive_entry_free(entry);
- if (reader)
- archive_read_free(reader);
-
- return r;
+ return 0;
}
int pakfire_file_create_from_archive_entry(struct pakfire_file** file, struct pakfire* pakfire,
}
struct archive_entry* pakfire_file_archive_entry(struct pakfire_file* file, int digest_types) {
+ struct archive_entry* entry = NULL;
struct vfs_cap_data cap_data = {};
- const char* path = NULL;
int r;
- struct archive_entry* entry = archive_entry_new();
- if (!entry) {
- ERROR(file->pakfire, "Could not allocate archive entry: %m\n");
+ // Clone the entry
+ entry = archive_entry_clone(file->entry);
+ if (!entry)
return NULL;
- }
-
- // Set source path
- archive_entry_copy_sourcepath(entry, file->abspath);
-
- // Set path
- path = pakfire_file_get_path(file);
- if (path && *path == '/') {
- archive_entry_copy_pathname(entry, path + 1);
- }
-
- // Set links
- if (*file->hardlink)
- archive_entry_set_hardlink(entry, file->hardlink);
- if (*file->symlink)
- archive_entry_set_symlink(entry, file->symlink);
-
- archive_entry_set_nlink(entry, pakfire_file_get_nlink(file));
- archive_entry_set_ino64(entry, pakfire_file_get_inode(file));
- archive_entry_set_dev(entry, pakfire_file_get_dev(file));
-
- // Set size
- archive_entry_set_size(entry, pakfire_file_get_size(file));
-
- // Set mode
- archive_entry_set_mode(entry, pakfire_file_get_mode(file));
-
- // Set uname
- archive_entry_set_uname(entry, pakfire_file_get_uname(file));
-
- // Set gname
- archive_entry_set_gname(entry, pakfire_file_get_gname(file));
-
- // Set times
- archive_entry_set_ctime(entry, pakfire_file_get_ctime(file), 0);
- archive_entry_set_mtime(entry, pakfire_file_get_mtime(file), 0);
// Flags
if (pakfire_file_has_flag(file, PAKFIRE_FILE_CONFIG)) {
// Compute any required file digests
r = pakfire_file_compute_digests(file, digest_types);
if (r)
- goto ERROR;
+ return NULL;
// Copy digests
r = pakfire_file_write_fcaps(file, &cap_data);
if (r) {
ERROR(file->pakfire, "Could not export capabilities: %m\n");
- goto ERROR;
+ return NULL;
}
// Store capabilities in archive entry
}
return entry;
-
-ERROR:
- if (entry)
- archive_entry_free(entry);
-
- return NULL;
}
static void pakfire_file_free(struct pakfire_file* file) {
// Free capabilities
if (file->caps)
cap_free(file->caps);
-
+ if (file->entry)
+ archive_entry_free(file->entry);
pakfire_unref(file->pakfire);
free(file);
}
break;
default:
- if (*file->hardlink) {
+ const char* hardlink = pakfire_file_get_hardlink(file);
+
+ if (hardlink) {
s[0] = 'h';
break;
}
// Format ownership
if (flags & PAKFIRE_FILE_DUMP_OWNERSHIP) {
- r = asprintf(&buffer, "%s %s/%s", buffer, file->uname, file->gname);
+ const char* uname = pakfire_file_get_uname(file);
+ const char* gname = pakfire_file_get_gname(file);
+
+ r = asprintf(&buffer, "%s %s/%s", buffer, uname, gname);
if (r < 0)
goto ERROR;
}
// Format size
if (flags & PAKFIRE_FILE_DUMP_SIZE) {
- r = asprintf(&buffer, "%s %8zu", buffer, file->st.st_size);
+ const size_t size = pakfire_file_get_size(file);
+
+ r = asprintf(&buffer, "%s %8zu", buffer, size);
if (r < 0)
goto ERROR;
}
// Format time
if (flags & PAKFIRE_FILE_DUMP_TIME) {
- r = pakfire_strftime(time, "%Y-%m-%d %H:%M", file->st.st_ctime);
+ const time_t ctime = pakfire_file_get_ctime(file);
+
+ r = pakfire_strftime(time, "%Y-%m-%d %H:%M", ctime);
if (r)
goto ERROR;
}
// Format path
- r = asprintf(&buffer, "%s %s", buffer, file->path);
+ r = asprintf(&buffer, "%s %s", buffer, pakfire_file_get_path(file));
if (r < 0)
goto ERROR;
if (flags & PAKFIRE_FILE_DUMP_LINK_TARGETS) {
switch (pakfire_file_get_type(file)) {
case S_IFLNK:
- r = asprintf(&buffer, "%s -> %s", buffer, file->symlink);
+ r = asprintf(&buffer, "%s -> %s", buffer, pakfire_file_get_symlink(file));
if (r < 0)
return NULL;
}
const char* pakfire_file_get_abspath(struct pakfire_file* file) {
- return file->abspath;
+ return archive_entry_sourcepath(file->entry);
}
int pakfire_file_set_abspath(struct pakfire_file* file, const char* path) {
- int r;
-
// Check if path is set and absolute
if (!path || *path != '/') {
errno = EINVAL;
}
// Store the abspath
- r = pakfire_string_set(file->abspath, path);
- if (r)
- goto ERROR;
+ archive_entry_copy_sourcepath(file->entry, path);
- // Store path if it isn't set, yet
- if (!*file->path) {
- r = pakfire_file_set_path(file, path);
- if (r)
- goto ERROR;
- }
-
- return r;
-
-ERROR:
- ERROR(file->pakfire, "Could not set abspath '%s': %m\n", path);
- return r;
+ return 0;
}
PAKFIRE_EXPORT const char* pakfire_file_get_path(struct pakfire_file* file) {
- return file->path;
+ return archive_entry_pathname(file->entry);
}
PAKFIRE_EXPORT int pakfire_file_set_path(struct pakfire_file* file, const char* path) {
- int r = 1;
-
- // Check if path is set
- if (!path) {
- errno = EINVAL;
- goto ERROR;
- }
+ char buffer[PATH_MAX];
+ int r = 0;
// Strip any leading dots from paths
if (pakfire_string_startswith(path, "./"))
switch (*path) {
// Just store the path if it is absolute
case '/':
- r = pakfire_string_set(file->path, path);
- if (r)
- goto ERROR;
+ archive_entry_set_pathname(file->entry, path);
break;
// Handle relative paths
default:
- r = pakfire_string_format(file->path, "/%s", path);
+ r = pakfire_string_format(buffer, "/%s", path);
if (r)
goto ERROR;
- break;
- }
- // Set abspath if it isn't set, yet
- if (!*file->abspath) {
- r = pakfire_file_set_abspath(file, file->path);
- if (r)
- goto ERROR;
+ archive_entry_set_pathname(file->entry, buffer);
+ break;
}
return r;
}
PAKFIRE_EXPORT const char* pakfire_file_get_hardlink(struct pakfire_file* file) {
- if (!*file->hardlink)
- return NULL;
-
- return file->hardlink;
+ return archive_entry_hardlink(file->entry);
}
PAKFIRE_EXPORT void pakfire_file_set_hardlink(struct pakfire_file* file, const char* link) {
- pakfire_string_set(file->hardlink, link);
+ archive_entry_set_hardlink(file->entry, link);
}
PAKFIRE_EXPORT const char* pakfire_file_get_symlink(struct pakfire_file* file) {
- if (!*file->symlink)
- return NULL;
-
- return file->symlink;
+ return archive_entry_symlink(file->entry);
}
PAKFIRE_EXPORT void pakfire_file_set_symlink(struct pakfire_file* file, const char* link) {
- pakfire_string_set(file->symlink, link);
+ archive_entry_set_symlink(file->entry, link);
}
PAKFIRE_EXPORT nlink_t pakfire_file_get_nlink(struct pakfire_file* file) {
- return file->st.st_nlink;
+ return archive_entry_nlink(file->entry);
}
PAKFIRE_EXPORT void pakfire_file_set_nlink(struct pakfire_file* file, const nlink_t nlink) {
- file->st.st_nlink = nlink;
+ archive_entry_set_nlink(file->entry, nlink);
}
PAKFIRE_EXPORT ino_t pakfire_file_get_inode(struct pakfire_file* file) {
- return file->st.st_ino;
+ return archive_entry_ino64(file->entry);
}
PAKFIRE_EXPORT void pakfire_file_set_inode(struct pakfire_file* file, const ino_t ino) {
- file->st.st_ino = ino;
+ archive_entry_set_ino64(file->entry, ino);
}
PAKFIRE_EXPORT dev_t pakfire_file_get_dev(struct pakfire_file* file) {
- return file->st.st_dev;
+ return archive_entry_dev(file->entry);
}
PAKFIRE_EXPORT void pakfire_file_set_dev(struct pakfire_file* file, const dev_t dev) {
- file->st.st_dev = dev;
+ archive_entry_set_dev(file->entry, dev);
}
PAKFIRE_EXPORT int pakfire_file_get_type(struct pakfire_file* file) {
- return file->st.st_mode & S_IFMT;
+ return archive_entry_filetype(file->entry);
}
PAKFIRE_EXPORT off_t pakfire_file_get_size(struct pakfire_file* file) {
- return file->st.st_size;
+ return archive_entry_size(file->entry);
}
PAKFIRE_EXPORT void pakfire_file_set_size(struct pakfire_file* file, off_t size) {
- file->st.st_size = size;
+ archive_entry_set_size(file->entry, size);
}
PAKFIRE_EXPORT const char* pakfire_file_get_uname(struct pakfire_file* file) {
- return file->uname;
+ return archive_entry_uname(file->entry);
}
PAKFIRE_EXPORT int pakfire_file_set_uname(struct pakfire_file* file, const char* uname) {
- return pakfire_string_set(file->uname, uname);
+ archive_entry_set_uname(file->entry, uname);
+
+ return 0;
}
PAKFIRE_EXPORT const char* pakfire_file_get_gname(struct pakfire_file* file) {
- return file->gname;
+ return archive_entry_gname(file->entry);
}
PAKFIRE_EXPORT int pakfire_file_set_gname(struct pakfire_file* file, const char* gname) {
- return pakfire_string_set(file->gname, gname);
+ archive_entry_set_gname(file->entry, gname);
+
+ return 0;
}
PAKFIRE_EXPORT mode_t pakfire_file_get_mode(struct pakfire_file* file) {
- return file->st.st_mode;
+ return archive_entry_mode(file->entry);
}
PAKFIRE_EXPORT void pakfire_file_set_mode(struct pakfire_file* file, mode_t mode) {
- file->st.st_mode = mode;
+ archive_entry_set_mode(file->entry, mode);
}
PAKFIRE_EXPORT mode_t pakfire_file_get_perms(struct pakfire_file* file) {
- return file->st.st_mode & ~S_IFMT;
+ return archive_entry_perm(file->entry);
}
PAKFIRE_EXPORT void pakfire_file_set_perms(struct pakfire_file* file, const mode_t perms) {
- // Clear any previous permissions
- file->st.st_mode &= S_IFMT;
-
- // Set new bits (with format cleared)
- file->st.st_mode |= ~S_IFMT & perms;
+ archive_entry_set_mode(file->entry, pakfire_file_get_type(file) | perms);
}
static int pakfire_file_is_executable(struct pakfire_file* file) {
- return file->st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH);
+ return pakfire_file_get_mode(file) & (S_IXUSR|S_IXGRP|S_IXOTH);
}
PAKFIRE_EXPORT time_t pakfire_file_get_ctime(struct pakfire_file* file) {
- return file->st.st_ctime;
+ return archive_entry_ctime(file->entry);
}
PAKFIRE_EXPORT void pakfire_file_set_ctime(struct pakfire_file* file, time_t time) {
- file->st.st_ctime = time;
+ archive_entry_set_ctime(file->entry, time, 0);
}
PAKFIRE_EXPORT time_t pakfire_file_get_mtime(struct pakfire_file* file) {
- return file->st.st_mtime;
+ return archive_entry_mtime(file->entry);
}
PAKFIRE_EXPORT void pakfire_file_set_mtime(struct pakfire_file* file, time_t time) {
- file->st.st_mtime = time;
+ archive_entry_set_mtime(file->entry, time, 0);
}
PAKFIRE_EXPORT const unsigned char* pakfire_file_get_digest(
PAKFIRE_EXPORT int pakfire_file_set_digest(struct pakfire_file* file,
const enum pakfire_digest_types type, const unsigned char* digest, const size_t length) {
- if (!digest) {
- errno = EINVAL;
- return 1;
- }
+ if (!digest)
+ return -EINVAL;
// Check buffer length
if (pakfire_digest_length(type) != length) {
ERROR(file->pakfire, "Digest has an incorrect length of %zu byte(s)\n", length);
- errno = ENOMSG;
- return 1;
+ return -ENOMSG;
}
// Store the digest
}
static int pakfire_file_levels(struct pakfire_file* file) {
- if (!*file->path)
+ const char* path = pakfire_file_get_path(file);
+ if (!path)
return 0;
int levels = 0;
- for (char* p = file->path; *p; p++) {
+ for (const char* p = path; *p; p++) {
if (*p == '/')
levels++;
}
}
FILE* pakfire_file_open(struct pakfire_file* file) {
- FILE* f = fopen(file->abspath, "r+");
+ const char* path = pakfire_file_get_abspath(file);
+ if (!path)
+ return NULL;
+
+ FILE* f = fopen(path, "r+");
if (!f)
- ERROR(file->pakfire, "Could not open %s: %m\n", file->abspath);
+ ERROR(file->pakfire, "Could not open %s: %m\n", path);
return f;
}
void* p = NULL;
int r;
+ const mode_t mode = pakfire_file_get_mode(file);
+
// Only run for regular files
- if (!S_ISREG(file->st.st_mode))
+ if (!S_ISREG(mode))
return 0;
+ const size_t size = pakfire_file_get_size(file);
+
// Skip empty files
- if (!file->st.st_size)
+ if (!size)
return 0;
// Open the file
FILE* f = NULL;
int r = 1;
+ const mode_t mode = pakfire_file_get_mode(file);
+
// Skip this for anything that isn't a regular file
- if (!S_ISREG(file->st.st_mode))
+ if (!S_ISREG(mode))
return 0;
// Reset digests
static int pakfire_file_remove(struct pakfire_file* file) {
int r;
- if (!*file->abspath) {
- errno = EINVAL;
- return 1;
- }
+ const char* path = pakfire_file_get_path(file);
+ const char* abspath = pakfire_file_get_abspath(file);
+
+ DEBUG(file->pakfire, "Removing %s...\n", path);
- DEBUG(file->pakfire, "Removing %s...\n", file->path);
+ // We cannot delete if we don't have the absolute path
+ if (!abspath)
+ return -ENOTSUP;
- switch (file->st.st_mode & S_IFMT) {
+ switch (pakfire_file_get_type(file)) {
// Call rmdir() for directories
case S_IFDIR:
- r = rmdir(file->abspath);
+ r = rmdir(abspath);
if (r) {
switch (errno) {
// Ignore when the directory is not empty
// Log anything else
default:
- ERROR(file->pakfire, "Could not remove directory %s: %m\n", file->path);
+ ERROR(file->pakfire, "Could not remove directory %s: %m\n", path);
break;
}
}
// Call unlink() for everything else
default:
- r = unlink(file->abspath);
+ r = unlink(abspath);
if (r) {
switch (errno) {
// Ignore if the file didn't exist
break;
default:
- ERROR(file->pakfire, "Could not remove %s: %m\n", file->path);
+ ERROR(file->pakfire, "Could not remove %s: %m\n", path);
break;
}
}
}
int pakfire_file_symlink_target_exists(struct pakfire_file* file) {
+ const mode_t mode = pakfire_file_get_mode(file);
+
// Fail if this got called for anything that isn't a symlink
- if (!S_ISLNK(file->st.st_mode)) {
- errno = EINVAL;
- return -1;
- }
+ if (!S_ISLNK(mode))
+ return -EINVAL;
- return pakfire_path_exists(file->abspath);
+ const char* path = pakfire_file_get_abspath(file);
+
+ return pakfire_path_exists(path);
}
/*
*/
int pakfire_file_detect_mimetype(struct pakfire_file* file) {
+ const mode_t mode = pakfire_file_get_mode(file);
+
// Only process regular files
- if (!S_ISREG(file->st.st_mode))
+ if (!S_ISREG(mode))
return 0;
// Skip if MIME type is already set
if (!magic)
return 1;
+ const char* path = pakfire_file_get_abspath(file);
+
// Check the file
- const char* mimetype = magic_file(magic, file->abspath);
+ const char* mimetype = magic_file(magic, path);
if (!mimetype) {
- ERROR(file->pakfire, "Could not classify %s: %s\n", file->path, magic_error(magic));
+ ERROR(file->pakfire, "Could not classify %s: %s\n",
+ pakfire_file_get_path(file), magic_error(magic));
return 1;
}
- DEBUG(file->pakfire, "Classified %s as %s\n", file->path, mimetype);
+ DEBUG(file->pakfire, "Classified %s as %s\n", pakfire_file_get_path(file), mimetype);
// Store the value
return pakfire_file_set_mimetype(file, mimetype);
}
static int pakfire_file_classify_mode(struct pakfire_file* file) {
+ const mode_t mode = pakfire_file_get_mode(file);
+
// Check for regular files
- if (S_ISREG(file->st.st_mode)) {
+ if (S_ISREG(mode)) {
file->class |= PAKFIRE_FILE_REGULAR;
// Does the file have executable permissions?
- if (file->st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
+ if (mode & (S_IXUSR|S_IXGRP|S_IXOTH))
file->class |= PAKFIRE_FILE_EXECUTABLE;
// Check for directories
- } else if (S_ISDIR(file->st.st_mode))
+ } else if (S_ISDIR(mode))
file->class |= PAKFIRE_FILE_DIRECTORY;
// Check for symlinks
- else if (S_ISLNK(file->st.st_mode))
+ else if (S_ISLNK(mode))
file->class |= PAKFIRE_FILE_SYMLINK;
// Check for character devices
- else if (S_ISCHR(file->st.st_mode))
+ else if (S_ISCHR(mode))
file->class |= PAKFIRE_FILE_CHARACTER;
// Check for block devices
- else if (S_ISBLK(file->st.st_mode))
+ else if (S_ISBLK(mode))
file->class |= PAKFIRE_FILE_BLOCK;
// Check for FIFO pipes
- else if (S_ISFIFO(file->st.st_mode))
+ else if (S_ISFIFO(mode))
file->class |= PAKFIRE_FILE_FIFO;
// Check for sockets
- else if (S_ISSOCK(file->st.st_mode))
+ else if (S_ISSOCK(mode))
file->class |= PAKFIRE_FILE_SOCKET;
return 0;
return r;
// Open the file
- f = fopen(file->abspath, "r");
+ f = pakfire_file_open(file);
if (!f) {
- ERROR(file->pakfire, "Could not open %s: %m\n", file->path);
+ ERROR(file->pakfire, "Could not open %s: %m\n", pakfire_file_get_path(file));
return 1;
}
// Try to tidy up afterwards
if (flags & PAKFIRE_FILE_CLEANUP_TIDY) {
+ const char* abspath = pakfire_file_get_abspath(file);
+
// Create a working copy of abspath
- r = pakfire_string_set(path, file->abspath);
+ r = pakfire_string_set(path, abspath);
if (r)
return r;
if (type != (st->st_mode & S_IFMT)) {
file->verify_status |= PAKFIRE_FILE_TYPE_CHANGED;
- DEBUG(file->pakfire, "%s: File Type changed\n", file->path);
+ DEBUG(file->pakfire, "%s: File Type changed\n", pakfire_file_get_path(file));
}
const mode_t perms = pakfire_file_get_perms(file);
if (perms != (st->st_mode & 0777)) {
file->verify_status |= PAKFIRE_FILE_PERMISSIONS_CHANGED;
- DEBUG(file->pakfire, "%s: Permissions changed\n", file->path);
+ DEBUG(file->pakfire, "%s: Permissions changed\n", pakfire_file_get_path(file));
}
#if 0
if (dev != st->st_dev) {
file->verify_status |= PAKFIRE_FILE_DEV_CHANGED;
- DEBUG(file->pakfire, "%s: Device Node changed\n", file->path);
+ DEBUG(file->pakfire, "%s: Device Node changed\n", pakfire_file_get_path(file));
}
}
#endif
}
static int pakfire_file_verify_size(struct pakfire_file* file, const struct stat* st) {
+ const ssize_t size = pakfire_file_get_size(file);
+
// Nothing to do if size matches
- if (file->st.st_size == st->st_size)
+ if (size == st->st_size)
return 0;
// Size differs
file->verify_status |= PAKFIRE_FILE_SIZE_CHANGED;
DEBUG(file->pakfire, "%s: Filesize differs (expected %zu, got %zu byte(s))\n",
- file->path, file->st.st_size, st->st_size);
+ pakfire_file_get_path(file), size, st->st_size);
return 0;
}
const gid_t gid = st->st_gid;
#endif
+ const char* uname = pakfire_file_get_uname(file);
+ const char* gname = pakfire_file_get_gname(file);
+
// Fetch owner & group
- struct passwd* owner = pakfire_getpwnam(file->pakfire, file->uname);
- struct group* group = pakfire_getgrnam(file->pakfire, file->gname);
+ struct passwd* owner = pakfire_getpwnam(file->pakfire, uname);
+ struct group* group = pakfire_getgrnam(file->pakfire, gname);
// Check if owner matches
if (!owner || owner->pw_uid != uid) {
file->verify_status |= PAKFIRE_FILE_OWNER_CHANGED;
- DEBUG(file->pakfire, "%s: Owner differs\n", file->path);
+ DEBUG(file->pakfire, "%s: Owner differs\n", pakfire_file_get_path(file));
}
// Check if group matches
if (!group || group->gr_gid != gid) {
file->verify_status |= PAKFIRE_FILE_GROUP_CHANGED;
- DEBUG(file->pakfire, "%s: Group differs\n", file->path);
+ DEBUG(file->pakfire, "%s: Group differs\n", pakfire_file_get_path(file));
}
return 0;
}
static int pakfire_file_verify_timestamps(struct pakfire_file* file, const struct stat* st) {
+ const time_t ctime = pakfire_file_get_ctime(file);
+ const time_t mtime = pakfire_file_get_mtime(file);
+
// Check creation time
- if (file->st.st_ctime != st->st_ctime) {
+ if (ctime != st->st_ctime) {
file->verify_status |= PAKFIRE_FILE_CTIME_CHANGED;
- DEBUG(file->pakfire, "%s: Creation time changed\n", file->path);
+ DEBUG(file->pakfire, "%s: Creation time changed\n", pakfire_file_get_path(file));
}
// Check modification time
- if (file->st.st_mtime != st->st_mtime) {
+ if (mtime != st->st_mtime) {
file->verify_status |= PAKFIRE_FILE_MTIME_CHANGED;
- DEBUG(file->pakfire, "%s: Modification time changed\n", file->path);
+ DEBUG(file->pakfire, "%s: Modification time changed\n", pakfire_file_get_path(file));
}
return 0;
digest_types = pakfire_digest_has_any(&file->digests);
if (!digest_types) {
- ERROR(file->pakfire, "%s: No digests available\n", file->path);
+ ERROR(file->pakfire, "%s: No digests available\n", pakfire_file_get_path(file));
return 0;
}
if (r) {
file->verify_status |= PAKFIRE_FILE_PAYLOAD_CHANGED;
- DEBUG(file->pakfire, "%s: Digest(s) do not match\n", file->path);
+ DEBUG(file->pakfire, "%s: Digest(s) do not match\n", pakfire_file_get_path(file));
}
ERROR:
struct stat st;
int r;
- DEBUG(file->pakfire, "Verifying %s...\n", file->path);
+ DEBUG(file->pakfire, "Verifying %s...\n", pakfire_file_get_path(file));
+
+ const char* abspath = pakfire_file_get_abspath(file);
// stat() the file
- r = lstat(file->abspath, &st);
+ r = lstat(abspath, &st);
if (r) {
// File does not exist
if (errno == ENOENT) {
}
PAKFIRE_EXPORT int pakfire_file_matches(struct pakfire_file* file, const char* pattern) {
- int r;
-
// Don't match on no pattern
if (!pattern)
return 0;
- // Check if the pattern matches
- r = fnmatch(pattern, file->path, 0);
- switch (r) {
- // Match
- case 0:
- return 1;
+ const char* path = pakfire_file_get_path(file);
- // No Match
- case FNM_NOMATCH:
- return 0;
-
- default:
- return -1;
- }
+ return pakfire_path_match(pattern, path);
}
/*
return r;
// Open the file
- f = fopen(file->abspath, "r");
+ f = pakfire_file_open(file);
if (!f) {
- ERROR(file->pakfire, "Could not open %s: %m\n", file->abspath);
+ ERROR(file->pakfire, "Could not open %s: %m\n", pakfire_file_get_abspath(file));
return 1;
}
break;
default:
- ERROR(file->pakfire, "%s is not an ELF object\n", file->path);
+ ERROR(file->pakfire, "%s is not an ELF object\n", pakfire_file_get_path(file));
r = 1;
goto ERROR;
}
// Find the dynamic linking information
r = pakfire_file_get_elf_section(file, elf, SHT_DYNAMIC, &dynamic, &shdr, &elf_data);
if (r) {
- ERROR(file->pakfire, "%s does not have a dynamic section\n", file->path);
+ ERROR(file->pakfire, "%s does not have a dynamic section\n", pakfire_file_get_path(file));
return 1;
}
// Not found
if (r) {
- DEBUG(file->pakfire, "%s has no debug sections\n", file->path);
+ DEBUG(file->pakfire, "%s has no debug sections\n", pakfire_file_get_path(file));
// Store the result
file->issues |= PAKFIRE_FILE_MISSING_DEBUGINFO;
// Fetch the symbol table
r = pakfire_file_get_elf_section(file, elf, SHT_SYMTAB, &symtab, &shdr, &elf_data);
if (r) {
- ERROR(file->pakfire, "%s has no symbol table\n", file->path);
+ ERROR(file->pakfire, "%s has no symbol table\n", pakfire_file_get_path(file));
return 1;
}
// We do not perform the check for libraries that do not contain any functions.
// Some packages use shared libraries to provide data.
if (!counter) {
- DEBUG(file->pakfire, "%s: File has no functions. Skipping SSP check.\n", file->path);
+ DEBUG(file->pakfire, "%s: File has no functions. Skipping SSP check.\n",
+ pakfire_file_get_path(file));
return 0;
}
case PT_GNU_STACK:
DEBUG(file->pakfire,
"%s: GNU_STACK flags: %c%c%c\n",
- file->path,
+ pakfire_file_get_path(file),
(phdr.p_flags & PF_R) ? 'R' : '-',
(phdr.p_flags & PF_W) ? 'W' : '-',
(phdr.p_flags & PF_X) ? 'X' : '-'
if (!value)
return 1;
- DEBUG(file->pakfire, "%s has a RUNPATH: %s\n", file->path, value);
+ DEBUG(file->pakfire, "%s has a RUNPATH: %s\n",
+ pakfire_file_get_path(file), value);
// Copy the value into a buffer we can modify
r = pakfire_string_set(buffer, value);
return 1;
}
+ const mode_t mode = pakfire_file_get_mode(file);
+
// Only run for regular files
- if (!S_ISREG(file->st.st_mode))
+ if (!S_ISREG(mode))
return 0;
// Only run for executable files
if (!pakfire_file_is_executable(file))
return 0;
+ const size_t size = pakfire_file_get_size(file);
+
// Nothing to do if the file is empty
- if (!file->st.st_size)
+ if (!size)
return 0;
// Open the file
// Handle any reading errors
if (bytes_read < 0) {
- ERROR(file->pakfire, "Could not read from file %s: %m\n", file->path);
+ ERROR(file->pakfire, "Could not read from file %s: %m\n",
+ pakfire_file_get_path(file));
r = 1;
goto ERROR;
}
}
if (strncmp("#!", shebang, 2) == 0) {
- DEBUG(file->pakfire, "%s is a script\n", file->path);
+ DEBUG(file->pakfire, "%s is a script\n", pakfire_file_get_path(file));
// Find the end of the first line (to be able to perform string operations)
p = memchr(shebang, '\n', sizeof(shebang));
if (!p) {
- ERROR(file->pakfire, "%s: First line seems to be too long\n", file->path);
+ ERROR(file->pakfire, "%s: First line seems to be too long\n",
+ pakfire_file_get_path(file));
errno = ENOBUFS;
r = 1;
goto ERROR;
char* data = NULL;
size_t length = 0;
- DEBUG(file->pakfire, "%s: Fixing interpreter %s\n", file->path, interpreter);
+ DEBUG(file->pakfire, "%s: Fixing interpreter %s\n",
+ pakfire_file_get_path(file), interpreter);
// Open the file
f = pakfire_file_open(file);
if (!f) {
- ERROR(file->pakfire, "Could not open %s: %m\n", file->path);
+ ERROR(file->pakfire, "Could not open %s: %m\n", pakfire_file_get_path(file));
r = 1;
goto ERROR;
}
if (pakfire_string_startswith(p, "#!")) {
p += 2;
} else {
- ERROR(file->pakfire, "%s: Could not find shebang\n", file->path);
+ ERROR(file->pakfire, "%s: Could not find shebang\n", pakfire_file_get_path(file));
errno = EINVAL;
r = 1;
goto ERROR;
// Terminate the command
*p++ = '\0';
- DEBUG(file->pakfire, "%s: Found command: %s\n", file->path, command);
+ DEBUG(file->pakfire, "%s: Found command: %s\n", pakfire_file_get_path(file), command);
// Find the absolute path to the command
r = pakfire_which(file->pakfire, path, command);
if (r) {
- DEBUG(file->pakfire, "%s: Could not resolve command %s: %m\n", file->path, command);
+ DEBUG(file->pakfire, "%s: Could not resolve command %s: %m\n",
+ pakfire_file_get_path(file), command);
goto ERROR;
}
// Write shebang
r = fprintf(f, (*p) ? "#!%s %s\n" : "#!%s\n", path, p);
if (r < 0) {
- ERROR(file->pakfire, "%s: Could not write back first line: %m\n", file->path);
+ ERROR(file->pakfire, "%s: Could not write back first line: %m\n",
+ pakfire_file_get_path(file));
r = 1;
goto ERROR;
}
// Write the rest
size_t bytes_written = fwrite(rest, 1, length, f);
if (bytes_written < length) {
- ERROR(file->pakfire, "%s: Could not write the payload: %m\n", file->path);
+ ERROR(file->pakfire, "%s: Could not write the payload: %m\n",
+ pakfire_file_get_path(file));
r = 1;
goto ERROR;
}
if (!interpreter)
return 0;
- DEBUG(file->pakfire, "%s: Interpreter: %s\n", file->path, interpreter);
+ DEBUG(file->pakfire, "%s: Interpreter: %s\n",
+ pakfire_file_get_path(file), interpreter);
// Paths must be absolute
if (*interpreter != '/')
else if (strcmp(interpreter, "/usr/bin/env") == 0) {
r = pakfire_file_fix_interpreter(file, interpreter);
if (r) {
- ERROR(file->pakfire, "%s: Could not fix interpreter: %m\n", file->path);
+ ERROR(file->pakfire, "%s: Could not fix interpreter: %m\n",
+ pakfire_file_get_path(file));
goto ERROR;
}
}
// Check for IBT
if (!(property & GNU_PROPERTY_X86_FEATURE_1_IBT)) {
- DEBUG(file->pakfire, "%s: IBT property is not enabled\n", file->path);
+ DEBUG(file->pakfire, "%s: IBT property is not enabled\n",
+ pakfire_file_get_path(file));
// XXX TODO Actually modify any flags
// Check for Shadow Stack
if (!(property & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) {
- DEBUG(file->pakfire, "%s: Shadow Stack is not enabled\n", file->path);
+ DEBUG(file->pakfire, "%s: Shadow Stack is not enabled\n",
+ pakfire_file_get_path(file));
// XXX TODO Actually modify any flags
// Fetch the ELF header
if (!gelf_getehdr(elf, &ehdr)) {
- ERROR(file->pakfire, "Could not fetch the ELF header for %s: %m\n", file->path);
+ ERROR(file->pakfire, "Could not fetch the ELF header for %s: %m\n",
+ pakfire_file_get_path(file));
return 1;
}