aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--util-linux/fsck_minix.c221
1 files changed, 95 insertions, 126 deletions
diff --git a/util-linux/fsck_minix.c b/util-linux/fsck_minix.c
index b90ccc5e3..f764597e3 100644
--- a/util-linux/fsck_minix.c
+++ b/util-linux/fsck_minix.c
@@ -219,14 +219,6 @@ static int version2;
219static struct termios termios; 219static struct termios termios;
220static int termios_set; 220static int termios_set;
221 221
222/* File-name data */
223enum { MAX_DEPTH = 32 };
224static int name_depth;
225// static char name_list[MAX_DEPTH][BUFSIZ + 1];
226static char **name_list;
227
228static char *inode_buffer;
229
230#define Inode (((struct minix_inode *) inode_buffer)-1) 222#define Inode (((struct minix_inode *) inode_buffer)-1)
231#define Inode2 (((struct minix2_inode *) inode_buffer)-1) 223#define Inode2 (((struct minix2_inode *) inode_buffer)-1)
232static char super_block_buffer[BLOCK_SIZE]; 224static char super_block_buffer[BLOCK_SIZE];
@@ -284,18 +276,55 @@ static void die(const char *str)
284 leave(8); 276 leave(8);
285} 277}
286 278
287/* 279/* File-name data */
288 * This simply goes through the file-name data and prints out the 280enum { MAX_DEPTH = 32 };
289 * current file. 281static int name_depth;
290 */ 282static char *current_name;
291static void print_current_name(void) 283static char *name_component[MAX_DEPTH+1];
284
285/* Wed Feb 9 15:17:06 MST 2000 */
286/* dynamically allocate name_list (instead of making it static) */
287static inline void alloc_current_name(void)
292{ 288{
293 int i = 0; 289 current_name = xmalloc(MAX_DEPTH * (BUFSIZ + 1));
290 current_name[0] = '/';
291 current_name[1] = '\0';
292 name_component[0] = &current_name[0];
293}
294 294
295 while (i < name_depth) 295#ifdef CONFIG_FEATURE_CLEAN_UP
296 printf("/%.*s", namelen, name_list[i++]); 296/* execute this atexit() to deallocate name_list[] */
297 if (i == 0) 297/* piptigger was here */
298 printf("/"); 298static inline void free_current_name(void)
299{
300 free(current_name);
301}
302#endif
303
304static void push_filename(const char *name)
305{
306 // /dir/dir/dir/file
307 // ^ ^ ^
308 // [0] [1] [2] <-name_component[i]
309 if (name_depth < MAX_DEPTH) {
310 int len;
311 char *p = name_component[name_depth];
312 *p++ = '/';
313 len = sprintf(p, "%.*s", namelen, name);
314 name_component[name_depth + 1] = p + len;
315 }
316 name_depth++;
317}
318
319static void pop_filename(void) {
320 name_depth--;
321 if (name_depth < MAX_DEPTH) {
322 *name_component[name_depth] = '\0';
323 if (!name_depth) {
324 current_name[0] = '/';
325 current_name[1] = '\0';
326 }
327 }
299} 328}
300 329
301static int ask(const char *string, int def) 330static int ask(const char *string, int def)
@@ -391,16 +420,16 @@ static void check_mount(void)
391 */ 420 */
392static int check_zone_nr2(uint32_t *nr, int *corrected) 421static int check_zone_nr2(uint32_t *nr, int *corrected)
393{ 422{
423 const char *msg;
394 if (!*nr) 424 if (!*nr)
395 return 0; 425 return 0;
396 if (*nr < FIRSTZONE) 426 if (*nr < FIRSTZONE)
397 printf("Zone nr < FIRSTZONE in file `"); 427 msg = "< FIRSTZONE";
398 else if (*nr >= ZONES) 428 else if (*nr >= ZONES)
399 printf("Zone nr >= ZONES in file `"); 429 msg = ">= ZONES";
400 else 430 else
401 return *nr; 431 return *nr;
402 print_current_name(); 432 printf("Zone nr %s in file '%s'.", msg, current_name);
403 printf("'.");
404 if (ask("Remove block", 1)) { 433 if (ask("Remove block", 1)) {
405 *nr = 0; 434 *nr = 0;
406 *corrected = 1; 435 *corrected = 1;
@@ -426,15 +455,12 @@ static void read_block(unsigned int nr, char *addr)
426 return; 455 return;
427 } 456 }
428 if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET)) { 457 if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET)) {
429 printf("Read error: unable to seek to block in file '"); 458 printf("Read error: unable to seek to block in file '%s'\n",
430 print_current_name(); 459 current_name);
431 printf("'\n");
432 errors_uncorrected = 1; 460 errors_uncorrected = 1;
433 memset(addr, 0, BLOCK_SIZE); 461 memset(addr, 0, BLOCK_SIZE);
434 } else if (BLOCK_SIZE != read(IN, addr, BLOCK_SIZE)) { 462 } else if (BLOCK_SIZE != read(IN, addr, BLOCK_SIZE)) {
435 printf("Read error: bad block in file '"); 463 printf("Read error: bad block in file '%s'\n", current_name);
436 print_current_name();
437 printf("'\n");
438 errors_uncorrected = 1; 464 errors_uncorrected = 1;
439 memset(addr, 0, BLOCK_SIZE); 465 memset(addr, 0, BLOCK_SIZE);
440 } 466 }
@@ -456,9 +482,7 @@ static void write_block(unsigned int nr, char *addr)
456 if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET)) 482 if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET))
457 die("seek failed in write_block"); 483 die("seek failed in write_block");
458 if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) { 484 if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) {
459 printf("Write error: bad block in file '"); 485 printf("Write error: bad block in file '%s'\n", current_name);
460 print_current_name();
461 printf("'\n");
462 errors_uncorrected = 1; 486 errors_uncorrected = 1;
463 } 487 }
464} 488}
@@ -621,9 +645,11 @@ static void read_superblock(void)
621 die("seek failed"); 645 die("seek failed");
622 if (BLOCK_SIZE != read(IN, super_block_buffer, BLOCK_SIZE)) 646 if (BLOCK_SIZE != read(IN, super_block_buffer, BLOCK_SIZE))
623 die("unable to read super block"); 647 die("unable to read super block");
648 /* already initialized to:
624 namelen = 14; 649 namelen = 14;
625 dirsize = 16; 650 dirsize = 16;
626 version2 = 0; 651 version2 = 0;
652 */
627 if (MAGIC == MINIX_SUPER_MAGIC) { 653 if (MAGIC == MINIX_SUPER_MAGIC) {
628 } else if (MAGIC == MINIX_SUPER_MAGIC2) { 654 } else if (MAGIC == MINIX_SUPER_MAGIC2) {
629 namelen = 30; 655 namelen = 30;
@@ -694,9 +720,8 @@ static struct minix_inode *get_inode(unsigned int nr)
694 inode = Inode + nr; 720 inode = Inode + nr;
695 if (!inode_count[nr]) { 721 if (!inode_count[nr]) {
696 if (!inode_in_use(nr)) { 722 if (!inode_in_use(nr)) {
697 printf("Inode %d marked not used, but used for file '", nr); 723 printf("Inode %d marked not used, but used for file "
698 print_current_name(); 724 "'%s'\n", nr, current_name);
699 printf("'\n");
700 if (repair) { 725 if (repair) {
701 if (ask("Mark in use", 1)) 726 if (ask("Mark in use", 1))
702 mark_inode(nr); 727 mark_inode(nr);
@@ -717,8 +742,7 @@ static struct minix_inode *get_inode(unsigned int nr)
717 else if (S_ISSOCK(inode->i_mode)); 742 else if (S_ISSOCK(inode->i_mode));
718 else if (S_ISFIFO(inode->i_mode)); 743 else if (S_ISFIFO(inode->i_mode));
719 else { 744 else {
720 print_current_name(); 745 printf("%s has mode %05o\n", current_name, inode->i_mode);
721 printf(" has mode %05o\n", inode->i_mode);
722 } 746 }
723 747
724 } else 748 } else
@@ -742,9 +766,8 @@ static struct minix2_inode *get_inode2(unsigned int nr)
742 inode = Inode2 + nr; 766 inode = Inode2 + nr;
743 if (!inode_count[nr]) { 767 if (!inode_count[nr]) {
744 if (!inode_in_use(nr)) { 768 if (!inode_in_use(nr)) {
745 printf("Inode %d marked not used, but used for file '", nr); 769 printf("Inode %d marked not used, but used for file "
746 print_current_name(); 770 "'%s'\n", nr, current_name);
747 printf("'\n");
748 if (repair) { 771 if (repair) {
749 if (ask("Mark in use", 1)) 772 if (ask("Mark in use", 1))
750 mark_inode(nr); 773 mark_inode(nr);
@@ -765,8 +788,7 @@ static struct minix2_inode *get_inode2(unsigned int nr)
765 else if (S_ISSOCK(inode->i_mode)); 788 else if (S_ISSOCK(inode->i_mode));
766 else if (S_ISFIFO(inode->i_mode)); 789 else if (S_ISFIFO(inode->i_mode));
767 else { 790 else {
768 print_current_name(); 791 printf("%s has mode %05o\n", current_name, inode->i_mode);
769 printf(" has mode %05o\n", inode->i_mode);
770 } 792 }
771 } else 793 } else
772 links++; 794 links++;
@@ -807,9 +829,8 @@ static int add_zone(uint16_t *znr, int *corrected)
807 if (!block) 829 if (!block)
808 return 0; 830 return 0;
809 if (zone_count[block]) { 831 if (zone_count[block]) {
810 printf("Block has been used before. Now in file `"); 832 printf("Block has been used before. Now in file '%s'.",
811 print_current_name(); 833 current_name);
812 printf("'.");
813 if (ask("Clear", 1)) { 834 if (ask("Clear", 1)) {
814 *znr = 0; 835 *znr = 0;
815 block = 0; 836 block = 0;
@@ -818,9 +839,8 @@ static int add_zone(uint16_t *znr, int *corrected)
818 } 839 }
819 } 840 }
820 if (!zone_in_use(block)) { 841 if (!zone_in_use(block)) {
821 printf("Block %d in file `", block); 842 printf("Block %d in file '%s' is marked not in use.",
822 print_current_name(); 843 block, current_name);
823 printf("' is marked not in use.");
824 if (ask("Correct", 1)) 844 if (ask("Correct", 1))
825 mark_zone(block); 845 mark_zone(block);
826 } 846 }
@@ -840,9 +860,8 @@ static int add_zone2(uint32_t *znr, int *corrected)
840 if (!block) 860 if (!block)
841 return 0; 861 return 0;
842 if (zone_count[block]) { 862 if (zone_count[block]) {
843 printf("Block has been used before. Now in file `"); 863 printf("Block has been used before. Now in file '%s'.",
844 print_current_name(); 864 current_name);
845 printf("'.");
846 if (ask("Clear", 1)) { 865 if (ask("Clear", 1)) {
847 *znr = 0; 866 *znr = 0;
848 block = 0; 867 block = 0;
@@ -851,9 +870,8 @@ static int add_zone2(uint32_t *znr, int *corrected)
851 } 870 }
852 } 871 }
853 if (!zone_in_use(block)) { 872 if (!zone_in_use(block)) {
854 printf("Block %d in file `", block); 873 printf("Block %d in file '%s' is marked not in use.",
855 print_current_name(); 874 block, current_name);
856 printf("' is marked not in use.");
857 if (ask("Correct", 1)) 875 if (ask("Correct", 1))
858 mark_zone(block); 876 mark_zone(block);
859 } 877 }
@@ -998,54 +1016,43 @@ static void check_file(struct minix_inode *dir, unsigned int offset)
998 name = blk + (offset % BLOCK_SIZE) + 2; 1016 name = blk + (offset % BLOCK_SIZE) + 2;
999 ino = *(uint16_t *) (name - 2); 1017 ino = *(uint16_t *) (name - 2);
1000 if (ino > INODES) { 1018 if (ino > INODES) {
1001 print_current_name(); 1019 printf("%s contains a bad inode number for file '%.*s'.",
1002 printf(" contains a bad inode number for file '"); 1020 current_name, namelen, name);
1003 printf("%.*s'.", namelen, name);
1004 if (ask(" Remove", 1)) { 1021 if (ask(" Remove", 1)) {
1005 *(uint16_t *) (name - 2) = 0; 1022 *(uint16_t *) (name - 2) = 0;
1006 write_block(block, blk); 1023 write_block(block, blk);
1007 } 1024 }
1008 ino = 0; 1025 ino = 0;
1009 } 1026 }
1010 if (name_depth < MAX_DEPTH) 1027 push_filename(name);
1011 strncpy(name_list[name_depth], name, namelen);
1012 name_depth++;
1013 inode = get_inode(ino); 1028 inode = get_inode(ino);
1014 name_depth--; 1029 pop_filename();
1015 if (!offset) { 1030 if (!offset) {
1016 if (!inode || strcmp(".", name)) { 1031 if (!inode || strcmp(".", name)) {
1017 print_current_name(); 1032 printf("%s: bad directory: '.' isn't first\n", current_name);
1018 printf(": bad directory: '.' isn't first\n");
1019 errors_uncorrected = 1; 1033 errors_uncorrected = 1;
1020 } else 1034 } else
1021 return; 1035 return;
1022 } 1036 }
1023 if (offset == dirsize) { 1037 if (offset == dirsize) {
1024 if (!inode || strcmp("..", name)) { 1038 if (!inode || strcmp("..", name)) {
1025 print_current_name(); 1039 printf("%s: bad directory: '..' isn't second\n", current_name);
1026 printf(": bad directory: '..' isn't second\n");
1027 errors_uncorrected = 1; 1040 errors_uncorrected = 1;
1028 } else 1041 } else
1029 return; 1042 return;
1030 } 1043 }
1031 if (!inode) 1044 if (!inode)
1032 return; 1045 return;
1033 if (name_depth < MAX_DEPTH) 1046 push_filename(name);
1034 strncpy(name_list[name_depth], name, namelen);
1035 name_depth++;
1036 if (list) { 1047 if (list) {
1037 if (verbose) 1048 if (verbose)
1038 printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks); 1049 printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks);
1039 print_current_name(); 1050 printf("%s%s\n", current_name, S_ISDIR(inode->i_mode) ? ":" : "");
1040 if (S_ISDIR(inode->i_mode))
1041 printf(":\n");
1042 else
1043 printf("\n");
1044 } 1051 }
1045 check_zones(ino); 1052 check_zones(ino);
1046 if (inode && S_ISDIR(inode->i_mode)) 1053 if (inode && S_ISDIR(inode->i_mode))
1047 recursive_check(ino); 1054 recursive_check(ino);
1048 name_depth--; 1055 pop_filename();
1049 return; 1056 return;
1050} 1057}
1051 1058
@@ -1063,52 +1070,43 @@ static void check_file2(struct minix2_inode *dir, unsigned int offset)
1063 name = blk + (offset % BLOCK_SIZE) + 2; 1070 name = blk + (offset % BLOCK_SIZE) + 2;
1064 ino = *(uint16_t *) (name - 2); 1071 ino = *(uint16_t *) (name - 2);
1065 if (ino > INODES) { 1072 if (ino > INODES) {
1066 print_current_name(); 1073 printf("%s contains a bad inode number for file '%.*s'.",
1067 printf(" contains a bad inode number for file '"); 1074 current_name, namelen, name);
1068 printf("%.*s'.", namelen, name);
1069 if (ask(" Remove", 1)) { 1075 if (ask(" Remove", 1)) {
1070 *(uint16_t *) (name - 2) = 0; 1076 *(uint16_t *) (name - 2) = 0;
1071 write_block(block, blk); 1077 write_block(block, blk);
1072 } 1078 }
1073 ino = 0; 1079 ino = 0;
1074 } 1080 }
1075 if (name_depth < MAX_DEPTH) 1081 push_filename(name);
1076 strncpy(name_list[name_depth], name, namelen);
1077 name_depth++;
1078 inode = get_inode2(ino); 1082 inode = get_inode2(ino);
1079 name_depth--; 1083 pop_filename();
1080 if (!offset) { 1084 if (!offset) {
1081 if (!inode || strcmp(".", name)) { 1085 if (!inode || strcmp(".", name)) {
1082 print_current_name(); 1086 printf("%s: bad directory: '.' isn't first\n", current_name);
1083 printf(": bad directory: '.' isn't first\n");
1084 errors_uncorrected = 1; 1087 errors_uncorrected = 1;
1085 } else 1088 } else
1086 return; 1089 return;
1087 } 1090 }
1088 if (offset == dirsize) { 1091 if (offset == dirsize) {
1089 if (!inode || strcmp("..", name)) { 1092 if (!inode || strcmp("..", name)) {
1090 print_current_name(); 1093 printf("%s: bad directory: '..' isn't second\n", current_name);
1091 printf(": bad directory: '..' isn't second\n");
1092 errors_uncorrected = 1; 1094 errors_uncorrected = 1;
1093 } else 1095 } else
1094 return; 1096 return;
1095 } 1097 }
1096 if (!inode) 1098 if (!inode)
1097 return; 1099 return;
1098 name_depth++; 1100 push_filename(name);
1099 if (list) { 1101 if (list) {
1100 if (verbose) 1102 if (verbose)
1101 printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks); 1103 printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks);
1102 print_current_name(); 1104 printf("%s%s\n", current_name, S_ISDIR(inode->i_mode) ? ":" : "");
1103 if (S_ISDIR(inode->i_mode))
1104 printf(":\n");
1105 else
1106 printf("\n");
1107 } 1105 }
1108 check_zones2(ino); 1106 check_zones2(ino);
1109 if (inode && S_ISDIR(inode->i_mode)) 1107 if (inode && S_ISDIR(inode->i_mode))
1110 recursive_check2(ino); 1108 recursive_check2(ino);
1111 name_depth--; 1109 pop_filename();
1112 return; 1110 return;
1113} 1111}
1114#endif 1112#endif
@@ -1122,8 +1120,7 @@ static void recursive_check(unsigned int ino)
1122 if (!S_ISDIR(dir->i_mode)) 1120 if (!S_ISDIR(dir->i_mode))
1123 die("internal error"); 1121 die("internal error");
1124 if (dir->i_size < 2 * dirsize) { 1122 if (dir->i_size < 2 * dirsize) {
1125 print_current_name(); 1123 printf("%s: bad directory: size<32", current_name);
1126 printf(": bad directory: size<32");
1127 errors_uncorrected = 1; 1124 errors_uncorrected = 1;
1128 } 1125 }
1129 for (offset = 0; offset < dir->i_size; offset += dirsize) 1126 for (offset = 0; offset < dir->i_size; offset += dirsize)
@@ -1140,8 +1137,7 @@ static void recursive_check2(unsigned int ino)
1140 if (!S_ISDIR(dir->i_mode)) 1137 if (!S_ISDIR(dir->i_mode))
1141 die("internal error"); 1138 die("internal error");
1142 if (dir->i_size < 2 * dirsize) { 1139 if (dir->i_size < 2 * dirsize) {
1143 print_current_name(); 1140 printf("%s: bad directory: size<32", current_name);
1144 printf(": bad directory: size < 32");
1145 errors_uncorrected = 1; 1141 errors_uncorrected = 1;
1146 } 1142 }
1147 for (offset = 0; offset < dir->i_size; offset += dirsize) 1143 for (offset = 0; offset < dir->i_size; offset += dirsize)
@@ -1281,43 +1277,16 @@ static void check2(void)
1281} 1277}
1282#endif 1278#endif
1283 1279
1284/* Wed Feb 9 15:17:06 MST 2000 */
1285/* dynamically allocate name_list (instead of making it static) */
1286static void alloc_name_list(void)
1287{
1288 int i;
1289
1290 name_list = xmalloc(sizeof(char *) * MAX_DEPTH);
1291 for (i = 0; i < MAX_DEPTH; i++)
1292 name_list[i] = xmalloc(sizeof(char) * (BUFSIZ + 1));
1293}
1294
1295#ifdef CONFIG_FEATURE_CLEAN_UP
1296/* execute this atexit() to deallocate name_list[] */
1297/* piptigger was here */
1298static void free_name_list(void)
1299{
1300 int i;
1301
1302 if (name_list) {
1303 for (i = 0; i < MAX_DEPTH; i++) {
1304 free(name_list[i]);
1305 }
1306 free(name_list);
1307 }
1308}
1309#endif
1310
1311int fsck_minix_main(int argc, char **argv) 1280int fsck_minix_main(int argc, char **argv)
1312{ 1281{
1313 struct termios tmp; 1282 struct termios tmp;
1314 int retcode = 0; 1283 int retcode = 0;
1315 1284
1316 alloc_name_list(); 1285 alloc_current_name();
1317#ifdef CONFIG_FEATURE_CLEAN_UP 1286#ifdef CONFIG_FEATURE_CLEAN_UP
1318 /* Don't bother to free memory. Exit does 1287 /* Don't bother to free memory. Exit does
1319 * that automagically, so we can save a few bytes */ 1288 * that automagically, so we can save a few bytes */
1320 atexit(free_name_list); 1289 atexit(free_current_name);
1321#endif 1290#endif
1322 1291
1323 if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) 1292 if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE)
@@ -1443,8 +1412,8 @@ int fsck_minix_main(int argc, char **argv)
1443 if (changed) { 1412 if (changed) {
1444 write_tables(); 1413 write_tables();
1445 printf("----------------------------\n" 1414 printf("----------------------------\n"
1446 "FILE SYSTEM HAS BEEN CHANGED\n" 1415 "FILE SYSTEM HAS BEEN CHANGED\n"
1447 "----------------------------\n"); 1416 "----------------------------\n");
1448 sync(); 1417 sync();
1449 } else if (repair) 1418 } else if (repair)
1450 write_super_block(); 1419 write_super_block();