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

📄 genext2fs.c

📁 genext2fs
💻 C
📖 第 1 页 / 共 3 页
字号:
// genext2fs.c//// ext2 filesystem generator for embedded systems// Copyright (C) 2000 Xavier Bestel <xavier.bestel@free.fr>//// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License// as published by the Free Software Foundation; version// 2 of the License.//// Changes:// 	 3 Jun 2000	Initial release// 	 6 Jun 2000	Bugfix: fs size multiple of 8// 			Bugfix: fill blocks with inodes// 	14 Jun 2000	Bugfix: bad chdir() with -d option// 			Bugfix: removed size=8n constraint// 			Changed -d file to -f file// 			Added -e option// 	22 Jun 2000	Changed types for 64bits archs// 	24 Jun 2000	Added endianness swap// 			Bugfix: bad dir name lookup// 	03 Aug 2000	Bugfix: ind. blocks endian swap// 	09 Aug 2000	Bugfix: symlinks endian swap// 	01 Sep 2000	Bugfix: getopt returns int, not char	proski@gnu.org// 	10 Sep 2000	Bugfix: device nodes endianness		xavier.gueguen@col.bsf.alcatel.fr// 			Bugfix: getcwd values for Solaris	xavier.gueguen@col.bsf.alcatel.fr// 			Bugfix: ANSI scanf for non-GNU C	xavier.gueguen@col.bsf.alcatel.fr// 	28 Jun 2001	Bugfix: getcwd differs for Solaris/GNU	mike@sowbug.com// `genext2fs' is a mean to generate an ext2 filesystem// as a normal (non-root) user. It doesn't require you to mount// the image file to copy files on it. It doesn't even require// you to be the superuser to make device nodes.//// Warning ! `genext2fs' has been designed for embedded// systems. As such, it will generate a filesystem for single-user// usage: all files/directories/etc... will belong to UID/GID 0//// Example usage://// # genext2fs -b 1440 -d srcdir /dev/fd0//// All files in the srcdir directory will be written to /dev/fd0 as// a new ext2 filesystem image. You can then mount the floppy as// usual.//// # genext2fs -b 1024 -d builddir -f devices.txt flashdisk.img//// This one would build a filesystem from all the files in builddir,// then would read a devices list and make apropriate nodes. The// format for the device list is://// drwx            /dev// crw-    10,190  /dev/lcd// brw-    1,0     /dev/ram0// // This device list builds the /dev directory, a character device// node /dev/lcd (major 10, minor 190) and a block device node// /dev/ram0 (major 1, minor 0)#include <stdio.h>#include <stdlib.h>#include <string.h>#include <dirent.h>#include <stdarg.h>#include <unistd.h>#include <sys/stat.h>// block size#define BLOCKSIZE         1024#define BLOCKS_PER_GROUP  8192#define BYTES_PER_INODE   (8*BLOCKSIZE)#define RESERVED_INODES   5/100// inode block size (why is it != BLOCKSIZE ?!?)#define INODE_BLOCKSIZE   512#define INOBLK            (BLOCKSIZE / INODE_BLOCKSIZE)// reserved inodes#define EXT2_BAD_INO         1     // Bad blocks inode#define EXT2_ROOT_INO        2     // Root inode#define EXT2_ACL_IDX_INO     3     // ACL inode#define EXT2_ACL_DATA_INO    4     // ACL inode#define EXT2_BOOT_LOADER_INO 5     // Boot loader inode#define EXT2_UNDEL_DIR_INO   6     // Undelete directory inode#define EXT2_FIRST_INO       11    // First non reserved inode// magic number for ext2#define EXT2_MAGIC_NUMBER  0xEF53// direct/indirect block addresses#define EXT2_NDIR_BLOCKS   11                    // direct blocks#define EXT2_IND_BLOCK     12                    // indirect block#define EXT2_DIND_BLOCK    13                    // double indirect block#define EXT2_TIND_BLOCK    14                    // triple indirect block#define EXT2_INIT_BLOCK    0xFFFFFFFF            // just initialized (not really a block address)// end of a block walk#define WALK_END           0xFFFFFFFE// file modes#define FM_IFMT    0xF000	// format mask#define FM_IFLNK   0xA000	// socket#define FM_IFSOCK  0xC000	// symbolic link#define FM_IFREG   0x8000	// regular file#define FM_IFBLK   0x6000	// block device#define FM_IFDIR   0x4000	// directory#define FM_IFCHR   0x2000	// character device#define FM_IFIFO   0x1000	// fifo#define FM_ISUID   0x0800	// SUID#define FM_ISGID   0x0400	// SGID#define FM_ISVTX   0x0200	// sticky bit#define FM_IRWXU   0x01C0	// user mask#define FM_IRUSR   0x0100	// read#define FM_IWUSR   0x0080	// write#define FM_IXUSR   0x0040	// execute#define FM_IRWXG   0x0038	// group mask#define FM_IRGRP   0x0020	// read#define FM_IWGRP   0x0010	// write#define FM_IXGRP   0x0008	// execute#define FM_IRWXO   0x0007	// other mask#define FM_IROTH   0x0004	// read#define FM_IWOTH   0x0002	// write#define FM_IXOTH   0x0001	// execute// options#define OP_HOLES     0x01       // make files with holes// used typestypedef signed char int8;typedef unsigned char uint8;typedef signed short int16;typedef unsigned short uint16;typedef signed int int32;typedef unsigned int uint32;// the GNU C library has a wonderful scanf("%as", string) which will// allocate the string with the right size, good to avoid buffer// overruns. the following macros use it if available or use a// hacky workaround// moreover it will define a snprintf() like a sprintf(), i.e.// without the buffer overrun checking,// and the correct getcwd() size argument for automatic allocation,// which of course is not the same on Solaris, old glibc and new// glibc ...#ifdef __GNUC__#define SCANF_PREFIX "a"#define SCANF_STRING(s) (&s)#define GETCWD_SIZE 0#else#define SCANF_PREFIX "511"#define SCANF_STRING(s) (s = malloc(512))#define GETCWD_SIZE -1inline int snprintf(char *str, size_t n, const char *fmt, ...){	int ret;	va_list ap;	va_start(ap, fmt);	ret = vsprintf(str, fmt, ap);	va_end(ap);	return ret;}#endif// endianness swapinline uint16 swab16(uint16 val){	return (val >> 8) | (val << 8);}inline uint32 swab32(uint32 val){	return ((val>>24) | ((val>>8)&0xFF00) |			((val<<8)&0xFF0000) | (val<<24));}// on-disk structures// this trick makes me declare things only once// (once for the structures, once for the endianness swap)#define superblock_decl \	udecl32(s_inodes_count)        /* Count of inodes in the filesystem */ \	udecl32(s_blocks_count)        /* Count of blocks in the filesystem */ \	udecl32(s_r_blocks_count)      /* Count of the number of reserved blocks */ \	udecl32(s_free_blocks_count)   /* Count of the number of free blocks */ \	udecl32(s_free_inodes_count)   /* Count of the number of free inodes */ \	udecl32(s_first_data_block)    /* The first block which contains data */ \	udecl32(s_log_block_size)      /* Indicator of the block size */ \	decl32(s_log_frag_size)        /* Indicator of the size of the fragments */ \	udecl32(s_blocks_per_group)    /* Count of the number of blocks in each block group */ \	udecl32(s_frags_per_group)     /* Count of the number of fragments in each block group */ \	udecl32(s_inodes_per_group)    /* Count of the number of inodes in each block group */ \	udecl32(s_mtime)               /* The time that the filesystem was last mounted */ \	udecl32(s_wtime)               /* The time that the filesystem was last written to */ \	udecl16(s_mnt_count)           /* The number of times the file system has been mounted */ \	decl16(s_max_mnt_count)        /* The number of times the file system can be mounted */ \	udecl16(s_magic)               /* Magic number indicating ex2fs */ \	udecl16(s_state)               /* Flags indicating the current state of the filesystem */ \	udecl16(s_errors)              /* Flags indicating the procedures for error reporting */ \	udecl16(s_minor_rev_level)     /* The minor revision level of the filesystem */ \	udecl32(s_lastcheck)           /* The time that the filesystem was last checked */ \	udecl32(s_checkinterval)       /* The maximum time permissable between checks */ \	udecl32(s_creator_os)          /* Indicator of which OS created the filesystem */ \	udecl32(s_rev_level)           /* The revision level of the filesystem */ \	udecl16(s_def_resuid)          /* The default uid for reserved blocks */ \	udecl16(s_def_resgid)          /* The default gid for reserved blocks */#define groupdescriptor_decl \	udecl32(bg_block_bitmap)       /* Block number of the block bitmap */ \	udecl32(bg_inode_bitmap)       /* Block number of the inode bitmap */ \	udecl32(bg_inode_table)        /* Block number of the inode table */ \	udecl16(bg_free_blocks_count)  /* Free blocks in the group */ \	udecl16(bg_free_inodes_count)  /* Free inodes in the group */ \	udecl16(bg_used_dirs_count)    /* Number of directories in the group */ \	udecl16(bg_pad)#define inode_decl \	udecl16(i_mode)                /* Entry type and file mode */ \	udecl16(i_uid)                 /* User id */ \	udecl32(i_size)                /* File/dir size in bytes */ \	udecl32(i_atime)               /* Last access time */ \	udecl32(i_ctime)               /* Creation time */ \	udecl32(i_mtime)               /* Last modification time */ \	udecl32(i_dtime)               /* Deletion time */ \	udecl16(i_gid)                 /* Group id */ \	udecl16(i_links_count)         /* Number of (hard) links to this inode */ \	udecl32(i_blocks)              /* Number of blocks used (1 block = 512 bytes) */ \	udecl32(i_flags)               /* ??? */ \	udecl32(i_reserved1) \	utdecl32(i_block,15)           /* Blocks table */ \	udecl32(i_version)             /* ??? */ \	udecl32(i_file_acl)            /* File access control list */ \	udecl32(i_dir_acl)             /* Directory access control list */ \	udecl32(i_faddr)               /* Fragment address */ \	udecl8(i_frag)                 /* Fragments count*/ \	udecl8(i_fsize)                /* Fragment size */ \	udecl16(i_pad1)#define directory_decl \	udecl32(d_inode)               /* Inode entry */ \	udecl16(d_rec_len)             /* Total size on record */ \	udecl16(d_name_len)            /* Size of entry name */#define decl8(x) int8 x;#define udecl8(x) uint8 x;#define decl16(x) int16 x;#define udecl16(x) uint16 x;#define decl32(x) int32 x;#define udecl32(x) uint32 x;#define utdecl32(x,n) uint32 x[n];typedef struct{	superblock_decl	uint32 s_reserved[235];       // Reserved} superblock;typedef struct{	groupdescriptor_decl	uint32 bg_reserved[3];	uint32 bg_pad_to_bk[(BLOCKSIZE-32)/sizeof(uint32)];} groupdescriptor;typedef struct{	inode_decl	uint32 i_reserved2[2];} inode;typedef struct{	directory_decl	char d_name[0];} directory;typedef uint8 block[BLOCKSIZE];typedef struct{	uint32 bnum;	uint32 bpdir;	uint32 bpind;	uint32 bpdind;	uint32 bptind;} blockwalker;#if BLOCKSIZE == 1024typedef struct{	block zero;          // The famous block 0	superblock sb;       // The superblock	groupdescriptor gd;  // The group desciptor	block bbm;           // The block bitmap	block ibm;           // The inode bitmap	inode itab[0];       // The inode table} filesystem;#else#error UNHANDLED BLOCKSIZE#endif// now the endianness swap#undef decl8#undef udecl8#undef decl16#undef udecl16#undef decl32#undef udecl32#undef utdecl32#define decl8(x)#define udecl8(x)#define decl16(x) this->x = swab16(this->x);#define udecl16(x) this->x = swab16(this->x);#define decl32(x) this->x = swab32(this->x);#define udecl32(x) this->x = swab32(this->x);#define utdecl32(x,n) { int i; for(i=0; i<n; i++) this->x[i] = swab32(this->x[i]); }void swap_sb(superblock *sb){#define this sb	superblock_decl#undef this}void swap_gd(groupdescriptor *gd){#define this gd	groupdescriptor_decl#undef this}void swap_nod(inode *nod){#define this nod	inode_decl#undef this}void swap_dir(directory *dir){#define this dir	directory_decl#undef this}void swap_block(block b){	int i;	uint32 *blk = (uint32*)b;	for(i = 0; i < BLOCKSIZE/4; i++)		blk[i] = swab32(blk[i]);}#undef decl8#undef udecl8#undef decl16#undef udecl16#undef decl32#undef udecl32#undef utdecl32char * argv0;// error (un)handlinginline void errexit(const char *fmt, ...){	va_list ap;	fprintf(stderr, "%s: ", argv0);	va_start(ap, fmt);	vfprintf(stderr, fmt, ap);	va_end(ap);	fprintf(stderr, "\n");	exit(1);}inline void pexit(const char * fname){	fprintf(stderr, "%s: ", argv0);	perror(fname);	exit(1);}// printf helper macro#define plural(a) (a), ((a) > 1) ? "s" : ""// temporary working blockinline uint8 * get_workblk(void){	static block b;	return b;}inline void free_workblk(block b){}// rounds a quantity up to a blocksizeuint32 rndup(uint32 qty, uint32 siz){	return (qty + (siz - 1)) & ~(siz - 1);}// check if something is allocated in the bitmapinline uint32 allocated(block b, uint32 item){	return b[(item-1) / 8] & (1 << ((item-1) % 8));}// return a given block from a filesysteminline uint8 * get_blk(filesystem *fs, uint32 blk){	return (uint8*)fs + blk*BLOCKSIZE;}// return a given inode from a filesysteminline inode * get_nod(filesystem *fs, uint32 nod){	return &fs->itab[nod-1];}// allocate a given block/inode in the bitmap// allocate first free if item == 0uint32 allocate(block b, uint32 item){	if(!item)	{		int i;		uint8 bits;		for(i = 0; i < BLOCKSIZE; i++)			if((bits = b[i]) != (uint8)-1)			{				int j;				for(j = 0; j < 8; j++)					if(!(bits & (1 << j)))						break;				item = i * 8 + j + 1;				break;			}		if(i == BLOCKSIZE)			return 0;	}	b[(item-1) / 8] |= (1 << ((item-1) % 8));	return item;}// deallocate a given block/inodevoid deallocate(block b, uint32 item){	b[(item-1) / 8] &= ~(1 << ((item-1) % 8));}// allocate a blockuint32 alloc_blk(filesystem *fs){	uint32 bk;	if(!(bk = allocate(fs->bbm, 0)))		errexit("couldn't allocate a block (no free space)");	if(!(fs->gd.bg_free_blocks_count--))		errexit("group descr. free blocks count == 0 (corrupted fs?)");	if(!(fs->sb.s_free_blocks_count--))		errexit("superblock free blocks count == 0 (corrupted fs?)");	return bk;}// allocate an inodeuint32 alloc_nod(filesystem *fs){	uint32 nod;	if(!(nod = allocate(fs->ibm, 0)))		errexit("couldn't allocate an inode (no free inode)");	if(!(fs->gd.bg_free_inodes_count--))		errexit("group descr. free blocks count == 0 (corrupted fs?)");	if(!(fs->sb.s_free_inodes_count--))		errexit("superblock free blocks count == 0 (corrupted fs?)");	return nod;}// print a bitmap allocationvoid print_bm(block b, uint32 max){	uint32 i;	printf("----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0\n");	for(i=1; i <= max; i++)	{		putchar(allocated(b, i) ? '*' : '.');		if(!(i % 100))			printf("\n");	}	if((i-1) % 100)		printf("\n");}// initalize a blockwalker (iterator for blocks list)void init_bw(filesystem *fs, uint32 nod, blockwalker *bw){	bw->bnum = 0;	bw->bpdir = EXT2_INIT_BLOCK;}// return next block of inode (WALK_END for end)// if create>0, append a newly allocated block at the end// if hole!=0, create a hole in the fileuint32 walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, uint32 *create, uint32 hole){	uint32 *bkref = 0;	uint32 *b;	int extend = 0;	if(bw->bnum >= get_nod(fs, nod)->i_blocks / INOBLK)	{		if(create && (*create)--)			extend = 1;		else				return WALK_END;	}	// first direct block	if(bw->bpdir == EXT2_INIT_BLOCK)	{		bkref = &get_nod(fs, nod)->i_block[bw->bpdir = 0];		if(extend) // allocate first block			*bkref = hole ? 0 : alloc_blk(fs);	}	// direct block	else if(bw->bpdir < EXT2_NDIR_BLOCKS)	{

⌨️ 快捷键说明

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