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