1
0
mirror of https://github.com/mpv-player/mpv synced 2025-03-21 10:51:51 +00:00

libarchive: unify entry iteration between stream/demux layers

No really good reason to duplicate this.
This commit is contained in:
wm4 2016-07-18 12:44:56 +02:00
parent 77e1e8e38e
commit fb8deb69a6
3 changed files with 54 additions and 42 deletions

View File

@ -65,23 +65,10 @@ static int open_file(struct demuxer *demuxer, enum demux_check check)
char **files = NULL; char **files = NULL;
int num_files = 0; int num_files = 0;
for (;;) { while (mp_archive_next_entry(mpa)) {
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);
// stream_libarchive.c does the real work // 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); MP_TARRAY_APPEND(mpa, files, num_files, f);
} }

View File

@ -218,6 +218,7 @@ struct mp_archive *mp_archive_new(struct mp_log *log, struct stream *src,
int flags) int flags)
{ {
struct mp_archive *mpa = talloc_zero(NULL, struct mp_archive); struct mp_archive *mpa = talloc_zero(NULL, struct mp_archive);
mpa->log = log;
mpa->arch = archive_read_new(); mpa->arch = archive_read_new();
mpa->primary_src = src; mpa->primary_src = src;
if (!mpa->arch) if (!mpa->arch)
@ -265,6 +266,43 @@ err:
return NULL; 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 priv {
struct mp_archive *mpa; struct mp_archive *mpa;
struct stream *src; struct stream *src;
@ -282,39 +320,18 @@ static int reopen_archive(stream_t *s)
// Follows the same logic as demux_libarchive.c. // Follows the same logic as demux_libarchive.c.
struct mp_archive *mpa = p->mpa; struct mp_archive *mpa = p->mpa;
int num_files = 0; while (mp_archive_next_entry(mpa)) {
for (;;) { if (strcmp(p->entry_name, mpa->entry_filename) == 0) {
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) {
p->entry_size = -1; p->entry_size = -1;
if (archive_entry_size_is_set(entry)) if (archive_entry_size_is_set(mpa->entry))
p->entry_size = archive_entry_size(entry); p->entry_size = archive_entry_size(mpa->entry);
return STREAM_OK; return STREAM_OK;
} }
num_files++;
} }
error:
mp_archive_free(p->mpa); mp_archive_free(p->mpa);
p->mpa = NULL; 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; return STREAM_ERROR;
} }

View File

@ -1,9 +1,15 @@
struct mp_log; struct mp_log;
struct mp_archive { struct mp_archive {
struct mp_log *log;
struct archive *arch; struct archive *arch;
struct stream *primary_src; struct stream *primary_src;
char buffer[4096]; 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); 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 #define MP_ARCHIVE_FLAG_UNSAFE 1
struct mp_archive *mp_archive_new(struct mp_log *log, struct stream *src, struct mp_archive *mp_archive_new(struct mp_log *log, struct stream *src,
int flags); int flags);
bool mp_archive_next_entry(struct mp_archive *mpa);