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 void hash_header(git_hash_ctx *ctx, git_off_t len, git_otype type) { char buffer[64]; size_t hdrlen; hdrlen = git_odb__format_object_header(buffer, sizeof(buffer), (size_t)len, type); git_hash_update(ctx, buffer, hdrlen); }
static void hash_header(git_hash_ctx *ctx, size_t size, git_otype type) { char header[64]; int hdrlen; hdrlen = git_odb__format_object_header(header, sizeof(header), size, type); git_hash_update(ctx, header, hdrlen); }
void test_odb_largefiles__streamread(void) { git_oid oid, read_oid; git_odb_stream *stream; char buf[10240]; char hdr[64]; size_t len, hdr_len, total = 0; git_hash_ctx hash; git_otype type; int ret; #ifndef GIT_ARCH_64 cl_skip(); #endif if (!cl_is_env_set("GITTEST_INVASIVE_FS_SIZE") || !cl_is_env_set("GITTEST_SLOW")) cl_skip(); writefile(&oid); cl_git_pass(git_odb_open_rstream(&stream, &len, &type, odb, &oid)); cl_assert_equal_sz(LARGEFILE_SIZE, len); cl_assert_equal_i(GIT_OBJ_BLOB, type); cl_git_pass(git_hash_ctx_init(&hash)); cl_git_pass(git_odb__format_object_header(&hdr_len, hdr, sizeof(hdr), len, type)); cl_git_pass(git_hash_update(&hash, hdr, hdr_len)); while ((ret = git_odb_stream_read(stream, buf, 10240)) > 0) { cl_git_pass(git_hash_update(&hash, buf, ret)); total += ret; } cl_assert_equal_sz(LARGEFILE_SIZE, total); git_hash_final(&read_oid, &hash); cl_assert_equal_oid(&oid, &read_oid); git_hash_ctx_cleanup(&hash); git_odb_stream_free(stream); }
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 loose_backend__writestream(git_odb_stream **stream_out, git_odb_backend *_backend, git_off_t length, git_otype type) { loose_backend *backend; loose_writestream *stream = NULL; char hdr[MAX_HEADER_LEN]; git_buf tmp_path = GIT_BUF_INIT; size_t hdrlen; int error; assert(_backend && length >= 0); backend = (loose_backend *)_backend; *stream_out = NULL; if ((error = git_odb__format_object_header(&hdrlen, hdr, sizeof(hdr), length, type)) < 0) return error; stream = git__calloc(1, sizeof(loose_writestream)); GITERR_CHECK_ALLOC(stream); stream->stream.backend = _backend; stream->stream.read = NULL; /* read only */ stream->stream.write = &loose_backend__writestream_write; stream->stream.finalize_write = &loose_backend__writestream_finalize; stream->stream.free = &loose_backend__writestream_free; stream->stream.mode = GIT_STREAM_WRONLY; if (git_buf_joinpath(&tmp_path, backend->objects_dir, "tmp_object") < 0 || git_filebuf_open(&stream->fbuf, tmp_path.ptr, filebuf_flags(backend), backend->object_file_mode) < 0 || stream->stream.write((git_odb_stream *)stream, hdr, hdrlen) < 0) { git_filebuf_cleanup(&stream->fbuf); git__free(stream); stream = NULL; } git_buf_dispose(&tmp_path); *stream_out = (git_odb_stream *)stream; return !stream ? -1 : 0; }
static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, const void *data, size_t len, git_otype type) { int error = 0; git_buf final_path = GIT_BUF_INIT; char header[MAX_HEADER_LEN]; size_t header_len; git_filebuf fbuf = GIT_FILEBUF_INIT; loose_backend *backend; backend = (loose_backend *)_backend; /* prepare the header for the file */ if ((error = git_odb__format_object_header(&header_len, header, sizeof(header), len, type)) < 0) goto cleanup; if (git_buf_joinpath(&final_path, backend->objects_dir, "tmp_object") < 0 || git_filebuf_open(&fbuf, final_path.ptr, filebuf_flags(backend), backend->object_file_mode) < 0) { error = -1; goto cleanup; } git_filebuf_write(&fbuf, header, header_len); git_filebuf_write(&fbuf, data, len); if (object_file_name(&final_path, backend, oid) < 0 || object_mkdir(&final_path, backend) < 0 || git_filebuf_commit_at(&fbuf, final_path.ptr) < 0) error = -1; cleanup: if (error < 0) git_filebuf_cleanup(&fbuf); git_buf_dispose(&final_path); return error; }