static void _zip_check_torrentzip(struct zip *za, const struct zip_cdir *cdir) { uLong crc_got, crc_should; char buf[8+1]; char *end; if (za->zp == NULL || cdir == NULL) return; if (_zip_string_length(cdir->comment) != TORRENT_SIG_LEN+8 || strncmp((const char *)cdir->comment->raw, TORRENT_SIG, TORRENT_SIG_LEN) != 0) return; memcpy(buf, cdir->comment->raw+TORRENT_SIG_LEN, 8); buf[8] = '\0'; errno = 0; crc_should = strtoul(buf, &end, 16); if ((crc_should == UINT_MAX && errno != 0) || (end && *end)) return; if (_zip_filerange_crc(za->zp, cdir->offset, cdir->size, &crc_got, NULL) < 0) return; if (crc_got == crc_should) za->flags |= ZIP_AFL_TORRENT; }
static int write_cdir(struct zip *za, struct zip_cdir *cd, FILE *out) { off_t offset; uLong crc; char buf[TORRENT_CRC_LEN+1]; if (_zip_cdir_write(cd, out, &za->error) < 0) return -1; if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0) return 0; /* fix up torrentzip comment */ offset = ftello(out); if (_zip_filerange_crc(out, cd->offset, cd->size, &crc, &za->error) < 0) return -1; snprintf(buf, sizeof(buf), "%08lX", (long)crc); if (fseeko(out, offset-TORRENT_CRC_LEN, SEEK_SET) < 0) { _zip_error_set(&za->error, ZIP_ER_SEEK, errno); return -1; } if (fwrite(buf, TORRENT_CRC_LEN, 1, out) != 1) { _zip_error_set(&za->error, ZIP_ER_WRITE, errno); return -1; } return 0; }
static int write_cdir(struct zip *za, const struct zip_filelist *filelist, zip_uint64_t survivors, FILE *out) { off_t cd_start, end; zip_int64_t size; uLong crc; char buf[TORRENT_CRC_LEN+1]; cd_start = ftello(out); if ((size=_zip_cdir_write(za, filelist, survivors, out)) < 0) return -1; end = ftello(out); if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0) == 0) return 0; /* fix up torrentzip comment */ if (_zip_filerange_crc(out, cd_start, size, &crc, &za->error) < 0) return -1; snprintf(buf, sizeof(buf), "%08lX", (long)crc); if (fseeko(out, end-TORRENT_CRC_LEN, SEEK_SET) < 0) { _zip_error_set(&za->error, ZIP_ER_SEEK, errno); return -1; } if (fwrite(buf, TORRENT_CRC_LEN, 1, out) != 1) { _zip_error_set(&za->error, ZIP_ER_WRITE, errno); return -1; } return 0; }