static zip_int64_t source_hole_cb(void *ud, void *data, zip_uint64_t length, zip_source_cmd_t command) { hole_t *ctx = (hole_t *)ud; switch (command) { case ZIP_SOURCE_BEGIN_WRITE: ctx->out = buffer_new(); return 0; case ZIP_SOURCE_CLOSE: return 0; case ZIP_SOURCE_COMMIT_WRITE: if (buffer_to_file(ctx->out, ctx->fname, &ctx->error) < 0) { return -1; } buffer_free(ctx->in); ctx->in = ctx->out; ctx->out = NULL; return 0; case ZIP_SOURCE_ERROR: return zip_error_to_data(&ctx->error, data, length); case ZIP_SOURCE_FREE: hole_free(ctx); return 0; case ZIP_SOURCE_OPEN: ctx->in->offset = 0; return 0; case ZIP_SOURCE_READ: return buffer_read(ctx->in, data, length, &ctx->error); case ZIP_SOURCE_REMOVE: buffer_free(ctx->in); ctx->in = buffer_new(); buffer_free(ctx->out); ctx->out = NULL; (void)remove(ctx->fname); return 0; case ZIP_SOURCE_ROLLBACK_WRITE: buffer_free(ctx->out); ctx->out = NULL; return 0; case ZIP_SOURCE_SEEK: return buffer_seek(ctx->in, data, length, &ctx->error); case ZIP_SOURCE_SEEK_WRITE: return buffer_seek(ctx->out, data, length, &ctx->error); case ZIP_SOURCE_STAT: { zip_stat_t *st = ZIP_SOURCE_GET_ARGS(zip_stat_t, data, length, &ctx->error); if (st == NULL) { return -1; } /* TODO: return ENOENT if fname doesn't exist */ st->valid |= ZIP_STAT_SIZE; st->size = ctx->in->size; return 0; } case ZIP_SOURCE_TELL: return (zip_int64_t)ctx->in->offset; case ZIP_SOURCE_TELL_WRITE: return (zip_int64_t)ctx->out->offset; case ZIP_SOURCE_WRITE: return buffer_write(ctx->out, data, length, &ctx->error); case ZIP_SOURCE_SUPPORTS: return zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_CLOSE, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_STAT, ZIP_SOURCE_TELL, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1); default: zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); return -1; } }
void course_free(void) { hole_free(); course_state = 0; }