#include #include #include #include #include #include #include #include #include #include #include "main.h" #include "disk.h" static int salvage_dir_inodes_again=0; static int salvage_dir_inodes_nr=0; struct mem_inode_s *create_dir_inode( __u32 num, __u32 data ) { struct mem_inode_s *p; __u32 inum; int g; p = (struct mem_inode_s *)malloc(sizeof(struct mem_inode_s)); if(!p) { fprintf(stderr,"Can't create inode: Out of memory\n"); return(NULL); } g= num / inodes_per_group; p->to_block= group_desc_block[g].bg_inode_table +(num - g * inodes_per_group)*sizeof(struct ext2_inode)/blocksize; inum= g * inodes_per_group +((p->to_block - group_desc_block[g].bg_inode_table) *(blocksize/sizeof(struct ext2_inode)))+1; p->block=p->to_block; p->block_offset=num-inum; p->need_to_write=1; p->ok=1; memset(&(p->inode),0,sizeof(struct ext2_inode)); p->inode.i_mode=0755|S_IFDIR; p->inode.i_size=blocksize; p->inode.i_atime=p->inode.i_ctime=p->inode.i_mtime=time(NULL); p->inode.i_links_count=99; p->inode.i_blocks=1; p->inode.i_block[0]=data; p->inode_nr=num; if(p->inode_nr==2) {printf("zzzz1\n"); getchar(); } p->next=mem_inodes; mem_inodes=p; return(p); } static int invalid_inode_block( __u32 block ) { struct mem_inode_s *p; for(p=mem_inodes;p!=NULL;p=p->next) if( p->block==block ) { p->to_block=0; p->inode_nr=0; p->need_to_write=1; if(p->ok) { fprintf(stderr,"!!!!!!!!!!\n"); p->ok=0; } } return(1); } static int set_inode_number_block( struct mem_inode_s *ib, __u32 num ) { struct mem_inode_s *p; __u32 inum,block; int g; g= num / inodes_per_group; block= group_desc_block[g].bg_inode_table +(num - g * inodes_per_group)*sizeof(struct ext2_inode)/blocksize; inum= g * inodes_per_group +((block - group_desc_block[g].bg_inode_table) *(blocksize/sizeof(struct ext2_inode)))+1; if( num-inum != ib->block_offset ) return(0); fprintf(stderr,"\nInode block drift %d (0x%x)\n",ib->block - block,abs(ib->block - block)); for(p=mem_inodes;p!=NULL;p=p->next) { if( p->block==ib->block ) { p->to_block=block; p->inode_nr= inum + p->block_offset; if(p->inode_nr==2) {printf("zzzz2\n"); getchar(); } p->need_to_write=1; p->ok=1; } /* else if( p->block==block ) { p->to_block=0; p->inode_nr=0; p->need_to_write=1; if(p->ok) { fprintf(stderr,"!!!!!!!!!!\n"); p->ok=0; } } */ } return(1); } static int fix_two_inode_bloks( struct mem_inode_s *ib, struct mem_inode_s *in ) { struct mem_inode_s *p; int i,ofs[128],nofs=0; __u32 inum; if( ib->block_offset!=in->block_offset ) { set_inode_number_block(ib,in->inode_nr); return(0); } fprintf(stderr,"\nInode block drift %d (0x%x)\n",ib->block - in->block,abs(ib->block - in->block)); /* !!!! predpokladam ze ib je novsi ako in ... mozno by sa malo otestovat ? */ inum= in->inode_nr - in->block_offset; for(p=mem_inodes;p!=NULL;p=p->next) if( p->block==ib->block ) { p->to_block=in->block; p->inode_nr= inum + p->block_offset; if(p->inode_nr==2) {printf("zzzz3\n"); getchar(); } p->need_to_write=1; p->ok=1; ofs[nofs++]=p->block_offset; } /* for(p=mem_inodes;p!=NULL;p=p->next) if( p->block==in->block ) { for(i=0;iblock_offset==ofs[i] ) { p->inode_nr=0; memset(&(p->inode),0,sizeof(p->inode)); break; if(p->ok) { fprintf(stderr,"!!!!!!!!!!\n"); p->ok=0; } } } */ salvage_dir_inodes_again=1; return(1); } static struct mem_inode_s *get_dir_inode( struct mem_dir_s *d ) { struct mem_inode_s *ib,*in; if( d->to_block!=0 ) ib=find_inode_by_firstblock(d->to_block); else ib=NULL; in=find_inode_by_number(d->inode_nr); if( ib==NULL && in==NULL ) { fprintf(stderr,"\nError: Directory has no inode!\n"); return(create_dir_inode(d->inode_nr,d->block)); } if( ib==NULL ) { fprintf(stderr,"\nError: Directory inode exist, but don't refer to first directory block! (in=%d)\n",in->inode_nr); if( !S_ISDIR(in->inode.i_mode) ) { // invalid_inode_block(in->block); } else if( !(in->ok) ) { d->to_block=in->inode.i_block[0]; d->need_to_write=1; fprintf(stderr,"\nOK: Directory moved\n"); in->ok=1; return(in); } else return(in); /* ZZZZZ ???? asi len hack, alebo ??? */ return(create_dir_inode(d->inode_nr,d->block)); } if( in==NULL ) { fprintf(stderr,"\nDirectory has inode outside! (ib=%d .=%d)\n",ib->inode_nr,d->inode_nr); if( set_inode_number_block(ib,d->inode_nr) ) { fprintf(stderr,"Fixed\n"); return(ib); } else fprintf(stderr,"!!! but in invalid offset\n"); return(NULL); } if( ib!=in ) { if( !fix_two_inode_bloks(ib,in) ) fprintf(stderr,"\nError: Directory has two inodes! (ib=%d in=%d)\n",ib->inode_nr,in->inode_nr); else fprintf(stderr,"\nDuplicated inodes!\n"); return(ib); } in->ok=1; return(in); } int salvage_dirs_in_itable( void ) { struct mem_dir_s *p,*q; for(p=mem_dirs_first;p!=NULL;p=p->next) if( p->to_block==0 ) { for(q=mem_dirs_first;q!=NULL;q=q->next) if( q->to_block>0 && q->inode_nr==p->inode_nr ) { /* !!! ten mimo je asi dobry */ p->to_block=q->block; p->need_to_write=1; fprintf(stderr,"OK: Directory moved from inode table.\n"); } } return(1); } int salvage_dir_inodes( void ) { struct mem_dir_s *p; int nr_dirs=0,i_dir=0,f_dir=0; for(p=mem_dirs_first;p!=NULL;p=p->next) nr_dirs++; salvage_dirs_in_itable(); again: progressbar_init("Salvage directories"); for(p=mem_dirs_first;p!=NULL;p=p->next) { progressbar_display( ((float)i_dir/((float)nr_dirs/100.)) , f_dir); if( p->inode==NULL ) { if( (p->inode=get_dir_inode(p))!=NULL ) { p->ok=1; f_dir++; } } i_dir++; } progressbar_display( ((float)i_dir/((float)nr_dirs/100.)) , f_dir); progressbar_stop(); { int i=0,id=0,w=0; struct mem_inode_s *ii; fprintf(stderr,"[ "); for(p=mem_dirs_first;p!=NULL;p=p->next) { if( !(p->ok) ) { i++; fprintf(stderr,"%d ",p->inode_nr); } } for(ii=mem_inodes;ii!=NULL;ii=ii->next) { if( ii->need_to_write ) w++; if( !ii->ok && S_ISDIR(ii->inode.i_mode) ) id++; } fprintf(stderr,"]\n%d directories has no inode\n%d directory inodes has no first block\n%d inodes modified\n",i,id,w); } if( salvage_dir_inodes_again && salvage_dir_inodes_nr<10 ) { salvage_dir_inodes_again=0; salvage_dir_inodes_nr++; fprintf(stdout,"Inode table modified, salvagging again...\n"); i_dir=0; f_dir=0; if( salvage_dir_inodes_nr<5 ) { for(p=mem_dirs_first;p!=NULL;p=p->next) p->inode=NULL; } goto again; } // !!!!!!!!!!!!!!!!!!!!!!!!! if( find_inode_by_number(2)==NULL ) return(f_dir); } int salvage_next_dir_blocks( void ) { struct mem_dir_s *p,*q; struct mem_inode_s *in,*ib; int nr_dirs=0,i_dir=0,f_dir=0; for(p=mem_dirs_first;p!=NULL;p=p->next) nr_dirs++; progressbar_init("Salvage other directories blocks"); for(p=mem_dirs_first;p!=NULL;p=p->next) { progressbar_display( ((float)i_dir/((float)nr_dirs/100.)) , f_dir); for(q=mem_dirs;q!=NULL;q=q->next) { if( is_in_dir(q->data,p->inode_nr) ) { ib=find_inode_by_direct_block(q->to_block); in=find_inode_by_number(p->parent_nr); if( ib==NULL && in==NULL ) {/* !!!! POZOR to_block nesmie byt 0 !!!!! */ ib=in=create_dir_inode(p->parent_nr,q->to_block); } else if( in==NULL ) { if( set_inode_number_block(ib,p->parent_nr) ) { fprintf(stderr,"\nFixed inode number\n"); in=ib; } else { fprintf(stderr,"\nError: Bad inode found\n"); } } else if( ib==NULL ) { if( S_ISDIR(in->inode.i_mode) ) { add_block_to_inode(in,q->to_block); fprintf(stderr,"\nOK: Directory block joined to its inode.\n"); ib=in; } else { fprintf(stderr,"\nError: Inode exist\n"); } } else if( ib!=in ) { if( !fix_two_inode_bloks(ib,in) ) fprintf(stderr,"\nError: Directory has two inodes! (ib=%d in=%d)\n",ib->inode_nr,in->inode_nr); else fprintf(stderr,"\nDuplicated inodes!\n"); in=ib; } if( in!=NULL && ib==in ) { q->ok=1; in->ok=1; f_dir++; } } } i_dir++; } { struct mem_inode_s *i=find_inode_by_number(2); printf("block=0x%x to_block=0x%x off=0x%x ok=%d ntw=%d 1.block=0x%x\n",i->block,i->to_block,i->block_offset,i->ok,i->need_to_write,i->inode.i_block[0]); for(i=i->next;i!=NULL;i=i->next) { if( i->inode_nr==2 ) printf("dalsi inod 2 ok=%d ntw=%d 1.block=0x%x\n",i->ok,i->need_to_write,i->inode.i_block[0]); } getchar(); } find_inode_by_number(2)->inode.i_block[0]=mem_root_dir_first->to_block; progressbar_display( ((float)i_dir/((float)nr_dirs/100.)) , f_dir); progressbar_stop(); { int n=0,nn=0; for(p=mem_dirs;p!=NULL;p=p->next) { if( !(p->ok) ) { nn++; add_block_to_inode(find_inode_by_number(2),p->to_block); } n++; } fprintf(stderr,"%d other directory blocks (not linked %d)\n",n,nn); } return(1); }