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

📄 genext2fs.c

📁 genext2fs
💻 C
📖 第 1 页 / 共 3 页
字号:
		bkref = &get_nod(fs, nod)->i_block[++bw->bpdir];		if(extend) // allocate block			*bkref = hole ? 0 : alloc_blk(fs);	}	// first block in indirect block	else if(bw->bpdir == EXT2_NDIR_BLOCKS)	{		bw->bnum++;		bw->bpdir = EXT2_IND_BLOCK;		bw->bpind = 0;		if(extend) // allocate indirect block			get_nod(fs, nod)->i_block[bw->bpdir] = alloc_blk(fs);		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);		bkref = &b[bw->bpind];		if(extend) // allocate first block			*bkref = hole ? 0 : alloc_blk(fs);	}	// block in indirect block	else if((bw->bpdir == EXT2_IND_BLOCK) && (bw->bpind < BLOCKSIZE/4 - 1))	{		bw->bpind++;		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);		bkref = &b[bw->bpind];		if(extend) // allocate block			*bkref = hole ? 0 : alloc_blk(fs);	}	// first block in first indirect block in first double indirect block	else if(bw->bpdir == EXT2_IND_BLOCK)	{		bw->bnum += 2;		bw->bpdir = EXT2_DIND_BLOCK;		bw->bpind = 0;		bw->bpdind = 0;		if(extend) // allocate double indirect block			get_nod(fs, nod)->i_block[bw->bpdir] = alloc_blk(fs);		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);		if(extend) // allocate first indirect block			b[bw->bpind] = alloc_blk(fs);		b = (uint32*)get_blk(fs, b[bw->bpind]);		bkref = &b[bw->bpdind];		if(extend) // allocate first block			*bkref = hole ? 0 : alloc_blk(fs);	}	// block in indirect block in double indirect block	else if((bw->bpdir == EXT2_DIND_BLOCK) && (bw->bpdind < BLOCKSIZE/4 - 1))	{		bw->bpdind++;		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);		b = (uint32*)get_blk(fs, b[bw->bpind]);		bkref = &b[bw->bpdind];		if(extend) // allocate block			*bkref = hole ? 0 : alloc_blk(fs);	}	// first block in indirect block in double indirect block	else if((bw->bpdir == EXT2_DIND_BLOCK) && (bw->bpind < BLOCKSIZE/4 - 1))	{		bw->bnum++;		bw->bpdind = 0;		bw->bpind++;		b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);		if(extend) // allocate indirect block			b[bw->bpind] = alloc_blk(fs);		b = (uint32*)get_blk(fs, b[bw->bpind]);		bkref = &b[bw->bpdind];		if(extend) // allocate first block			*bkref = hole ? 0 : alloc_blk(fs);	}	// I don't do triple indirect - it's such a small filesystem ...	else		errexit("file too big ! blocks list for inode %d extends past double indirect blocks!", nod);	if(*bkref)	{		bw->bnum++;		if(!allocated(fs->bbm, *bkref))			errexit("[block %d of inode %d is unallocated !]", *bkref, nod);	}	if(extend)		get_nod(fs, nod)->i_blocks = bw->bnum * INOBLK;	return *bkref;}// add blocks to an inode (file/dir/etc...)void extend_blk(filesystem *fs, uint32 nod, block b, int amount){	int create = amount;	blockwalker bw, lbw;	uint32 bk;	init_bw(fs, nod, &bw);	lbw = bw;	while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)		lbw = bw;	bw = lbw;	while(create)	{		int i, copyb = 0;		if(!(fs->sb.s_reserved[200] & OP_HOLES))			copyb = 1;		else			for(i = 0; i < BLOCKSIZE / 4; i++)				if(((int32*)(b + BLOCKSIZE * (amount - create)))[i])				{					copyb = 1;					break;				}		if((bk = walk_bw(fs, nod, &bw, &create, !copyb)) == WALK_END)			break;		if(copyb)			memcpy(get_blk(fs, bk), b + BLOCKSIZE * (amount - create - 1), BLOCKSIZE);	}}// link an entry (inode #) to a directoryvoid add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name){	blockwalker bw;	uint32 bk;	uint8 *b;	directory *d;	int reclen, nlen;	if((get_nod(fs, dnod)->i_mode & FM_IFMT) != FM_IFDIR)		errexit("can't add '%s' to a non-directory", name);	if(!*name)		errexit("bad name '%s' (not meaningful)", name);	if(strchr(name, '/'))		errexit("bad name '%s' (contains a slash)", name);	nlen = strlen(name);	reclen = sizeof(directory) + rndup(nlen, 4);	if(reclen > BLOCKSIZE)		errexit("bad name '%s' (too long)", name);	init_bw(fs, dnod, &bw);	while((bk = walk_bw(fs, dnod, &bw, 0, 0)) != WALK_END) // for all blocks in dir	{		b = get_blk(fs, bk);		// for all dir entries in block		for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))		{			// if empty dir entry, large enough, use it			if((!d->d_inode) && (d->d_rec_len >= reclen))			{				d->d_inode = nod;				get_nod(fs, nod)->i_links_count++;				d->d_name_len = nlen;				strncpy(d->d_name, name, nlen);				return;			}			// if entry with enough room (last one?), shrink it & use it			if(d->d_rec_len >= (sizeof(directory) + rndup(d->d_name_len, 4) + reclen))			{				reclen = d->d_rec_len;				d->d_rec_len = sizeof(directory) + rndup(d->d_name_len, 4);				reclen -= d->d_rec_len;				d = (directory*) (((int8*)d) + d->d_rec_len);				d->d_rec_len = reclen;				d->d_inode = nod;				get_nod(fs, nod)->i_links_count++;				d->d_name_len = nlen;				strncpy(d->d_name, name, nlen);				return;			}		}	}	// we found no free entry in the directory, so we add a block	b = get_workblk();	d = (directory*)b;	d->d_inode = nod;	get_nod(fs, nod)->i_links_count++;	d->d_rec_len = BLOCKSIZE;	d->d_name_len = nlen;	strncpy(d->d_name, name, nlen);	extend_blk(fs, dnod, b, 1);	get_nod(fs, dnod)->i_size += BLOCKSIZE;	free_workblk(b);}// find an entry in a directoryuint32 find_dir(filesystem *fs, uint32 nod, const char * name){	blockwalker bw;	uint32 bk;	int nlen = strlen(name);	init_bw(fs, nod, &bw);	while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)	{		directory *d;		uint8 *b;		b = get_blk(fs, bk);		for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))			if(d->d_inode && (nlen == d->d_name_len) && !strncmp(d->d_name, name, nlen))				return d->d_inode;	}	return 0;}// find the inode of a full pathuint32 find_path(filesystem *fs, uint32 nod, const char * name){	char *p, *n, *n2 = strdup(name);	n = n2;	while(*n == '/')	{		nod = EXT2_ROOT_INO;		n++;	}	while(*n)	{		if((p = strchr(n, '/')))			(*p) = 0;		if(!(nod = find_dir(fs, nod, n)))			break;		if(p)			n = p + 1;		else			break;	}	free(n2);	return nod;}// make a full-fledged directory (i.e. with "." & "..")uint32 mkdir_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode){	uint32 nod;	if((nod = find_dir(fs, parent_nod, name)))		return nod;       	nod = alloc_nod(fs);	get_nod(fs, nod)->i_mode = FM_IFDIR | mode;	add2dir(fs, parent_nod, nod, name);	add2dir(fs, nod, nod, ".");	add2dir(fs, nod, parent_nod, "..");	fs->gd.bg_used_dirs_count++;	return nod;}// make a symlinkuint32 mklink_fs(filesystem *fs, uint32 parent_nod, const char *name, size_t size, uint8 * b){	uint32 nod = alloc_nod(fs);	get_nod(fs, nod)->i_mode = FM_IFLNK | FM_IRWXU | FM_IRWXG | FM_IRWXO;	get_nod(fs, nod)->i_size = size;	add2dir(fs, parent_nod, nod, name);	if(size <= 4 * (EXT2_TIND_BLOCK+1))	{		strncpy((char*)get_nod(fs, nod)->i_block, (char*)b, size);		return nod;	}	extend_blk(fs, nod, b, rndup(size, BLOCKSIZE) / BLOCKSIZE);	return nod;}// make a file from a FILE*uint32 mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, size_t size, FILE *f){	uint8 * b;	uint32 nod = alloc_nod(fs);	get_nod(fs, nod)->i_mode = FM_IFREG | mode;	get_nod(fs, nod)->i_size = size;	add2dir(fs, parent_nod, nod, name);	if(!(b = (uint8*)malloc(rndup(size, BLOCKSIZE))))		errexit("not enough mem to read file '%s'", name);	memset(b, 0,rndup(size, BLOCKSIZE));	if(f)		fread(b, size, 1, f);	else		memset(b, 0, size);	extend_blk(fs, nod, b, rndup(size, BLOCKSIZE) / BLOCKSIZE);	free(b);	return nod;}// retrieves a mode info from a struct statuint32 get_mode(struct stat *st){	uint32 mode = 0;	if(st->st_mode & S_IRUSR)		mode |= FM_IRUSR | FM_IRGRP | FM_IROTH;	if(st->st_mode & S_IWUSR)		mode |= FM_IWUSR | FM_IWGRP | FM_IWOTH;	if(st->st_mode & S_IXUSR)		mode |= FM_IXUSR | FM_IXGRP | FM_IXOTH;	return mode;}// retrieves a mode info from a stringuint32 get_modestr(const char *p){	uint32 mode = 0;	if(p[0] == 'r')		mode |= FM_IRUSR | FM_IRGRP | FM_IROTH;	if(p[1] == 'w')		mode |= FM_IWUSR | FM_IWGRP | FM_IWOTH;	if(p[2] == 'x' || p[2] == 's')		mode |= FM_IXUSR | FM_IXGRP | FM_IXOTH;	return mode;}// basename of a path - free mechar * basename(const char * fullpath){	char * p = strrchr(fullpath, '/');	return strdup(p ? p + 1 : fullpath);}// dirname of a path - free mechar * dirname(const char * fullpath){	char * p, * n = strdup(fullpath);	if((p = strrchr(n, '/')))		*(p+1) = 0;	else		*n = 0;	return n;}// adds entries to the filesystem from a text filevoid add2fs_from_file(filesystem *fs, uint32 this_nod, FILE * fh){	uint32 mode;	uint32 nod, nod2;	char cmod[11], *path, *name, *dir;	int major, minor;	while(fscanf(fh, "%10s", cmod))	{		if(feof(fh))			break;		mode = get_modestr(cmod + 1);		switch(*cmod)		{			case 'd':				fscanf(fh, "%" SCANF_PREFIX "s\n", SCANF_STRING(path));				break;			case 'c':				mode |= FM_IFCHR;				fscanf(fh, "%i, %i %" SCANF_PREFIX "s\n", &major, &minor, SCANF_STRING(path));				break;			case 'b':				mode |= FM_IFBLK;				fscanf(fh, "%i, %i %" SCANF_PREFIX "s\n", &major, &minor, SCANF_STRING(path));				break;			case '#':				while(fgetc(fh) != '\n');				continue;			default:				errexit("malformed text input file");		}		name = basename(path);		dir = dirname(path);		free(path);		if(!(nod = find_path(fs, this_nod, dir)))			errexit("can't find directory '%s' to create '%s''", dir, name);		free(dir);		if((!strcmp(name, ".")) || (!strcmp(name, "..")))		{			free(name);			continue;		}		switch(*cmod)		{			case 'd':				mkdir_fs(fs, nod, name, mode);				break;			case 'c':			case 'b':				nod2 = alloc_nod(fs);				get_nod(fs, nod2)->i_mode = mode;				((uint8*)get_nod(fs, nod2)->i_block)[0] = minor;				((uint8*)get_nod(fs, nod2)->i_block)[1] = major;				add2dir(fs, nod, nod2, name);				break;		}		free(name);	}}// adds a tree of entries to the filesystem from current dirvoid add2fs_from_dir(filesystem *fs, uint32 this_nod){	uint32 nod;	FILE *fh;	DIR *dh;	struct dirent *dent;	struct stat st;	uint8 *b;	if(!(dh = opendir(".")))		pexit(".");	while((dent = readdir(dh)))	{		if((!strcmp(dent->d_name, ".")) || (!strcmp(dent->d_name, "..")))			continue;		lstat(dent->d_name, &st);		switch(st.st_mode & S_IFMT)		{			case S_IFCHR:			case S_IFBLK:				nod = alloc_nod(fs);				get_nod(fs, nod)->i_mode = (((st.st_mode & S_IFMT) == S_IFCHR) ? FM_IFCHR : FM_IFBLK) | get_mode(&st);				((uint8*)get_nod(fs, nod)->i_block)[0] = (st.st_rdev & 0xff);				((uint8*)get_nod(fs, nod)->i_block)[1] = (st.st_rdev >> 8);				add2dir(fs, this_nod, nod, dent->d_name);				break;			case S_IFLNK:				if(!(b = (uint8*)malloc(rndup(st.st_size, BLOCKSIZE))))					errexit("out of memory");				if(readlink(dent->d_name, (char*)b, st.st_size) < 0)					pexit(dent->d_name);				mklink_fs(fs, this_nod, dent->d_name, st.st_size, b);				free(b);				break;			case S_IFREG:				if(!(fh = fopen(dent->d_name, "r")))					pexit(dent->d_name);				mkfile_fs(fs, this_nod, dent->d_name, get_mode(&st), st.st_size, fh);				fclose(fh);				break;			case S_IFDIR:				nod = mkdir_fs(fs, this_nod, dent->d_name, get_mode(&st));				if(chdir(dent->d_name) < 0)					pexit(dent->d_name);				add2fs_from_dir(fs, nod);				chdir("..");				break;			default:				fprintf(stderr, "ignoring entry %s", dent->d_name);		}	}	closedir(dh);}// endianness swap of x-indirect blocksvoid swap_goodblocks(filesystem *fs, inode *nod){	int i;	int nblk = nod->i_blocks / INOBLK;	if((nod->i_size && !nblk) || (nod->i_mode & (FM_IFBLK | FM_IFCHR)))		for(i = 0; i <= EXT2_TIND_BLOCK; i++)			nod->i_block[i] = swab32(nod->i_block[i]);	if(nblk <= EXT2_IND_BLOCK)		return;	swap_block(get_blk(fs, nod->i_block[EXT2_IND_BLOCK]));	if(nblk <= EXT2_IND_BLOCK + BLOCKSIZE/4)		return;	for(i = 0; i < BLOCKSIZE/4; i++)		if(nblk > EXT2_IND_BLOCK + BLOCKSIZE/4 + i)			swap_block(get_blk(fs, ((uint32*)get_blk(fs, nod->i_block[EXT2_DIND_BLOCK]))[i]));	swap_block(get_blk(fs, nod->i_block[EXT2_DIND_BLOCK]));	if(nblk <= EXT2_IND_BLOCK + BLOCKSIZE/4 + BLOCKSIZE/4 * BLOCKSIZE/4)		return;	errexit("too big file on the filesystem");}void swap_badblocks(filesystem *fs, inode *nod){	int i;	int nblk = nod->i_blocks / INOBLK;	if((nod->i_size && !nblk) || (nod->i_mode & (FM_IFBLK | FM_IFCHR)))		for(i = 0; i <= EXT2_TIND_BLOCK; i++)			nod->i_block[i] = swab32(nod->i_block[i]);	if(nblk <= EXT2_IND_BLOCK)		return;	swap_block(get_blk(fs, nod->i_block[EXT2_IND_BLOCK]));	if(nblk <= EXT2_IND_BLOCK + BLOCKSIZE/4)		return;	swap_block(get_blk(fs, nod->i_block[EXT2_DIND_BLOCK]));	for(i = 0; i < BLOCKSIZE/4; i++)		if(nblk > EXT2_IND_BLOCK + BLOCKSIZE/4 + i)			swap_block(get_blk(fs, ((uint32*)get_blk(fs, nod->i_block[EXT2_DIND_BLOCK]))[i]));	if(nblk <= EXT2_IND_BLOCK + BLOCKSIZE/4 + BLOCKSIZE/4 * BLOCKSIZE/4)		return;	errexit("too big file on the filesystem");}// endianness swap of the whole filesystemvoid swap_goodfs(filesystem *fs){	int i;	for(i = 1; i < fs->sb.s_inodes_count; i++)	{		inode *nod = get_nod(fs, i);		if(nod->i_mode & FM_IFDIR)		{			blockwalker bw;			uint32 bk;			init_bw(fs, i, &bw);			while((bk = walk_bw(fs, i, &bw, 0, 0)) != WALK_END)			{				directory *d;				uint8 *b;				b = get_blk(fs, bk);				for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + swab16(d->d_rec_len)))					swap_dir(d);			}		}		swap_goodblocks(fs, nod);		swap_nod(nod);	}	swap_gd(&fs->gd);	swap_sb(&fs->sb);}void swap_badfs(filesystem *fs){	int i;	swap_sb(&fs->sb);	swap_gd(&fs->gd);	for(i = 1; i < fs->sb.s_inodes_count; i++)	{		inode *nod = get_nod(fs, i);		swap_nod(nod);		swap_badblocks(fs, nod);		if(nod->i_mode & FM_IFDIR)		{			blockwalker bw;			uint32 bk;			init_bw(fs, i, &bw);			while((bk = walk_bw(fs, i, &bw, 0, 0)) != WALK_END)			{				directory *d;				uint8 *b;				b = get_blk(fs, bk);				for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))					swap_dir(d);			}		}	}}// initialize an empty filesystemfilesystem * init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes){	int i;	filesystem *fs;	directory *d;	uint8 * b;	uint32 nod;		if(nbblocks < 16) // totally arbitrary		errexit("too small filesystem");	if(nbblocks >BLOCKS_PER_GROUP) // I build only one group		errexit("too big filesystem");	if(!(fs = (filesystem*)calloc(nbblocks, BLOCKSIZE)))		errexit("not enough memory for filesystem");	// create the superblock for an empty filesystem	fs->sb.s_inodes_count = rndup(nbinodes, BLOCKSIZE/sizeof(inode));	fs->sb.s_blocks_count = nbblocks;	fs->sb.s_r_blocks_count = nbresrvd;	fs->sb.s_free_blocks_count = nbblocks;	fs->sb.s_free_inodes_count = fs->sb.s_inodes_count - EXT2_FIRST_INO + 1;	fs->sb.s_first_data_block = (BLOCKSIZE == 1024);	fs->sb.s_log_block_size = BLOCKSIZE >> 11;	fs->sb.s_log_frag_size = BLOCKSIZE >> 11;	fs->sb.s_blocks_per_group = BLOCKS_PER_GROUP;	fs->sb.s_frags_per_group = BLOCKS_PER_GROUP;	fs->sb.s_inodes_per_group = fs->sb.s_inodes_count;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -