Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/util-linux/mkfs_minix.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/util-linux/mkfs_minix.c
r821 r1770 34 34 * (Dr. Wettstein, greg%wind.uucp@plains.nodak.edu) 35 35 * 36 * 30.10.94 -added support for v2 filesystem37 * (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)36 * 30.10.94 - added support for v2 filesystem 37 * (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de) 38 38 * 39 39 * 09.11.94 - Added test to prevent overwrite of mounted fs adapted … … 63 63 */ 64 64 65 #include <stdio.h> 66 #include <time.h> 67 #include <unistd.h> 68 #include <string.h> 69 #include <signal.h> 70 #include <fcntl.h> 71 #include <ctype.h> 72 #include <stdlib.h> 73 #include <stdint.h> 74 #include <termios.h> 75 #include <sys/ioctl.h> 76 #include <sys/param.h> 65 #include "libbb.h" 77 66 #include <mntent.h> 78 #include "busybox.h" 79 80 #define MINIX_ROOT_INO 1 81 #define MINIX_LINK_MAX 250 82 #define MINIX2_LINK_MAX 65530 83 84 #define MINIX_I_MAP_SLOTS 8 85 #define MINIX_Z_MAP_SLOTS 64 86 #define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ 87 #define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ 88 #define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ 89 #define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ 90 #define MINIX_VALID_FS 0x0001 /* Clean fs. */ 91 #define MINIX_ERROR_FS 0x0002 /* fs has errors. */ 92 93 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) 94 #define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode))) 95 96 #define MINIX_V1 0x0001 /* original minix fs */ 97 #define MINIX_V2 0x0002 /* minix V2 fs */ 98 99 #define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version 100 101 /* 102 * This is the original minix inode layout on disk. 103 * Note the 8-bit gid and atime and ctime. 104 */ 105 struct minix_inode { 106 uint16_t i_mode; 107 uint16_t i_uid; 108 uint32_t i_size; 109 uint32_t i_time; 110 uint8_t i_gid; 111 uint8_t i_nlinks; 112 uint16_t i_zone[9]; 67 68 #include "minix.h" 69 70 #define DEBUG 0 71 72 /* If debugging, store the very same times/uids/gids for image consistency */ 73 #if DEBUG 74 # define CUR_TIME 0 75 # define GETUID 0 76 # define GETGID 0 77 #else 78 # define CUR_TIME time(NULL) 79 # define GETUID getuid() 80 # define GETGID getgid() 81 #endif 82 83 enum { 84 MAX_GOOD_BLOCKS = 512, 85 TEST_BUFFER_BLOCKS = 16, 113 86 }; 114 87 115 /* 116 * The new minix inode has all the time entries, as well as 117 * long block numbers and a third indirect block (7+1+1+1 118 * instead of 7+1+1). Also, some previously 8-bit values are 119 * now 16-bit. The inode is now 64 bytes instead of 32. 120 */ 121 struct minix2_inode { 122 uint16_t i_mode; 123 uint16_t i_nlinks; 124 uint16_t i_uid; 125 uint16_t i_gid; 126 uint32_t i_size; 127 uint32_t i_atime; 128 uint32_t i_mtime; 129 uint32_t i_ctime; 130 uint32_t i_zone[10]; 88 #if !ENABLE_FEATURE_MINIX2 89 enum { version2 = 0 }; 90 #endif 91 92 struct globals { 93 int dev_fd; 94 95 #if ENABLE_FEATURE_MINIX2 96 smallint version2; 97 #define version2 G.version2 98 #endif 99 char *device_name; 100 uint32_t total_blocks; 101 int badblocks; 102 int namelen; 103 int dirsize; 104 int magic; 105 char *inode_buffer; 106 char *inode_map; 107 char *zone_map; 108 int used_good_blocks; 109 unsigned long req_nr_inodes; 110 unsigned currently_testing; 111 112 113 char root_block[BLOCK_SIZE]; 114 char super_block_buffer[BLOCK_SIZE]; 115 char boot_block_buffer[512]; 116 unsigned short good_blocks_table[MAX_GOOD_BLOCKS]; 117 /* check_blocks(): buffer[] was the biggest static in entire bbox */ 118 char check_blocks_buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS]; 131 119 }; 132 120 133 /* 134 * minix super-block data on disk 135 */ 136 struct minix_super_block { 137 uint16_t s_ninodes; 138 uint16_t s_nzones; 139 uint16_t s_imap_blocks; 140 uint16_t s_zmap_blocks; 141 uint16_t s_firstdatazone; 142 uint16_t s_log_zone_size; 143 uint32_t s_max_size; 144 uint16_t s_magic; 145 uint16_t s_state; 146 uint32_t s_zones; 147 }; 148 149 struct minix_dir_entry { 150 uint16_t inode; 151 char name[0]; 152 }; 153 154 #define NAME_MAX 255 /* # chars in a file name */ 155 156 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) 157 158 #define MINIX_VALID_FS 0x0001 /* Clean fs. */ 159 #define MINIX_ERROR_FS 0x0002 /* fs has errors. */ 160 161 #define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ 162 #define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ 121 #define G (*ptr_to_globals) 122 123 static ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n) 124 { 125 return (size + n-1) / n; 126 } 127 128 #define INODE_BUF1 (((struct minix1_inode*)G.inode_buffer) - 1) 129 #define INODE_BUF2 (((struct minix2_inode*)G.inode_buffer) - 1) 130 131 #define SB (*(struct minix_super_block*)G.super_block_buffer) 132 133 #define SB_INODES (SB.s_ninodes) 134 #define SB_IMAPS (SB.s_imap_blocks) 135 #define SB_ZMAPS (SB.s_zmap_blocks) 136 #define SB_FIRSTZONE (SB.s_firstdatazone) 137 #define SB_ZONE_SIZE (SB.s_log_zone_size) 138 #define SB_MAXSIZE (SB.s_max_size) 139 #define SB_MAGIC (SB.s_magic) 140 141 #if !ENABLE_FEATURE_MINIX2 142 # define SB_ZONES (SB.s_nzones) 143 # define INODE_BLOCKS div_roundup(SB_INODES, MINIX1_INODES_PER_BLOCK) 144 #else 145 # define SB_ZONES (version2 ? SB.s_zones : SB.s_nzones) 146 # define INODE_BLOCKS div_roundup(SB_INODES, \ 147 version2 ? MINIX2_INODES_PER_BLOCK : MINIX1_INODES_PER_BLOCK) 148 #endif 149 150 #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE) 151 #define NORM_FIRSTZONE (2 + SB_IMAPS + SB_ZMAPS + INODE_BLOCKS) 152 153 /* Before you ask "where they come from?": */ 154 /* setbit/clrbit are supplied by sys/param.h */ 155 156 static int minix_bit(const char* a, unsigned i) 157 { 158 return a[i >> 3] & (1<<(i & 7)); 159 } 160 161 static void minix_setbit(char *a, unsigned i) 162 { 163 setbit(a, i); 164 } 165 static void minix_clrbit(char *a, unsigned i) 166 { 167 clrbit(a, i); 168 } 169 170 /* Note: do not assume 0/1, it is 0/nonzero */ 171 #define zone_in_use(x) minix_bit(G.zone_map,(x)-SB_FIRSTZONE+1) 172 /*#define inode_in_use(x) minix_bit(G.inode_map,(x))*/ 173 174 #define mark_inode(x) minix_setbit(G.inode_map,(x)) 175 #define unmark_inode(x) minix_clrbit(G.inode_map,(x)) 176 #define mark_zone(x) minix_setbit(G.zone_map,(x)-SB_FIRSTZONE+1) 177 #define unmark_zone(x) minix_clrbit(G.zone_map,(x)-SB_FIRSTZONE+1) 163 178 164 179 #ifndef BLKGETSIZE 165 #define BLKGETSIZE _IO(0x12,96) /* return device size */ 166 #endif 167 168 169 #ifndef __linux__ 170 #define volatile 171 #endif 172 173 #define MINIX_ROOT_INO 1 174 #define MINIX_BAD_INO 2 175 176 #define TEST_BUFFER_BLOCKS 16 177 #define MAX_GOOD_BLOCKS 512 178 179 #define UPPER(size,n) (((size)+((n)-1))/(n)) 180 #define INODE_SIZE (sizeof(struct minix_inode)) 181 #ifdef CONFIG_FEATURE_MINIX2 182 #define INODE_SIZE2 (sizeof(struct minix2_inode)) 183 #define INODE_BLOCKS UPPER(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \ 184 : MINIX_INODES_PER_BLOCK)) 185 #else 186 #define INODE_BLOCKS UPPER(INODES, (MINIX_INODES_PER_BLOCK)) 187 #endif 188 #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE) 189 190 #define BITS_PER_BLOCK (BLOCK_SIZE<<3) 191 192 static char *device_name; 193 static int DEV = -1; 194 static uint32_t BLOCKS; 195 static int check; 196 static int badblocks; 197 static int namelen = 30; /* default (changed to 30, per Linus's 198 199 suggestion, Sun Nov 21 08:05:07 1993) */ 200 static int dirsize = 32; 201 static int magic = MINIX_SUPER_MAGIC2; 202 static int version2; 203 204 static char root_block[BLOCK_SIZE]; 205 206 static char *inode_buffer; 207 208 #define Inode (((struct minix_inode *) inode_buffer)-1) 209 #ifdef CONFIG_FEATURE_MINIX2 210 #define Inode2 (((struct minix2_inode *) inode_buffer)-1) 211 #endif 212 static char super_block_buffer[BLOCK_SIZE]; 213 static char boot_block_buffer[512]; 214 215 #define Super (*(struct minix_super_block *)super_block_buffer) 216 #define INODES (Super.s_ninodes) 217 #ifdef CONFIG_FEATURE_MINIX2 218 #define ZONES (version2 ? Super.s_zones : Super.s_nzones) 219 #else 220 #define ZONES (Super.s_nzones) 221 #endif 222 #define IMAPS (Super.s_imap_blocks) 223 #define ZMAPS (Super.s_zmap_blocks) 224 #define FIRSTZONE (Super.s_firstdatazone) 225 #define ZONESIZE (Super.s_log_zone_size) 226 #define MAXSIZE (Super.s_max_size) 227 #define MAGIC (Super.s_magic) 228 #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS) 229 230 static char *inode_map; 231 static char *zone_map; 232 233 static unsigned short good_blocks_table[MAX_GOOD_BLOCKS]; 234 static int used_good_blocks; 235 static unsigned long req_nr_inodes; 236 237 static inline int bit(char * a,unsigned int i) 238 { 239 return (a[i >> 3] & (1<<(i & 7))) != 0; 240 } 241 #define inode_in_use(x) (bit(inode_map,(x))) 242 #define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1)) 243 244 #define mark_inode(x) (setbit(inode_map,(x))) 245 #define unmark_inode(x) (clrbit(inode_map,(x))) 246 247 #define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1)) 248 #define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1)) 249 250 /* 251 * Check to make certain that our new filesystem won't be created on 252 * an already mounted partition. Code adapted from mke2fs, Copyright 253 * (C) 1994 Theodore Ts'o. Also licensed under GPL. 254 */ 255 static inline void check_mount(void) 256 { 257 FILE *f; 258 struct mntent *mnt; 259 260 if ((f = setmntent(MOUNTED, "r")) == NULL) 261 return; 262 while ((mnt = getmntent(f)) != NULL) 263 if (strcmp(device_name, mnt->mnt_fsname) == 0) 264 break; 265 endmntent(f); 266 if (!mnt) 267 return; 268 269 bb_error_msg_and_die("%s is mounted; will not make a filesystem here!", device_name); 270 } 180 # define BLKGETSIZE _IO(0x12,96) /* return device size */ 181 #endif 182 271 183 272 184 static long valid_offset(int fd, int offset) … … 274 186 char ch; 275 187 276 if (lseek(fd, offset, 0) < 0)188 if (lseek(fd, offset, SEEK_SET) < 0) 277 189 return 0; 278 190 if (read(fd, &ch, 1) < 1) … … 281 193 } 282 194 283 static in line int count_blocks(int fd)195 static int count_blocks(int fd) 284 196 { 285 197 int high, low; … … 288 200 for (high = 1; valid_offset(fd, high); high *= 2) 289 201 low = high; 202 290 203 while (low < high - 1) { 291 204 const int mid = (low + high) / 2; … … 300 213 } 301 214 302 static in line int get_size(const char *file)215 static int get_size(const char *file) 303 216 { 304 217 int fd; 305 218 long size; 306 219 307 fd = bb_xopen3(file, O_RDWR, 0);220 fd = xopen(file, O_RDWR); 308 221 if (ioctl(fd, BLKGETSIZE, &size) >= 0) { 309 222 close(fd); … … 316 229 } 317 230 318 static inlinevoid write_tables(void)231 static void write_tables(void) 319 232 { 320 233 /* Mark the super block valid. */ 321 Super.s_state |= MINIX_VALID_FS; 322 Super.s_state &= ~MINIX_ERROR_FS; 323 324 if (lseek(DEV, 0, SEEK_SET)) 325 bb_error_msg_and_die("seek to boot block failed in write_tables"); 326 if (512 != write(DEV, boot_block_buffer, 512)) 327 bb_error_msg_and_die("unable to clear boot sector"); 328 if (BLOCK_SIZE != lseek(DEV, BLOCK_SIZE, SEEK_SET)) 329 bb_error_msg_and_die("seek failed in write_tables"); 330 if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE)) 331 bb_error_msg_and_die("unable to write super-block"); 332 if (IMAPS * BLOCK_SIZE != write(DEV, inode_map, IMAPS * BLOCK_SIZE)) 333 bb_error_msg_and_die("unable to write inode map"); 334 if (ZMAPS * BLOCK_SIZE != write(DEV, zone_map, ZMAPS * BLOCK_SIZE)) 335 bb_error_msg_and_die("unable to write zone map"); 336 if (INODE_BUFFER_SIZE != write(DEV, inode_buffer, INODE_BUFFER_SIZE)) 337 bb_error_msg_and_die("unable to write inodes"); 338 234 SB.s_state |= MINIX_VALID_FS; 235 SB.s_state &= ~MINIX_ERROR_FS; 236 237 msg_eol = "seek to 0 failed"; 238 xlseek(G.dev_fd, 0, SEEK_SET); 239 240 msg_eol = "cannot clear boot sector"; 241 xwrite(G.dev_fd, G.boot_block_buffer, 512); 242 243 msg_eol = "seek to BLOCK_SIZE failed"; 244 xlseek(G.dev_fd, BLOCK_SIZE, SEEK_SET); 245 246 msg_eol = "cannot write superblock"; 247 xwrite(G.dev_fd, G.super_block_buffer, BLOCK_SIZE); 248 249 msg_eol = "cannot write inode map"; 250 xwrite(G.dev_fd, G.inode_map, SB_IMAPS * BLOCK_SIZE); 251 252 msg_eol = "cannot write zone map"; 253 xwrite(G.dev_fd, G.zone_map, SB_ZMAPS * BLOCK_SIZE); 254 255 msg_eol = "cannot write inodes"; 256 xwrite(G.dev_fd, G.inode_buffer, INODE_BUFFER_SIZE); 257 258 msg_eol = "\n"; 339 259 } 340 260 341 261 static void write_block(int blk, char *buffer) 342 262 { 343 if (blk * BLOCK_SIZE != lseek(DEV, blk * BLOCK_SIZE, SEEK_SET)) 344 bb_error_msg_and_die("seek failed in write_block"); 345 if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE)) 346 bb_error_msg_and_die("write failed in write_block"); 263 xlseek(G.dev_fd, blk * BLOCK_SIZE, SEEK_SET); 264 xwrite(G.dev_fd, buffer, BLOCK_SIZE); 347 265 } 348 266 … … 351 269 int blk; 352 270 353 if ( used_good_blocks + 1 >= MAX_GOOD_BLOCKS)271 if (G.used_good_blocks + 1 >= MAX_GOOD_BLOCKS) 354 272 bb_error_msg_and_die("too many bad blocks"); 355 if ( used_good_blocks)356 blk = good_blocks_table[used_good_blocks - 1] + 1;273 if (G.used_good_blocks) 274 blk = G.good_blocks_table[G.used_good_blocks - 1] + 1; 357 275 else 358 blk = FIRSTZONE;359 while (blk < ZONES && zone_in_use(blk))276 blk = SB_FIRSTZONE; 277 while (blk < SB_ZONES && zone_in_use(blk)) 360 278 blk++; 361 if (blk >= ZONES)279 if (blk >= SB_ZONES) 362 280 bb_error_msg_and_die("not enough good blocks"); 363 good_blocks_table[used_good_blocks] = blk;364 used_good_blocks++;281 G.good_blocks_table[G.used_good_blocks] = blk; 282 G.used_good_blocks++; 365 283 return blk; 366 284 } 367 285 368 static inlinevoid mark_good_blocks(void)286 static void mark_good_blocks(void) 369 287 { 370 288 int blk; 371 289 372 for (blk = 0; blk < used_good_blocks; blk++)373 mark_zone( good_blocks_table[blk]);290 for (blk = 0; blk < G.used_good_blocks; blk++) 291 mark_zone(G.good_blocks_table[blk]); 374 292 } 375 293 … … 377 295 { 378 296 if (!zone) 379 zone = FIRSTZONE - 1;380 while (++zone < ZONES)297 zone = SB_FIRSTZONE - 1; 298 while (++zone < SB_ZONES) 381 299 if (zone_in_use(zone)) 382 300 return zone; … … 384 302 } 385 303 386 static inlinevoid make_bad_inode(void)387 { 388 struct minix _inode *inode = &Inode[MINIX_BAD_INO];304 static void make_bad_inode(void) 305 { 306 struct minix1_inode *inode = &INODE_BUF1[MINIX_BAD_INO]; 389 307 int i, j, zone; 390 308 int ind = 0, dind = 0; … … 394 312 #define NEXT_BAD (zone = next(zone)) 395 313 396 if (! badblocks)314 if (!G.badblocks) 397 315 return; 398 316 mark_inode(MINIX_BAD_INO); 399 317 inode->i_nlinks = 1; 400 inode->i_time = time(NULL); 318 /* BTW, setting this makes all images different */ 319 /* it's harder to check for bugs then - diff isn't helpful :(... */ 320 inode->i_time = CUR_TIME; 401 321 inode->i_mode = S_IFREG + 0000; 402 inode->i_size = badblocks * BLOCK_SIZE;322 inode->i_size = G.badblocks * BLOCK_SIZE; 403 323 zone = next(0); 404 324 for (i = 0; i < 7; i++) { … … 427 347 } 428 348 bb_error_msg_and_die("too many bad blocks"); 429 349 end_bad: 430 350 if (ind) 431 351 write_block(ind, (char *) ind_block); … … 434 354 } 435 355 436 #if def CONFIG_FEATURE_MINIX2437 static inlinevoid make_bad_inode2(void)438 { 439 struct minix2_inode *inode = &I node2[MINIX_BAD_INO];356 #if ENABLE_FEATURE_MINIX2 357 static void make_bad_inode2(void) 358 { 359 struct minix2_inode *inode = &INODE_BUF2[MINIX_BAD_INO]; 440 360 int i, j, zone; 441 361 int ind = 0, dind = 0; … … 443 363 unsigned long dind_block[BLOCK_SIZE >> 2]; 444 364 445 if (! badblocks)365 if (!G.badblocks) 446 366 return; 447 367 mark_inode(MINIX_BAD_INO); 448 368 inode->i_nlinks = 1; 449 inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);369 inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME; 450 370 inode->i_mode = S_IFREG + 0000; 451 inode->i_size = badblocks * BLOCK_SIZE;371 inode->i_size = G.badblocks * BLOCK_SIZE; 452 372 zone = next(0); 453 373 for (i = 0; i < 7; i++) { … … 477 397 /* Could make triple indirect block here */ 478 398 bb_error_msg_and_die("too many bad blocks"); 479 399 end_bad: 480 400 if (ind) 481 401 write_block(ind, (char *) ind_block); … … 483 403 write_block(dind, (char *) dind_block); 484 404 } 485 #endif 486 487 static inline void make_root_inode(void) 488 { 489 struct minix_inode *inode = &Inode[MINIX_ROOT_INO]; 405 #else 406 void make_bad_inode2(void); 407 #endif 408 409 static void make_root_inode(void) 410 { 411 struct minix1_inode *inode = &INODE_BUF1[MINIX_ROOT_INO]; 490 412 491 413 mark_inode(MINIX_ROOT_INO); 492 414 inode->i_zone[0] = get_free_block(); 493 415 inode->i_nlinks = 2; 494 inode->i_time = time(NULL);495 if ( badblocks)496 inode->i_size = 3 * dirsize;416 inode->i_time = CUR_TIME; 417 if (G.badblocks) 418 inode->i_size = 3 * G.dirsize; 497 419 else { 498 root_block[2 *dirsize] = '\0';499 root_block[2 *dirsize + 1] = '\0';500 inode->i_size = 2 * dirsize;420 G.root_block[2 * G.dirsize] = '\0'; 421 G.root_block[2 * G.dirsize + 1] = '\0'; 422 inode->i_size = 2 * G.dirsize; 501 423 } 502 424 inode->i_mode = S_IFDIR + 0755; 503 inode->i_uid = getuid();425 inode->i_uid = GETUID; 504 426 if (inode->i_uid) 505 inode->i_gid = getgid();506 write_block(inode->i_zone[0], root_block);507 } 508 509 #if def CONFIG_FEATURE_MINIX2510 static inlinevoid make_root_inode2(void)511 { 512 struct minix2_inode *inode = &I node2[MINIX_ROOT_INO];427 inode->i_gid = GETGID; 428 write_block(inode->i_zone[0], G.root_block); 429 } 430 431 #if ENABLE_FEATURE_MINIX2 432 static void make_root_inode2(void) 433 { 434 struct minix2_inode *inode = &INODE_BUF2[MINIX_ROOT_INO]; 513 435 514 436 mark_inode(MINIX_ROOT_INO); 515 437 inode->i_zone[0] = get_free_block(); 516 438 inode->i_nlinks = 2; 517 inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);518 if ( badblocks)519 inode->i_size = 3 * dirsize;439 inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME; 440 if (G.badblocks) 441 inode->i_size = 3 * G.dirsize; 520 442 else { 521 root_block[2 *dirsize] = '\0';522 root_block[2 *dirsize + 1] = '\0';523 inode->i_size = 2 * dirsize;443 G.root_block[2 * G.dirsize] = '\0'; 444 G.root_block[2 * G.dirsize + 1] = '\0'; 445 inode->i_size = 2 * G.dirsize; 524 446 } 525 447 inode->i_mode = S_IFDIR + 0755; 526 inode->i_uid = getuid();448 inode->i_uid = GETUID; 527 449 if (inode->i_uid) 528 inode->i_gid = getgid(); 529 write_block(inode->i_zone[0], root_block); 530 } 531 #endif 532 533 static inline void setup_tables(void) 534 { 535 int i; 450 inode->i_gid = GETGID; 451 write_block(inode->i_zone[0], G.root_block); 452 } 453 #else 454 void make_root_inode2(void); 455 #endif 456 457 /* 458 * Perform a test of a block; return the number of 459 * blocks readable. 460 */ 461 static size_t do_check(char *buffer, size_t try, unsigned current_block) 462 { 463 ssize_t got; 464 465 /* Seek to the correct loc. */ 466 msg_eol = "seek failed during testing of blocks"; 467 xlseek(G.dev_fd, current_block * BLOCK_SIZE, SEEK_SET); 468 msg_eol = "\n"; 469 470 /* Try the read */ 471 got = read(G.dev_fd, buffer, try * BLOCK_SIZE); 472 if (got < 0) 473 got = 0; 474 try = ((size_t)got) / BLOCK_SIZE; 475 476 if (got & (BLOCK_SIZE - 1)) 477 fprintf(stderr, "Short read at block %u\n", (unsigned)(current_block + try)); 478 return try; 479 } 480 481 static void alarm_intr(int alnum) 482 { 483 if (G.currently_testing >= SB_ZONES) 484 return; 485 signal(SIGALRM, alarm_intr); 486 alarm(5); 487 if (!G.currently_testing) 488 return; 489 printf("%d ...", G.currently_testing); 490 fflush(stdout); 491 } 492 493 static void check_blocks(void) 494 { 495 size_t try, got; 496 497 G.currently_testing = 0; 498 signal(SIGALRM, alarm_intr); 499 alarm(5); 500 while (G.currently_testing < SB_ZONES) { 501 msg_eol = "seek failed in check_blocks"; 502 xlseek(G.dev_fd, G.currently_testing * BLOCK_SIZE, SEEK_SET); 503 msg_eol = "\n"; 504 try = TEST_BUFFER_BLOCKS; 505 if (G.currently_testing + try > SB_ZONES) 506 try = SB_ZONES - G.currently_testing; 507 got = do_check(G.check_blocks_buffer, try, G.currently_testing); 508 G.currently_testing += got; 509 if (got == try) 510 continue; 511 if (G.currently_testing < SB_FIRSTZONE) 512 bb_error_msg_and_die("bad blocks before data-area: cannot make fs"); 513 mark_zone(G.currently_testing); 514 G.badblocks++; 515 G.currently_testing++; 516 } 517 alarm(0); 518 printf("%d bad block(s)\n", G.badblocks); 519 } 520 521 static void get_list_blocks(char *filename) 522 { 523 FILE *listfile; 524 unsigned long blockno; 525 526 listfile = xfopen(filename, "r"); 527 while (!feof(listfile)) { 528 fscanf(listfile, "%ld\n", &blockno); 529 mark_zone(blockno); 530 G.badblocks++; 531 } 532 printf("%d bad block(s)\n", G.badblocks); 533 } 534 535 static void setup_tables(void) 536 { 536 537 unsigned long inodes; 537 538 memset(super_block_buffer, 0, BLOCK_SIZE); 539 memset(boot_block_buffer, 0, 512); 540 MAGIC = magic; 541 ZONESIZE = 0; 542 MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024; 543 #ifdef CONFIG_FEATURE_MINIX2 544 if (version2) { 545 Super.s_zones = BLOCKS; 546 } else 547 #endif 548 Super.s_nzones = BLOCKS; 549 550 /* some magic nrs: 1 inode / 3 blocks */ 551 if (req_nr_inodes == 0) 552 inodes = BLOCKS / 3; 538 unsigned norm_firstzone; 539 unsigned sb_zmaps; 540 unsigned i; 541 542 /* memset(G.super_block_buffer, 0, BLOCK_SIZE); */ 543 /* memset(G.boot_block_buffer, 0, 512); */ 544 SB_MAGIC = G.magic; 545 SB_ZONE_SIZE = 0; 546 SB_MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024; 547 if (version2) 548 SB.s_zones = G.total_blocks; 553 549 else 554 inodes = req_nr_inodes; 550 SB.s_nzones = G.total_blocks; 551 552 /* some magic nrs: 1 inode / 3 blocks */ 553 if (G.req_nr_inodes == 0) 554 inodes = G.total_blocks / 3; 555 else 556 inodes = G.req_nr_inodes; 555 557 /* Round up inode count to fill block size */ 556 #ifdef CONFIG_FEATURE_MINIX2557 558 if (version2) 558 inodes = ( (inodes + MINIX2_INODES_PER_BLOCK - 1) &559 ~(MINIX2_INODES_PER_BLOCK - 1));559 inodes = (inodes + MINIX2_INODES_PER_BLOCK - 1) & 560 ~(MINIX2_INODES_PER_BLOCK - 1); 560 561 else 561 #endif 562 inodes = ((inodes + MINIX_INODES_PER_BLOCK - 1) & 563 ~(MINIX_INODES_PER_BLOCK - 1)); 562 inodes = (inodes + MINIX1_INODES_PER_BLOCK - 1) & 563 ~(MINIX1_INODES_PER_BLOCK - 1); 564 564 if (inodes > 65535) 565 565 inodes = 65535; 566 INODES = inodes; 567 IMAPS = UPPER(INODES + 1, BITS_PER_BLOCK); 568 ZMAPS = 0; 569 i = 0; 570 while (ZMAPS != 571 UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1, 572 BITS_PER_BLOCK) && i < 1000) { 573 ZMAPS = 574 UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1, 575 BITS_PER_BLOCK); 576 i++; 577 } 566 SB_INODES = inodes; 567 SB_IMAPS = div_roundup(SB_INODES + 1, BITS_PER_BLOCK); 568 578 569 /* Real bad hack but overwise mkfs.minix can be thrown 579 570 * in infinite loop... 580 571 * try: 581 572 * dd if=/dev/zero of=test.fs count=10 bs=1024 582 * /sbin/mkfs.minix -i 200 test.fs 583 * */ 584 if (i >= 999) { 585 bb_error_msg_and_die("unable to allocate buffers for maps"); 586 } 587 FIRSTZONE = NORM_FIRSTZONE; 588 inode_map = xmalloc(IMAPS * BLOCK_SIZE); 589 zone_map = xmalloc(ZMAPS * BLOCK_SIZE); 590 memset(inode_map, 0xff, IMAPS * BLOCK_SIZE); 591 memset(zone_map, 0xff, ZMAPS * BLOCK_SIZE); 592 for (i = FIRSTZONE; i < ZONES; i++) 573 * mkfs.minix -i 200 test.fs 574 */ 575 /* This code is not insane: NORM_FIRSTZONE is not a constant, 576 * it is calculated from SB_INODES, SB_IMAPS and SB_ZMAPS */ 577 i = 999; 578 SB_ZMAPS = 0; 579 do { 580 norm_firstzone = NORM_FIRSTZONE; 581 sb_zmaps = div_roundup(G.total_blocks - norm_firstzone + 1, BITS_PER_BLOCK); 582 if (SB_ZMAPS == sb_zmaps) goto got_it; 583 SB_ZMAPS = sb_zmaps; 584 /* new SB_ZMAPS, need to recalc NORM_FIRSTZONE */ 585 } while (--i); 586 bb_error_msg_and_die("incompatible size/inode count, try different -i N"); 587 got_it: 588 589 SB_FIRSTZONE = norm_firstzone; 590 G.inode_map = xmalloc(SB_IMAPS * BLOCK_SIZE); 591 G.zone_map = xmalloc(SB_ZMAPS * BLOCK_SIZE); 592 memset(G.inode_map, 0xff, SB_IMAPS * BLOCK_SIZE); 593 memset(G.zone_map, 0xff, SB_ZMAPS * BLOCK_SIZE); 594 for (i = SB_FIRSTZONE; i < SB_ZONES; i++) 593 595 unmark_zone(i); 594 for (i = MINIX_ROOT_INO; i <= INODES; i++)596 for (i = MINIX_ROOT_INO; i <= SB_INODES; i++) 595 597 unmark_inode(i); 596 inode_buffer = xmalloc(INODE_BUFFER_SIZE); 597 memset(inode_buffer, 0, INODE_BUFFER_SIZE); 598 printf("%ld inodes\n", (long)INODES); 599 printf("%ld blocks\n", (long)ZONES); 600 printf("Firstdatazone=%ld (%ld)\n", (long)FIRSTZONE, (long)NORM_FIRSTZONE); 601 printf("Zonesize=%d\n", BLOCK_SIZE << ZONESIZE); 602 printf("Maxsize=%ld\n\n", (long)MAXSIZE); 603 } 604 605 /* 606 * Perform a test of a block; return the number of 607 * blocks readable/writable. 608 */ 609 static inline long do_check(char *buffer, int try, unsigned int current_block) 610 { 611 long got; 612 613 /* Seek to the correct loc. */ 614 if (lseek(DEV, current_block * BLOCK_SIZE, SEEK_SET) != 615 current_block * BLOCK_SIZE) { 616 bb_error_msg_and_die("seek failed during testing of blocks"); 617 } 618 619 620 /* Try the read */ 621 got = read(DEV, buffer, try * BLOCK_SIZE); 622 if (got < 0) 623 got = 0; 624 if (got & (BLOCK_SIZE - 1)) { 625 printf("Weird values in do_check: probably bugs\n"); 626 } 627 got /= BLOCK_SIZE; 628 return got; 629 } 630 631 static unsigned int currently_testing; 632 633 static void alarm_intr(int alnum) 634 { 635 if (currently_testing >= ZONES) 636 return; 637 signal(SIGALRM, alarm_intr); 638 alarm(5); 639 if (!currently_testing) 640 return; 641 printf("%d ...", currently_testing); 642 fflush(stdout); 643 } 644 645 static void check_blocks(void) 646 { 647 int try, got; 648 static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS]; 649 650 currently_testing = 0; 651 signal(SIGALRM, alarm_intr); 652 alarm(5); 653 while (currently_testing < ZONES) { 654 if (lseek(DEV, currently_testing * BLOCK_SIZE, SEEK_SET) != 655 currently_testing * BLOCK_SIZE) 656 bb_error_msg_and_die("seek failed in check_blocks"); 657 try = TEST_BUFFER_BLOCKS; 658 if (currently_testing + try > ZONES) 659 try = ZONES - currently_testing; 660 got = do_check(buffer, try, currently_testing); 661 currently_testing += got; 662 if (got == try) 663 continue; 664 if (currently_testing < FIRSTZONE) 665 bb_error_msg_and_die("bad blocks before data-area: cannot make fs"); 666 mark_zone(currently_testing); 667 badblocks++; 668 currently_testing++; 669 } 670 if (badblocks > 1) 671 printf("%d bad blocks\n", badblocks); 672 else if (badblocks == 1) 673 printf("one bad block\n"); 674 } 675 676 static void get_list_blocks(char *filename) 677 { 678 FILE *listfile; 679 unsigned long blockno; 680 681 listfile = bb_xfopen(filename, "r"); 682 while (!feof(listfile)) { 683 fscanf(listfile, "%ld\n", &blockno); 684 mark_zone(blockno); 685 badblocks++; 686 } 687 if (badblocks > 1) 688 printf("%d bad blocks\n", badblocks); 689 else if (badblocks == 1) 690 printf("one bad block\n"); 691 } 692 598 G.inode_buffer = xzalloc(INODE_BUFFER_SIZE); 599 printf("%ld inodes\n", (long)SB_INODES); 600 printf("%ld blocks\n", (long)SB_ZONES); 601 printf("Firstdatazone=%ld (%ld)\n", (long)SB_FIRSTZONE, (long)norm_firstzone); 602 printf("Zonesize=%d\n", BLOCK_SIZE << SB_ZONE_SIZE); 603 printf("Maxsize=%ld\n", (long)SB_MAXSIZE); 604 } 605 606 int mkfs_minix_main(int argc, char **argv); 693 607 int mkfs_minix_main(int argc, char **argv) 694 608 { 695 int i=1; 609 struct mntent *mp; 610 unsigned opt; 696 611 char *tmp; 697 612 struct stat statbuf; 613 char *str_i, *str_n; 698 614 char *listfile = NULL; 699 int stopIt=FALSE; 700 701 if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) 615 616 PTR_TO_GLOBALS = xzalloc(sizeof(G)); 617 /* default (changed to 30, per Linus's suggestion, Sun Nov 21 08:05:07 1993) */ 618 G.namelen = 30; 619 G.dirsize = 32; 620 G.magic = MINIX1_SUPER_MAGIC2; 621 622 if (INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE) 702 623 bb_error_msg_and_die("bad inode size"); 703 #if def CONFIG_FEATURE_MINIX2624 #if ENABLE_FEATURE_MINIX2 704 625 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) 705 626 bb_error_msg_and_die("bad inode size"); 706 627 #endif 707 628 708 /* Parse options */ 709 argv++; 710 while (--argc >= 0 && *argv && **argv) { 711 if (**argv == '-') { 712 stopIt=FALSE; 713 while (i > 0 && *++(*argv) && stopIt==FALSE) { 714 switch (**argv) { 715 case 'c': 716 check = 1; 717 break; 718 case 'i': 719 { 720 char *cp=NULL; 721 if (*(*argv+1) != 0) { 722 cp = ++(*argv); 723 } else { 724 if (--argc == 0) { 725 goto goodbye; 726 } 727 cp = *(++argv); 728 } 729 req_nr_inodes = strtoul(cp, &tmp, 0); 730 if (*tmp) 731 bb_show_usage(); 732 stopIt=TRUE; 733 break; 734 } 735 case 'l': 736 if (--argc == 0) { 737 goto goodbye; 738 } 739 listfile = *(++argv); 740 break; 741 case 'n': 742 { 743 char *cp=NULL; 744 745 if (*(*argv+1) != 0) { 746 cp = ++(*argv); 747 } else { 748 if (--argc == 0) { 749 goto goodbye; 750 } 751 cp = *(++argv); 752 } 753 i = strtoul(cp, &tmp, 0); 754 if (*tmp) 755 bb_show_usage(); 756 if (i == 14) 757 magic = MINIX_SUPER_MAGIC; 758 else if (i == 30) 759 magic = MINIX_SUPER_MAGIC2; 760 else 761 bb_show_usage(); 762 namelen = i; 763 dirsize = i + 2; 764 stopIt=TRUE; 765 break; 766 } 767 case 'v': 768 #ifdef CONFIG_FEATURE_MINIX2 769 version2 = 1; 629 opt = getopt32(argv, "ci:l:n:v", &str_i, &listfile, &str_n); 630 argv += optind; 631 //if (opt & 1) -c 632 if (opt & 2) G.req_nr_inodes = xatoul(str_i); // -i 633 //if (opt & 4) -l 634 if (opt & 8) { // -n 635 G.namelen = xatoi_u(str_n); 636 if (G.namelen == 14) G.magic = MINIX1_SUPER_MAGIC; 637 else if (G.namelen == 30) G.magic = MINIX1_SUPER_MAGIC2; 638 else bb_show_usage(); 639 G.dirsize = G.namelen + 2; 640 } 641 if (opt & 0x10) { // -v 642 #if ENABLE_FEATURE_MINIX2 643 version2 = 1; 770 644 #else 771 bb_error_msg("%s: not compiled with minix v2 support", 772 device_name); 773 exit(-1); 774 #endif 775 break; 776 case '-': 777 case 'h': 778 default: 779 goodbye: 780 bb_show_usage(); 781 } 782 } 783 } else { 784 if (device_name == NULL) 785 device_name = *argv; 786 else if (BLOCKS == 0) 787 BLOCKS = strtol(*argv, &tmp, 0); 788 else { 789 goto goodbye; 790 } 791 } 792 argv++; 793 } 794 795 if (device_name && !BLOCKS) 796 BLOCKS = get_size(device_name) / 1024; 797 if (!device_name || BLOCKS < 10) { 645 bb_error_msg_and_die("not compiled with minix v2 support"); 646 #endif 647 } 648 649 G.device_name = *argv++; 650 if (!G.device_name) 798 651 bb_show_usage(); 799 } 800 #ifdef CONFIG_FEATURE_MINIX2 652 if (*argv) 653 G.total_blocks = xatou32(*argv); 654 else 655 G.total_blocks = get_size(G.device_name) / 1024; 656 657 if (G.total_blocks < 10) 658 bb_error_msg_and_die("must have at least 10 blocks"); 659 801 660 if (version2) { 802 if (namelen == 14) 803 magic = MINIX2_SUPER_MAGIC; 804 else 805 magic = MINIX2_SUPER_MAGIC2; 806 } else 807 #endif 808 if (BLOCKS > 65535) 809 BLOCKS = 65535; 810 check_mount(); /* is it already mounted? */ 811 tmp = root_block; 661 G.magic = MINIX2_SUPER_MAGIC2; 662 if (G.namelen == 14) 663 G.magic = MINIX2_SUPER_MAGIC; 664 } else if (G.total_blocks > 65535) 665 G.total_blocks = 65535; 666 667 /* Check if it is mounted */ 668 mp = find_mount_point(G.device_name, NULL); 669 if (mp && strcmp(G.device_name, mp->mnt_fsname) == 0) 670 bb_error_msg_and_die("%s is mounted on %s; " 671 "refusing to make a filesystem", 672 G.device_name, mp->mnt_dir); 673 674 G.dev_fd = xopen(G.device_name, O_RDWR); 675 if (fstat(G.dev_fd, &statbuf) < 0) 676 bb_error_msg_and_die("cannot stat %s", G.device_name); 677 if (!S_ISBLK(statbuf.st_mode)) 678 opt &= ~1; // clear -c (check) 679 680 /* I don't know why someone has special code to prevent mkfs.minix 681 * on IDE devices. Why IDE but not SCSI, etc?... */ 682 #if 0 683 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) 684 /* what is this? */ 685 bb_error_msg_and_die("will not try " 686 "to make filesystem on '%s'", G.device_name); 687 #endif 688 689 tmp = G.root_block; 812 690 *(short *) tmp = 1; 813 691 strcpy(tmp + 2, "."); 814 tmp += dirsize;692 tmp += G.dirsize; 815 693 *(short *) tmp = 1; 816 694 strcpy(tmp + 2, ".."); 817 tmp += dirsize;695 tmp += G.dirsize; 818 696 *(short *) tmp = 2; 819 697 strcpy(tmp + 2, ".badblocks"); 820 DEV = bb_xopen3(device_name, O_RDWR, 0); 821 if (fstat(DEV, &statbuf) < 0) 822 bb_error_msg_and_die("unable to stat %s", device_name); 823 if (!S_ISBLK(statbuf.st_mode)) 824 check = 0; 825 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) 826 bb_error_msg_and_die("will not try to make filesystem on '%s'", device_name); 698 827 699 setup_tables(); 828 if (check) 700 701 if (opt & 1) // -c ? 829 702 check_blocks(); 830 703 else if (listfile) 831 704 get_list_blocks(listfile); 832 #ifdef CONFIG_FEATURE_MINIX2 705 833 706 if (version2) { 834 707 make_root_inode2(); 835 708 make_bad_inode2(); 836 } else 837 #endif 838 { 709 } else { 839 710 make_root_inode(); 840 711 make_bad_inode(); 841 712 } 713 842 714 mark_good_blocks(); 843 715 write_tables(); 844 716 return 0; 845 846 } 717 }
Note:
See TracChangeset
for help on using the changeset viewer.