int file_archive_parse_file_iterate( file_archive_transfer_t *state, bool *returnerr, const char *file, const char *valid_exts, file_archive_file_cb file_cb, void *userdata) { if (!state) return -1; switch (state->type) { case ZLIB_TRANSFER_NONE: break; case ZLIB_TRANSFER_INIT: if (file_archive_parse_file_init(state, file) == 0) state->type = ZLIB_TRANSFER_ITERATE; else state->type = ZLIB_TRANSFER_DEINIT_ERROR; break; case ZLIB_TRANSFER_ITERATE: { int ret = file_archive_parse_file_iterate_step(state, valid_exts, userdata, file_cb); if (ret != 1) state->type = ZLIB_TRANSFER_DEINIT; if (ret == -1) state->type = ZLIB_TRANSFER_DEINIT_ERROR; } break; case ZLIB_TRANSFER_DEINIT_ERROR: *returnerr = false; case ZLIB_TRANSFER_DEINIT: if (state->handle) file_archive_free(state->handle); state->handle = NULL; break; } if (state->type == ZLIB_TRANSFER_DEINIT || state->type == ZLIB_TRANSFER_DEINIT_ERROR) return -1; return 0; }
int file_archive_parse_file_iterate( file_archive_transfer_t *state, bool *returnerr, const char *file, const char *valid_exts, file_archive_file_cb file_cb, struct archive_extract_userdata *userdata) { if (!state) return -1; switch (state->type) { case ARCHIVE_TRANSFER_NONE: break; case ARCHIVE_TRANSFER_INIT: if (file_archive_parse_file_init(state, file) == 0) { if (userdata) { userdata->context = state->stream; strlcpy(userdata->archive_path, file, sizeof(userdata->archive_path)); } state->type = ARCHIVE_TRANSFER_ITERATE; } else state->type = ARCHIVE_TRANSFER_DEINIT_ERROR; break; case ARCHIVE_TRANSFER_ITERATE: if (file_archive_get_file_backend(file)) { const struct file_archive_file_backend *backend = file_archive_get_file_backend(file); int ret = backend->archive_parse_file_iterate_step(state, valid_exts, userdata, file_cb); if (ret != 1) state->type = ARCHIVE_TRANSFER_DEINIT; if (ret == -1) state->type = ARCHIVE_TRANSFER_DEINIT_ERROR; /* early return to prevent deinit from never firing */ return 0; } return -1; case ARCHIVE_TRANSFER_DEINIT_ERROR: *returnerr = false; case ARCHIVE_TRANSFER_DEINIT: if (state->handle) { file_archive_free(state->handle); state->handle = NULL; } if (state->stream && state->backend) { if (state->backend->stream_free) state->backend->stream_free(state->stream); if (state->stream) free(state->stream); state->stream = NULL; if (userdata) userdata->context = NULL; } break; } if ( state->type == ARCHIVE_TRANSFER_DEINIT || state->type == ARCHIVE_TRANSFER_DEINIT_ERROR) return -1; return 0; }