changeset 83:4b25264da01b

mke2fs: Stopping for dinner. It compiles.
author Rob Landley <rob@landley.net>
date Mon, 29 Jan 2007 17:44:28 -0500
parents 612c8d6c2829
children bdbef4ab4ac6
files toys/mke2fs.c
diffstat 1 files changed, 99 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/toys/mke2fs.c	Sun Jan 28 04:54:01 2007 -0500
+++ b/toys/mke2fs.c	Mon Jan 29 17:44:28 2007 -0500
@@ -116,41 +116,65 @@
 	sb->state = sb->errors = SWAP_LE16(1);
 
 	sb->rev_level = SWAP_LE32(1);
+	sb->first_ino = SWAP_LE32(11);  // First 10 reserved for special uses.
 	sb->inode_size = SWAP_LE16(sizeof(struct ext2_inode));
 	sb->feature_incompat = SWAP_LE32(EXT2_FEATURE_INCOMPAT_FILETYPE);
 	sb->feature_ro_compat = SWAP_LE32(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER);
 
 	create_uuid(sb->uuid);
 
-	// If we're called as mke3fs or mkfs.ext3, do a journal.
+	// TODO If we're called as mke3fs or mkfs.ext3, do a journal.
 
 	//if (strchr(toys.which->name,'3'))
 	//	sb->feature_compat = SWAP_LE32(EXT3_FEATURE_COMPAT_HAS_JOURNAL);
+
+	// TODO fill out free_blocks, free_inodes, first_ino
 }
 
 // Number of blocks used in this group by superblock/group list backup.
 // Returns 0 if this group doesn't have a superblock backup.
 static int group_superblock_used(uint32_t group)
 {
-	int used ;
+	int used = 0, i;
+
+	// Superblock backups are on groups 0, 1, and powers of 3, 5, and 7.
+	if(!group || group==1) used++;
+	for (i=3; i<9; i+=2) {
+		int j = i;
+		while (j<group) j*=i;
+		if (j==group) used++;
+	}
 
-	if (0) return 0;	// todo, which groups have no superblock?
-	
-	// How blocks does the group table take up?
-	used = TT.groups * sizeof(struct ext2_group);
-	used += TT.blocksize - 1;
-	used /= TT.blocksize;
-	// Plus the superblock itself.
-	used++;
-	// And a corner case.
-	if (!group && TT.blocksize == 1024) used++;
+	if (used) {
+		// How blocks does the group table take up?
+		used = TT.groups * sizeof(struct ext2_group);
+		used += TT.blocksize - 1;
+		used /= TT.blocksize;
+		// Plus the superblock itself.
+		used++;
+		// And a corner case.
+		if (!group && TT.blocksize == 1024) used++;
+	}
 
 	return used;
 }
 
+static void bits_set(char *array, int start, int len)
+{
+	while(len) {
+		if ((start&7) || len<8) {
+			array[start/8]|=(1<<(start&7));
+			start++;
+		} else {
+			array[start/8]=255;
+			start+=8;
+		}
+	}
+}
+
 int mke2fs_main(void)
 {
-	int i, temp;
+	int i, temp, blockbits;
 	off_t length;
 
 	// Handle command line arguments.
@@ -160,7 +184,7 @@
 		temp = O_RDWR|O_CREAT;
 	} else temp = O_RDWR;
 
-	// TODO: collect gene2fs list, calculate requirements.
+	// TODO: collect gene2fs list/lost+found, calculate requirements.
 
 	// TODO: Check if filesystem is mounted here
 
@@ -170,9 +194,9 @@
 	// Determine appropriate block size and block count from file length.
 
 	length = fdlength(TT.fsfd);
-	if (length<1) error_exit("gene2fs is a todo item");
 	if (!TT.blocksize) TT.blocksize = (length && length < 1<<29) ? 1024 : 4096;
 	if (!TT.blocks) TT.blocks = length/TT.blocksize;
+	if (!TT.blocks) error_exit("gene2fs is a TODO item");
 
 	// Skip the first 1k to avoid the boot sector (if any).  Use this to
 	// figure out if this file is seekable.
@@ -184,14 +208,19 @@
 	// Initialize superblock structure
 
 	init_superblock(&TT.sb);
