📄 ext2subs.c
字号:
clear_bit(b, eb.u.bmp); dirtyext2(eb); putext2(eb); es = getext2(xf, EXT2_SUPER, 0); es.u.sb->s_free_inodes_count++; dirtyext2(es); putext2(es);}intcreate_dir(Xfile *fdir, char *name, int mode){ Xfs *xf = fdir->xf; DirEntry *de; Inode *inode; Iobuf *buf, *ibuf; Xfile tf; int inr, baddr; inr = new_inode(fdir, mode); if( inr == 0 ){ chat("create one new inode failed..."); return -1; } if( add_entry(fdir, name, inr) < 0 ){ chat("add entry failed..."); free_inode(fdir->xf, inr); return -1; } /* create the empty dir */ tf = *fdir; if( get_inode(&tf, inr) < 0 ){ chat("can't get inode %d...", inr); free_inode(fdir->xf, inr); return -1; } ibuf = getbuf(xf, tf.bufaddr); if( !ibuf ){ free_inode(fdir->xf, inr); return -1; } inode = ((Inode *)ibuf->iobuf) + tf.bufoffset; baddr = inode_getblk(&tf, 0); if( !baddr ){ putbuf(ibuf); ibuf = getbuf(xf, fdir->bufaddr); if( !ibuf ){ free_inode(fdir->xf, inr); return -1; } inode = ((Inode *)ibuf->iobuf) + fdir->bufoffset; delete_entry(fdir->xf, inode, inr); putbuf(ibuf); free_inode(fdir->xf, inr); return -1; } inode->i_size = xf->block_size; buf = getbuf(xf, baddr); de = (DirEntry *)buf->iobuf; de->inode = inr; de->name_len = 1; de->rec_len = DIR_REC_LEN(de->name_len); strcpy(de->name, "."); de = (DirEntry *)( (char *)de + de->rec_len); de->inode = fdir->inbr; de->name_len = 2; de->rec_len = xf->block_size - DIR_REC_LEN(1); strcpy(de->name, ".."); dirtybuf(buf); putbuf(buf); inode->i_links_count = 2; dirtybuf(ibuf); putbuf(ibuf); ibuf = getbuf(xf, fdir->bufaddr); if( !ibuf ) return -1; inode = ((Inode *)ibuf->iobuf) + fdir->bufoffset; inode->i_links_count++; dirtybuf(ibuf); putbuf(ibuf); return inr;}intadd_entry(Xfile *f, char *name, int inr){ Xfs *xf = f->xf; DirEntry *de, *de1; int offset, baddr; int rec_len, cur_block; int namelen = strlen(name); Inode *inode; Iobuf *buf, *ibuf; ibuf = getbuf(xf, f->bufaddr); if( !ibuf ) return -1; inode = ((Inode *)ibuf->iobuf) + f->bufoffset; if( inode->i_size == 0 ){ chat("add_entry() no entry !!!..."); putbuf(ibuf); return -1; } cur_block = offset = 0; rec_len = DIR_REC_LEN(namelen); buf = getbuf(xf, inode->i_block[cur_block++]); if( !buf ){ putbuf(ibuf); return -1; } de = (DirEntry *)buf->iobuf; for(;;){ if( ((char *)de) >= (xf->block_size + buf->iobuf) ){ putbuf(buf); if( cur_block >= EXT2_NDIR_BLOCKS ){ errno = Enospace; putbuf(ibuf); return -1; } if( (baddr = inode_getblk(f, cur_block++)) == 0 ){ putbuf(ibuf); return -1; } buf = getbuf(xf, baddr); if( !buf ){ putbuf(ibuf); return -1; } if( inode->i_size <= offset ){ de = (DirEntry *)buf->iobuf; de->inode = 0; de->rec_len = xf->block_size; dirtybuf(buf); inode->i_size = offset + xf->block_size; dirtybuf(ibuf); }else{ de = (DirEntry *)buf->iobuf; } } if( de->inode != 0 && de->name_len == namelen && !strncmp(name, de->name, namelen) ){ errno = Eexist; putbuf(ibuf); putbuf(buf); return -1; } offset += de->rec_len; if( (de->inode == 0 && de->rec_len >= rec_len) || (de->rec_len >= DIR_REC_LEN(de->name_len) + rec_len) ){ if( de->inode ){ de1 = (DirEntry *) ((char *)de + DIR_REC_LEN(de->name_len)); de1->rec_len = de->rec_len - DIR_REC_LEN(de->name_len); de->rec_len = DIR_REC_LEN(de->name_len); de = de1; } de->inode = inr; de->name_len = namelen; memcpy(de->name, name, namelen); dirtybuf(buf); putbuf(buf); inode->i_mtime = inode->i_ctime = time(0); dirtybuf(ibuf); putbuf(ibuf); return 0; } de = (DirEntry *)((char *)de + de->rec_len); } /* not reached */}intunlink( Xfile *file ){ Xfs *xf = file->xf; Inode *dir; int bg, b; Inode *inode; Iobuf *buf, *ibuf; Ext2 ed, es, eb; if( S_ISDIR(getmode(file)) && !empty_dir(file) ){ chat("non empty directory..."); errno = Eperm; return -1; } es = getext2(xf, EXT2_SUPER, 0); /* get dir inode */ if( file->pinbr >= es.u.sb->s_inodes_count ){ chat("inode number %d is too big...", file->pinbr); putext2(es); errno = Eintern; return -1; } bg = (file->pinbr - 1) / xf->inodes_per_group; if( bg >= xf->ngroups ){ chat("block group (%d) > groups count...", bg); putext2(es); errno = Eintern; return -1; } ed = getext2(xf, EXT2_DESC, bg); b = ed.u.gd->bg_inode_table + (((file->pinbr-1) % xf->inodes_per_group) / xf->inodes_per_block); putext2(ed); buf = getbuf(xf, b); if( !buf ){ putext2(es); return -1; } dir = ((struct Inode *) buf->iobuf) + ((file->pinbr-1) % xf->inodes_per_block); /* Clean dir entry */ if( delete_entry(xf, dir, file->inbr) < 0 ){ putbuf(buf); putext2(es); return -1; } if( S_ISDIR(getmode(file)) ){ dir->i_links_count--; dirtybuf(buf); } putbuf(buf); /* clean blocks */ ibuf = getbuf(xf, file->bufaddr); if( !ibuf ){ putext2(es); return -1; } inode = ((Inode *)ibuf->iobuf) + file->bufoffset; if( !S_ISLNK(getmode(file)) || (S_ISLNK(getmode(file)) && (inode->i_size > EXT2_N_BLOCKS<<2)) ) if( free_block_inode(file) < 0 ){ chat("error while freeing blocks..."); putext2(es); putbuf(ibuf); return -1; } /* clean inode */ bg = (file->inbr -1) / xf->inodes_per_group; b = (file->inbr -1) % xf->inodes_per_group; eb = getext2(xf, EXT2_BINODE, bg); clear_bit(b, eb.u.bmp); dirtyext2(eb); putext2(eb); inode->i_dtime = time(0); inode->i_links_count--; if( S_ISDIR(getmode(file)) ) inode->i_links_count = 0; es.u.sb->s_free_inodes_count++; dirtyext2(es); putext2(es); ed = getext2(xf, EXT2_DESC, bg); ed.u.gd->bg_free_inodes_count++; if( S_ISDIR(getmode(file)) ) ed.u.gd->bg_used_dirs_count--; dirtyext2(ed); putext2(ed); dirtybuf(ibuf); putbuf(ibuf); return 1;}intempty_dir(Xfile *dir){ Xfs *xf = dir->xf; int nblock; uint offset, i,count; DirEntry *de; Inode *inode; Iobuf *buf, *ibuf; if( !S_ISDIR(getmode(dir)) ) return 0; ibuf = getbuf(xf, dir->bufaddr); if( !ibuf ) return -1; inode = ((Inode *)ibuf->iobuf) + dir->bufoffset; nblock = (inode->i_blocks * 512) / xf->block_size; for(i=0, count=0 ; (i < nblock) && (i < EXT2_NDIR_BLOCKS) ; i++){ buf = getbuf(xf, inode->i_block[i]); if( !buf ){ putbuf(ibuf); return 0; } for(offset=0 ; offset < xf->block_size ; ){ de = (DirEntry *)(buf->iobuf + offset); if(de->inode) count++; offset += de->rec_len; } putbuf(buf); if( count > 2 ){ putbuf(ibuf); return 0; } } putbuf(ibuf); return 1;}int free_block_inode(Xfile *file){ Xfs *xf = file->xf; int i, j, k; ulong b, *y, *z; uint *x; int naddr; Inode *inode; Iobuf *buf, *buf1, *buf2, *ibuf; ibuf = getbuf(xf, file->bufaddr); if( !ibuf ) return -1; inode = ((Inode *)ibuf->iobuf) + file->bufoffset; for(i=0 ; i < EXT2_IND_BLOCK ; i++){ x = inode->i_block + i; if( *x == 0 ){ putbuf(ibuf); return 0; } free_block(xf, *x); } naddr = xf->addr_per_block; /* indirect blocks */ if( (b=inode->i_block[EXT2_IND_BLOCK]) ){ buf = getbuf(xf, b); if( !buf ){ putbuf(ibuf); return -1; } for(i=0 ; i < naddr ; i++){ x = ((uint *)buf->iobuf) + i; if( *x == 0 ) break; free_block(xf, *x); } free_block(xf, b); putbuf(buf); } /* double indirect block */ if( (b=inode->i_block[EXT2_DIND_BLOCK]) ){ buf = getbuf(xf, b); if( !buf ){ putbuf(ibuf); return -1; } for(i=0 ; i < naddr ; i++){ x = ((uint *)buf->iobuf) + i; if( *x== 0 ) break; buf1 = getbuf(xf, *x); if( !buf1 ){ putbuf(buf); putbuf(ibuf); return -1; } for(j=0 ; j < naddr ; j++){ y = ((ulong *)buf1->iobuf) + j; if( *y == 0 ) break; free_block(xf, *y); } free_block(xf, *x); putbuf(buf1); } free_block(xf, b); putbuf(buf); } /* triple indirect block */ if( (b=inode->i_block[EXT2_TIND_BLOCK]) ){ buf = getbuf(xf, b); if( !buf ){ putbuf(ibuf); return -1; } for(i=0 ; i < naddr ; i++){ x = ((uint *)buf->iobuf) + i; if( *x == 0 ) break; buf1 = getbuf(xf, *x); if( !buf1 ){ putbuf(buf); putbuf(ibuf); return -1; } for(j=0 ; j < naddr ; j++){ y = ((ulong *)buf1->iobuf) + j; if( *y == 0 ) break; buf2 = getbuf(xf, *y); if( !buf2 ){ putbuf(buf); putbuf(buf1); putbuf(ibuf); return -1; } for(k=0 ; k < naddr ; k++){ z = ((ulong *)buf2->iobuf) + k; if( *z == 0 ) break; free_block(xf, *z); } free_block(xf, *y); putbuf(buf2); } free_block(xf, *x); putbuf(buf1); } free_block(xf, b); putbuf(buf); } putbuf(ibuf); return 0;}void free_block( Xfs *xf, ulong block ){ ulong bg; Ext2 ed, es, eb; es = getext2(xf, EXT2_SUPER, 0); bg = (block - es.u.sb->s_first_data_block) / xf->blocks_per_group; block = (block - es.u.sb->s_first_data_block) % xf->blocks_per_group; eb = getext2(xf, EXT2_BBLOCK, bg); clear_bit(block, eb.u.bmp); dirtyext2(eb); putext2(eb); es.u.sb->s_free_blocks_count++; dirtyext2(es); putext2(es); ed = getext2(xf, EXT2_DESC, bg); ed.u.gd->bg_free_blocks_count++; dirtyext2(ed); putext2(ed);}int delete_entry(Xfs *xf, Inode *inode, int inbr){ int nblock = (inode->i_blocks * 512) / xf->block_size; uint offset, i; DirEntry *de, *pde; Iobuf *buf; if( !S_ISDIR(inode->i_mode) ) return -1; for(i=0 ; (i < nblock) && (i < EXT2_NDIR_BLOCKS) ; i++){ buf = getbuf(xf, inode->i_block[i]); if( !buf ) return -1; pde = 0; for(offset=0 ; offset < xf->block_size ; ){ de = (DirEntry *)(buf->iobuf + offset); if( de->inode == inbr ){ if( pde ) pde->rec_len += de->rec_len; de->inode = 0; dirtybuf(buf); putbuf(buf); return 1; } offset += de->rec_len; pde = de; } putbuf(buf); } errno = Enonexist; return -1;}inttruncfile(Xfile *f){ Inode *inode; Iobuf *ibuf; chat("trunc(fid=%d) ...", f->fid); ibuf = getbuf(f->xf, f->bufaddr); if( !ibuf ) return -1; inode = ((Inode *)ibuf->iobuf) + f->bufoffset; if( free_block_inode(f) < 0 ){ chat("error while freeing blocks..."); putbuf(ibuf); return -1; } inode->i_atime = inode->i_mtime = time(0); inode->i_blocks = 0; inode->i_size = 0; memset(inode->i_block, 0, EXT2_N_BLOCKS*sizeof(ulong)); dirtybuf(ibuf); putbuf(ibuf); chat("trunc ok..."); return 0;}longgetmode(Xfile *f){ Iobuf *ibuf; long mode; ibuf = getbuf(f->xf, f->bufaddr); if( !ibuf ) return -1; mode = (((Inode *)ibuf->iobuf) + f->bufoffset)->i_mode; putbuf(ibuf); return mode;}voidCleanSuper(Xfs *xf){ Ext2 es; es = getext2(xf, EXT2_SUPER, 0); es.u.sb->s_state = EXT2_VALID_FS; dirtyext2(es); putext2(es);}int test_bit(int i, void *data){ char *pt = (char *)data; return pt[i>>3] & (0x01 << (i&7));}intset_bit(int i, void *data){ char *pt; if( test_bit(i, data) ) return 1; /* bit already set !!! */ pt = (char *)data; pt[i>>3] |= (0x01 << (i&7)); return 0;}int clear_bit(int i, void *data){ char *pt; if( !test_bit(i, data) ) return 1; /* bit already clear !!! */ pt = (char *)data; pt[i>>3] &= ~(0x01 << (i&7)); return 0;}void *memscan( void *data, int c, int count ){ char *pt = (char *)data; while( count ){ if( *pt == c ) return (void *)pt; count--; pt++; } return (void *)pt;}int find_first_zero_bit( void *data, int count /* in byte */){ char *pt = (char *)data; int n, i; n = 0; while( n < count ){ for(i=0 ; i < 8 ; i++) if( !(*pt & (0x01 << (i&7))) ) return (n<<3) + i; n++; pt++; } return n << 3;}int find_next_zero_bit( void *data, int count /* in byte */, int where){ char *pt = (((char *)data) + (where >> 3)); int n, i; n = where >> 3; i = where & 7; while( n < count ){ for(; i < 8 ; i++) if( !(*pt & (0x01 << (i&7))) ) return (n<<3) + i; n++; pt++; i=0; } return n << 3;}intffz( int x ){ int c = 0; while( x&1 ){ c++; x >>= 1; } return c;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -