Basic index manipulation
This commit is contained in:
169
src/fs.c
169
src/fs.c
@@ -11,7 +11,9 @@
|
|||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
#include "index.h"
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
int local_repo_exist()
|
int local_repo_exist()
|
||||||
{
|
{
|
||||||
@@ -19,30 +21,133 @@ int local_repo_exist()
|
|||||||
return stat(LOCAL_REPO, &buffer) == 0;
|
return stat(LOCAL_REPO, &buffer) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int index_exist()
|
||||||
|
{
|
||||||
|
struct stat buffer;
|
||||||
|
return stat(INDEX_FILE, &buffer) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_index(struct index *index)
|
||||||
|
{
|
||||||
|
printf("index:\n");
|
||||||
|
printf("\tentries_size: %ld\n", index->entries_size);
|
||||||
|
printf("\tentries:\n");
|
||||||
|
struct entry *current = index->first_entry;
|
||||||
|
for(int i = 0; i < index->entries_size; i ++)
|
||||||
|
{
|
||||||
|
printf("\t\tfilename: %s, checksum: %s\n", current->filename, current->checksum);
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int load_index(struct index *index)
|
||||||
|
{
|
||||||
|
if(!local_repo_exist() || !index_exist())
|
||||||
|
{
|
||||||
|
return REPO_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* index_file = fopen(INDEX_FILE, "r");
|
||||||
|
struct stat buffer;
|
||||||
|
stat(INDEX_FILE, &buffer);
|
||||||
|
|
||||||
|
char* file_content = calloc(sizeof(char), buffer.st_size + 1);
|
||||||
|
fread(file_content, buffer.st_size, 1, index_file);
|
||||||
|
fclose(index_file);
|
||||||
|
|
||||||
|
char* current_line;
|
||||||
|
current_line = strtok(file_content, "\n");
|
||||||
|
index->entries_size = strtol(current_line, NULL, 10);
|
||||||
|
|
||||||
|
for(int i = 0; i < index->entries_size; i++)
|
||||||
|
{
|
||||||
|
current_line = strtok(NULL, "\n");
|
||||||
|
int j = 0;
|
||||||
|
while(current_line[j] != ' ')
|
||||||
|
{
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* checksum = calloc(sizeof(char), j + 1);
|
||||||
|
char* filename = calloc(sizeof(char), strlen(current_line) - j);
|
||||||
|
strncat(checksum, current_line, j);
|
||||||
|
strncat(filename, current_line + j + 1, strlen(current_line) - j);
|
||||||
|
|
||||||
|
struct entry *entry = malloc(sizeof(struct entry));
|
||||||
|
entry->checksum = checksum;
|
||||||
|
entry->filename = filename;
|
||||||
|
entry->next = NULL;
|
||||||
|
|
||||||
|
if(i == 0)
|
||||||
|
{
|
||||||
|
index->first_entry = entry;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
entry->previous = index->last_entry;
|
||||||
|
index->last_entry->next = entry;
|
||||||
|
}
|
||||||
|
index->last_entry = entry;
|
||||||
|
debug_print("checksum: %s, filename: %s", entry->checksum, entry->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(file_content);
|
||||||
|
|
||||||
|
return FS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int save_index(struct index *index)
|
||||||
|
{
|
||||||
|
if(!local_repo_exist())
|
||||||
|
{
|
||||||
|
return REPO_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *index_file = fopen(INDEX_FILE, "w");
|
||||||
|
if(index_exist == NULL)
|
||||||
|
{
|
||||||
|
return FS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(index_file, "%li\n", index->entries_size);
|
||||||
|
|
||||||
|
struct entry *current = index->first_entry;
|
||||||
|
for(int i = 0; i < index->entries_size; i++)
|
||||||
|
{
|
||||||
|
fprintf(index_file, "%s %s\n", current->checksum, current->filename);
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(index_file);
|
||||||
|
}
|
||||||
|
|
||||||
int write_object(struct object *obj)
|
int write_object(struct object *obj)
|
||||||
{
|
{
|
||||||
if(!local_repo_exist())
|
if(!local_repo_exist())
|
||||||
{
|
{
|
||||||
return -2;
|
return REPO_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
int result = 0;
|
int result = FS_OK;
|
||||||
|
|
||||||
struct stat buffer;
|
struct stat buffer;
|
||||||
if (stat(LOCAL_REPO"/objects", &buffer) != 0)
|
if (stat(OBJECTS_REPO, &buffer) != 0)
|
||||||
{
|
{
|
||||||
mkdir(LOCAL_REPO"/objects", DEFAULT_DIR_MODE);
|
mkdir(OBJECTS_REPO, DEFAULT_DIR_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
DIR *objects_dir = opendir(LOCAL_REPO"/objects");
|
DIR *objects_dir = opendir(OBJECTS_REPO);
|
||||||
int objects_dir_fd = dirfd(objects_dir);
|
int objects_dir_fd = dirfd(objects_dir);
|
||||||
|
|
||||||
char checksum[DIGEST_LENGTH * 2];
|
char checksum[DIGEST_LENGTH * 2];
|
||||||
hash_object(obj, checksum);
|
hash_object(obj, checksum);
|
||||||
|
|
||||||
int save_file_fd = openat(objects_dir_fd, checksum, O_CREAT | O_WRONLY | O_TRUNC, 0774);
|
int save_file_fd = openat(objects_dir_fd, checksum, O_CREAT | O_WRONLY | O_TRUNC, DEFAULT_FILE_MODE);
|
||||||
if(save_file_fd == -1) {
|
if(save_file_fd == -1) {
|
||||||
error_print("Object %s already exists", checksum);
|
if (errno == EACCES)
|
||||||
defer(-1);
|
{
|
||||||
|
debug_print("Object %s already exists", checksum);
|
||||||
|
defer(OBJECT_ALREADY_EXIST);
|
||||||
|
}
|
||||||
|
defer(FS_ERROR);
|
||||||
}
|
}
|
||||||
FILE* save_file = fdopen(save_file_fd, "w");
|
FILE* save_file = fdopen(save_file_fd, "w");
|
||||||
|
|
||||||
@@ -53,7 +158,7 @@ int write_object(struct object *obj)
|
|||||||
int res = compress_object(obj, compressed, &comp_size);
|
int res = compress_object(obj, compressed, &comp_size);
|
||||||
if (res != Z_OK)
|
if (res != Z_OK)
|
||||||
{
|
{
|
||||||
defer(res);
|
defer(COMPRESSION_ERROR);
|
||||||
}
|
}
|
||||||
fwrite(compressed, comp_size, 1, save_file);
|
fwrite(compressed, comp_size, 1, save_file);
|
||||||
free(compressed);
|
free(compressed);
|
||||||
@@ -68,25 +173,29 @@ int read_object(char *checksum, struct object *obj)
|
|||||||
{
|
{
|
||||||
if(!local_repo_exist())
|
if(!local_repo_exist())
|
||||||
{
|
{
|
||||||
return -2;
|
return REPO_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
int result = 0;
|
int result = FS_OK;
|
||||||
|
|
||||||
struct stat buffer;
|
struct stat buffer;
|
||||||
if (stat(LOCAL_REPO"/objects", &buffer) != 0)
|
if (stat(OBJECTS_REPO, &buffer) != 0)
|
||||||
{
|
{
|
||||||
error_print("Object dir does not exist");
|
error_print("Object dir does not exist");
|
||||||
return -1;
|
return OBJECT_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIR *objects_dir = opendir(LOCAL_REPO"/objects");
|
DIR *objects_dir = opendir(OBJECTS_REPO);
|
||||||
int objects_dir_fd = dirfd(objects_dir);
|
int objects_dir_fd = dirfd(objects_dir);
|
||||||
|
|
||||||
int save_file_fd = openat(objects_dir_fd, checksum, O_RDONLY, DEFAULT_FILE_MODE);
|
int save_file_fd = openat(objects_dir_fd, checksum, O_RDONLY, DEFAULT_FILE_MODE);
|
||||||
if (save_file_fd == -1)
|
if (save_file_fd == -1)
|
||||||
{
|
{
|
||||||
error_print("Object %s does not exist", checksum);
|
if(errno == EACCES)
|
||||||
defer(-1);
|
{
|
||||||
|
error_print("Object %s does not exist", checksum);
|
||||||
|
defer(OBJECT_DOES_NOT_EXIST);
|
||||||
|
}
|
||||||
|
defer(FS_ERROR);
|
||||||
}
|
}
|
||||||
fstatat(objects_dir_fd, checksum, &buffer, 0);
|
fstatat(objects_dir_fd, checksum, &buffer, 0);
|
||||||
char* file_content = malloc(buffer.st_size);
|
char* file_content = malloc(buffer.st_size);
|
||||||
@@ -96,9 +205,9 @@ int read_object(char *checksum, struct object *obj)
|
|||||||
fclose(save_file);
|
fclose(save_file);
|
||||||
|
|
||||||
int res = uncompress_object(obj, file_content, buffer.st_size);
|
int res = uncompress_object(obj, file_content, buffer.st_size);
|
||||||
if(res != 0)
|
if(res != Z_OK)
|
||||||
{
|
{
|
||||||
defer(res);
|
defer(COMPRESSION_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(file_content);
|
free(file_content);
|
||||||
@@ -110,12 +219,15 @@ defer:
|
|||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
struct object obj = {0};
|
struct index index = {0};
|
||||||
obj.content = "Hello, world!\n";
|
load_index(&index);
|
||||||
obj.size = strlen(obj.content);
|
|
||||||
obj.object_type = "blob";
|
|
||||||
|
|
||||||
return write_object(&obj);
|
// struct object obj = {0};
|
||||||
|
// obj.content = "Hello, world!\n";
|
||||||
|
// obj.size = strlen(obj.content);
|
||||||
|
// obj.object_type = "blob";
|
||||||
|
|
||||||
|
// return write_object(&obj);
|
||||||
|
|
||||||
// read_object("af5626b4a114abcb82d63db7c8082c3c4756e51b", &obj);
|
// read_object("af5626b4a114abcb82d63db7c8082c3c4756e51b", &obj);
|
||||||
|
|
||||||
@@ -124,5 +236,14 @@ int main(void)
|
|||||||
// debug_print("Content is %.*s", (int)obj.size, obj.content);
|
// debug_print("Content is %.*s", (int)obj.size, obj.content);
|
||||||
|
|
||||||
// free_object(&obj);
|
// free_object(&obj);
|
||||||
// return 0;
|
|
||||||
|
add_to_index(&index, "src/fs.c");
|
||||||
|
|
||||||
|
dump_index(&index);
|
||||||
|
|
||||||
|
save_index(&index);
|
||||||
|
|
||||||
|
free_index(&index);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
14
src/fs.h
14
src/fs.h
@@ -4,9 +4,23 @@
|
|||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
|
|
||||||
#define LOCAL_REPO ".cgit"
|
#define LOCAL_REPO ".cgit"
|
||||||
|
#define INDEX_FILE LOCAL_REPO"/index"
|
||||||
|
#define OBJECTS_REPO LOCAL_REPO"/objects"
|
||||||
#define DEFAULT_DIR_MODE 0755
|
#define DEFAULT_DIR_MODE 0755
|
||||||
#define DEFAULT_FILE_MODE 0444
|
#define DEFAULT_FILE_MODE 0444
|
||||||
|
|
||||||
|
#define FS_OK (0)
|
||||||
|
#define FS_ERROR (-1)
|
||||||
|
#define COMPRESSION_ERROR (-2)
|
||||||
|
#define REPO_NOT_INITIALIZED (-10)
|
||||||
|
#define OBJECT_ALREADY_EXIST (-20)
|
||||||
|
#define OBJECT_DOES_NOT_EXIST (-21)
|
||||||
|
#define FILE_NOT_FOUND (-22)
|
||||||
|
#define ENTRY_NOT_FOUND (-23)
|
||||||
|
|
||||||
|
int local_repo_exist();
|
||||||
|
int index_exist();
|
||||||
|
|
||||||
int write_object(struct object *obj);
|
int write_object(struct object *obj);
|
||||||
int read_object(char *checksum, struct object *obj);
|
int read_object(char *checksum, struct object *obj);
|
||||||
|
|
||||||
|
|||||||
133
src/index.c
Normal file
133
src/index.c
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "index.h"
|
||||||
|
#include "includes.h"
|
||||||
|
#include "fs.h"
|
||||||
|
|
||||||
|
void free_entry(struct entry *entry)
|
||||||
|
{
|
||||||
|
if (entry->checksum != NULL)
|
||||||
|
free(entry->checksum);
|
||||||
|
|
||||||
|
if (entry->filename != NULL)
|
||||||
|
free(entry->filename);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_index(struct index *index)
|
||||||
|
{
|
||||||
|
struct entry *current = index->first_entry;
|
||||||
|
struct entry *next;
|
||||||
|
while(current != NULL)
|
||||||
|
{
|
||||||
|
free_entry(current);
|
||||||
|
next = current->next;
|
||||||
|
free(current);
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct entry *find_entry(struct index *index, char* filename)
|
||||||
|
{
|
||||||
|
struct entry *current = index->first_entry;
|
||||||
|
for (int i = 0; i < index->entries_size; i ++)
|
||||||
|
{
|
||||||
|
if (strncmp(filename, current->filename, strlen(filename)) == 0) {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_to_index(struct index *index, char *filename)
|
||||||
|
{
|
||||||
|
if(!local_repo_exist() || !index_exist())
|
||||||
|
{
|
||||||
|
return REPO_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = FS_OK;
|
||||||
|
int new = 0;
|
||||||
|
|
||||||
|
struct entry *entry = find_entry(index, filename);
|
||||||
|
if (entry == NULL)
|
||||||
|
{
|
||||||
|
new = 1;
|
||||||
|
entry = calloc(sizeof(struct entry), 1);
|
||||||
|
} else {
|
||||||
|
free_entry(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct object object = {0};
|
||||||
|
if (blob_from_file(filename, &object) != 0)
|
||||||
|
{
|
||||||
|
return FILE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->filename = calloc(sizeof(char), strlen(filename) + 1);
|
||||||
|
strncat(entry->filename, filename, strlen(filename));
|
||||||
|
entry->checksum = calloc(sizeof(char), DIGEST_LENGTH * 2 + 1);
|
||||||
|
hash_object(&object, entry->checksum);
|
||||||
|
int res = write_object(&object);
|
||||||
|
if (res != FS_OK && res != OBJECT_ALREADY_EXIST)
|
||||||
|
{
|
||||||
|
defer(FS_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(new)
|
||||||
|
{
|
||||||
|
if(index->entries_size == 0)
|
||||||
|
{
|
||||||
|
index->first_entry = entry;
|
||||||
|
index->last_entry = entry;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
entry->previous = index->last_entry;
|
||||||
|
index->last_entry->next = entry;
|
||||||
|
index->last_entry = entry;
|
||||||
|
}
|
||||||
|
index->entries_size = index->entries_size + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
defer:
|
||||||
|
free_object(&object);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int remove_from_index(struct index *index, char *filename)
|
||||||
|
{
|
||||||
|
if (!local_repo_exist() || !index_exist())
|
||||||
|
{
|
||||||
|
return REPO_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct entry *entry = find_entry(index, filename);
|
||||||
|
if (entry == NULL)
|
||||||
|
{
|
||||||
|
return ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(index->first_entry == entry)
|
||||||
|
{
|
||||||
|
index->first_entry = entry->next;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
entry->previous->next = entry->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index->last_entry == entry)
|
||||||
|
{
|
||||||
|
index->last_entry = entry->previous;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
entry->next->previous = entry->previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
index->entries_size = index->entries_size - 1;
|
||||||
|
free_entry(entry);
|
||||||
|
free(entry);
|
||||||
|
return FS_OK;
|
||||||
|
}
|
||||||
28
src/index.h
Normal file
28
src/index.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef INDEX_H
|
||||||
|
#define INDEX_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
// Index file should follow the format
|
||||||
|
// number of entries\n
|
||||||
|
// entry1\n
|
||||||
|
// entry2\n
|
||||||
|
// ...
|
||||||
|
struct entry {
|
||||||
|
char *checksum;
|
||||||
|
char *filename;
|
||||||
|
struct entry *previous;
|
||||||
|
struct entry *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct index {
|
||||||
|
size_t entries_size;
|
||||||
|
struct entry *first_entry;
|
||||||
|
struct entry *last_entry;
|
||||||
|
};
|
||||||
|
|
||||||
|
void free_index(struct index *index);
|
||||||
|
int add_to_index(struct index *index, char *filename);
|
||||||
|
int remove_from_index(struct index *index, char *filename);
|
||||||
|
|
||||||
|
#endif // INDEX_H
|
||||||
@@ -1,22 +1,16 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
#include "utils.h"
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
|
|
||||||
int decimal_len(size_t size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return floor(log10(size)) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t header_size(struct object *obj)
|
size_t header_size(struct object *obj)
|
||||||
{
|
{
|
||||||
return strlen(obj->object_type) + 2 + decimal_len(obj->size);
|
return strlen(obj->object_type) + 2 + decimal_len(obj->size);
|
||||||
@@ -51,7 +45,7 @@ int full_object(struct object *obj, char *buffer, size_t buffer_size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hash_object(struct object *obj, char* result)
|
void hash_object(struct object *obj, char *result)
|
||||||
{
|
{
|
||||||
unsigned char md_buffer[DIGEST_LENGTH] = {0};
|
unsigned char md_buffer[DIGEST_LENGTH] = {0};
|
||||||
size_t data_size = object_size(obj);
|
size_t data_size = object_size(obj);
|
||||||
@@ -62,7 +56,7 @@ void hash_object(struct object *obj, char* result)
|
|||||||
|
|
||||||
for (int i = 0; i < DIGEST_LENGTH; i++)
|
for (int i = 0; i < DIGEST_LENGTH; i++)
|
||||||
{
|
{
|
||||||
sprintf((result + 2 * i), "%.2x", md_buffer[i]);
|
sprintf((result + (2 * i)), "%.2x", md_buffer[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
@@ -113,11 +107,27 @@ int compress_object(struct object *obj, char* compressed, uLongf *comp_size)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int blob_from_file(char *filename, struct object *object)
|
||||||
|
{
|
||||||
|
FILE* file = fopen(filename, "r");
|
||||||
|
if (file == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
struct stat file_info;
|
||||||
|
if (stat(filename, &file_info) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
object->object_type = "blob";
|
||||||
|
object->size = file_info.st_size;
|
||||||
|
object->content = realloc(object->content, object->size);
|
||||||
|
fread(object->content, 1, object->size, file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void free_object(struct object *obj)
|
void free_object(struct object *obj)
|
||||||
{
|
{
|
||||||
if (obj->object_type != NULL)
|
|
||||||
free(obj->object_type);
|
|
||||||
|
|
||||||
if (obj->content != NULL)
|
if (obj->content != NULL)
|
||||||
free(obj->content);
|
free(obj->content);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define OBJECTS_H 1
|
#define OBJECTS_H 1
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <zconf.h>
|
||||||
|
|
||||||
#define DIGEST_LENGTH 20
|
#define DIGEST_LENGTH 20
|
||||||
#define HEADER_MAX_SIZE 20
|
#define HEADER_MAX_SIZE 20
|
||||||
@@ -18,6 +19,7 @@ int full_object(struct object *obj, char* buffer, size_t buffer_size);
|
|||||||
int uncompress_object(struct object *obj, char* compressed, uLongf comp_size);
|
int uncompress_object(struct object *obj, char* compressed, uLongf comp_size);
|
||||||
int compress_object(struct object *obj, char* compressed, uLongf *comp_size);
|
int compress_object(struct object *obj, char* compressed, uLongf *comp_size);
|
||||||
void hash_object(struct object *obj, char* result);
|
void hash_object(struct object *obj, char* result);
|
||||||
|
int blob_from_file(char *filename, struct object *object);
|
||||||
void free_object(struct object *obj);
|
void free_object(struct object *obj);
|
||||||
|
|
||||||
#endif // OBJECTS_H
|
#endif // OBJECTS_H
|
||||||
|
|||||||
11
src/utils.c
Normal file
11
src/utils.c
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
int decimal_len(size_t size)
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return floor(log10(size)) + 1;
|
||||||
|
}
|
||||||
8
src/utils.h
Normal file
8
src/utils.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef UTILS_H
|
||||||
|
#define UTILS_H 1
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
int decimal_len(size_t size);
|
||||||
|
|
||||||
|
#endif // UTILS_H
|
||||||
Reference in New Issue
Block a user