ZIP_EXTERN int zip_source_stat(zip_source_t *src, zip_stat_t *st) { if (src->source_closed) { return -1; } if (st == NULL) { zip_error_set(&src->error, ZIP_ER_INVAL, 0); return -1; } zip_stat_init(st); if (ZIP_SOURCE_IS_LAYERED(src)) { if (zip_source_stat(src->src, st) < 0) { _zip_error_set_from_source(&src->error, src->src); return -1; } } if (_zip_source_call(src, st, sizeof(*st), ZIP_SOURCE_STAT) < 0) { return -1; } return 0; }
zip_int64_t _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command) { zip_int64_t ret; if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(command)) == 0) { zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0); return -1; } if (src->src == NULL) { ret = src->cb.f(src->ud, data, length, command); } else { ret = src->cb.l(src->src, src->ud, data, length, command); } if (ret < 0) { if (command != ZIP_SOURCE_ERROR && command != ZIP_SOURCE_SUPPORTS) { int e[2]; if (_zip_source_call(src, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) { zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); } else { zip_error_set(&src->error, e[0], e[1]); } } } return ret; }
ZIP_EXTERN void zip_source_rollback_write(zip_source_t *src) { if (src->write_state != ZIP_SOURCE_WRITE_OPEN && src->write_state != ZIP_SOURCE_WRITE_FAILED) { return; } _zip_source_call(src, NULL, 0, ZIP_SOURCE_ROLLBACK_WRITE); src->write_state = ZIP_SOURCE_WRITE_CLOSED; }
zip_int64_t zip_source_read(zip_source_t *src, void *data, zip_uint64_t len) { if (src->source_closed) { return -1; } if (!ZIP_SOURCE_IS_OPEN_READING(src) || len > ZIP_INT64_MAX || (len > 0 && data == NULL)) { zip_error_set(&src->error, ZIP_ER_INVAL, 0); return -1; } return _zip_source_call(src, data, len, ZIP_SOURCE_READ); }
ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *src) { if (src->source_closed) { return -1; } if (!ZIP_SOURCE_IS_OPEN_READING(src)) { zip_error_set(&src->error, ZIP_ER_INVAL, 0); return -1; } return _zip_source_call(src, NULL, 0, ZIP_SOURCE_TELL); }
ZIP_EXTERN int zip_source_seek_write(zip_source_t *src, zip_int64_t offset, int whence) { zip_source_args_seek_t args; if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)) { zip_error_set(&src->error, ZIP_ER_INVAL, 0); return -1; } args.offset = offset; args.whence = whence; return (_zip_source_call(src, &args, sizeof(args), ZIP_SOURCE_SEEK_WRITE) < 0 ? -1 : 0); }
ZIP_EXTERN int zip_source_begin_write(zip_source_t *src) { if (ZIP_SOURCE_IS_OPEN_WRITING(src)) { zip_error_set(&src->error, ZIP_ER_INVAL, 0); return -1; } if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_BEGIN_WRITE) < 0) { return -1; } src->write_state = ZIP_SOURCE_WRITE_OPEN; return 0; }
zip_int8_t zip_source_get_compression_flags(zip_source_t *src) { while (src) { if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_COMPRESSION_FLAGS))) { zip_int64_t ret = _zip_source_call(src, NULL, 0, ZIP_SOURCE_GET_COMPRESSION_FLAGS); if (ret < 0) { return -1; } if (ret > ZIP_COMPRESSION_BITFLAG_MAX) { zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); return -1; } return (zip_int8_t)ret; } src = src->src; } return 0; }
ZIP_EXTERN int zip_source_open(zip_source_t *src) { if (src->source_closed) { return -1; } if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) { zip_error_set(&src->error, ZIP_ER_DELETED, 0); return -1; } if (ZIP_SOURCE_IS_OPEN_READING(src)) { if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) == 0) { zip_error_set(&src->error, ZIP_ER_INUSE, 0); return -1; } } else { if (ZIP_SOURCE_IS_LAYERED(src)) { if (zip_source_open(src->src) < 0) { _zip_error_set_from_source(&src->error, src->src); return -1; } } if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_OPEN) < 0) { if (ZIP_SOURCE_IS_LAYERED(src)) { zip_source_close(src->src); } return -1; } } src->eof = false; src->had_read_error = false; _zip_error_clear(&src->error); src->open_count++; return 0; }