⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ext2subs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 + -