static int loose_backend__readstream_packlike( obj_hdr *hdr, loose_readstream *stream) { const unsigned char *data; size_t data_len, head_len; int error; data = stream->map.data; data_len = stream->map.len; /* * read the object header, which is an (uncompressed) * binary encoding of the object type and size. */ if ((error = parse_header_packlike(hdr, &head_len, data, data_len)) < 0) return error; if (!git_object_typeisloose(hdr->type)) { giterr_set(GITERR_ODB, "failed to inflate loose object"); return -1; } return git_zstream_set_input(&stream->zstream, data + head_len, data_len - head_len); }
static int loose_backend__readstream_standard( obj_hdr *hdr, loose_readstream *stream) { unsigned char head[MAX_HEADER_LEN]; size_t init, head_len; int error; if ((error = git_zstream_set_input(&stream->zstream, stream->map.data, stream->map.len)) < 0) return error; init = sizeof(head); /* * inflate the initial part of the compressed buffer in order to * parse the header; read the largest header possible, then store * it in the `start` field of the stream object. */ if ((error = git_zstream_get_output(head, &init, &stream->zstream)) < 0 || (error = parse_header(hdr, &head_len, head, init)) < 0) return error; if (!git_object_typeisloose(hdr->type)) { giterr_set(GITERR_ODB, "failed to inflate disk object"); return -1; } if (init > head_len) { stream->start_len = init - head_len; memcpy(stream->start, head + head_len, init - head_len); } return 0; }
int git_odb__hashobj(git_oid *id, git_rawobj *obj) { git_buf_vec vec[2]; char header[64]; int hdrlen; assert(id && obj); if (!git_object_typeisloose(obj->type)) return -1; if (!obj->data && obj->len != 0) return -1; hdrlen = git_odb__format_object_header(header, sizeof(header), obj->len, obj->type); vec[0].data = header; vec[0].len = hdrlen; vec[1].data = obj->data; vec[1].len = obj->len; git_hash_vec(id, vec, 2); return 0; }
static int read_header_loose(git_rawobj *out, git_buf *loc) { unsigned char obj[1024]; int fd, obj_len, error; assert(out && loc); if (git_buf_oom(loc)) return -1; out->data = NULL; if ((error = fd = git_futils_open_ro(loc->ptr)) < 0 || (error = obj_len = p_read(fd, obj, sizeof(obj))) < 0) goto done; if (!is_zlib_compressed_data(obj, (size_t)obj_len)) error = read_header_loose_packlike(out, obj, (size_t)obj_len); else error = read_header_loose_standard(out, obj, (size_t)obj_len); if (!error && !git_object_typeisloose(out->type)) { giterr_set(GITERR_ZLIB, "failed to read loose object header"); error = -1; goto done; } done: if (fd >= 0) p_close(fd); return error; }
int git_odb__hash_obj(git_oid *id, char *hdr, size_t n, int *len, git_rawobj *obj) { git_buf_vec vec[2]; int hdrlen; assert(id && hdr && len && obj); if (!git_object_typeisloose(obj->type)) return GIT_ERROR; if (!obj->data && obj->len != 0) return GIT_ERROR; if ((hdrlen = format_object_header(hdr, n, obj)) < 0) return GIT_ERROR; *len = hdrlen; vec[0].data = hdr; vec[0].len = hdrlen; vec[1].data = obj->data; vec[1].len = obj->len; git_hash_vec(id, vec, 2); return GIT_SUCCESS; }
/* * At one point, there was a loose object format that was intended to * mimic the format used in pack-files. This was to allow easy copying * of loose object data into packs. This format is no longer used, but * we must still read it. */ static int read_loose_packlike(git_rawobj *out, git_buf *obj) { git_buf body = GIT_BUF_INIT; const unsigned char *obj_data; obj_hdr hdr; size_t obj_len, head_len, alloc_size; int error; obj_data = (unsigned char *)obj->ptr; obj_len = obj->size; /* * read the object header, which is an (uncompressed) * binary encoding of the object type and size. */ if ((error = parse_header_packlike(&hdr, &head_len, obj_data, obj_len)) < 0) goto done; if (!git_object_typeisloose(hdr.type) || head_len > obj_len) { giterr_set(GITERR_ODB, "failed to inflate loose object"); error = -1; goto done; } obj_data += head_len; obj_len -= head_len; /* * allocate a buffer and inflate the data into it */ if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, hdr.size, 1) || git_buf_init(&body, alloc_size) < 0) { error = -1; goto done; } if ((error = git_zstream_inflatebuf(&body, obj_data, obj_len)) < 0) goto done; out->len = hdr.size; out->type = hdr.type; out->data = git_buf_detach(&body); done: git_buf_dispose(&body); return error; }
int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type) { int hdr_len; char hdr[64], buffer[2048]; git_hash_ctx ctx; ssize_t read_len = 0; int error = 0; if (!git_object_typeisloose(type)) { giterr_set(GITERR_INVALID, "Invalid object type for hash"); return -1; } if ((error = git_hash_ctx_init(&ctx)) < 0) return -1; hdr_len = git_odb__format_object_header(hdr, sizeof(hdr), size, type); if ((error = git_hash_update(&ctx, hdr, hdr_len)) < 0) goto done; while (size > 0 && (read_len = p_read(fd, buffer, sizeof(buffer))) > 0) { if ((error = git_hash_update(&ctx, buffer, read_len)) < 0) goto done; size -= read_len; } /* If p_read returned an error code, the read obviously failed. * If size is not zero, the file was truncated after we originally * stat'd it, so we consider this a read failure too */ if (read_len < 0 || size > 0) { giterr_set(GITERR_OS, "Error reading file for hashing"); error = -1; goto done; } error = git_hash_final(out, &ctx); done: git_hash_ctx_cleanup(&ctx); return error; }
static int read_loose_standard(git_rawobj *out, git_buf *obj) { git_zstream zstream = GIT_ZSTREAM_INIT; unsigned char head[MAX_HEADER_LEN], *body = NULL; size_t decompressed, head_len, body_len, alloc_size; obj_hdr hdr; int error; if ((error = git_zstream_init(&zstream, GIT_ZSTREAM_INFLATE)) < 0 || (error = git_zstream_set_input(&zstream, git_buf_cstr(obj), git_buf_len(obj))) < 0) goto done; decompressed = sizeof(head); /* * inflate the initial part of the compressed buffer in order to * parse the header; read the largest header possible, then push the * remainder into the body buffer. */ if ((error = git_zstream_get_output(head, &decompressed, &zstream)) < 0 || (error = parse_header(&hdr, &head_len, head, decompressed)) < 0) goto done; if (!git_object_typeisloose(hdr.type)) { giterr_set(GITERR_ODB, "failed to inflate disk object"); error = -1; goto done; } /* * allocate a buffer and inflate the object data into it * (including the initial sequence in the head buffer). */ if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, hdr.size, 1) || (body = git__malloc(alloc_size)) == NULL) { error = -1; goto done; } assert(decompressed >= head_len); body_len = decompressed - head_len; if (body_len) memcpy(body, head + head_len, body_len); decompressed = hdr.size - body_len; if ((error = git_zstream_get_output(body + body_len, &decompressed, &zstream)) < 0) goto done; if (!git_zstream_done(&zstream)) { giterr_set(GITERR_ZLIB, "failed to finish zlib inflation: stream aborted prematurely"); error = -1; goto done; } body[hdr.size] = '\0'; out->data = body; out->len = hdr.size; out->type = hdr.type; done: if (error < 0) git__free(body); git_zstream_free(&zstream); return error; }
bool Object::isLooseType(git_otype type) { return git_object_typeisloose(type) != 0; }