comparison toys/mke2fs.c @ 237:7cb15eae1664

Zap toylist.h, moving contents of global structures into DEFINE_GLOBALS() macros in each C file, and making generated/globals.h from that. Rename "toy" to "this" along the way to avoid toy/toys confusion.
author Rob Landley <rob@landley.net>
date Sun, 20 Jan 2008 17:25:44 -0600
parents 6b292ee780ab
children 44abf4d901f3
comparison
equal deleted inserted replaced
236:6b292ee780ab 237:7cb15eae1664
75 sparse_super Don't allocate huge numbers of redundant superblocks 75 sparse_super Don't allocate huge numbers of redundant superblocks
76 */ 76 */
77 77
78 #include "toys.h" 78 #include "toys.h"
79 79
80 DEFINE_GLOBALS(
81 // Command line arguments.
82 long blocksize;
83 long bytes_per_inode;
84 long inodes; // Total inodes in filesystem.
85 long reserved_percent; // Integer precent of space to reserve for root.
86 char *gendir; // Where to read dirtree from.
87
88 // Internal data.
89 struct dirtree *dt; // Tree of files to copy into the new filesystem.
90 unsigned treeblocks; // Blocks used by dt
91 unsigned treeinodes; // Inodes used by dt
92
93 unsigned blocks; // Total blocks in the filesystem.
94 unsigned freeblocks; // Free blocks in the filesystem.
95 unsigned inodespg; // Inodes per group
96 unsigned groups; // Total number of block groups.
97 unsigned blockbits; // Bits per block. (Also blocks per group.)
98
99 // For gene2fs
100 unsigned nextblock; // Next data block to allocate
101 unsigned nextgroup; // Next group we'll be allocating from
102 int fsfd; // File descriptor of filesystem (to output to).
103
104 struct ext2_superblock sb;
105 )
106
80 // Shortcut to our global data structure, since we use it so much. 107 // Shortcut to our global data structure, since we use it so much.
81 #define TT toy.mke2fs 108 #define TT this.mke2fs
82 109
83 #define INODES_RESERVED 10 110 #define INODES_RESERVED 10
84 111
85 static uint32_t div_round_up(uint32_t a, uint32_t b) 112 static uint32_t div_round_up(uint32_t a, uint32_t b)
86 { 113 {
138 165
139 // Recursively calculate the number of blocks used by each inode in the tree. 166 // Recursively calculate the number of blocks used by each inode in the tree.
140 // Returns blocks used by this directory, assigns bytes used to *size. 167 // Returns blocks used by this directory, assigns bytes used to *size.
141 // Writes total block count to TT.treeblocks and inode count to TT.treeinodes. 168 // Writes total block count to TT.treeblocks and inode count to TT.treeinodes.
142 169
143 static long check_treesize(struct dirtree *this, off_t *size) 170 static long check_treesize(struct dirtree *that, off_t *size)
144 { 171 {
145 long blocks; 172 long blocks;
146 173
147 while (this) { 174 while (that) {
148 *size += sizeof(struct ext2_dentry) + strlen(this->name); 175 *size += sizeof(struct ext2_dentry) + strlen(that->name);
149 176
150 if (this->child) 177 if (that->child)
151 this->st.st_blocks = check_treesize(this->child, &this->st.st_size); 178 that->st.st_blocks = check_treesize(that->child, &that->st.st_size);
152 else if (S_ISREG(this->st.st_mode)) { 179 else if (S_ISREG(that->st.st_mode)) {
153 this->st.st_blocks = file_blocks_used(this->st.st_size, 0); 180 that->st.st_blocks = file_blocks_used(that->st.st_size, 0);
154 TT.treeblocks += this->st.st_blocks; 181 TT.treeblocks += that->st.st_blocks;
155 } 182 }
156 this = this->next; 183 that = that->next;
157 } 184 }
158 TT.treeblocks += blocks = file_blocks_used(*size, 0); 185 TT.treeblocks += blocks = file_blocks_used(*size, 0);
159 TT.treeinodes++; 186 TT.treeinodes++;
160 187
161 return blocks; 188 return blocks;
168 // numbers of files (> 100,000) but can be done in very little code. 195 // numbers of files (> 100,000) but can be done in very little code.
169 // This rewrites inode numbers to their final values, allocating depth first. 196 // This rewrites inode numbers to their final values, allocating depth first.
170 197
171 static void check_treelinks(struct dirtree *tree) 198 static void check_treelinks(struct dirtree *tree)
172 { 199 {
173 struct dirtree *this=tree, *that; 200 struct dirtree *current=tree, *that;
174 long inode = INODES_RESERVED; 201 long inode = INODES_RESERVED;
175 202
176 while (this) { 203 while (current) {
177 ++inode; 204 ++inode;
178 // Since we can't hardlink to directories, we know their link count. 205 // Since we can't hardlink to directories, we know their link count.
179 if (S_ISDIR(this->st.st_mode)) this->st.st_nlink = 2; 206 if (S_ISDIR(current->st.st_mode)) current->st.st_nlink = 2;
180 else { 207 else {
181 dev_t new = this->st.st_dev; 208 dev_t new = current->st.st_dev;
182 209
183 if (!new) continue; 210 if (!new) continue;
184 211
185 this->st.st_nlink = 0; 212 // Look for other copies of current node
213 current->st.st_nlink = 0;
186 for (that = tree; that; that = treenext(that)) { 214 for (that = tree; that; that = treenext(that)) {
187 if (this->st.st_ino == that->st.st_ino && 215 if (current->st.st_ino == that->st.st_ino &&
188 this->st.st_dev == that->st.st_dev) 216 current->st.st_dev == that->st.st_dev)
189 { 217 {
190 this->st.st_nlink++; 218 current->st.st_nlink++;
191 this->st.st_ino = inode; 219 current->st.st_ino = inode;
192 } 220 }
193 } 221 }
194 } 222 }
195 this->st.st_ino = inode; 223 current->st.st_ino = inode;
196 this = treenext(this); 224 current = treenext(current);
197 } 225 }
198 } 226 }
199 227
200 // According to http://www.opengroup.org/onlinepubs/9629399/apdxa.htm 228 // According to http://www.opengroup.org/onlinepubs/9629399/apdxa.htm
201 // we should generate a uuid structure by reading a clock with 100 nanosecond 229 // we should generate a uuid structure by reading a clock with 100 nanosecond
361 } 389 }
362 } 390 }
363 } 391 }
364 392
365 // Fill out an inode structure from struct stat info in dirtree. 393 // Fill out an inode structure from struct stat info in dirtree.
366 static void fill_inode(struct ext2_inode *in, struct dirtree *this) 394 static void fill_inode(struct ext2_inode *in, struct dirtree *that)
367 { 395 {
368 uint32_t fbu[15]; 396 uint32_t fbu[15];
369 int temp; 397 int temp;
370 398
371 file_blocks_used(this->st.st_size, fbu); 399 file_blocks_used(that->st.st_size, fbu);
372 400
373 // If this inode needs data blocks allocated to it. 401 // If that inode needs data blocks allocated to it.
374 if (this->st.st_size) { 402 if (that->st.st_size) {
375 int i, group = TT.nextblock/TT.blockbits; 403 int i, group = TT.nextblock/TT.blockbits;
376 404
377 // TODO: teach this about indirect blocks. 405 // TODO: teach this about indirect blocks.
378 for (i=0; i<15; i++) { 406 for (i=0; i<15; i++) {
379 // If we just jumped into a new group, skip group overhead blocks. 407 // If we just jumped into a new group, skip group overhead blocks.
380 while (group >= TT.nextgroup) 408 while (group >= TT.nextgroup)
381 TT.nextblock += group_overhead(TT.nextgroup++); 409 TT.nextblock += group_overhead(TT.nextgroup++);
382 } 410 }
383 } 411 }
384 // TODO : S_ISREG/DIR/CHR/BLK/FIFO/LNK/SOCK(m) 412 // TODO : S_ISREG/DIR/CHR/BLK/FIFO/LNK/SOCK(m)
385 in->mode = SWAP_LE32(this->st.st_mode); 413 in->mode = SWAP_LE32(that->st.st_mode);
386 414
387 in->uid = SWAP_LE16(this->st.st_uid & 0xFFFF); 415 in->uid = SWAP_LE16(that->st.st_uid & 0xFFFF);
388 in->uid_high = SWAP_LE16(this->st.st_uid >> 16); 416 in->uid_high = SWAP_LE16(that->st.st_uid >> 16);
389 in->gid = SWAP_LE16(this->st.st_gid & 0xFFFF); 417 in->gid = SWAP_LE16(that->st.st_gid & 0xFFFF);
390 in->gid_high = SWAP_LE16(this->st.st_gid >> 16); 418 in->gid_high = SWAP_LE16(that->st.st_gid >> 16);
391 in->size = SWAP_LE32(this->st.st_size & 0xFFFFFFFF); 419 in->size = SWAP_LE32(that->st.st_size & 0xFFFFFFFF);
392 420
393 // Contortions to make the compiler not generate a warning for x>>32 421 // Contortions to make the compiler not generate a warning for x>>32
394 // when x is 32 bits. The optimizer should clean this up. 422 // when x is 32 bits. The optimizer should clean this up.
395 if (sizeof(this->st.st_size) > 4) temp = 32; 423 if (sizeof(that->st.st_size) > 4) temp = 32;
396 else temp = 0; 424 else temp = 0;
397 if (temp) in->dir_acl = SWAP_LE32(this->st.st_size >> temp); 425 if (temp) in->dir_acl = SWAP_LE32(that->st.st_size >> temp);
398 426
399 in->atime = SWAP_LE32(this->st.st_atime); 427 in->atime = SWAP_LE32(that->st.st_atime);
400 in->ctime = SWAP_LE32(this->st.st_ctime); 428 in->ctime = SWAP_LE32(that->st.st_ctime);
401 in->mtime = SWAP_LE32(this->st.st_mtime); 429 in->mtime = SWAP_LE32(that->st.st_mtime);
402 430
403 in->links_count = SWAP_LE16(this->st.st_nlink); 431 in->links_count = SWAP_LE16(that->st.st_nlink);
404 in->blocks = SWAP_LE32(this->st.st_blocks); 432 in->blocks = SWAP_LE32(that->st.st_blocks);
405 // in->faddr 433 // in->faddr
406 } 434 }
407 435
408 // Works like an archiver. 436 // Works like an archiver.
409 // The first argument is the name of the file to create. If it already 437 // The first argument is the name of the file to create. If it already