static int reopen_archive(stream_t *s) { struct priv *p = s->priv; mp_archive_free(p->mpa); p->mpa = mp_archive_new(s->log, p->src, MP_ARCHIVE_FLAG_UNSAFE); if (!p->mpa) return STREAM_ERROR; // Follows the same logic as demux_libarchive.c. struct mp_archive *mpa = p->mpa; while (mp_archive_next_entry(mpa)) { if (strcmp(p->entry_name, mpa->entry_filename) == 0) { locale_t oldlocale = uselocale(mpa->locale); p->entry_size = -1; if (archive_entry_size_is_set(mpa->entry)) p->entry_size = archive_entry_size(mpa->entry); uselocale(oldlocale); return STREAM_OK; } } mp_archive_free(p->mpa); p->mpa = NULL; MP_ERR(s, "archive entry not found. '%s'\n", p->entry_name); return STREAM_ERROR; }
static int open_file(struct demuxer *demuxer, enum demux_check check) { if (stream_get_size(demuxer->stream) == 0) return -1; int flags = 0; if (check <= DEMUX_CHECK_REQUEST) flags |= MP_ARCHIVE_FLAG_UNSAFE; struct mp_archive *mpa = mp_archive_new(demuxer->log, demuxer->stream, flags); if (!mpa) return -1; struct playlist *pl = talloc_zero(demuxer, struct playlist); demuxer->playlist = pl; // make it load archive:// pl->disable_safety = true; char *prefix = mp_url_escape(mpa, demuxer->stream->url, "~|"); 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, "libarchive: %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 char *f = talloc_asprintf(mpa, "archive://%s|%s", prefix, fn); MP_TARRAY_APPEND(mpa, files, num_files, f); } if (files) qsort(files, num_files, sizeof(files[0]), cmp_filename); for (int n = 0; n < num_files; n++) playlist_add_file(pl, files[n]); demuxer->filetype = "archive"; demuxer->fully_read = true; mp_archive_free(mpa); return 0; }