/* cache2.c */ #include "config.h" #include "object.h" #include "globals.h" #include "construct.h" #include "dbhandle.h" #include "interp.h" #include "file.h" #include "compile.h" #include "clearq.h" struct obj_link { struct object *obj; struct obj_link *prev_link; struct obj_link *next_link; struct obj_link *prev_queue; struct obj_link *next_queue; }; extern struct obj_link *hash_list[CACHE_HASH]; extern struct obj_link *cache_head; extern struct obj_link *cache_tail; extern signed long loaded_obj_count; /* if access_load_file is 0, then all loads from the db will be from the save_name file. if it is non-zero, loads will be from the load_name file. */ extern int access_load_file; struct object *db_ref_to_obj(signed long refno); void pass_data(FILE *infile); void writeinstr(FILE *outfile, struct var *v); char *readstring(FILE *infile); void readinstr(FILE *infile, struct var *v); void writedata(FILE *outfile, struct object *obj); void readdata(FILE *infile, struct object *obj); void freedata(struct object *obj); void write_filesystem(FILE *outfile, struct file_entry *parent_dir, char *parent_dir_name); signed long db_obj_to_ref(struct object *obj); void writeverb(FILE *outfile, struct verb *curr_verb); int manual_move(char *oldname, char *newname) { FILE *oldf,*newf; int c; oldf=fopen(oldname,"r"); if (!oldf) return 1; newf=fopen(newname,"w"); if (!newf) { fclose(oldf); return 1; } c=fgetc(oldf); while (c!=(-1)) { fputc(c,newf); c=fgetc(oldf); } fclose(oldf); fclose(newf); remove(oldname); return 0; } int save_db(char *filename) { long count,index,place,loop; struct obj_blk *curr_block; struct cmdq *curr_cmd; struct alarmq *curr_alarm; struct object *curr_obj; struct file_entry *curr_file; FILE *outfile,*infile,*file3,*cachefile; char *buf1,*buf2; struct proto *curr_proto; struct fns *curr_fns; struct var_tab *curr_var; struct array_size *curr_array; cachefile=fopen(cache_path,"r"); outfile=fopen(tmpdb_path,"w"); if (!outfile) { if (cachefile) fclose(cachefile); log_sysmsg(" cache: save_db() couldn't write to temporary database"); return 1; } if (access_load_file==1) infile=fopen(load_name,"r"); else if (access_load_file==0) infile=fopen(save_name,"r"); else infile=NULL; if (access_load_file!=(-1) && !infile) { log_sysmsg(" cache: save_db() couldn't read from database"); fclose(outfile); return 1; } count=0; index=0; curr_block=obj_list; curr_file=root_dir; fprintf(outfile,"%s%ld\n%d\n%ld\n",DB_IDENSTR,(long) db_top, (int) root_dir->flags,(long) root_dir->owner); write_filesystem(outfile,root_dir,""); fprintf(outfile,".END\n"); while (count<db_top) { curr_obj=&(curr_block->block[index]); fprintf(outfile,"%ld\n",(long) curr_obj->flags); fprintf(outfile,"%ld\n",(long) db_obj_to_ref(curr_obj->next_child)); fprintf(outfile,"%ld\n",(long) db_obj_to_ref(curr_obj->location)); fprintf(outfile,"%ld\n",(long) db_obj_to_ref(curr_obj->contents)); fprintf(outfile,"%ld\n",(long) db_obj_to_ref(curr_obj->next_object)); if (curr_obj->obj_state==IN_DB) { place=ftell(outfile); fseek(infile,curr_obj->file_offset,SEEK_SET); readdata(infile,curr_obj); writedata(outfile,curr_obj); freedata(curr_obj); curr_obj->file_offset=place; } else if (curr_obj->obj_state==IN_CACHE) { if (!cachefile) { log_sysmsg(" cache: save_db() couldn't read from cache"); return 1; } place=ftell(outfile); fseek(cachefile,curr_obj->file_offset,SEEK_SET); readdata(cachefile,curr_obj); writedata(outfile,curr_obj); freedata(curr_obj); curr_obj->file_offset=place; curr_obj->obj_state=IN_DB; } else { place=ftell(outfile); writedata(outfile,curr_obj); curr_obj->file_offset=place; curr_obj->obj_state=FROM_DB; } writeverb(outfile,curr_obj->verb_list); fprintf(outfile,".END\n"); count++; index++; if (index==OBJ_ALLOC_BLKSIZ) { index=0; curr_block=curr_block->next; } } if (cachefile) fclose(cachefile); remove(cache_path); cache_top=0; curr_proto=ref_to_obj(0)->parent; while (curr_proto) { fprintf(outfile,"%s\n%ld\n%ld\n",curr_proto->pathname, (long) curr_proto->proto_obj->refno, (long) curr_proto->funcs->num_globals); curr_var=curr_proto->funcs->gst; while (curr_var) { fprintf(outfile,"*%s\n%d\n",curr_var->name,(int) curr_var->base); curr_array=curr_var->array; while (curr_array) { fprintf(outfile,"%d\n",(int) curr_array->size); curr_array=curr_array->next; } fprintf(outfile,"\n"); curr_var=curr_var->next; } curr_fns=curr_proto->funcs->func_list; while (curr_fns) { fprintf(outfile,"%d\n%ld\n%ld\n%ld\n%ld\n%s", (int) curr_fns->is_static, (long) curr_fns->num_args, (long) curr_fns->num_locals, (long) curr_fns->num_instr, (long) strlen(curr_fns->funcname), curr_fns->funcname); loop=0; while (loop<curr_fns->num_instr) { writeinstr(outfile,&(curr_fns->code[loop])); loop++; } curr_fns=curr_fns->next; } fprintf(outfile,".END\n"); curr_proto=curr_proto->next_proto; } fprintf(outfile,".END\n"); curr_cmd=cmd_head; while (curr_cmd) { fprintf(outfile,"%ld\n%ld\n%s",(long) curr_cmd->obj->refno, (long) strlen(curr_cmd->cmd), curr_cmd->cmd); curr_cmd=curr_cmd->next; } fprintf(outfile,".END\n"); curr_alarm=alarm_list; while (curr_alarm) { fprintf(outfile,"%ld\n%ld\n%ld\n%s",(long) curr_alarm->obj->refno, (long) curr_alarm->delay, (long) strlen(curr_alarm->funcname), curr_alarm->funcname); curr_alarm=curr_alarm->next; } fprintf(outfile,".END\n"); fprintf(outfile,"db.END\n"); fclose(outfile); if (infile) fclose(infile); if (filename) if (strcmp(save_name,filename)) { FREE(save_name); save_name=copy_string(filename); } remove(save_name); if (rename(tmpdb_path,save_name)) if (manual_move(tmpdb_path,save_name)) { log_sysmsg(" cache: save_db() couldn't move temporary database to " "save database"); return 1; } access_load_file=0; return 0; } int init_db() { FILE *infile; char *buf; char *string,*string2; signed long flags,uid,count,num_blocks,loop1,loop2,index; struct obj_blk *curr_block,*object_block; unsigned int num_globals; struct verb *verbptr; unsigned char is_xverb; struct proto *curr_proto; struct object *curr_obj; struct fns *curr_fns; char c; struct array_size *new_array,*curr_array; struct var_tab *new_var,*curr_var; access_load_file=1; infile=fopen(load_name,"r"); if (!infile) { log_sysmsg(" cache: init_db() couldn't read from database"); return 1; } buf=MALLOC(MAX_STR_LEN); fgets(buf,MAX_STR_LEN,infile); if (strcmp(buf,DB_IDENSTR)) { FREE(buf); buf=MALLOC(strlen(load_name)+28); sprintf(buf," system: %s not a CI database",load_name); log_sysmsg(buf); FREE(buf); fclose(infile); return 1; } fgets(buf,MAX_STR_LEN,infile); db_top=atol(buf); if (db_top<=0) { FREE(buf); buf=MALLOC(strlen(load_name)+43); sprintf(buf," system: %s corrupt (while reading db_top)",load_name); log_sysmsg(buf); FREE(buf); fclose(infile); return 1; } num_blocks=db_top/OBJ_ALLOC_BLKSIZ+1; objects_allocd=num_blocks*OBJ_ALLOC_BLKSIZ; obj_list=NULL; free_obj_list=NULL; loop1=0; while (loop1<num_blocks) { object_block=MALLOC(sizeof(struct obj_blk)); object_block->block=MALLOC(sizeof(struct object)*OBJ_ALLOC_BLKSIZ); object_block->next=obj_list; obj_list=object_block; loop1++; } count=0; fgets(buf,MAX_STR_LEN,infile); root_dir->flags=atoi(buf); fgets(buf,MAX_STR_LEN,infile); root_dir->owner=atol(buf); fgets(buf,MAX_STR_LEN,infile); while (strcmp(buf,".END\n")) { if (feof(infile)) { FREE(buf); buf=MALLOC(strlen(load_name)+47); sprintf(buf," system: %s corrupt (while reading filesystem)",load_name); log_sysmsg(buf); FREE(buf); fclose(infile); return 1; } string=copy_string(buf); string[strlen(string)-1]='\0'; fgets(buf,MAX_STR_LEN,infile); flags=atoi(buf); fgets(buf,MAX_STR_LEN,infile); uid=atol(buf); db_add_entry(string,uid,flags); FREE(string); fgets(buf,MAX_STR_LEN,infile); } count=0; curr_block=obj_list; index=0; while (count<db_top) { if (feof(infile)) { FREE(buf); buf=MALLOC(strlen(load_name)+48+ITOA_BUFSIZ); sprintf(buf," system: %s corrupt (while reading object #%ld)",load_name, (long) count); log_sysmsg(buf); FREE(buf); fclose(infile); return 1; } curr_block->block[index].refno=count; curr_block->block[index].devnum=-1; fgets(buf,MAX_STR_LEN,infile); flags=atoi(buf); flags&=~(IN_EDITOR | RESIDENT); curr_block->block[index].flags=flags; fgets(buf,MAX_STR_LEN,infile); curr_block->block[index].next_child=db_ref_to_obj(atol(buf)); fgets(buf,MAX_STR_LEN,infile); curr_block->block[index].location=db_ref_to_obj(atol(buf)); fgets(buf,MAX_STR_LEN,infile); curr_block->block[index].contents=db_ref_to_obj(atol(buf)); fgets(buf,MAX_STR_LEN,infile); curr_block->block[index].next_object=db_ref_to_obj(atol(buf)); curr_block->block[index].file_offset=ftell(infile); if (flags & GARBAGE) curr_block->block[index].obj_state=DIRTY; else curr_block->block[index].obj_state=IN_DB; curr_block->block[index].globals=NULL; curr_block->block[index].refd_by=NULL; curr_block->block[index].verb_list=NULL; if (flags & GARBAGE) { curr_block->block[index].next_object=free_obj_list; free_obj_list=&(curr_block->block[index]); } pass_data(infile); fgets(buf,MAX_STR_LEN,infile); while (strcmp(buf,".END\n") && !(feof(infile))) { is_xverb=atoi(buf); string=readstring(infile); string2=readstring(infile); verbptr=MALLOC(sizeof(struct verb)); verbptr->verb_name=string; verbptr->is_xverb=is_xverb; verbptr->function=string2; verbptr->next=curr_block->block[index].verb_list; curr_block->block[index].verb_list=verbptr; fgets(buf,MAX_STR_LEN,infile); } count++; index++; if (index==OBJ_ALLOC_BLKSIZ) { index=0; curr_block=curr_block->next; } } fgets(buf,MAX_STR_LEN,infile); while (strcmp(buf,".END\n")) { if (feof(infile)) { FREE(buf); buf=MALLOC(strlen(load_name)+47); sprintf(buf," system: %s corrupt (while reading prototypes)",load_name); log_sysmsg(buf); FREE(buf); fclose(infile); return 1; } curr_proto=MALLOC(sizeof(struct proto)); buf[strlen(buf)-1]='\0'; curr_proto->pathname=copy_string(buf); fgets(buf,MAX_STR_LEN,infile); curr_proto->proto_obj=db_ref_to_obj(atol(buf)); curr_obj=curr_proto->proto_obj; while (curr_obj) { curr_obj->parent=curr_proto; curr_obj=curr_obj->next_child; } curr_obj=db_ref_to_obj(0); if (curr_obj->parent!=curr_proto) { curr_proto->next_proto=curr_obj->parent->next_proto; curr_obj->parent->next_proto=curr_proto; } else curr_proto->next_proto=NULL; curr_proto->funcs=MALLOC(sizeof(struct code)); fgets(buf,MAX_STR_LEN,infile); num_globals=atoi(buf); curr_proto->funcs->num_globals=num_globals; curr_proto->funcs->func_list=NULL; curr_proto->funcs->gst=NULL; c=fgetc(infile); curr_var=NULL; while (c=='*' && !feof(infile)) { new_var=MALLOC(sizeof(struct var_tab)); fgets(buf,MAX_STR_LEN,infile); buf[strlen(buf)-1]='\0'; new_var->name=copy_string(buf); fgets(buf,MAX_STR_LEN,infile); new_var->base=atoi(buf); fgets(buf,MAX_STR_LEN,infile); new_var->array=NULL; new_var->next=NULL; curr_array=NULL; while (strcmp(buf,"\n") && !feof(infile)) { new_array=MALLOC(sizeof(struct array_size)); new_array->size=atoi(buf); if (curr_array) curr_array->next=new_array; else new_var->array=new_array; new_array->next=NULL; curr_array=new_array; fgets(buf,MAX_STR_LEN,infile); } if (curr_var) curr_var->next=new_var; else curr_proto->funcs->gst=new_var; curr_var=new_var; c=fgetc(infile); } ungetc(c,infile); fgets(buf,MAX_STR_LEN,infile); while (strcmp(buf,".END\n")) { if (feof(infile)) { FREE(buf); buf=MALLOC(strlen(load_name)+46); sprintf(buf," system: %s corrupt (while reading functions)",load_name); log_sysmsg(buf); FREE(buf); fclose(infile); return 1; } curr_fns=MALLOC(sizeof(struct fns)); curr_fns->is_static=atoi(buf); fgets(buf,MAX_STR_LEN,infile); curr_fns->num_args=atoi(buf); fgets(buf,MAX_STR_LEN,infile); curr_fns->num_locals=atoi(buf); fgets(buf,MAX_STR_LEN,infile); curr_fns->num_instr=atol(buf); curr_fns->funcname=readstring(infile); curr_fns->next=curr_proto->funcs->func_list; curr_proto->funcs->func_list=curr_fns; if (curr_fns->num_instr) curr_fns->code=MALLOC(sizeof(struct var)*(curr_fns->num_instr)); else curr_fns->code=NULL; loop1=0; while (loop1<curr_fns->num_instr) { readinstr(infile,&(curr_fns->code[loop1])); loop1++; } fgets(buf,MAX_STR_LEN,infile); } fgets(buf,MAX_STR_LEN,infile); } fgets(buf,MAX_STR_LEN,infile); while (strcmp(buf,".END\n")) { if (feof(infile)) { FREE(buf); buf=MALLOC(strlen(load_name)+45); sprintf(buf," system: %s corrupt (while reading commands)",load_name); log_sysmsg(buf); FREE(buf); fclose(infile); return 1; } curr_obj=db_ref_to_obj(atol(buf)); string=readstring(infile); queue_command(curr_obj,string); FREE(string); fgets(buf,MAX_STR_LEN,infile); } fgets(buf,MAX_STR_LEN,infile); while (strcmp(buf,".END\n")) { if (feof(infile)) { FREE(buf); buf=MALLOC(strlen(load_name)+43); sprintf(buf," system: %s corrupt (while reading alarms)",load_name); log_sysmsg(buf); FREE(buf); fclose(infile); return 1; } curr_obj=db_ref_to_obj(atol(buf)); fgets(buf,MAX_STR_LEN,infile); count=atol(buf); string=readstring(infile); db_queue_for_alarm(curr_obj,count,string); FREE(string); fgets(buf,MAX_STR_LEN,infile); } fgets(buf,MAX_STR_LEN,infile); if (feof(infile) || strcmp(buf,"db.END\n")) { FREE(buf); buf=MALLOC(strlen(load_name)+45); sprintf(buf," system: %s corrupt (no db.END magic cookie)",load_name); log_sysmsg(buf); FREE(buf); fclose(infile); return 1; } FREE(buf); fclose(infile); return 0; } int create_db() { struct code *the_code; unsigned int result; struct object *obj; struct proto *proto_obj; long loop; struct fns *init_func; struct var_stack *rts; struct var tmp; access_load_file=-1; db_add_entry("/boot.c",0,0); result=parse_code("/boot",NULL,&the_code); if (result==((unsigned int) -1)) return 1; if (result) { compile_error(NULL,"/boot",result); return 1; } obj=newobj(); proto_obj=MALLOC(sizeof(struct proto)); proto_obj->pathname=copy_string("/boot"); proto_obj->funcs=the_code; proto_obj->proto_obj=obj; proto_obj->next_proto=NULL; obj->refno=0; obj->devnum=-1; obj->flags=PROTOTYPE | PRIV; obj->parent=proto_obj; obj->next_child=NULL; obj->location=NULL; obj->contents=NULL; obj->next_object=NULL; if (the_code->num_globals) { obj->globals=MALLOC(sizeof(struct var)*(the_code->num_globals)); loop=0; while (loop<the_code->num_globals) { obj->globals[loop].type=INTEGER; obj->globals[loop].value.integer=0; loop++; } } else obj->globals=NULL; obj->refd_by=NULL; obj->verb_list=NULL; add_loaded(obj); obj->obj_state=DIRTY; #ifdef CYCLE_HARD_MAX hard_cycles=0; #endif /* CYCLE_HARD_MAX */ #ifdef CYCLE_SOFT_MAX soft_cycles=0; #endif /* CYCLE_SOFT_MAX */ init_func=find_fns("init",obj); if (init_func) { rts=NULL; tmp.type=NUM_ARGS; tmp.value.num=0; push(&tmp,&rts); interp(NULL,obj,NULL,&rts,init_func); free_stack(&rts); } handle_destruct(); return 0; }