+	blockbits = 8*TT.blocksize;
 
 	// Loop through block groups.
 
 	for (i=0; i<TT.groups; i++) {
+		struct ext2_inode *in = (struct ext2_inode *)toybuf;
+		uint32_t start;
+		int j, slot;
+
 		// If a superblock goes here, write it out.
-		if (group_superblock_used(i)) {
+		start = group_superblock_used(i);
+		if (start) {
 			struct ext2_group *bg = (struct ext2_group *)toybuf;
-			int j;
 
 			TT.sb.block_group_nr = SWAP_LE16(i);
 
@@ -204,16 +233,15 @@
 
 			// Loop through groups to write group descriptor table.
 			for(j=0; j<TT.groups; j++) {
-				uint32_t start, used, k;
+				uint32_t used;
 
 				// Figure out what sector this group starts in.
-				start = j*TT.blocksize*8;
 				used = group_superblock_used(j);
 
 				// Find next array slot in this block (flush block if full).
-				k = j % (TT.blocksize/sizeof(struct ext2_group));
-				if (!k) {
-					if (j) write(TT.fsfd, bg, TT.blocksize);
+				slot = j % (TT.blocksize/sizeof(struct ext2_group));
+				if (!slot) {
+					if (j) xwrite(TT.fsfd, bg, TT.blocksize);
 					memset(bg, 0, TT.blocksize);
 				}
 
@@ -221,22 +249,60 @@
 				// is uint16_t.  Add in endianness conversion and this little
 				// dance is called for.
 				temp = SWAP_LE32(TT.sb.inodes_per_group);
-				bg[k].free_inodes_count = SWAP_LE16(temp);
+				bg[slot].free_inodes_count = SWAP_LE16(temp);
 				
-				// How many blocks used by inode table?
+				// How many blocks will the inode table use?
 				temp *= sizeof(struct ext2_inode);
 				temp /= TT.blocksize;
 
-				// Fill out rest of group structure
-				bg[k].block_bitmap = SWAP_LE32(start+(used++));
-				bg[k].inode_bitmap = SWAP_LE32(start+(used++));
-				bg[k].inode_table = SWAP_LE32(start+used);
-				temp = (TT.blocksize*8)-used-temp;
-				bg[k].free_blocks_count = SWAP_LE32(temp);
-				bg[k].used_dirs_count = 0;
+				// How many does that leave?  (TODO: fill it up)
+				temp = blockbits-used-temp;
+				bg[slot].free_blocks_count = SWAP_LE32(temp);
+
+				// Fill out rest of group structure (TODO: gene2fs allocation)
+				used += j*blockbits;
+				bg[slot].block_bitmap = SWAP_LE32(used++);
+				bg[slot].inode_bitmap = SWAP_LE32(used++);
+				bg[slot].inode_table = SWAP_LE32(used);
+				bg[slot].used_dirs_count = 0;  // (TODO)
 			}
-			write(TT.fsfd, bg, TT.blocksize);
-		}		
+			xwrite(TT.fsfd, bg, TT.blocksize);
+		}
+
+		// Now write out stuff that every block group has.
+
+		// Write block usage bitmap  (TODO: fill it)
+
+		// Blocks used by inode table
+		temp = (TT.inodes/TT.groups)*sizeof(struct ext2_inode);
+		temp += TT.blocksize-1;
+		temp /= TT.blocksize;
+
+		memset(toybuf, 0, TT.blocksize);
+		bits_set(toybuf, 0, start+temp);
+		if ((i+1)*TT.blocksize*8 > TT.blocks) {
+			temp = TT.blocks & (blockbits-1);
+			bits_set(toybuf, temp, blockbits-temp);
+		}
+		xwrite(TT.fsfd, toybuf, TT.blocksize);
+
+		temp = TT.inodes/TT.groups;
+
+		// Write inode bitmap  (TODO)
+		memset(toybuf, 0, TT.blocksize);
+		if (!i) bits_set(toybuf,0,10);
+		bits_set(toybuf, temp, blockbits-temp);
+		xwrite(TT.fsfd, toybuf, TT.blocksize);
+
+		// Write inode table for this group
+		for (j = 0; j<temp; j++) {
+			slot = j % (TT.blocksize/sizeof(struct ext2_inode));
+			if (!slot) {
+				if (j) xwrite(TT.fsfd, in, TT.blocksize);
+				memset(in, 0, TT.blocksize);
+			}
+		}
+		xwrite(TT.fsfd, in, TT.blocksize);
 	}
 
 	return 0;