"gname TEXT, "
"ctime INTEGER, "
"mtime INTEGER, "
+ "mimetype TEXT, "
"capabilities TEXT, "
"digest_sha2_512 BLOB, "
"digest_sha2_256 BLOB, "
"gname, "
"ctime, "
"mtime, "
+ "mimetype, "
"capabilities, "
"digest_sha2_512, "
"digest_sha2_256, "
"digest_sha3_512, "
"digest_sha3_256"
") "
- "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
// Prepare the statement
r = sqlite3_prepare_v2(db->handle, sql, strlen(sql), &stmt, NULL);
goto END;
}
+ // Bind MIME type
+ const char* mimetype = pakfire_file_get_mimetype(file);
+
+ if (mimetype) {
+ r = sqlite3_bind_text(stmt, 11, mimetype, -1, NULL);
+ if (r) {
+ ERROR(db->pakfire, "Could not bind MIME type: %s\n",
+ sqlite3_errmsg(db->handle));
+ pakfire_file_unref(file);
+ goto END;
+ }
+ } else {
+ r = sqlite3_bind_null(stmt, 11);
+ if (r) {
+ ERROR(db->pakfire, "Could not bind an empty MIME type: %s\n",
+ sqlite3_errmsg(db->handle));
+ pakfire_file_unref(file);
+ goto END;
+ }
+ }
+
// Bind capabilities - XXX TODO
- r = sqlite3_bind_null(stmt, 11);
+ r = sqlite3_bind_null(stmt, 12);
if (r) {
ERROR(db->pakfire, "Could not bind capabilities: %s\n", sqlite3_errmsg(db->handle));
pakfire_file_unref(file);
}
// SHA2-512 Digest
- r = pakfire_db_bind_digest(db, stmt, 12, file, PAKFIRE_DIGEST_SHA2_512);
+ r = pakfire_db_bind_digest(db, stmt, 13, file, PAKFIRE_DIGEST_SHA2_512);
if (r) {
ERROR(db->pakfire, "Could not bind SHA2-512 digest: %s\n",
sqlite3_errmsg(db->handle));
}
// SHA2-256 Digest
- r = pakfire_db_bind_digest(db, stmt, 13, file, PAKFIRE_DIGEST_SHA2_256);
+ r = pakfire_db_bind_digest(db, stmt, 14, file, PAKFIRE_DIGEST_SHA2_256);
if (r) {
ERROR(db->pakfire, "Could not bind SHA2-256 digest: %s\n",
sqlite3_errmsg(db->handle));
}
// BLAKE2b512 Digest
- r = pakfire_db_bind_digest(db, stmt, 14, file, PAKFIRE_DIGEST_BLAKE2B512);
+ r = pakfire_db_bind_digest(db, stmt, 15, file, PAKFIRE_DIGEST_BLAKE2B512);
if (r) {
ERROR(db->pakfire, "Could not bind BLAKE2b512 digest: %s\n",
sqlite3_errmsg(db->handle));
}
// BLAKE2s256 Digest
- r = pakfire_db_bind_digest(db, stmt, 15, file, PAKFIRE_DIGEST_BLAKE2S256);
+ r = pakfire_db_bind_digest(db, stmt, 16, file, PAKFIRE_DIGEST_BLAKE2S256);
if (r) {
ERROR(db->pakfire, "Could not bind BLAKE2s256 digest: %s\n",
sqlite3_errmsg(db->handle));
}
// SHA3-512 Digest
- r = pakfire_db_bind_digest(db, stmt, 16, file, PAKFIRE_DIGEST_SHA3_512);
+ r = pakfire_db_bind_digest(db, stmt, 17, file, PAKFIRE_DIGEST_SHA3_512);
if (r) {
ERROR(db->pakfire, "Could not bind SHA3-512 digest: %s\n",
sqlite3_errmsg(db->handle));
}
// SHA3-256 Digest
- r = pakfire_db_bind_digest(db, stmt, 17, file, PAKFIRE_DIGEST_SHA3_256);
+ r = pakfire_db_bind_digest(db, stmt, 18, file, PAKFIRE_DIGEST_SHA3_256);
if (r) {
ERROR(db->pakfire, "Could not bind SHA3-256 digest: %s\n",
sqlite3_errmsg(db->handle));
if (mtime)
pakfire_file_set_mtime(file, mtime);
+ const char* mimetype = (const char*)sqlite3_column_text(stmt, 7);
+
+ // MIME type
+ r = pakfire_file_set_mimetype(file, mimetype);
+ if (r)
+ goto ERROR;
+
// SHA2-512 Digest
- r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA2_512, 7);
+ r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA2_512, 8);
if (r)
goto ERROR;
// SHA2-256 Digest
- r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA2_256, 8);
+ r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA2_256, 9);
if (r)
goto ERROR;
// BLAKE2b512 Digest
- r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_BLAKE2B512, 9);
+ r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_BLAKE2B512, 10);
if (r)
goto ERROR;
// BLAKE2s256 Digest
- r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_BLAKE2S256, 10);
+ r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_BLAKE2S256, 11);
if (r)
goto ERROR;
// SHA3-512 Digest
- r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA3_512, 11);
+ r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA3_512, 12);
if (r)
goto ERROR;
// SHA3-256 Digest
- r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA3_256, 12);
+ r = pakfire_db_load_file_digest(db, file, stmt, PAKFIRE_DIGEST_SHA3_256, 13);
if (r)
goto ERROR;
"gname, "
"ctime, "
"mtime, "
+ "mimetype, "
"digest_sha2_512, "
"digest_sha2_256, "
"digest_blake2b512, "
"gname, "
"ctime, "
"mtime, "
+ "mimetype, "
"digest_sha2_512, "
"digest_sha2_256, "
"digest_blake2b512, "
// Digests
struct pakfire_digests digests;
+ // MIME Type
+ char mimetype[NAME_MAX];
+
// Class
int class;
};
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;
pakfire_file_set_ctime(file, archive_entry_ctime(entry));
pakfire_file_set_mtime(file, archive_entry_mtime(entry));
+ // Reset iterating over extended attributes
archive_entry_xattr_reset(entry);
// Read any extended attributes
while (archive_entry_xattr_next(entry, &attr, &value, &size) == ARCHIVE_OK) {
+ // MIME type
+ if (strcmp(attr, "PAKFIRE.mimetype") == 0) {
+ // Copy the value into a NULL-terminated buffer
+ r = asprintf(&buffer, "%.*s", (int)size, (const char*)value);
+ if (r < 0)
+ goto ERROR;
+
+ // Assign the value
+ r = pakfire_file_set_mimetype(file, buffer);
+ if (r)
+ goto ERROR;
+
// Digest: SHA-3-512
- if (strcmp(attr, "PAKFIRE.digests.sha3_512") == 0) {
+ } else if (strcmp(attr, "PAKFIRE.digests.sha3_512") == 0) {
r = pakfire_file_set_digest(file, PAKFIRE_DIGEST_SHA3_512, value, size);
if (r)
goto ERROR;
}
ERROR:
+ if (buffer)
+ free(buffer);
+
return r;
}
archive_entry_set_ctime(entry, pakfire_file_get_ctime(file), 0);
archive_entry_set_mtime(entry, pakfire_file_get_mtime(file), 0);
+ // Set MIME type
+ const char* mimetype = pakfire_file_get_mimetype(file);
+ if (mimetype) {
+ archive_entry_xattr_add_entry(entry,
+ "PAKFIRE.mimetype", mimetype, strlen(mimetype));
+ }
+
// Compute any required file digests
r = pakfire_file_compute_digests(file, digest_types);
if (r)
return pakfire_path_exists(file->abspath);
}
+/*
+ MIME Type
+*/
+
+int pakfire_file_detect_mimetype(struct pakfire_file* file) {
+ // Only process regular files
+ if (!S_ISREG(file->st.st_mode))
+ return 0;
+
+ // Skip if MIME type is already set
+ if (*file->mimetype)
+ return 0;
+
+ // Fetch the magic cookie
+ magic_t magic = pakfire_get_magic(file->pakfire);
+ if (!magic)
+ return 1;
+
+ // Check the file
+ const char* mimetype = magic_file(magic, file->abspath);
+ if (!mimetype) {
+ ERROR(file->pakfire, "Could not classify %s: %s\n", file->path, magic_error(magic));
+ return 1;
+ }
+
+ DEBUG(file->pakfire, "Classified %s as %s\n", file->path, mimetype);
+
+ // Store the value
+ return pakfire_file_set_mimetype(file, mimetype);
+}
+
+PAKFIRE_EXPORT const char* pakfire_file_get_mimetype(struct pakfire_file* file) {
+ // Return nothing on an empty mimetype
+ if (!*file->mimetype)
+ return NULL;
+
+ return file->mimetype;
+}
+
+PAKFIRE_EXPORT int pakfire_file_set_mimetype(
+ struct pakfire_file* file, const char* mimetype) {
+ // Store the value
+ return pakfire_string_set(file->mimetype, mimetype);
+}
+
/*
Classification
*/
const char* mimetype;
int class;
} mimetypes[] = {
+ { "application/x-pie-executable", PAKFIRE_FILE_EXECUTABLE },
{ "application/x-sharedlibary", PAKFIRE_FILE_EXECUTABLE },
{ "text/x-perl", PAKFIRE_FILE_PERL },
{ NULL, 0 },
};
static int pakfire_file_classify_magic(struct pakfire_file* file) {
+ int r;
+
// Don't run this if the file has already been classified
if (file->class & ~PAKFIRE_FILE_REGULAR)
return 0;
- // Fetch the magic cookie
- magic_t magic = pakfire_get_magic(file->pakfire);
- if (!magic)
- return 1;
+ // Detect the MIME type
+ r = pakfire_file_detect_mimetype(file);
+ if (r)
+ return r;
- // Check the file
- const char* mimetype = magic_file(magic, file->abspath);
- if (!mimetype) {
- ERROR(file->pakfire, "Could not classify %s: %s\n", file->path, magic_error(magic));
+ // Fetch the MIME type
+ const char* mimetype = pakfire_file_get_mimetype(file);
+ if (!mimetype)
return 1;
- }
-
- DEBUG(file->pakfire, "Classified %s as %s\n", file->path, mimetype);
+ // Match the MIME type with a flag
for (const struct mimetype* m = mimetypes; m->mimetype; m++) {
if (strcmp(m->mimetype, mimetype) == 0) {
file->class |= m->class;