From fb8deb69a6afc311deb2c3f9bfa13e460e03256f Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 18 Jul 2016 12:44:56 +0200 Subject: [PATCH] libarchive: unify entry iteration between stream/demux layers No really good reason to duplicate this. --- demux/demux_libarchive.c | 19 ++--------- stream/stream_libarchive.c | 69 ++++++++++++++++++++++++-------------- stream/stream_libarchive.h | 8 +++++ 3 files changed, 54 insertions(+), 42 deletions(-) diff --git a/demux/demux_libarchive.c b/demux/demux_libarchive.c index 3f1a655726..dcdbe65fc0 100644 --- a/demux/demux_libarchive.c +++ b/demux/demux_libarchive.c @@ -65,23 +65,10 @@ static int open_file(struct demuxer *demuxer, enum demux_check check) char **files = NULL; int num_files = 0; - for (;;) { - struct archive_entry *entry; - int r = archive_read_next_header(mpa->arch, &entry); - if (r == ARCHIVE_EOF) - break; - if (r < ARCHIVE_OK) - MP_ERR(demuxer, "%s\n", archive_error_string(mpa->arch)); - if (r < ARCHIVE_WARN) - break; - if (archive_entry_filetype(entry) != AE_IFREG) - continue; - const char *fn = archive_entry_pathname(entry); - // Some archives may have no filenames. - if (!fn) - fn = talloc_asprintf(mpa, "mpv_unknown#%d\n", num_files); + while (mp_archive_next_entry(mpa)) { // stream_libarchive.c does the real work - char *f = talloc_asprintf(mpa, "archive://%s|%s", prefix, fn); + char *f = talloc_asprintf(mpa, "archive://%s|%s", prefix, + mpa->entry_filename); MP_TARRAY_APPEND(mpa, files, num_files, f); } diff --git a/stream/stream_libarchive.c b/stream/stream_libarchive.c index a164da85b8..9d93af5450 100644 --- a/stream/stream_libarchive.c +++ b/stream/stream_libarchive.c @@ -218,6 +218,7 @@ struct mp_archive *mp_archive_new(struct mp_log *log, struct stream *src, int flags) { struct mp_archive *mpa = talloc_zero(NULL, struct mp_archive); + mpa->log = log; mpa->arch = archive_read_new(); mpa->primary_src = src; if (!mpa->arch) @@ -265,6 +266,43 @@ err: return NULL; } +// Iterate entries. The first call establishes the first entry. Returns false +// if no entry found, otherwise returns true and sets mpa->entry/entry_filename. +bool mp_archive_next_entry(struct mp_archive *mpa) +{ + mpa->entry = NULL; + talloc_free(mpa->entry_filename); + mpa->entry_filename = NULL; + + for (;;) { + struct archive_entry *entry; + int r = archive_read_next_header(mpa->arch, &entry); + if (r == ARCHIVE_EOF) + break; + if (r < ARCHIVE_OK) + MP_ERR(mpa, "%s\n", archive_error_string(mpa->arch)); + if (r < ARCHIVE_WARN) { + MP_FATAL(mpa, "could not read archive entry\n"); + break; + } + if (archive_entry_filetype(entry) != AE_IFREG) + continue; + // Some archives may have no filenames, or libarchive won't return some. + const char *fn = archive_entry_pathname(entry); + char buf[64]; + if (!fn) { + snprintf(buf, sizeof(buf), "mpv_unknown#%d\n", mpa->entry_num); + fn = buf; + } + mpa->entry = entry; + mpa->entry_filename = talloc_strdup(mpa, fn); + mpa->entry_num += 1; + return true; + } + + return false; +} + struct priv { struct mp_archive *mpa; struct stream *src; @@ -282,39 +320,18 @@ static int reopen_archive(stream_t *s) // Follows the same logic as demux_libarchive.c. struct mp_archive *mpa = p->mpa; - int num_files = 0; - for (;;) { - struct archive_entry *entry; - int r = archive_read_next_header(mpa->arch, &entry); - if (r == ARCHIVE_EOF) { - MP_ERR(s, "archive entry not found. '%s'\n", p->entry_name); - goto error; - } - if (r < ARCHIVE_OK) - MP_ERR(s, "%s\n", archive_error_string(mpa->arch)); - if (r < ARCHIVE_WARN) - goto error; - if (archive_entry_filetype(entry) != AE_IFREG) - continue; - const char *fn = archive_entry_pathname(entry); - char buf[64]; - if (!fn) { - snprintf(buf, sizeof(buf), "mpv_unknown#%d\n", num_files); - fn = buf; - } - if (strcmp(p->entry_name, fn) == 0) { + while (mp_archive_next_entry(mpa)) { + if (strcmp(p->entry_name, mpa->entry_filename) == 0) { p->entry_size = -1; - if (archive_entry_size_is_set(entry)) - p->entry_size = archive_entry_size(entry); + if (archive_entry_size_is_set(mpa->entry)) + p->entry_size = archive_entry_size(mpa->entry); return STREAM_OK; } - num_files++; } -error: mp_archive_free(p->mpa); p->mpa = NULL; - MP_ERR(s, "could not open archive\n"); + MP_ERR(s, "archive entry not found. '%s'\n", p->entry_name); return STREAM_ERROR; } diff --git a/stream/stream_libarchive.h b/stream/stream_libarchive.h index ebded5b5ba..c15dc1b528 100644 --- a/stream/stream_libarchive.h +++ b/stream/stream_libarchive.h @@ -1,9 +1,15 @@ struct mp_log; struct mp_archive { + struct mp_log *log; struct archive *arch; struct stream *primary_src; char buffer[4096]; + + // Current entry, as set by mp_archive_next_entry(). + struct archive_entry *entry; + char *entry_filename; + int entry_num; }; void mp_archive_free(struct mp_archive *mpa); @@ -11,3 +17,5 @@ void mp_archive_free(struct mp_archive *mpa); #define MP_ARCHIVE_FLAG_UNSAFE 1 struct mp_archive *mp_archive_new(struct mp_log *log, struct stream *src, int flags); + +bool mp_archive_next_entry(struct mp_archive *mpa);