void test_object_raw_hash__hash_by_blocks(void) { git_hash_ctx *ctx; git_oid id1, id2; cl_assert((ctx = git_hash_new_ctx()) != NULL); /* should already be init'd */ git_hash_update(ctx, hello_text, strlen(hello_text)); git_hash_final(&id2, ctx); cl_git_pass(git_oid_fromstr(&id1, hello_id)); cl_assert(git_oid_cmp(&id1, &id2) == 0); /* reinit should permit reuse */ git_hash_init(ctx); git_hash_update(ctx, bye_text, strlen(bye_text)); git_hash_final(&id2, ctx); cl_git_pass(git_oid_fromstr(&id1, bye_id)); cl_assert(git_oid_cmp(&id1, &id2) == 0); git_hash_free_ctx(ctx); }
int git_index__write(git_index *index, git_filelock *file) { static const char NULL_BYTES[] = {0, 0, 0, 0, 0, 0, 0, 0}; int error = 0; unsigned int i; git_hash_ctx *digest; git_oid hash_final; assert(index && file && file->is_locked); if ((digest = git_hash_new_ctx()) == NULL) return GIT_ENOMEM; #define WRITE_WORD(_word) {\ uint32_t network_word = htonl((_word));\ git_filelock_write(file, &network_word, 4);\ git_hash_update(digest, &network_word, 4);\ } #define WRITE_SHORT(_shrt) {\ uint16_t network_shrt = htons((_shrt));\ git_filelock_write(file, &network_shrt, 2);\ git_hash_update(digest, &network_shrt, 2);\ } #define WRITE_BYTES(_bytes, _n) {\ git_filelock_write(file, _bytes, _n);\ git_hash_update(digest, _bytes, _n);\ } WRITE_BYTES(INDEX_HEADER_SIG, 4); WRITE_WORD(INDEX_VERSION_NUMBER); WRITE_WORD(index->entry_count); for (i = 0; i < index->entry_count; ++i) { git_index_entry *entry; size_t path_length, padding; entry = &index->entries[i]; path_length = strlen(entry->path); WRITE_WORD(entry->ctime.seconds); WRITE_WORD(entry->ctime.nanoseconds); WRITE_WORD(entry->mtime.seconds); WRITE_WORD(entry->mtime.nanoseconds); WRITE_WORD(entry->dev); WRITE_WORD(entry->ino); WRITE_WORD(entry->mode); WRITE_WORD(entry->uid); WRITE_WORD(entry->gid); WRITE_WORD(entry->file_size); WRITE_BYTES(entry->oid.id, GIT_OID_RAWSZ); WRITE_SHORT(entry->flags); if (entry->flags & GIT_IDXENTRY_EXTENDED) { WRITE_SHORT(entry->flags_extended); padding = long_entry_padding(path_length); } else padding = short_entry_padding(path_length); WRITE_BYTES(entry->path, path_length); WRITE_BYTES(NULL_BYTES, padding); } #undef WRITE_WORD #undef WRITE_BYTES #undef WRITE_SHORT #undef WRITE_FLAGS /* TODO: write extensions (tree cache) */ git_hash_final(&hash_final, digest); git_hash_free_ctx(digest); git_filelock_write(file, hash_final.id, GIT_OID_RAWSZ); return error; }
int git_filebuf_open(git_filebuf *file, const char *path, int flags) { int compression; size_t path_len; /* opening an already open buffer is a programming error; * assert that this never happens instead of returning * an error code */ assert(file && path && file->buffer == NULL); memset(file, 0x0, sizeof(git_filebuf)); if (flags & GIT_FILEBUF_DO_NOT_BUFFER) file->do_not_buffer = true; file->buf_size = WRITE_BUFFER_SIZE; file->buf_pos = 0; file->fd = -1; file->last_error = BUFERR_OK; /* Allocate the main cache buffer */ if (!file->do_not_buffer) { file->buffer = git__malloc(file->buf_size); GITERR_CHECK_ALLOC(file->buffer); } /* If we are hashing on-write, allocate a new hash context */ if (flags & GIT_FILEBUF_HASH_CONTENTS) { file->digest = git_hash_new_ctx(); GITERR_CHECK_ALLOC(file->digest); } compression = flags >> GIT_FILEBUF_DEFLATE_SHIFT; /* If we are deflating on-write, */ if (compression != 0) { /* Initialize the ZLib stream */ if (deflateInit(&file->zs, compression) != Z_OK) { giterr_set(GITERR_ZLIB, "Failed to initialize zlib"); goto cleanup; } /* Allocate the Zlib cache buffer */ file->z_buf = git__malloc(file->buf_size); GITERR_CHECK_ALLOC(file->z_buf); /* Never flush */ file->flush_mode = Z_NO_FLUSH; file->write = &write_deflate; } else { file->write = &write_normal; } /* If we are writing to a temp file */ if (flags & GIT_FILEBUF_TEMPORARY) { git_buf tmp_path = GIT_BUF_INIT; /* Open the file as temporary for locking */ file->fd = git_futils_mktmp(&tmp_path, path); if (file->fd < 0) { git_buf_free(&tmp_path); goto cleanup; } file->fd_is_open = true; /* No original path */ file->path_original = NULL; file->path_lock = git_buf_detach(&tmp_path); GITERR_CHECK_ALLOC(file->path_lock); } else { path_len = strlen(path); /* Save the original path of the file */ file->path_original = git__strdup(path); GITERR_CHECK_ALLOC(file->path_original); /* create the locking path by appending ".lock" to the original */ file->path_lock = git__malloc(path_len + GIT_FILELOCK_EXTLENGTH); GITERR_CHECK_ALLOC(file->path_lock); memcpy(file->path_lock, file->path_original, path_len); memcpy(file->path_lock + path_len, GIT_FILELOCK_EXTENSION, GIT_FILELOCK_EXTLENGTH); /* open the file for locking */ if (lock_file(file, flags) < 0) goto cleanup; } return 0; cleanup: git_filebuf_cleanup(file); return -1; }
int git_filebuf_open(git_filebuf *file, const char *path, int flags) { int error; size_t path_len; assert(file && path); memset(file, 0x0, sizeof(git_filebuf)); file->buf_size = WRITE_BUFFER_SIZE; file->buf_pos = 0; file->fd = -1; /* Allocate the main cache buffer */ file->buffer = git__malloc(file->buf_size); if (file->buffer == NULL) { error = GIT_ENOMEM; goto cleanup; } /* If we are hashing on-write, allocate a new hash context */ if (flags & GIT_FILEBUF_HASH_CONTENTS) { if ((file->digest = git_hash_new_ctx()) == NULL) { error = GIT_ENOMEM; goto cleanup; } } /* If we are deflating on-write, */ if (flags & GIT_FILEBUF_DEFLATE_CONTENTS) { /* Initialize the ZLib stream */ if (deflateInit(&file->zs, Z_BEST_SPEED) != Z_OK) { error = git__throw(GIT_EZLIB, "Failed to initialize zlib"); goto cleanup; } /* Allocate the Zlib cache buffer */ file->z_buf = git__malloc(file->buf_size); if (file->z_buf == NULL) { error = GIT_ENOMEM; goto cleanup; } /* Never flush */ file->flush_mode = Z_NO_FLUSH; file->write = &write_deflate; } else { file->write = &write_normal; } /* If we are writing to a temp file */ if (flags & GIT_FILEBUF_TEMPORARY) { char tmp_path[GIT_PATH_MAX]; /* Open the file as temporary for locking */ file->fd = gitfo_mktemp(tmp_path, path); if (file->fd < 0) { error = GIT_EOSERR; goto cleanup; } /* No original path */ file->path_original = NULL; file->path_lock = git__strdup(tmp_path); if (file->path_lock == NULL) { error = GIT_ENOMEM; goto cleanup; } } else { path_len = strlen(path); /* Save the original path of the file */ file->path_original = git__strdup(path); if (file->path_original == NULL) { error = GIT_ENOMEM; goto cleanup; } /* create the locking path by appending ".lock" to the original */ file->path_lock = git__malloc(path_len + GIT_FILELOCK_EXTLENGTH); if (file->path_lock == NULL) { error = GIT_ENOMEM; goto cleanup; } memcpy(file->path_lock, file->path_original, path_len); memcpy(file->path_lock + path_len, GIT_FILELOCK_EXTENSION, GIT_FILELOCK_EXTLENGTH); /* open the file for locking */ if ((error = lock_file(file, flags)) < GIT_SUCCESS) goto cleanup; } return GIT_SUCCESS; cleanup: git_filebuf_cleanup(file); return git__rethrow(error, "Failed to open file buffer for '%s'", path); }
int git_filebuf_open(git_filebuf *file, const char *path, int flags) { int error; size_t path_len; if (file == NULL || path == NULL) return GIT_ERROR; memset(file, 0x0, sizeof(git_filebuf)); file->buf_size = WRITE_BUFFER_SIZE; file->buf_pos = 0; file->fd = -1; path_len = strlen(path); file->path_original = git__strdup(path); if (file->path_original == NULL) { error = GIT_ENOMEM; goto cleanup; } file->path_lock = git__malloc(path_len + GIT_FILELOCK_EXTLENGTH); if (file->path_lock == NULL) { error = GIT_ENOMEM; goto cleanup; } memcpy(file->path_lock, file->path_original, path_len); memcpy(file->path_lock + path_len, GIT_FILELOCK_EXTENSION, GIT_FILELOCK_EXTLENGTH); file->buffer = git__malloc(file->buf_size); if (file->buffer == NULL){ error = GIT_ENOMEM; goto cleanup; } #ifdef GIT_FILEBUF_THREADS file->buffer_back = git__malloc(file->buf_size); if (file->buffer_back == NULL){ error = GIT_ENOMEM; goto cleanup; } #endif if (flags & GIT_FILEBUF_HASH_CONTENTS) { if ((file->digest = git_hash_new_ctx()) == NULL) { error = GIT_ENOMEM; goto cleanup; } } if ((error = lock_file(file, flags)) < GIT_SUCCESS) goto cleanup; return GIT_SUCCESS; cleanup: git_filebuf_cleanup(file); return error; }