#include <pakfire/logging.h>
#include <pakfire/package.h>
#include <pakfire/pakfire.h>
+#include <pakfire/path.h>
#include <pakfire/private.h>
#include <pakfire/repo.h>
#include <pakfire/scriptlet.h>
// File handle opened by the cookie
FILE* __f;
+
+ // Some flags
+ int flags;
};
static ssize_t __pakfire_archive_cookie_read(void* c, char* buffer, size_t size) {
static int __pakfire_archive_read_filter(struct pakfire* pakfire, struct archive* a,
struct archive_entry* e, void* data) {
struct pakfire_archive_read_cookie* cookie = (struct pakfire_archive_read_cookie*)data;
+ const char* symlink = NULL;
+ int r;
// Fetch path
const char* p = archive_entry_pathname(e);
return PAKFIRE_WALK_ERROR;
// We found a match
- if (strcmp(cookie->path + 1, p) == 0)
+ if (strcmp(cookie->path + 1, p) == 0) {
+ if (cookie->flags & PAKFIRE_ARCHIVE_READ_FOLLOW_SYMLINKS) {
+ switch (archive_entry_filetype(e)) {
+ case AE_IFLNK:
+ break;
+
+ default:
+ return PAKFIRE_WALK_DONE;
+ }
+
+ // Resolve the destination of the symlink
+ symlink = archive_entry_symlink(e);
+ if (!symlink)
+ return PAKFIRE_WALK_ERROR;
+
+ // Update path
+ r = pakfire_path_merge(cookie->path, cookie->path, symlink);
+ if (r)
+ return PAKFIRE_WALK_ERROR;
+
+ return PAKFIRE_WALK_AGAIN;
+ }
+
return PAKFIRE_WALK_DONE;
+ }
// Otherwise we skip the file
return PAKFIRE_WALK_SKIP;
return PAKFIRE_WALK_DONE;
}
-PAKFIRE_EXPORT FILE* pakfire_archive_read(struct pakfire_archive* archive, const char* path) {
+PAKFIRE_EXPORT FILE* pakfire_archive_read(struct pakfire_archive* archive, const char* path, int flags) {
struct pakfire_archive_read_cookie* cookie = NULL;
int r;
// Store a reference to the archive
cookie->archive = pakfire_archive_ref(archive);
+ // Store flags
+ cookie->flags = flags;
+
// Store the path
r = pakfire_string_set(cookie->path, path);
if (r) {
}
// Open the archive
+AGAIN:
cookie->a = open_archive(archive, cookie->f);
if (!cookie->a)
goto ERROR;
// Walk through the archive
r = pakfire_walk(archive->pakfire, cookie->a,
__pakfire_archive_read, __pakfire_archive_read_filter, cookie);
- if (r)
- goto ERROR;
+ if (r) {
+ switch (-r) {
+ case EAGAIN:
+ if (cookie->a)
+ archive_read_free(cookie->a);
+ if (cookie->f)
+ rewind(cookie->f);
+ goto AGAIN;
+
+ default:
+ goto ERROR;
+ }
+ }
// Nothing found
if (!cookie->__f) {
struct pakfire_archive* pakfire_archive_ref(struct pakfire_archive* archive);
struct pakfire_archive* pakfire_archive_unref(struct pakfire_archive* archive);
-FILE* pakfire_archive_read(struct pakfire_archive* archive, const char* filename);
+enum pakfire_archive_read_flags {
+ PAKFIRE_ARCHIVE_READ_FOLLOW_SYMLINKS = (1 << 0),
+};
+
+FILE* pakfire_archive_read(struct pakfire_archive* archive, const char* filename, int flags);
int pakfire_archive_extract(struct pakfire_archive* archive,
const char* path, const int flags);