os/tar_fs/main.c
2020-09-06 08:11:12 -05:00

140 lines
3.2 KiB
C

#include <stddef.h>
#include <string.h>
#include <serdes.h>
#include <rpc.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dbg.h>
typedef struct {
char filename[100];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char typeflag[1];
} tar_header;
typedef struct tar_file {
int pos;
char name[100];
char* dev;
struct tar_file* next;
} tar_file;
typedef struct {
FILE* access_file;
int base_pos;
} open_file_info;
size_t getsize(const char *in) {
size_t size=0;
size_t j;
size_t count=1;
for (j=11;j>0;j--,count*=8) {
size+=((in[j-1]-'0')*count);
}
return size;
}
tar_file* get_file_list(char* dev) {
FILE* tar_archive=fopen(dev,"r");
size_t pos=0;
tar_header tar_hdr;
tar_file* list=NULL;
for (int i=0;;i++) {
fseek(tar_archive,pos,SEEK_SET);
fread(&tar_hdr,sizeof(tar_header),1,tar_archive);
if (tar_hdr.filename[0]=='\0') break;
size_t size=getsize(tar_hdr.size);
pos+=512;
tar_file* list_entry=malloc(sizeof(tar_file));
list_entry->pos=pos;
list_entry->dev=dev;
strcpy(list_entry->name,tar_hdr.filename);
list_entry->next=list;
list=list_entry;
pos+=size;
if (pos%512!=0) {
pos+=512-(pos%512);
}
}
return list;
}
void tar_fs_mount(void* args) {
char* dev=(char*)args;
tar_file* file_list=get_file_list(dev);
serdes_state state;
serialize_int(0,&state);
serialize_ptr(file_list,&state);
rpc_return(state.buf,state.sizeorpos);
free(state.buf);
pthread_exit(NULL);
}
void open(void* args) {
serdes_state state;
start_deserialize(args,&state);
char* path=deserialize_str(&state);
tar_file* file_list=deserialize_ptr(&state);
for (;file_list!=NULL;file_list=file_list->next) {
if (strcmp(path,file_list->name)==0) {
break;
}
}
if (file_list) {
open_file_info* info=malloc(sizeof(open_file_info));
info->access_file=fopen(file_list->dev,"r");
info->base_pos=file_list->pos;
state.buf=NULL;
state.sizeorpos=0;
serialize_int(0,&state);
serialize_ptr(info,&state);
serialize_int(0,&state);
rpc_return(state.buf,state.sizeorpos);
pthread_exit(NULL);
} else {
state.buf=NULL;
state.sizeorpos=0;
serialize_int(1,&state);
serialize_ptr(NULL,&state);
serialize_int(0,&state);
rpc_return(state.buf,state.sizeorpos);
pthread_exit(NULL);
}
}
void read(void* args) {
serdes_state state;
start_deserialize(args,&state);
open_file_info* info=deserialize_ptr(&state);
size_t size=deserialize_int(&state);
int pos=deserialize_int(&state);
rpc_deallocate_buf(args,state.sizeorpos);
char* data=malloc(sizeof(char)*size);
fseek(info->access_file,info->base_pos+pos,SEEK_SET);
fread(data,size,1,info->access_file);
state.buf=NULL;
state.sizeorpos=0;
serialize_int(size,&state);
serialize_ary(data,size,&state);
free(data);
rpc_return(state.buf,state.sizeorpos);
free(state.buf);
pthread_exit(NULL);
}
int main() {
rpc_register_func("mount",&tar_fs_mount);
rpc_register_func("open",&open);
rpc_register_func("read",&read);
register_fs("tarfs",getpid());
serial_print("Tarfs initialized\n");
rpc_mark_as_init();
}