static int fetch_icstream(struct icstream *ics) { #if WITH_LZO int retval; unsigned short int *iptr = ics->ibuf; lzo_uint ilen = 2 * sizeof(*iptr), olen, clen; if (read_istream(ics->impl, iptr, ilen) < ilen) goto fail_io; ilen = *iptr++; olen = *iptr++; if (olen > ics->size) goto fail_size; if (read_istream(ics->impl, iptr, ilen) < ilen) goto fail_io; retval = lzo1x_decompress((unsigned char*)iptr, ilen, ics->obuf, &clen, NULL); if (retval != LZO_E_OK) goto fail_lzo; ics->used = olen; ics->free = 0; return 0; fail_io: return -1; fail_lzo: return -2; fail_size: return -3; #else ics->used = read_istream(ics->impl, ics->obuf, ics->size); ics->free = 0; return 0; #endif }
long long int pipe_streams(struct istream *i, struct ostream *o) { char buf[4096], *ptr; long long int size = 0; for (;;) { long long int rsize = read_istream(i, buf, sizeof(buf)); if (rsize < 0) { logf_e("i/o read error #%lld", rsize); return rsize; } if (!rsize) break; ptr = buf; while (rsize) { long long int wsize = write_ostream(o, ptr, rsize); if (wsize < 0) { logf_e("i/o write error #%lld", wsize); return wsize; } rsize -= wsize; ptr += wsize; size += wsize; } } return size; }
long long int fill_membuf(struct membuf *self, struct istream *istream) { unsigned long long int offset = self->off; long long int retval; for (;;) { if (self->off >= self->len) { unsigned char *tmp; self->len += 4096; tmp = b6_reallocate(self->allocator, self->buf, self->len); if (!tmp) { log_w(_s("out of memory")); retval = -1; break; } self->buf = tmp; } if ((retval = read_istream(istream, self->buf + self->off, self->len - self->off)) <= 0) break; self->off += retval; } if (retval < 0) { logf_w("error %d", retval); self->off = offset; } else retval = self->off - offset; return retval; }
static read_method_decl(filtered) { struct filtered_istream *fs = &(st->u.filtered); size_t filled = 0; while (sz) { /* do we already have filtered output? */ if (fs->o_ptr < fs->o_end) { size_t to_move = fs->o_end - fs->o_ptr; if (sz < to_move) to_move = sz; memcpy(buf + filled, fs->obuf + fs->o_ptr, to_move); fs->o_ptr += to_move; sz -= to_move; filled += to_move; continue; } fs->o_end = fs->o_ptr = 0; /* do we have anything to feed the filter with? */ if (fs->i_ptr < fs->i_end) { size_t to_feed = fs->i_end - fs->i_ptr; size_t to_receive = FILTER_BUFFER; if (stream_filter(fs->filter, fs->ibuf + fs->i_ptr, &to_feed, fs->obuf, &to_receive)) return -1; fs->i_ptr = fs->i_end - to_feed; fs->o_end = FILTER_BUFFER - to_receive; continue; } /* tell the filter to drain upon no more input */ if (fs->input_finished) { size_t to_receive = FILTER_BUFFER; if (stream_filter(fs->filter, NULL, NULL, fs->obuf, &to_receive)) return -1; fs->o_end = FILTER_BUFFER - to_receive; if (!fs->o_end) break; continue; } fs->i_end = fs->i_ptr = 0; /* refill the input from the upstream */ if (!fs->input_finished) { fs->i_end = read_istream(fs->upstream, fs->ibuf, FILTER_BUFFER); if (fs->i_end < 0) return -1; if (fs->i_end) continue; } fs->input_finished = 1; } return filled; }
int stream_blob_to_fd(int fd, unsigned const char *sha1, struct stream_filter *filter, int can_seek) { struct git_istream *st; enum object_type type; unsigned long sz; ssize_t kept = 0; int result = -1; st = open_istream(sha1, &type, &sz, filter); if (!st) { if (filter) free_stream_filter(filter); return result; } if (type != OBJ_BLOB) goto close_and_exit; for (;;) { char buf[1024 * 16]; ssize_t wrote, holeto; ssize_t readlen = read_istream(st, buf, sizeof(buf)); if (readlen < 0) goto close_and_exit; if (!readlen) break; if (can_seek && sizeof(buf) == readlen) { for (holeto = 0; holeto < readlen; holeto++) if (buf[holeto]) break; if (readlen == holeto) { kept += holeto; continue; } } if (kept && lseek(fd, kept, SEEK_CUR) == (off_t) -1) goto close_and_exit; else kept = 0; wrote = write_in_full(fd, buf, readlen); if (wrote != readlen) goto close_and_exit; } if (kept && (lseek(fd, kept - 1, SEEK_CUR) == (off_t) -1 || xwrite(fd, "", 1) != 1)) goto close_and_exit; result = 0; close_and_exit: close_istream(st); return result; }
/* * queues up writes, so that all our write(2) calls write exactly one * full block; pads writes to RECORDSIZE */ static int stream_blocked(const unsigned char *sha1) { struct git_istream *st; enum object_type type; unsigned long sz; char buf[BLOCKSIZE]; ssize_t readlen; st = open_istream(sha1, &type, &sz, NULL); if (!st) return error("cannot stream blob %s", sha1_to_hex(sha1)); for (;;) { readlen = read_istream(st, buf, sizeof(buf)); if (readlen <= 0) break; do_write_blocked(buf, readlen); } close_istream(st); if (!readlen) finish_record(); return readlen; }
static long long int read_izstream(struct istream *up, void *buf, unsigned long long int len) { struct izstream *self = b6_cast_of(up, struct izstream, up); int retval; if (!self->zstream.avail_in) { self->zstream.next_in = self->buf; self->zstream.avail_in = read_istream(self->istream, self->buf, self->len); } self->zstream.next_out = buf; self->zstream.avail_out = len; retval = inflate(&self->zstream, Z_SYNC_FLUSH); switch (retval) { case Z_NEED_DICT: case Z_DATA_ERROR: case Z_MEM_ERROR: case Z_STREAM_ERROR: return -1; case Z_STREAM_END: default: return len - self->zstream.avail_out; } }
static int write_zip_entry(struct archiver_args *args, const unsigned char *sha1, const char *path, size_t pathlen, unsigned int mode, int big_file_threshold, int zip_dir_size, int zip_dir_offset, int zip_dir, int zip_time, int zip_date, int zip_offset, int zip_dir_entries) { struct zip_local_header header; struct zip_dir_header dirent; struct zip_extra_mtime extra; unsigned long attr2 = 0; unsigned long compressed_size = 0; unsigned long crc = 0; unsigned long direntsize = 0; int method = 0; int out = 0; int deflated = 0; int buffer = 0; int stream = 0; unsigned long flags = 0; unsigned long size = 0; crc = crc32(0, NULL, 0); if (!has_only_ascii(path)) { if (is_utf8(path)) flags |= ZIP_UTF8; else warning("Path is not valid UTF-8: %s", path); } if (pathlen > 0xffff) { return error("path too long (%d chars, SHA1: %s): %s", (int)pathlen, sha1_to_hex(sha1), path); } if (S_ISDIR(mode) || S_ISGITLINK(mode)) { method = 0; attr2 = 16; out = NULL; size = 0; compressed_size = 0; buffer = NULL; } else if (S_ISREG(mode) || S_ISLNK(mode)) { int type = sha1_object_info(sha1, &size); method = 0; attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) : (mode & 0111) ? ((mode) << 16) : 0; if (S_ISREG(mode) && args->compression_level != 0 && size > 0) method = 8; if (method == 0) { compressed_size = size; } else { compressed_size = 0; } if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert && size > big_file_threshold) { stream = open_istream(sha1, &type, &size, NULL); if (!stream) return error("cannot stream blob %s", sha1_to_hex(sha1)); flags |= ZIP_STREAM; out = buffer = NULL; } else { buffer = sha1_file_to_archive(args, path, sha1, mode, &type, &size); if (!buffer) return error("cannot read %s", sha1_to_hex(sha1)); crc = crc32(crc, buffer, size); out = buffer; } } else { return error("unsupported file mode: 0%o (SHA1: %s)", mode, sha1_to_hex(sha1)); } if (buffer && method == 8) { deflated = zlib_deflate(buffer, size, args->compression_level, &compressed_size); if (deflated && compressed_size - 6 < size) { /* ZLIB --> raw compressed data (see RFC 1950) */ /* CMF and FLG ... */ out = deflated + 2; compressed_size -= 6; /* ... and ADLER32 */ } else { method = 0; compressed_size = size; } } copy_le16(extra.magic, 0x5455); copy_le16(extra.extra_size, ZIP_EXTRA_MTIME_PAYLOAD_SIZE); extra.flags[0] = 1; /* just mtime */ copy_le32(extra.mtime, args->time); /* make sure we have enough free space in the dictionary */ direntsize = ZIP_DIR_HEADER_SIZE + pathlen + ZIP_EXTRA_MTIME_SIZE; while (zip_dir_size < zip_dir_offset + direntsize) { zip_dir_size += ZIP_DIRECTORY_MIN_SIZE; zip_dir = xrealloc(zip_dir, zip_dir_size); } copy_le32(dirent.magic, 0x02014b50); copy_le16(dirent.creator_version, S_ISLNK(mode) || (S_ISREG(mode) && (mode & 0111)) ? 0x0317 : 0); copy_le16(dirent.version, 10); copy_le16(dirent.flags, flags); copy_le16(dirent.compression_method, method); copy_le16(dirent.mtime, zip_time); copy_le16(dirent.mdate, zip_date); set_zip_dir_data_desc(&dirent, size, compressed_size, crc); copy_le16(dirent.filename_length, pathlen); copy_le16(dirent.extra_length, ZIP_EXTRA_MTIME_SIZE); copy_le16(dirent.comment_length, 0); copy_le16(dirent.disk, 0); copy_le16(dirent.attr1, 0); copy_le32(dirent.attr2, attr2); copy_le32(dirent.offset, zip_offset); copy_le32(header.magic, 0x04034b50); copy_le16(header.version, 10); copy_le16(header.flags, flags); copy_le16(header.compression_method, method); copy_le16(header.mtime, zip_time); copy_le16(header.mdate, zip_date); set_zip_header_data_desc(&header, size, compressed_size, crc); copy_le16(header.filename_length, pathlen); copy_le16(header.extra_length, ZIP_EXTRA_MTIME_SIZE); write_or_die(1, &header, ZIP_LOCAL_HEADER_SIZE); zip_offset += ZIP_LOCAL_HEADER_SIZE; write_or_die(1, path, pathlen); zip_offset += pathlen; write_or_die(1, &extra, ZIP_EXTRA_MTIME_SIZE); zip_offset += ZIP_EXTRA_MTIME_SIZE; if (stream && method == 0) { unsigned char buf[STREAM_BUFFER_SIZE]; ssize_t readlen = 0; for (;;) { readlen = read_istream(stream, buf, sizeof(buf)); if (readlen <= 0) break; crc = crc32(crc, buf, readlen); write_or_die(1, buf, readlen); } close_istream(stream); if (readlen) return readlen; compressed_size = size; zip_offset += compressed_size; write_zip_data_desc(size, compressed_size, crc); zip_offset += ZIP_DATA_DESC_SIZE; set_zip_dir_data_desc(&dirent, size, compressed_size, crc); } else if (stream && method == 8) { int buf; ssize_t readlen; git_zstream zstream; int result; size_t out_len; int compressed; memset(&zstream, 0, sizeof(zstream)); git_deflate_init(&zstream, args->compression_level); compressed_size = 0; zstream.next_out = compressed; zstream.avail_out = sizeof(compressed); for (;;) { readlen = read_istream(stream, buf, sizeof(buf)); if (readlen <= 0) break; crc = crc32(crc, buf, readlen); zstream.next_in = buf; zstream.avail_in = readlen; result = git_deflate(&zstream, 0); if (result != Z_OK) die("deflate error (%d)", result); out = compressed; if (!compressed_size) out += 2; out_len = zstream.next_out - out; if (out_len > 0) { write_or_die(1, out, out_len); compressed_size += out_len; zstream.next_out = compressed; zstream.avail_out = sizeof(compressed); } } close_istream(stream); if (readlen) return readlen; zstream.next_in = buf; zstream.avail_in = 0; result = git_deflate(&zstream, Z_FINISH); if (result != Z_STREAM_END) die("deflate error (%d)", result); git_deflate_end(&zstream); out = compressed; if (!compressed_size) out += 2; out_len = zstream.next_out - out - 4; write_or_die(1, out, out_len); compressed_size += out_len; zip_offset += compressed_size; write_zip_data_desc(size, compressed_size, crc); zip_offset += ZIP_DATA_DESC_SIZE; set_zip_dir_data_desc(&dirent, size, compressed_size, crc); } else if (compressed_size > 0) { write_or_die(1, out, compressed_size); zip_offset += compressed_size; } free(deflated); free(buffer); memcpy(zip_dir + zip_dir_offset, &dirent, ZIP_DIR_HEADER_SIZE); zip_dir_offset += ZIP_DIR_HEADER_SIZE; memcpy(zip_dir + zip_dir_offset, path, pathlen); zip_dir_offset += pathlen; memcpy(zip_dir + zip_dir_offset, &extra, ZIP_EXTRA_MTIME_SIZE); zip_dir_offset += ZIP_EXTRA_MTIME_SIZE; zip_dir_entries++; return 0; }