Make haggis_node->filetype a sub-structure instead of pointer

This commit is contained in:
Nathan Fisher 2023-08-08 01:25:15 -04:00
parent d7a5c40637
commit 9457d03a45
3 changed files with 96 additions and 142 deletions

View file

@ -107,19 +107,18 @@ typedef union {
typedef struct {
haggis_typeflag tag;
haggis_ft *f_type;
haggis_ft f_type;
} haggis_filetype;
typedef struct {
haggis_filename *name;
haggis_filename name;
u32 uid;
u32 gid;
u64 mtime;
u16 mode;
haggis_filetype *filetype;
haggis_filetype filetype;
} haggis_node;
haggis_node* haggis_node_init();
void haggis_node_deinit(haggis_node *node);
haggis_node* haggis_create_node(char *file, haggis_hardlink_list *list);
int haggis_extract_node(FILE *stram, haggis_node *node);

View file

@ -80,10 +80,6 @@ void haggis_device_init(dev_t rdev, haggis_device *dev) {
dev->minor.val = (uint32_t)minor(rdev);
}
void haggis_device_deinit(haggis_device *dev) {
free(dev);
}
int haggis_store_device(FILE *stream, haggis_device *dev) {
if (fwrite(dev->major.bytes, 1, 4, stream) != 4)
return 1;
@ -92,10 +88,10 @@ int haggis_store_device(FILE *stream, haggis_device *dev) {
return 0;
}
int haggis_load_device(FILE *stream, haggis_ft *ft) {
if (fread(ft->dev.major.bytes, 1, 4, stream) != 4)
int haggis_load_device(FILE *stream, haggis_device *dev) {
if (fread(dev->major.bytes, 1, 4, stream) != 4)
return 1;
if (fread(ft->dev.minor.bytes, 1, 4, stream) != 4)
if (fread(dev->minor.bytes, 1, 4, stream) != 4)
return 1;
return 0;
}
@ -240,35 +236,31 @@ int haggis_validate_cksum(haggis_file *file) {
return 0;
}
haggis_file* haggis_file_init(char *path) {
int haggis_file_init(char *path, haggis_file *hf) {
FILE *f;
long len;
haggis_file *hf;
f = fopen(path, "r");
if (f == NULL) return NULL;
if (f == NULL) return 2;
if (fseek(f, 0, SEEK_END) == -1) {
fclose(f);
return NULL;
return 2;
}
len = ftell(f);
if (len == -1) {
fclose(f);
return NULL;
return 2;
}
hf = malloc(sizeof(haggis_file));
if (hf == NULL) return NULL;
hf->len.val = (uint64_t)len;
rewind(f);
hf->data = malloc((size_t)len);
if (fread(hf->data, 1, (size_t)len, f) != (size_t)len) {
free(hf->data);
free(hf);
fclose(f);
return NULL;
return 1;
}
fclose(f);
return hf;
return 0;
}
void haggis_file_deinit(haggis_file *f) {
@ -286,33 +278,32 @@ int haggis_store_file(FILE *stream, haggis_file *file) {
return 0;
}
int haggis_load_file(FILE *stream, haggis_ft *ft) {
if (load_u64(stream, ft->file.len) != 8)
int haggis_load_file(FILE *stream, haggis_file *f) {
if (load_u64(stream, f->len) != 8)
return 1;
if (haggis_load_cksum(stream, &ft->file.cksum) != 0)
if (haggis_load_cksum(stream, &f->cksum) != 0)
return 1;
ft->file.data = malloc((size_t)ft->file.len.val);
if (ft->file.data == NULL)
f->data = malloc((size_t)f->len.val);
if (f->data == NULL)
return -1;
int res = fread(ft->file.data, 1, (size_t)ft->file.len.val, stream);
if (res != (size_t)ft->file.len.val) {
free(ft);
int res = fread(f->data, 1, (size_t)f->len.val, stream);
if (res != (size_t)f->len.val) {
free(f->data);
return 1;
}
if (haggis_validate_cksum(&ft->file)) {
free(ft);
if (haggis_validate_cksum(f)) {
free(f->data);
return 1;
}
return 0;
}
haggis_filename* haggis_filename_init(char *target, haggis_filename *fname) {
void haggis_filename_init(char *target, haggis_filename *fname) {
size_t len;
len = strlen(target) - 1;
fname->len.val = (uint16_t)len;
fname->name = target;
return fname;
}
void haggis_filename_deinit(haggis_filename *fname) {
@ -347,22 +338,22 @@ int haggis_load_filetype(FILE *stream, haggis_typeflag tag, haggis_filetype *fil
switch (tag) {
case normal:
file->tag = 0;
return haggis_load_file(stream, file->f_type);
return haggis_load_file(stream, &file->f_type.file);
case hardlink:
return haggis_load_filename(stream, &file->f_type->target);
return haggis_load_filename(stream, &file->f_type.target);
file->tag = 1;
case softlink:
return haggis_load_filename(stream, &file->f_type->target);
return haggis_load_filename(stream, &file->f_type.target);
file->tag = 2;
case directory:
file->tag = 3;
break;
case character:
file->tag = 4;
return haggis_load_device(stream, file->f_type);
return haggis_load_device(stream, &file->f_type.dev);
case block:
file->tag = 5;
return haggis_load_device(stream, file->f_type);
return haggis_load_device(stream, &file->f_type.dev);
case fifo:
file->tag = 6;
break;
@ -381,19 +372,19 @@ int haggis_store_filetype(FILE *stream, haggis_filetype *filetype) {
flag = 0;
if (fwrite(&flag, 1, 1, stream) != 1)
return 1;
if (haggis_store_file(stream, &filetype->f_type->file) != 0)
if (haggis_store_file(stream, &filetype->f_type.file) != 0)
return 1;
break;
case hardlink:
flag = 1;
if (fwrite(&flag, 1, 1, stream) != 1)
return 1;
return haggis_store_filename(stream, &filetype->f_type->target);
return haggis_store_filename(stream, &filetype->f_type.target);
case softlink:
flag = 2;
if (fwrite(&flag, 1, 1, stream) != 1)
return 1;
return haggis_store_filename(stream, &filetype->f_type->target);
return haggis_store_filename(stream, &filetype->f_type.target);
case directory:
flag = 3;
if (fwrite(&flag, 1, 1, stream) != 1)
@ -403,14 +394,14 @@ int haggis_store_filetype(FILE *stream, haggis_filetype *filetype) {
flag = 4;
if (fwrite(&flag, 1, 1, stream) != 1)
return 1;
if (haggis_store_device(stream, &filetype->f_type->dev) != 0)
if (haggis_store_device(stream, &filetype->f_type.dev) != 0)
return 1;
break;
case block:
flag = 5;
if (fwrite(&flag, 1, 1, stream) != 1)
return 1;
if (haggis_store_device(stream, &filetype->f_type->dev) != 0)
if (haggis_store_device(stream, &filetype->f_type.dev) != 0)
return 1;
break;
case fifo:
@ -441,17 +432,17 @@ u16 haggis_derive_mode(u16 raw, haggis_filetype *ft) {
void haggis_node_deinit(haggis_node *node) {
if (node == NULL) return;
if (node->name != NULL) haggis_filename_deinit(node->name);
switch (node->filetype->tag) {
if (node->name.name != NULL) haggis_filename_deinit(&node->name);
switch (node->filetype.tag) {
case normal:
if (node->filetype->f_type->file.data != NULL) {
free(node->filetype->f_type->file.data);
if (node->filetype.f_type.file.data != NULL) {
free(node->filetype.f_type.file.data);
}
break;
case hardlink:
case softlink:
if (node->filetype->f_type->target.name != NULL) {
haggis_filename_deinit(&node->filetype->f_type->target);
if (node->filetype.f_type.target.name != NULL) {
haggis_filename_deinit(&node->filetype.f_type.target);
}
break;
case character:
@ -466,120 +457,93 @@ void haggis_node_deinit(haggis_node *node) {
haggis_node* haggis_create_node(char *file, haggis_hardlink_list *list) {
struct stat *st = NULL;
haggis_typeflag tf;
u16 mode;
u32 uid;
u32 gid;
u64 mtime;
char *target;
char pathbuf[PATH_MAX];
haggis_filename *fname;
haggis_file *f;
int res;
haggis_node *node;
node = malloc(sizeof(haggis_node));
if (node == NULL)
return NULL;
node->filetype = malloc(sizeof(haggis_filetype));
if (node->filetype == NULL)
return NULL;
if (node == NULL) return NULL;
if (stat(file, st) != 0) {
free(node);
return NULL;
}
if (S_ISBLK(st->st_mode)) {
tf = block;
node->filetype.tag = block;
} else if (S_ISCHR(st->st_mode)) {
tf = character;
node->filetype.tag = character;
} else if (S_ISDIR(st->st_mode)) {
tf = directory;
node->filetype.tag = directory;
} else if (S_ISFIFO(st->st_mode)) {
tf = fifo;
node->filetype.tag = fifo;
} else if (S_ISLNK(st->st_mode)) {
tf = softlink;
node->filetype.tag = softlink;
} else if (S_ISREG(st->st_mode)) {
tf = normal;
node->filetype.tag = normal;
} else {
free(node);
return NULL;
}
uid.val = (uint32_t)st->st_uid;
node->uid = uid;
gid.val = (uint32_t)st->st_gid;
node->gid = gid;
mtime.val = (uint64_t)st->st_mtim.tv_sec;
node->mtime = mtime;
node->uid.val = (uint32_t)st->st_uid;
node->gid.val = (uint32_t)st->st_gid;
node->mtime.val = (uint64_t)st->st_mtim.tv_sec;
mode.val = (uint16_t)(st->st_mode & 07777);
node->mode = mode;
switch (tf) {
switch (node->filetype.tag) {
case normal:
target = haggis_linklist_get_or_put(list, st->st_ino, file);
if (target == NULL) {
node->filetype->tag = normal;
f = haggis_file_init(file);
if (f == NULL) {
haggis_node_deinit(node);
return NULL;
}
} else {
node->filetype->tag = hardlink;
fname = haggis_filename_init(target, &node->filetype->f_type->target);
if (fname == NULL) {
haggis_node_deinit(node);
return NULL;
if (st->st_nlink > 1) {
target = haggis_linklist_get_or_put(list, st->st_ino, file);
if (target != NULL) {
node->filetype.tag = hardlink;
haggis_filename_init(target, &node->filetype.f_type.target);
return node;
}
}
res = haggis_file_init(file, &node->filetype.f_type.file);
if (res != 0) {
haggis_node_deinit(node);
return NULL;
}
break;
case block:
target = haggis_linklist_get_or_put(list, st->st_ino, file);
if (target == NULL) {
node->filetype->tag = block;
haggis_device_init(st->st_rdev, &node->filetype->f_type->dev);
} else {
node->filetype->tag = hardlink;
fname = haggis_filename_init(target, &node->filetype->f_type->target);
if (fname == NULL) {
haggis_node_deinit(node);
return NULL;
if (st->st_nlink > 1) {
target = haggis_linklist_get_or_put(list, st->st_ino, file);
if (target != NULL) {
node->filetype.tag = hardlink;
haggis_filename_init(target, &node->filetype.f_type.target);
return node;
}
}
haggis_device_init(st->st_rdev, &node->filetype.f_type.dev);
break;
case character:
target = haggis_linklist_get_or_put(list, st->st_ino, file);
if (target == NULL) {
node->filetype->tag = character;
haggis_device_init(st->st_rdev, &node->filetype->f_type->dev);
} else {
node->filetype->tag = hardlink;
fname = haggis_filename_init(target, &node->filetype->f_type->target);
if (fname == NULL) {
haggis_node_deinit(node);
return NULL;
if (st->st_nlink > 1) {
target = haggis_linklist_get_or_put(list, st->st_ino, file);
if (target != NULL) {
node->filetype.tag = hardlink;
haggis_filename_init(target, &node->filetype.f_type.target);
return node;
}
}
haggis_device_init(st->st_rdev, &node->filetype.f_type.dev);
break;
case fifo:
target = haggis_linklist_get_or_put(list, st->st_ino, file);
if (target == NULL) {
node->filetype->tag = fifo;
} else {
node->filetype->tag = hardlink;
fname = haggis_filename_init(target, &node->filetype->f_type->target);
if (fname == NULL) {
haggis_node_deinit(node);
return NULL;
if (st->st_nlink > 1) {
target = haggis_linklist_get_or_put(list, st->st_ino, file);
if (target != NULL) {
node->filetype.tag = hardlink;
haggis_filename_init(target, &node->filetype.f_type.target);
return node;
}
fname->name = target;
}
break;
return node;
case directory:
node->filetype->tag = directory;
break;
case hardlink:
node->filetype->tag = hardlink;
break;
case eof:
return node;
case softlink:
node->filetype->tag = softlink;
node->filetype.tag = softlink;
ssize_t res = readlink(file, pathbuf, PATH_MAX);
if (res == -1) {
haggis_node_deinit(node);
@ -587,17 +551,9 @@ haggis_node* haggis_create_node(char *file, haggis_hardlink_list *list) {
}
target = malloc(res + 1);
memcpy(target, pathbuf, (unsigned long)res);
fname = haggis_filename_init(target, &node->filetype->f_type->target);
if (fname == NULL) {
haggis_node_deinit(node);
return NULL;
}
break;
case eof:
node->filetype->tag = eof;
break;
haggis_filename_init(target, &node->filetype.f_type.target);
return node;
}
// todo
return node;
}
@ -612,7 +568,7 @@ int haggis_load_node(FILE *stream, haggis_node *node) {
haggis_typeflag tag;
mode.val = 0;
res = haggis_load_filename(stream, node->name);
res = haggis_load_filename(stream, &node->name);
if (res)
return res;
res = load_u32(stream, node->uid);
@ -630,7 +586,7 @@ int haggis_load_node(FILE *stream, haggis_node *node) {
tag = haggis_filetype_from_mode(mode);
node->mode.bytes[0] = mode.bytes[0] & 037;
node->mode.bytes[1] = mode.bytes[1];
res = haggis_load_filetype(stream, tag, node->filetype);
res = haggis_load_filetype(stream, tag, &node->filetype);
if (res)
return res;
return 0;
@ -639,12 +595,12 @@ int haggis_load_node(FILE *stream, haggis_node *node) {
int haggis_store_node(FILE *stream, haggis_node *node) {
u16 mode;
if (haggis_store_filename(stream, node->name) != (size_t)(node->name->len.val) + 2)
if (haggis_store_filename(stream, &node->name) != (size_t)(node->name.len.val) + 2)
return 2;
if (store_u32(stream, node->uid) != 4) return 2;
if (store_u32(stream, node->gid) != 4) return 2;
if (store_u64(stream, node->mtime) != 8) return 2;
mode = haggis_derive_mode(node->mode, node->filetype);
mode = haggis_derive_mode(node->mode, &node->filetype);
if (store_u16(stream, mode) != 2) return 2;
return haggis_store_filetype(stream, node->filetype);
return haggis_store_filetype(stream, &node->filetype);
}

View file

@ -41,8 +41,7 @@
int haggis_store_header(FILE *stream);
int haggis_check_header(FILE *stream);
haggis_device* haggis_device_init(dev_t rdev);
void haggis_device_deinit(haggis_device *dev);
void haggis_device_init(dev_t rdev, haggis_device *dev);
int haggis_store_device(FILE *stream, haggis_device *dev);
int haggis_load_device(FILE *stream, haggis_ft *ft);
int haggis_store_cksum(FILE *stream, haggis_checksum *cksum);
@ -51,10 +50,10 @@ int validate_md5(haggis_file *file);
int validate_sha1(haggis_file *file);
int validate_sha256(haggis_file *file);
int haggis_validate_cksum(haggis_file *file);
haggis_file* haggis_file_init(char *path);
int haggis_file_init(char *path, haggis_file *hf);
int haggis_store_file(FILE *stream, haggis_file *file);
int haggis_load_file(FILE *stream, haggis_ft *ft);
haggis_filename* haggis_filename_init(char *target);
void haggis_filename_init(char *target, haggis_filename *fname);
void haggis_filename_deinit(haggis_filename *fname);
int haggis_load_filename(FILE *stream, haggis_filename *n);
int haggis_store_filename(FILE *stream, haggis_filename *n);