#include <pakfire/string.h>
#include <pakfire/util.h>
+enum pakfire_file_verification_status {
+ PAKFIRE_FILE_NOENT = (1 << 0),
+ PAKFIRE_FILE_SIZE_DIFFERS = (1 << 1),
+ PAKFIRE_FILE_OWNER_DIFFERS = (1 << 2),
+ PAKFIRE_FILE_GROUP_DIFFERS = (1 << 3),
+};
+
struct pakfire_file {
struct pakfire* pakfire;
int nrefs;
unsigned char sha256[SHA256_DIGEST_LENGTH];
} digests;
+ // Verification Status
+ int verify_status;
+
#warning TODO capabilities, config, data
// capabilities
//int is_configfile;
return 0;
}
+static int pakfire_file_verify_size(struct pakfire_file* file, const struct stat* st) {
+ // Nothing to do if size matches
+ if (file->size == st->st_size)
+ return 0;
+
+ // Size differs
+ file->verify_status |= PAKFIRE_FILE_SIZE_DIFFERS;
+
+ DEBUG(file->pakfire, "%s: Filesize differs (expected %zu, got %zu byte(s))\n",
+ file->path, file->size, st->st_size);
+
+ return 0;
+}
+
+static int pakfire_file_verify_ownership(struct pakfire_file* file, const struct stat* st) {
+ // Fetch UID/GID
+#if 0
+ const uid_t uid = pakfire_unmap_id(file->pakfire, st->st_uid);
+ const gid_t gid = pakfire_unmap_id(file->pakfire, st->st_gid);
+#else
+ const uid_t uid = st->st_uid;
+ const gid_t gid = st->st_gid;
+#endif
+
+ // Fetch owner & group
+ struct passwd* owner = pakfire_getpwnam(file->pakfire, file->user);
+ struct group* group = pakfire_getgrnam(file->pakfire, file->group);
+
+ // Check if owner matches
+ if (!owner || owner->pw_uid != uid) {
+ file->verify_status |= PAKFIRE_FILE_OWNER_DIFFERS;
+
+ DEBUG(file->pakfire, "%s: Owner differs\n", file->path);
+ }
+
+ // Check if group matches
+ if (!group || group->gr_gid != gid) {
+ file->verify_status |= PAKFIRE_FILE_GROUP_DIFFERS;
+
+ DEBUG(file->pakfire, "%s: Group differs\n", file->path);
+ }
+
+ return 0;
+}
+
/*
Verify the file - i.e. does the metadata match what is on disk?
*/
-int pakfire_file_verify(struct pakfire_file* file) {
+int pakfire_file_verify(struct pakfire_file* file, int* status) {
+ struct stat st;
+ int r;
+
DEBUG(file->pakfire, "Verifying %s...\n", file->path);
- // XXX TODO
+ // stat() the file
+ r = lstat(file->abspath, &st);
+ if (r) {
+ // File does not exist
+ if (errno == ENOENT) {
+ file->verify_status |= PAKFIRE_FILE_NOENT;
+ return 1;
+ }
+
+ // Raise any other errors from stat()
+ return r;
+ }
+
+ // Verify size
+ r = pakfire_file_verify_size(file, &st);
+ if (r)
+ return r;
+
+ // Verify ownership
+ r = pakfire_file_verify_ownership(file, &st);
+ if (r)
+ return r;
+
return 0;
}
int pakfire_filelist_verify(struct pakfire_filelist* list, struct pakfire_filelist* errors) {
struct pakfire_progressbar* progressbar = NULL;
struct pakfire_file* file = NULL;
+ int status;
int r;
DEBUG(list->pakfire, "Verifying filelist (%zu file(s))...\n", list->size);
file = list->elements[i];
// Verify the file
- r = pakfire_file_verify(file);
- if (r) {
+ r = pakfire_file_verify(file, &status);
+ if (r)
+ goto ERROR;
+
+ // If the verification failed, we append it to the errors list
+ if (status) {
// Append the file to the error list
r = pakfire_filelist_append(errors, file);
if (r)