29 |
* 28.02.93 - added support for different directory entry sizes.. |
* 28.02.93 - added support for different directory entry sizes.. |
30 |
* |
* |
31 |
* Sat Mar 6 18:59:42 1993, faith@cs.unc.edu: Output namelen with |
* Sat Mar 6 18:59:42 1993, faith@cs.unc.edu: Output namelen with |
32 |
* super-block information |
* superblock information |
33 |
* |
* |
34 |
* Sat Oct 9 11:17:11 1993, faith@cs.unc.edu: make exit status conform |
* Sat Oct 9 11:17:11 1993, faith@cs.unc.edu: make exit status conform |
35 |
* to that required by fsutil |
* to that required by fsutil |
64 |
* 06.11.96 - Added v2 code submitted by Joerg Dorchain, but written by |
* 06.11.96 - Added v2 code submitted by Joerg Dorchain, but written by |
65 |
* Andreas Schwab. |
* Andreas Schwab. |
66 |
* |
* |
67 |
* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org> |
* 1999-02-22 Arkadiusz Mickiewicz <misiek@misiek.eu.org> |
68 |
* - added Native Language Support |
* - added Native Language Support |
69 |
* |
* |
70 |
* |
* |
79 |
* -a for automatic repairs (not implemented) |
* -a for automatic repairs (not implemented) |
80 |
* -r for repairs (interactive) (not implemented) |
* -r for repairs (interactive) (not implemented) |
81 |
* -v for verbose (tells how many files) |
* -v for verbose (tells how many files) |
82 |
* -s for super-block info |
* -s for superblock info |
83 |
* -m for minix-like "mode not cleared" warnings |
* -m for minix-like "mode not cleared" warnings |
84 |
* -f force filesystem check even if filesystem marked as valid |
* -f force filesystem check even if filesystem marked as valid |
85 |
* |
* |
87 |
* enforced (but it's not much fun on a character device :-). |
* enforced (but it's not much fun on a character device :-). |
88 |
*/ |
*/ |
89 |
|
|
|
#include "busybox.h" |
|
90 |
#include <mntent.h> |
#include <mntent.h> |
91 |
|
#include "libbb.h" |
92 |
#include "minix.h" |
#include "minix.h" |
93 |
|
|
94 |
#ifndef BLKGETSIZE |
#ifndef BLKGETSIZE |
95 |
#define BLKGETSIZE _IO(0x12,96) /* return device size */ |
#define BLKGETSIZE _IO(0x12,96) /* return device size */ |
96 |
#endif |
#endif |
97 |
|
|
98 |
#ifdef UNUSED |
struct BUG_bad_inode_size { |
99 |
|
char BUG_bad_inode1_size[(INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE) ? -1 : 1]; |
100 |
|
#if ENABLE_FEATURE_MINIX2 |
101 |
|
char BUG_bad_inode2_size[(INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) ? -1 : 1]; |
102 |
|
#endif |
103 |
|
}; |
104 |
|
|
105 |
enum { |
enum { |
106 |
|
#ifdef UNUSED |
107 |
MINIX1_LINK_MAX = 250, |
MINIX1_LINK_MAX = 250, |
108 |
MINIX2_LINK_MAX = 65530, |
MINIX2_LINK_MAX = 65530, |
109 |
MINIX_I_MAP_SLOTS = 8, |
MINIX_I_MAP_SLOTS = 8, |
110 |
MINIX_Z_MAP_SLOTS = 64, |
MINIX_Z_MAP_SLOTS = 64, |
111 |
MINIX_V1 = 0x0001, /* original minix fs */ |
MINIX_V1 = 0x0001, /* original minix fs */ |
112 |
MINIX_V2 = 0x0002, /* minix V2 fs */ |
MINIX_V2 = 0x0002, /* minix V2 fs */ |
113 |
NAME_MAX = 255, /* # chars in a file name */ |
#endif |
114 |
|
MINIX_NAME_MAX = 255, /* # chars in a file name */ |
115 |
}; |
}; |
116 |
|
|
117 |
|
|
118 |
|
#if !ENABLE_FEATURE_MINIX2 |
119 |
|
enum { version2 = 0 }; |
120 |
#endif |
#endif |
121 |
|
|
122 |
|
enum { MAX_DEPTH = 32 }; |
123 |
|
|
124 |
|
enum { dev_fd = 3 }; |
125 |
|
|
126 |
|
struct globals { |
127 |
#if ENABLE_FEATURE_MINIX2 |
#if ENABLE_FEATURE_MINIX2 |
128 |
static smallint version2; |
smallint version2; |
|
#else |
|
|
enum { version2 = 0 }; |
|
129 |
#endif |
#endif |
130 |
|
smallint changed; /* is filesystem modified? */ |
131 |
|
smallint errors_uncorrected; /* flag if some error was not corrected */ |
132 |
|
smallint termios_set; |
133 |
|
smallint dirsize; |
134 |
|
smallint namelen; |
135 |
|
const char *device_name; |
136 |
|
int directory, regular, blockdev, chardev, links, symlinks, total; |
137 |
|
char *inode_buffer; |
138 |
|
|
139 |
|
char *inode_map; |
140 |
|
char *zone_map; |
141 |
|
|
142 |
|
unsigned char *inode_count; |
143 |
|
unsigned char *zone_count; |
144 |
|
|
145 |
|
/* File-name data */ |
146 |
|
int name_depth; |
147 |
|
char *name_component[MAX_DEPTH+1]; |
148 |
|
|
149 |
|
/* Bigger stuff */ |
150 |
|
struct termios sv_termios; |
151 |
|
char superblock_buffer[BLOCK_SIZE]; |
152 |
|
char add_zone_ind_blk[BLOCK_SIZE]; |
153 |
|
char add_zone_dind_blk[BLOCK_SIZE]; |
154 |
|
USE_FEATURE_MINIX2(char add_zone_tind_blk[BLOCK_SIZE];) |
155 |
|
char check_file_blk[BLOCK_SIZE]; |
156 |
|
|
157 |
|
/* File-name data */ |
158 |
|
char current_name[MAX_DEPTH * MINIX_NAME_MAX]; |
159 |
|
}; |
160 |
|
|
161 |
|
#define G (*ptr_to_globals) |
162 |
|
#if ENABLE_FEATURE_MINIX2 |
163 |
|
#define version2 (G.version2 ) |
164 |
|
#endif |
165 |
|
#define changed (G.changed ) |
166 |
|
#define errors_uncorrected (G.errors_uncorrected ) |
167 |
|
#define termios_set (G.termios_set ) |
168 |
|
#define dirsize (G.dirsize ) |
169 |
|
#define namelen (G.namelen ) |
170 |
|
#define device_name (G.device_name ) |
171 |
|
#define directory (G.directory ) |
172 |
|
#define regular (G.regular ) |
173 |
|
#define blockdev (G.blockdev ) |
174 |
|
#define chardev (G.chardev ) |
175 |
|
#define links (G.links ) |
176 |
|
#define symlinks (G.symlinks ) |
177 |
|
#define total (G.total ) |
178 |
|
#define inode_buffer (G.inode_buffer ) |
179 |
|
#define inode_map (G.inode_map ) |
180 |
|
#define zone_map (G.zone_map ) |
181 |
|
#define inode_count (G.inode_count ) |
182 |
|
#define zone_count (G.zone_count ) |
183 |
|
#define name_depth (G.name_depth ) |
184 |
|
#define name_component (G.name_component ) |
185 |
|
#define sv_termios (G.sv_termios ) |
186 |
|
#define superblock_buffer (G.superblock_buffer ) |
187 |
|
#define add_zone_ind_blk (G.add_zone_ind_blk ) |
188 |
|
#define add_zone_dind_blk (G.add_zone_dind_blk ) |
189 |
|
#define add_zone_tind_blk (G.add_zone_tind_blk ) |
190 |
|
#define check_file_blk (G.check_file_blk ) |
191 |
|
#define current_name (G.current_name ) |
192 |
|
#define INIT_G() do { \ |
193 |
|
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
194 |
|
dirsize = 16; \ |
195 |
|
namelen = 14; \ |
196 |
|
current_name[0] = '/'; \ |
197 |
|
/*current_name[1] = '\0';*/ \ |
198 |
|
name_component[0] = ¤t_name[0]; \ |
199 |
|
} while (0) |
200 |
|
|
201 |
|
|
202 |
|
#define OPTION_STR "larvsmf" |
203 |
|
enum { |
204 |
|
OPT_l = (1 << 0), |
205 |
|
OPT_a = (1 << 1), |
206 |
|
OPT_r = (1 << 2), |
207 |
|
OPT_v = (1 << 3), |
208 |
|
OPT_s = (1 << 4), |
209 |
|
OPT_w = (1 << 5), |
210 |
|
OPT_f = (1 << 6), |
211 |
|
}; |
212 |
|
#define OPT_list (option_mask32 & OPT_l) |
213 |
|
#define OPT_automatic (option_mask32 & OPT_a) |
214 |
|
#define OPT_repair (option_mask32 & OPT_r) |
215 |
|
#define OPT_verbose (option_mask32 & OPT_v) |
216 |
|
#define OPT_show (option_mask32 & OPT_s) |
217 |
|
#define OPT_warn_mode (option_mask32 & OPT_w) |
218 |
|
#define OPT_force (option_mask32 & OPT_f) |
219 |
|
/* non-automatic repairs requested? */ |
220 |
|
#define OPT_manual ((option_mask32 & (OPT_a|OPT_r)) == OPT_r) |
221 |
|
|
|
#define PROGRAM_VERSION "1.2 - 11/11/96" |
|
|
static smallint repair, automatic, verbose, list, show, warn_mode, force; |
|
|
static smallint changed; /* is filesystem modified? */ |
|
|
static smallint errors_uncorrected; /* flag if some error was not corrected */ |
|
|
|
|
|
static smallint termios_set; |
|
|
static struct termios termios; |
|
|
|
|
|
static char *device_name; |
|
|
static int IN; |
|
|
static int directory, regular, blockdev, chardev, links, symlinks, total; |
|
|
|
|
|
//also smallint? |
|
|
static int dirsize = 16; |
|
|
static int namelen = 14; |
|
|
|
|
|
static char *inode_buffer; |
|
|
//xzalloc? |
|
|
static char super_block_buffer[BLOCK_SIZE]; |
|
222 |
|
|
223 |
#define Inode1 (((struct minix1_inode *) inode_buffer)-1) |
#define Inode1 (((struct minix1_inode *) inode_buffer)-1) |
224 |
#define Inode2 (((struct minix2_inode *) inode_buffer)-1) |
#define Inode2 (((struct minix2_inode *) inode_buffer)-1) |
225 |
|
|
226 |
#define Super (*(struct minix_super_block *)super_block_buffer) |
#define Super (*(struct minix_superblock *)(superblock_buffer)) |
227 |
|
|
228 |
#if ENABLE_FEATURE_MINIX2 |
#if ENABLE_FEATURE_MINIX2 |
229 |
# define ZONES ((unsigned)(version2 ? Super.s_zones : Super.s_nzones)) |
# define ZONES ((unsigned)(version2 ? Super.s_zones : Super.s_nzones)) |
239 |
#define MAGIC (Super.s_magic) |
#define MAGIC (Super.s_magic) |
240 |
|
|
241 |
/* gcc likes this more (code is smaller) than macro variant */ |
/* gcc likes this more (code is smaller) than macro variant */ |
242 |
static ATTRIBUTE_ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n) |
static ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n) |
243 |
{ |
{ |
244 |
return (size + n-1) / n; |
return (size + n-1) / n; |
245 |
} |
} |
246 |
|
|
247 |
#if ENABLE_FEATURE_MINIX2 |
#if !ENABLE_FEATURE_MINIX2 |
248 |
#define INODE_BLOCKS div_roundup(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \ |
#define INODE_BLOCKS div_roundup(INODES, MINIX1_INODES_PER_BLOCK) |
|
: MINIX1_INODES_PER_BLOCK)) |
|
249 |
#else |
#else |
250 |
#define INODE_BLOCKS div_roundup(INODES, MINIX1_INODES_PER_BLOCK) |
#define INODE_BLOCKS div_roundup(INODES, \ |
251 |
|
(version2 ? MINIX2_INODES_PER_BLOCK : MINIX1_INODES_PER_BLOCK)) |
252 |
#endif |
#endif |
253 |
|
|
254 |
#define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE) |
#define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE) |
255 |
#define NORM_FIRSTZONE (2 + IMAPS + ZMAPS + INODE_BLOCKS) |
#define NORM_FIRSTZONE (2 + IMAPS + ZMAPS + INODE_BLOCKS) |
256 |
|
|
257 |
static char *inode_map; |
/* Before you ask "where they come from?": */ |
258 |
static char *zone_map; |
/* setbit/clrbit are supplied by sys/param.h */ |
259 |
|
|
260 |
static unsigned char *inode_count; |
static int minix_bit(const char *a, unsigned i) |
261 |
static unsigned char *zone_count; |
{ |
262 |
|
return (a[i >> 3] & (1<<(i & 7))); |
263 |
|
} |
264 |
|
|
265 |
static int bit(char *a, unsigned i) |
static void minix_setbit(char *a, unsigned i) |
266 |
{ |
{ |
267 |
return (a[i >> 3] & (1<<(i & 7))) != 0; |
setbit(a, i); |
268 |
|
changed = 1; |
269 |
|
} |
270 |
|
static void minix_clrbit(char *a, unsigned i) |
271 |
|
{ |
272 |
|
clrbit(a, i); |
273 |
|
changed = 1; |
274 |
} |
} |
275 |
|
|
276 |
#define inode_in_use(x) (bit(inode_map,(x))) |
/* Note: do not assume 0/1, it is 0/nonzero */ |
277 |
#define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1)) |
#define zone_in_use(x) (minix_bit(zone_map,(x)-FIRSTZONE+1)) |
278 |
|
#define inode_in_use(x) (minix_bit(inode_map,(x))) |
279 |
|
|
280 |
#define mark_inode(x) (setbit(inode_map,(x)),changed=1) |
#define mark_inode(x) (minix_setbit(inode_map,(x))) |
281 |
#define unmark_inode(x) (clrbit(inode_map,(x)),changed=1) |
#define unmark_inode(x) (minix_clrbit(inode_map,(x))) |
282 |
|
|
283 |
#define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1),changed=1) |
#define mark_zone(x) (minix_setbit(zone_map,(x)-FIRSTZONE+1)) |
284 |
#define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1),changed=1) |
#define unmark_zone(x) (minix_clrbit(zone_map,(x)-FIRSTZONE+1)) |
285 |
|
|
286 |
|
|
287 |
static void recursive_check(unsigned ino); |
static void recursive_check(unsigned ino); |
289 |
static void recursive_check2(unsigned ino); |
static void recursive_check2(unsigned ino); |
290 |
#endif |
#endif |
291 |
|
|
292 |
static void die(const char *str) ATTRIBUTE_NORETURN; |
static void die(const char *str) NORETURN; |
293 |
static void die(const char *str) |
static void die(const char *str) |
294 |
{ |
{ |
295 |
if (termios_set) |
if (termios_set) |
296 |
tcsetattr(0, TCSANOW, &termios); |
tcsetattr_stdin_TCSANOW(&sv_termios); |
297 |
bb_error_msg_and_die("%s", str); |
bb_error_msg_and_die("%s", str); |
298 |
} |
} |
299 |
|
|
|
/* File-name data */ |
|
|
enum { MAX_DEPTH = 32 }; |
|
|
static int name_depth; |
|
|
static char *current_name; |
|
|
static char *name_component[MAX_DEPTH+1]; |
|
|
|
|
|
/* Wed Feb 9 15:17:06 MST 2000 */ |
|
|
/* dynamically allocate name_list (instead of making it static) */ |
|
|
static void alloc_current_name(void) |
|
|
{ |
|
|
current_name = xmalloc(MAX_DEPTH * (BUFSIZ + 1)); |
|
|
current_name[0] = '/'; |
|
|
current_name[1] = '\0'; |
|
|
name_component[0] = ¤t_name[0]; |
|
|
} |
|
|
|
|
|
#if ENABLE_FEATURE_CLEAN_UP |
|
|
/* execute this atexit() to deallocate name_list[] */ |
|
|
/* piptigger was here */ |
|
|
static void free_current_name(void) |
|
|
{ |
|
|
free(current_name); |
|
|
} |
|
|
#endif |
|
|
|
|
300 |
static void push_filename(const char *name) |
static void push_filename(const char *name) |
301 |
{ |
{ |
302 |
// /dir/dir/dir/file |
// /dir/dir/dir/file |
328 |
{ |
{ |
329 |
int c; |
int c; |
330 |
|
|
331 |
if (!repair) { |
if (!OPT_repair) { |
332 |
puts(""); |
bb_putchar('\n'); |
333 |
errors_uncorrected = 1; |
errors_uncorrected = 1; |
334 |
return 0; |
return 0; |
335 |
} |
} |
336 |
if (automatic) { |
if (OPT_automatic) { |
337 |
puts(""); |
bb_putchar('\n'); |
338 |
if (!def) |
if (!def) |
339 |
errors_uncorrected = 1; |
errors_uncorrected = 1; |
340 |
return def; |
return def; |
378 |
struct mntent *mnt; |
struct mntent *mnt; |
379 |
int cont; |
int cont; |
380 |
int fd; |
int fd; |
381 |
|
//XXX:FIXME use find_mount_point() |
382 |
f = setmntent(MOUNTED, "r"); |
f = setmntent(MOUNTED, "r"); |
383 |
if (f == NULL) |
if (f == NULL) |
384 |
return; |
return; |
405 |
cont = ask("Do you really want to continue", 0); |
cont = ask("Do you really want to continue", 0); |
406 |
if (!cont) { |
if (!cont) { |
407 |
printf("Check aborted\n"); |
printf("Check aborted\n"); |
408 |
exit(0); |
exit(EXIT_SUCCESS); |
409 |
} |
} |
410 |
} |
} |
411 |
|
|
445 |
/* |
/* |
446 |
* read-block reads block nr into the buffer at addr. |
* read-block reads block nr into the buffer at addr. |
447 |
*/ |
*/ |
448 |
static void read_block(unsigned nr, char *addr) |
static void read_block(unsigned nr, void *addr) |
449 |
{ |
{ |
450 |
if (!nr) { |
if (!nr) { |
451 |
memset(addr, 0, BLOCK_SIZE); |
memset(addr, 0, BLOCK_SIZE); |
452 |
return; |
return; |
453 |
} |
} |
454 |
if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET)) { |
xlseek(dev_fd, BLOCK_SIZE * nr, SEEK_SET); |
455 |
printf("%s: cannot seek to block in file '%s'\n", |
if (BLOCK_SIZE != full_read(dev_fd, addr, BLOCK_SIZE)) { |
456 |
bb_msg_read_error, current_name); |
printf("%s: bad block %u in file '%s'\n", |
457 |
errors_uncorrected = 1; |
bb_msg_read_error, nr, current_name); |
|
memset(addr, 0, BLOCK_SIZE); |
|
|
} else if (BLOCK_SIZE != read(IN, addr, BLOCK_SIZE)) { |
|
|
printf("%s: bad block in file '%s'\n", |
|
|
bb_msg_read_error, current_name); |
|
458 |
errors_uncorrected = 1; |
errors_uncorrected = 1; |
459 |
memset(addr, 0, BLOCK_SIZE); |
memset(addr, 0, BLOCK_SIZE); |
460 |
} |
} |
463 |
/* |
/* |
464 |
* write_block writes block nr to disk. |
* write_block writes block nr to disk. |
465 |
*/ |
*/ |
466 |
static void write_block(unsigned nr, char *addr) |
static void write_block(unsigned nr, void *addr) |
467 |
{ |
{ |
468 |
if (!nr) |
if (!nr) |
469 |
return; |
return; |
473 |
errors_uncorrected = 1; |
errors_uncorrected = 1; |
474 |
return; |
return; |
475 |
} |
} |
476 |
if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET)) |
xlseek(dev_fd, BLOCK_SIZE * nr, SEEK_SET); |
477 |
die("seek failed in write_block"); |
if (BLOCK_SIZE != full_write(dev_fd, addr, BLOCK_SIZE)) { |
478 |
if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) { |
printf("%s: bad block %u in file '%s'\n", |
479 |
printf("%s: bad block in file '%s'\n", |
bb_msg_write_error, nr, current_name); |
|
bb_msg_write_error, current_name); |
|
480 |
errors_uncorrected = 1; |
errors_uncorrected = 1; |
481 |
} |
} |
482 |
} |
} |
489 |
static int map_block(struct minix1_inode *inode, unsigned blknr) |
static int map_block(struct minix1_inode *inode, unsigned blknr) |
490 |
{ |
{ |
491 |
uint16_t ind[BLOCK_SIZE >> 1]; |
uint16_t ind[BLOCK_SIZE >> 1]; |
|
uint16_t dind[BLOCK_SIZE >> 1]; |
|
492 |
int block, result; |
int block, result; |
493 |
smallint blk_chg; |
smallint blk_chg; |
494 |
|
|
497 |
blknr -= 7; |
blknr -= 7; |
498 |
if (blknr < 512) { |
if (blknr < 512) { |
499 |
block = check_zone_nr(inode->i_zone + 7, &changed); |
block = check_zone_nr(inode->i_zone + 7, &changed); |
500 |
read_block(block, (char *) ind); |
goto common; |
|
blk_chg = 0; |
|
|
result = check_zone_nr(blknr + ind, &blk_chg); |
|
|
if (blk_chg) |
|
|
write_block(block, (char *) ind); |
|
|
return result; |
|
501 |
} |
} |
502 |
blknr -= 512; |
blknr -= 512; |
503 |
block = check_zone_nr(inode->i_zone + 8, &changed); |
block = check_zone_nr(inode->i_zone + 8, &changed); |
504 |
read_block(block, (char *) dind); |
read_block(block, ind); /* double indirect */ |
505 |
blk_chg = 0; |
blk_chg = 0; |
506 |
result = check_zone_nr(dind + (blknr / 512), &blk_chg); |
result = check_zone_nr(&ind[blknr / 512], &blk_chg); |
507 |
if (blk_chg) |
if (blk_chg) |
508 |
write_block(block, (char *) dind); |
write_block(block, ind); |
509 |
block = result; |
block = result; |
510 |
read_block(block, (char *) ind); |
common: |
511 |
|
read_block(block, ind); |
512 |
blk_chg = 0; |
blk_chg = 0; |
513 |
result = check_zone_nr(ind + (blknr % 512), &blk_chg); |
result = check_zone_nr(&ind[blknr % 512], &blk_chg); |
514 |
if (blk_chg) |
if (blk_chg) |
515 |
write_block(block, (char *) ind); |
write_block(block, ind); |
516 |
return result; |
return result; |
517 |
} |
} |
518 |
|
|
520 |
static int map_block2(struct minix2_inode *inode, unsigned blknr) |
static int map_block2(struct minix2_inode *inode, unsigned blknr) |
521 |
{ |
{ |
522 |
uint32_t ind[BLOCK_SIZE >> 2]; |
uint32_t ind[BLOCK_SIZE >> 2]; |
|
uint32_t dind[BLOCK_SIZE >> 2]; |
|
|
uint32_t tind[BLOCK_SIZE >> 2]; |
|
523 |
int block, result; |
int block, result; |
524 |
smallint blk_chg; |
smallint blk_chg; |
525 |
|
|
528 |
blknr -= 7; |
blknr -= 7; |
529 |
if (blknr < 256) { |
if (blknr < 256) { |
530 |
block = check_zone_nr2(inode->i_zone + 7, &changed); |
block = check_zone_nr2(inode->i_zone + 7, &changed); |
531 |
read_block(block, (char *) ind); |
goto common2; |
|
blk_chg = 0; |
|
|
result = check_zone_nr2(blknr + ind, &blk_chg); |
|
|
if (blk_chg) |
|
|
write_block(block, (char *) ind); |
|
|
return result; |
|
532 |
} |
} |
533 |
blknr -= 256; |
blknr -= 256; |
534 |
if (blknr >= 256 * 256) { |
if (blknr < 256 * 256) { |
535 |
block = check_zone_nr2(inode->i_zone + 8, &changed); |
block = check_zone_nr2(inode->i_zone + 8, &changed); |
536 |
read_block(block, (char *) dind); |
goto common1; |
|
blk_chg = 0; |
|
|
result = check_zone_nr2(dind + blknr / 256, &blk_chg); |
|
|
if (blk_chg) |
|
|
write_block(block, (char *) dind); |
|
|
block = result; |
|
|
read_block(block, (char *) ind); |
|
|
blk_chg = 0; |
|
|
result = check_zone_nr2(ind + blknr % 256, &blk_chg); |
|
|
if (blk_chg) |
|
|
write_block(block, (char *) ind); |
|
|
return result; |
|
537 |
} |
} |
538 |
blknr -= 256 * 256; |
blknr -= 256 * 256; |
539 |
block = check_zone_nr2(inode->i_zone + 9, &changed); |
block = check_zone_nr2(inode->i_zone + 9, &changed); |
540 |
read_block(block, (char *) tind); |
read_block(block, ind); /* triple indirect */ |
541 |
blk_chg = 0; |
blk_chg = 0; |
542 |
result = check_zone_nr2(tind + blknr / (256 * 256), &blk_chg); |
result = check_zone_nr2(&ind[blknr / (256 * 256)], &blk_chg); |
543 |
if (blk_chg) |
if (blk_chg) |
544 |
write_block(block, (char *) tind); |
write_block(block, ind); |
545 |
block = result; |
block = result; |
546 |
read_block(block, (char *) dind); |
common1: |
547 |
|
read_block(block, ind); /* double indirect */ |
548 |
blk_chg = 0; |
blk_chg = 0; |
549 |
result = check_zone_nr2(dind + (blknr / 256) % 256, &blk_chg); |
result = check_zone_nr2(&ind[(blknr / 256) % 256], &blk_chg); |
550 |
if (blk_chg) |
if (blk_chg) |
551 |
write_block(block, (char *) dind); |
write_block(block, ind); |
552 |
block = result; |
block = result; |
553 |
read_block(block, (char *) ind); |
common2: |
554 |
|
read_block(block, ind); |
555 |
blk_chg = 0; |
blk_chg = 0; |
556 |
result = check_zone_nr2(ind + blknr % 256, &blk_chg); |
result = check_zone_nr2(&ind[blknr % 256], &blk_chg); |
557 |
if (blk_chg) |
if (blk_chg) |
558 |
write_block(block, (char *) ind); |
write_block(block, ind); |
559 |
return result; |
return result; |
560 |
} |
} |
561 |
#endif |
#endif |
562 |
|
|
563 |
static void write_super_block(void) |
static void write_superblock(void) |
564 |
{ |
{ |
565 |
/* |
/* |
566 |
* Set the state of the filesystem based on whether or not there |
* Set the state of the filesystem based on whether or not there |
571 |
if (!errors_uncorrected) |
if (!errors_uncorrected) |
572 |
Super.s_state &= ~MINIX_ERROR_FS; |
Super.s_state &= ~MINIX_ERROR_FS; |
573 |
|
|
574 |
if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET)) |
xlseek(dev_fd, BLOCK_SIZE, SEEK_SET); |
575 |
die("seek failed in write_super_block"); |
if (BLOCK_SIZE != full_write(dev_fd, superblock_buffer, BLOCK_SIZE)) |
576 |
if (BLOCK_SIZE != write(IN, super_block_buffer, BLOCK_SIZE)) |
die("cannot write superblock"); |
|
die("cannot write super-block"); |
|
577 |
} |
} |
578 |
|
|
579 |
static void write_tables(void) |
static void write_tables(void) |
580 |
{ |
{ |
581 |
write_super_block(); |
write_superblock(); |
582 |
|
|
583 |
if (IMAPS * BLOCK_SIZE != write(IN, inode_map, IMAPS * BLOCK_SIZE)) |
if (IMAPS * BLOCK_SIZE != write(dev_fd, inode_map, IMAPS * BLOCK_SIZE)) |
584 |
die("cannot write inode map"); |
die("cannot write inode map"); |
585 |
if (ZMAPS * BLOCK_SIZE != write(IN, zone_map, ZMAPS * BLOCK_SIZE)) |
if (ZMAPS * BLOCK_SIZE != write(dev_fd, zone_map, ZMAPS * BLOCK_SIZE)) |
586 |
die("cannot write zone map"); |
die("cannot write zone map"); |
587 |
if (INODE_BUFFER_SIZE != write(IN, inode_buffer, INODE_BUFFER_SIZE)) |
if (INODE_BUFFER_SIZE != write(dev_fd, inode_buffer, INODE_BUFFER_SIZE)) |
588 |
die("cannot write inodes"); |
die("cannot write inodes"); |
589 |
} |
} |
590 |
|
|
613 |
|
|
614 |
static void read_superblock(void) |
static void read_superblock(void) |
615 |
{ |
{ |
616 |
if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET)) |
xlseek(dev_fd, BLOCK_SIZE, SEEK_SET); |
617 |
die("seek failed"); |
if (BLOCK_SIZE != full_read(dev_fd, superblock_buffer, BLOCK_SIZE)) |
618 |
if (BLOCK_SIZE != read(IN, super_block_buffer, BLOCK_SIZE)) |
die("cannot read superblock"); |
|
die("cannot read super block"); |
|
619 |
/* already initialized to: |
/* already initialized to: |
620 |
namelen = 14; |
namelen = 14; |
621 |
dirsize = 16; |
dirsize = 16; |
634 |
version2 = 1; |
version2 = 1; |
635 |
#endif |
#endif |
636 |
} else |
} else |
637 |
die("bad magic number in super-block"); |
die("bad magic number in superblock"); |
638 |
if (ZONESIZE != 0 || BLOCK_SIZE != 1024) |
if (ZONESIZE != 0 || BLOCK_SIZE != 1024) |
639 |
die("only 1k blocks/zones supported"); |
die("only 1k blocks/zones supported"); |
640 |
if (IMAPS * BLOCK_SIZE * 8 < INODES + 1) |
if (IMAPS * BLOCK_SIZE * 8 < INODES + 1) |
641 |
die("bad s_imap_blocks field in super-block"); |
die("bad s_imap_blocks field in superblock"); |
642 |
if (ZMAPS * BLOCK_SIZE * 8 < ZONES - FIRSTZONE + 1) |
if (ZMAPS * BLOCK_SIZE * 8 < ZONES - FIRSTZONE + 1) |
643 |
die("bad s_zmap_blocks field in super-block"); |
die("bad s_zmap_blocks field in superblock"); |
644 |
} |
} |
645 |
|
|
646 |
static void read_tables(void) |
static void read_tables(void) |
650 |
inode_buffer = xmalloc(INODE_BUFFER_SIZE); |
inode_buffer = xmalloc(INODE_BUFFER_SIZE); |
651 |
inode_count = xmalloc(INODES + 1); |
inode_count = xmalloc(INODES + 1); |
652 |
zone_count = xmalloc(ZONES); |
zone_count = xmalloc(ZONES); |
653 |
if (IMAPS * BLOCK_SIZE != read(IN, inode_map, IMAPS * BLOCK_SIZE)) |
if (IMAPS * BLOCK_SIZE != read(dev_fd, inode_map, IMAPS * BLOCK_SIZE)) |
654 |
die("cannot read inode map"); |
die("cannot read inode map"); |
655 |
if (ZMAPS * BLOCK_SIZE != read(IN, zone_map, ZMAPS * BLOCK_SIZE)) |
if (ZMAPS * BLOCK_SIZE != read(dev_fd, zone_map, ZMAPS * BLOCK_SIZE)) |
656 |
die("cannot read zone map"); |
die("cannot read zone map"); |
657 |
if (INODE_BUFFER_SIZE != read(IN, inode_buffer, INODE_BUFFER_SIZE)) |
if (INODE_BUFFER_SIZE != read(dev_fd, inode_buffer, INODE_BUFFER_SIZE)) |
658 |
die("cannot read inodes"); |
die("cannot read inodes"); |
659 |
if (NORM_FIRSTZONE != FIRSTZONE) { |
if (NORM_FIRSTZONE != FIRSTZONE) { |
660 |
printf("warning: firstzone!=norm_firstzone\n"); |
printf("warning: firstzone!=norm_firstzone\n"); |
661 |
errors_uncorrected = 1; |
errors_uncorrected = 1; |
662 |
} |
} |
663 |
get_dirsize(); |
get_dirsize(); |
664 |
if (show) { |
if (OPT_show) { |
665 |
printf("%u inodes\n" |
printf("%u inodes\n" |
666 |
"%u blocks\n" |
"%u blocks\n" |
667 |
"Firstdatazone=%u (%u)\n" |
"Firstdatazone=%u (%u)\n" |
679 |
} |
} |
680 |
} |
} |
681 |
|
|
682 |
static struct minix1_inode *get_inode(unsigned nr) |
static void get_inode_common(unsigned nr, uint16_t i_mode) |
683 |
{ |
{ |
|
struct minix1_inode *inode; |
|
|
|
|
|
if (!nr || nr > INODES) |
|
|
return NULL; |
|
684 |
total++; |
total++; |
|
inode = Inode1 + nr; |
|
685 |
if (!inode_count[nr]) { |
if (!inode_count[nr]) { |
686 |
if (!inode_in_use(nr)) { |
if (!inode_in_use(nr)) { |
687 |
printf("Inode %d is marked as 'unused', but it is used " |
printf("Inode %d is marked as 'unused', but it is used " |
688 |
"for file '%s'\n", nr, current_name); |
"for file '%s'\n", nr, current_name); |
689 |
if (repair) { |
if (OPT_repair) { |
690 |
if (ask("Mark as 'in use'", 1)) |
if (ask("Mark as 'in use'", 1)) |
691 |
mark_inode(nr); |
mark_inode(nr); |
692 |
} else { |
else |
693 |
errors_uncorrected = 1; |
errors_uncorrected = 1; |
694 |
} |
} |
695 |
} |
} |
696 |
if (S_ISDIR(inode->i_mode)) |
if (S_ISDIR(i_mode)) |
697 |
directory++; |
directory++; |
698 |
else if (S_ISREG(inode->i_mode)) |
else if (S_ISREG(i_mode)) |
699 |
regular++; |
regular++; |
700 |
else if (S_ISCHR(inode->i_mode)) |
else if (S_ISCHR(i_mode)) |
701 |
chardev++; |
chardev++; |
702 |
else if (S_ISBLK(inode->i_mode)) |
else if (S_ISBLK(i_mode)) |
703 |
blockdev++; |
blockdev++; |
704 |
else if (S_ISLNK(inode->i_mode)) |
else if (S_ISLNK(i_mode)) |
705 |
symlinks++; |
symlinks++; |
706 |
else if (S_ISSOCK(inode->i_mode)); |
else if (S_ISSOCK(i_mode)); |
707 |
else if (S_ISFIFO(inode->i_mode)); |
else if (S_ISFIFO(i_mode)); |
708 |
else { |
else { |
709 |
printf("%s has mode %05o\n", current_name, inode->i_mode); |
printf("%s has mode %05o\n", current_name, i_mode); |
710 |
} |
} |
|
|
|
711 |
} else |
} else |
712 |
links++; |
links++; |
713 |
if (!++inode_count[nr]) { |
if (!++inode_count[nr]) { |
715 |
inode_count[nr]--; |
inode_count[nr]--; |
716 |
errors_uncorrected = 1; |
errors_uncorrected = 1; |
717 |
} |
} |
718 |
|
} |
719 |
|
|
720 |
|
static struct minix1_inode *get_inode(unsigned nr) |
721 |
|
{ |
722 |
|
struct minix1_inode *inode; |
723 |
|
|
724 |
|
if (!nr || nr > INODES) |
725 |
|
return NULL; |
726 |
|
inode = Inode1 + nr; |
727 |
|
get_inode_common(nr, inode->i_mode); |
728 |
return inode; |
return inode; |
729 |
} |
} |
730 |
|
|
735 |
|
|
736 |
if (!nr || nr > INODES) |
if (!nr || nr > INODES) |
737 |
return NULL; |
return NULL; |
|
total++; |
|
738 |
inode = Inode2 + nr; |
inode = Inode2 + nr; |
739 |
if (!inode_count[nr]) { |
get_inode_common(nr, inode->i_mode); |
|
if (!inode_in_use(nr)) { |
|
|
printf("Inode %d is marked as 'unused', but it is used " |
|
|
"for file '%s'\n", nr, current_name); |
|
|
if (repair) { |
|
|
if (ask("Mark as 'in use'", 1)) |
|
|
mark_inode(nr); |
|
|
else |
|
|
errors_uncorrected = 1; |
|
|
} |
|
|
} |
|
|
if (S_ISDIR(inode->i_mode)) |
|
|
directory++; |
|
|
else if (S_ISREG(inode->i_mode)) |
|
|
regular++; |
|
|
else if (S_ISCHR(inode->i_mode)) |
|
|
chardev++; |
|
|
else if (S_ISBLK(inode->i_mode)) |
|
|
blockdev++; |
|
|
else if (S_ISLNK(inode->i_mode)) |
|
|
symlinks++; |
|
|
else if (S_ISSOCK(inode->i_mode)); |
|
|
else if (S_ISFIFO(inode->i_mode)); |
|
|
else { |
|
|
printf("%s has mode %05o\n", current_name, inode->i_mode); |
|
|
} |
|
|
} else |
|
|
links++; |
|
|
if (!++inode_count[nr]) { |
|
|
printf("Warning: inode count too big\n"); |
|
|
inode_count[nr]--; |
|
|
errors_uncorrected = 1; |
|
|
} |
|
740 |
return inode; |
return inode; |
741 |
} |
} |
742 |
#endif |
#endif |
761 |
void check_root2(void); |
void check_root2(void); |
762 |
#endif |
#endif |
763 |
|
|
764 |
static int add_zone(uint16_t *znr, smallint *corrected) |
static int add_zone_common(int block, smallint *corrected) |
765 |
{ |
{ |
|
int result; |
|
|
int block; |
|
|
|
|
|
result = 0; |
|
|
block = check_zone_nr(znr, corrected); |
|
766 |
if (!block) |
if (!block) |
767 |
return 0; |
return 0; |
768 |
if (zone_count[block]) { |
if (zone_count[block]) { |
769 |
printf("Already used block is reused in file '%s'. ", |
printf("Already used block is reused in file '%s'. ", |
770 |
current_name); |
current_name); |
771 |
if (ask("Clear", 1)) { |
if (ask("Clear", 1)) { |
|
*znr = 0; |
|
772 |
block = 0; |
block = 0; |
773 |
*corrected = 1; |
*corrected = 1; |
774 |
return 0; |
return -1; /* "please zero out *znr" */ |
775 |
} |
} |
776 |
} |
} |
777 |
if (!zone_in_use(block)) { |
if (!zone_in_use(block)) { |
785 |
return block; |
return block; |
786 |
} |
} |
787 |
|
|
788 |
|
static int add_zone(uint16_t *znr, smallint *corrected) |
789 |
|
{ |
790 |
|
int block; |
791 |
|
|
792 |
|
block = check_zone_nr(znr, corrected); |
793 |
|
block = add_zone_common(block, corrected); |
794 |
|
if (block == -1) { |
795 |
|
*znr = 0; |
796 |
|
block = 0; |
797 |
|
} |
798 |
|
return block; |
799 |
|
} |
800 |
|
|
801 |
#if ENABLE_FEATURE_MINIX2 |
#if ENABLE_FEATURE_MINIX2 |
802 |
static int add_zone2(uint32_t *znr, smallint *corrected) |
static int add_zone2(uint32_t *znr, smallint *corrected) |
803 |
{ |
{ |
|
int result; |
|
804 |
int block; |
int block; |
805 |
|
|
|
result = 0; |
|
806 |
block = check_zone_nr2(znr, corrected); |
block = check_zone_nr2(znr, corrected); |
807 |
if (!block) |
block = add_zone_common(block, corrected); |
808 |
return 0; |
if (block == -1) { |
809 |
if (zone_count[block]) { |
*znr = 0; |
810 |
printf("Already used block is reused in file '%s'. ", |
block = 0; |
|
current_name); |
|
|
if (ask("Clear", 1)) { |
|
|
*znr = 0; |
|
|
block = 0; |
|
|
*corrected = 1; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
if (!zone_in_use(block)) { |
|
|
printf("Block %d in file '%s' is marked as 'unused'. ", |
|
|
block, current_name); |
|
|
if (ask("Correct", 1)) |
|
|
mark_zone(block); |
|
811 |
} |
} |
|
if (!++zone_count[block]) |
|
|
zone_count[block]--; |
|
812 |
return block; |
return block; |
813 |
} |
} |
814 |
#endif |
#endif |
815 |
|
|
816 |
static void add_zone_ind(uint16_t *znr, smallint *corrected) |
static void add_zone_ind(uint16_t *znr, smallint *corrected) |
817 |
{ |
{ |
|
static char blk[BLOCK_SIZE]; |
|
818 |
int i; |
int i; |
819 |
int block; |
int block; |
820 |
smallint chg_blk = 0; |
smallint chg_blk = 0; |
822 |
block = add_zone(znr, corrected); |
block = add_zone(znr, corrected); |
823 |
if (!block) |
if (!block) |
824 |
return; |
return; |
825 |
read_block(block, blk); |
read_block(block, add_zone_ind_blk); |
826 |
for (i = 0; i < (BLOCK_SIZE >> 1); i++) |
for (i = 0; i < (BLOCK_SIZE >> 1); i++) |
827 |
add_zone(i + (uint16_t *) blk, &chg_blk); |
add_zone(i + (uint16_t *) add_zone_ind_blk, &chg_blk); |
828 |
if (chg_blk) |
if (chg_blk) |
829 |
write_block(block, blk); |
write_block(block, add_zone_ind_blk); |
830 |
} |
} |
831 |
|
|
832 |
#if ENABLE_FEATURE_MINIX2 |
#if ENABLE_FEATURE_MINIX2 |
833 |
static void add_zone_ind2(uint32_t *znr, smallint *corrected) |
static void add_zone_ind2(uint32_t *znr, smallint *corrected) |
834 |
{ |
{ |
|
static char blk[BLOCK_SIZE]; |
|
835 |
int i; |
int i; |
836 |
int block; |
int block; |
837 |
smallint chg_blk = 0; |
smallint chg_blk = 0; |
839 |
block = add_zone2(znr, corrected); |
block = add_zone2(znr, corrected); |
840 |
if (!block) |
if (!block) |
841 |
return; |
return; |
842 |
read_block(block, blk); |
read_block(block, add_zone_ind_blk); |
843 |
for (i = 0; i < BLOCK_SIZE >> 2; i++) |
for (i = 0; i < BLOCK_SIZE >> 2; i++) |
844 |
add_zone2(i + (uint32_t *) blk, &chg_blk); |
add_zone2(i + (uint32_t *) add_zone_ind_blk, &chg_blk); |
845 |
if (chg_blk) |
if (chg_blk) |
846 |
write_block(block, blk); |
write_block(block, add_zone_ind_blk); |
847 |
} |
} |
848 |
#endif |
#endif |
849 |
|
|
850 |
static void add_zone_dind(uint16_t *znr, smallint *corrected) |
static void add_zone_dind(uint16_t *znr, smallint *corrected) |
851 |
{ |
{ |
|
static char blk[BLOCK_SIZE]; |
|
852 |
int i; |
int i; |
853 |
int block; |
int block; |
854 |
smallint chg_blk = 0; |
smallint chg_blk = 0; |
856 |
block = add_zone(znr, corrected); |
block = add_zone(znr, corrected); |
857 |
if (!block) |
if (!block) |
858 |
return; |
return; |
859 |
read_block(block, blk); |
read_block(block, add_zone_dind_blk); |
860 |
for (i = 0; i < (BLOCK_SIZE >> 1); i++) |
for (i = 0; i < (BLOCK_SIZE >> 1); i++) |
861 |
add_zone_ind(i + (uint16_t *) blk, &chg_blk); |
add_zone_ind(i + (uint16_t *) add_zone_dind_blk, &chg_blk); |
862 |
if (chg_blk) |
if (chg_blk) |
863 |
write_block(block, blk); |
write_block(block, add_zone_dind_blk); |
864 |
} |
} |
865 |
|
|
866 |
#if ENABLE_FEATURE_MINIX2 |
#if ENABLE_FEATURE_MINIX2 |
867 |
static void add_zone_dind2(uint32_t *znr, smallint *corrected) |
static void add_zone_dind2(uint32_t *znr, smallint *corrected) |
868 |
{ |
{ |
|
static char blk[BLOCK_SIZE]; |
|
869 |
int i; |
int i; |
870 |
int block; |
int block; |
871 |
smallint chg_blk = 0; |
smallint chg_blk = 0; |
873 |
block = add_zone2(znr, corrected); |
block = add_zone2(znr, corrected); |
874 |
if (!block) |
if (!block) |
875 |
return; |
return; |
876 |
read_block(block, blk); |
read_block(block, add_zone_dind_blk); |
877 |
for (i = 0; i < BLOCK_SIZE >> 2; i++) |
for (i = 0; i < BLOCK_SIZE >> 2; i++) |
878 |
add_zone_ind2(i + (uint32_t *) blk, &chg_blk); |
add_zone_ind2(i + (uint32_t *) add_zone_dind_blk, &chg_blk); |
879 |
if (chg_blk) |
if (chg_blk) |
880 |
write_block(block, blk); |
write_block(block, add_zone_dind_blk); |
881 |
} |
} |
882 |
|
|
883 |
static void add_zone_tind2(uint32_t *znr, smallint *corrected) |
static void add_zone_tind2(uint32_t *znr, smallint *corrected) |
884 |
{ |
{ |
|
static char blk[BLOCK_SIZE]; |
|
885 |
int i; |
int i; |
886 |
int block; |
int block; |
887 |
smallint chg_blk = 0; |
smallint chg_blk = 0; |
889 |
block = add_zone2(znr, corrected); |
block = add_zone2(znr, corrected); |
890 |
if (!block) |
if (!block) |
891 |
return; |
return; |
892 |
read_block(block, blk); |
read_block(block, add_zone_tind_blk); |
893 |
for (i = 0; i < BLOCK_SIZE >> 2; i++) |
for (i = 0; i < BLOCK_SIZE >> 2; i++) |
894 |
add_zone_dind2(i + (uint32_t *) blk, &chg_blk); |
add_zone_dind2(i + (uint32_t *) add_zone_tind_blk, &chg_blk); |
895 |
if (chg_blk) |
if (chg_blk) |
896 |
write_block(block, blk); |
write_block(block, add_zone_tind_blk); |
897 |
} |
} |
898 |
#endif |
#endif |
899 |
|
|
937 |
|
|
938 |
static void check_file(struct minix1_inode *dir, unsigned offset) |
static void check_file(struct minix1_inode *dir, unsigned offset) |
939 |
{ |
{ |
|
static char blk[BLOCK_SIZE]; |
|
940 |
struct minix1_inode *inode; |
struct minix1_inode *inode; |
941 |
int ino; |
int ino; |
942 |
char *name; |
char *name; |
943 |
int block; |
int block; |
944 |
|
|
945 |
block = map_block(dir, offset / BLOCK_SIZE); |
block = map_block(dir, offset / BLOCK_SIZE); |
946 |
read_block(block, blk); |
read_block(block, check_file_blk); |
947 |
name = blk + (offset % BLOCK_SIZE) + 2; |
name = check_file_blk + (offset % BLOCK_SIZE) + 2; |
948 |
ino = *(uint16_t *) (name - 2); |
ino = *(uint16_t *) (name - 2); |
949 |
if (ino > INODES) { |
if (ino > INODES) { |
950 |
printf("%s contains a bad inode number for file '%.*s'. ", |
printf("%s contains a bad inode number for file '%.*s'. ", |
951 |
current_name, namelen, name); |
current_name, namelen, name); |
952 |
if (ask("Remove", 1)) { |
if (ask("Remove", 1)) { |
953 |
*(uint16_t *) (name - 2) = 0; |
*(uint16_t *) (name - 2) = 0; |
954 |
write_block(block, blk); |
write_block(block, check_file_blk); |
955 |
} |
} |
956 |
ino = 0; |
ino = 0; |
957 |
} |
} |
973 |
if (!inode) |
if (!inode) |
974 |
return; |
return; |
975 |
push_filename(name); |
push_filename(name); |
976 |
if (list) { |
if (OPT_list) { |
977 |
if (verbose) |
if (OPT_verbose) |
978 |
printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks); |
printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks); |
979 |
printf("%s%s\n", current_name, S_ISDIR(inode->i_mode) ? ":" : ""); |
printf("%s%s\n", current_name, S_ISDIR(inode->i_mode) ? ":" : ""); |
980 |
} |
} |
987 |
#if ENABLE_FEATURE_MINIX2 |
#if ENABLE_FEATURE_MINIX2 |
988 |
static void check_file2(struct minix2_inode *dir, unsigned offset) |
static void check_file2(struct minix2_inode *dir, unsigned offset) |
989 |
{ |
{ |
|
static char blk[BLOCK_SIZE]; |
|
990 |
struct minix2_inode *inode; |
struct minix2_inode *inode; |
991 |
int ino; |
int ino; |
992 |
char *name; |
char *name; |
993 |
int block; |
int block; |
994 |
|
|
995 |
block = map_block2(dir, offset / BLOCK_SIZE); |
block = map_block2(dir, offset / BLOCK_SIZE); |
996 |
read_block(block, blk); |
read_block(block, check_file_blk); |
997 |
name = blk + (offset % BLOCK_SIZE) + 2; |
name = check_file_blk + (offset % BLOCK_SIZE) + 2; |
998 |
ino = *(uint16_t *) (name - 2); |
ino = *(uint16_t *) (name - 2); |
999 |
if (ino > INODES) { |
if (ino > INODES) { |
1000 |
printf("%s contains a bad inode number for file '%.*s'. ", |
printf("%s contains a bad inode number for file '%.*s'. ", |
1001 |
current_name, namelen, name); |
current_name, namelen, name); |
1002 |
if (ask("Remove", 1)) { |
if (ask("Remove", 1)) { |
1003 |
*(uint16_t *) (name - 2) = 0; |
*(uint16_t *) (name - 2) = 0; |
1004 |
write_block(block, blk); |
write_block(block, check_file_blk); |
1005 |
} |
} |
1006 |
ino = 0; |
ino = 0; |
1007 |
} |
} |
1023 |
if (!inode) |
if (!inode) |
1024 |
return; |
return; |
1025 |
push_filename(name); |
push_filename(name); |
1026 |
if (list) { |
if (OPT_list) { |
1027 |
if (verbose) |
if (OPT_verbose) |
1028 |
printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks); |
printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks); |
1029 |
printf("%s%s\n", current_name, S_ISDIR(inode->i_mode) ? ":" : ""); |
printf("%s%s\n", current_name, S_ISDIR(inode->i_mode) ? ":" : ""); |
1030 |
} |
} |
1073 |
{ |
{ |
1074 |
char buffer[BLOCK_SIZE]; |
char buffer[BLOCK_SIZE]; |
1075 |
|
|
1076 |
if (BLOCK_SIZE * i != lseek(IN, BLOCK_SIZE * i, SEEK_SET)) |
xlseek(dev_fd, BLOCK_SIZE * i, SEEK_SET); |
1077 |
die("seek failed in bad_zone"); |
return (BLOCK_SIZE != full_read(dev_fd, buffer, BLOCK_SIZE)); |
|
return (BLOCK_SIZE != read(IN, buffer, BLOCK_SIZE)); |
|
1078 |
} |
} |
1079 |
|
|
1080 |
static void check_counts(void) |
static void check_counts(void) |
1082 |
int i; |
int i; |
1083 |
|
|
1084 |
for (i = 1; i <= INODES; i++) { |
for (i = 1; i <= INODES; i++) { |
1085 |
if (warn_mode && Inode1[i].i_mode && !inode_in_use(i)) { |
if (OPT_warn_mode && Inode1[i].i_mode && !inode_in_use(i)) { |
1086 |
printf("Inode %d has non-zero mode. ", i); |
printf("Inode %d has non-zero mode. ", i); |
1087 |
if (ask("Clear", 1)) { |
if (ask("Clear", 1)) { |
1088 |
Inode1[i].i_mode = 0; |
Inode1[i].i_mode = 0; |
1104 |
} |
} |
1105 |
if (Inode1[i].i_nlinks != inode_count[i]) { |
if (Inode1[i].i_nlinks != inode_count[i]) { |
1106 |
printf("Inode %d (mode=%07o), i_nlinks=%d, counted=%d. ", |
printf("Inode %d (mode=%07o), i_nlinks=%d, counted=%d. ", |
1107 |
i, Inode1[i].i_mode, Inode1[i].i_nlinks, inode_count[i]); |
i, Inode1[i].i_mode, Inode1[i].i_nlinks, |
1108 |
|
inode_count[i]); |
1109 |
if (ask("Set i_nlinks to count", 1)) { |
if (ask("Set i_nlinks to count", 1)) { |
1110 |
Inode1[i].i_nlinks = inode_count[i]; |
Inode1[i].i_nlinks = inode_count[i]; |
1111 |
changed = 1; |
changed = 1; |
1113 |
} |
} |
1114 |
} |
} |
1115 |
for (i = FIRSTZONE; i < ZONES; i++) { |
for (i = FIRSTZONE; i < ZONES; i++) { |
1116 |
if (zone_in_use(i) == zone_count[i]) |
if ((zone_in_use(i) != 0) == zone_count[i]) |
1117 |
continue; |
continue; |
1118 |
if (!zone_count[i]) { |
if (!zone_count[i]) { |
1119 |
if (bad_zone(i)) |
if (bad_zone(i)) |
1134 |
int i; |
int i; |
1135 |
|
|
1136 |
for (i = 1; i <= INODES; i++) { |
for (i = 1; i <= INODES; i++) { |
1137 |
if (warn_mode && Inode2[i].i_mode && !inode_in_use(i)) { |
if (OPT_warn_mode && Inode2[i].i_mode && !inode_in_use(i)) { |
1138 |
printf("Inode %d has non-zero mode. ", i); |
printf("Inode %d has non-zero mode. ", i); |
1139 |
if (ask("Clear", 1)) { |
if (ask("Clear", 1)) { |
1140 |
Inode2[i].i_mode = 0; |
Inode2[i].i_mode = 0; |
1156 |
} |
} |
1157 |
if (Inode2[i].i_nlinks != inode_count[i]) { |
if (Inode2[i].i_nlinks != inode_count[i]) { |
1158 |
printf("Inode %d (mode=%07o), i_nlinks=%d, counted=%d. ", |
printf("Inode %d (mode=%07o), i_nlinks=%d, counted=%d. ", |
1159 |
i, Inode2[i].i_mode, Inode2[i].i_nlinks, |
i, Inode2[i].i_mode, Inode2[i].i_nlinks, |
1160 |
inode_count[i]); |
inode_count[i]); |
1161 |
if (ask("Set i_nlinks to count", 1)) { |
if (ask("Set i_nlinks to count", 1)) { |
1162 |
Inode2[i].i_nlinks = inode_count[i]; |
Inode2[i].i_nlinks = inode_count[i]; |
1163 |
changed = 1; |
changed = 1; |
1165 |
} |
} |
1166 |
} |
} |
1167 |
for (i = FIRSTZONE; i < ZONES; i++) { |
for (i = FIRSTZONE; i < ZONES; i++) { |
1168 |
if (zone_in_use(i) == zone_count[i]) |
if ((zone_in_use(i) != 0) == zone_count[i]) |
1169 |
continue; |
continue; |
1170 |
if (!zone_count[i]) { |
if (!zone_count[i]) { |
1171 |
if (bad_zone(i)) |
if (bad_zone(i)) |
1203 |
void check2(void); |
void check2(void); |
1204 |
#endif |
#endif |
1205 |
|
|
1206 |
int fsck_minix_main(int argc, char **argv) |
int fsck_minix_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1207 |
|
int fsck_minix_main(int argc UNUSED_PARAM, char **argv) |
1208 |
{ |
{ |
1209 |
struct termios tmp; |
struct termios tmp; |
1210 |
int retcode = 0; |
int retcode = 0; |
1211 |
|
|
1212 |
xfunc_error_retval = 8; |
xfunc_error_retval = 8; |
1213 |
|
|
1214 |
alloc_current_name(); |
INIT_G(); |
|
#if ENABLE_FEATURE_CLEAN_UP |
|
|
/* Don't bother to free memory. Exit does |
|
|
* that automagically, so we can save a few bytes */ |
|
|
atexit(free_current_name); |
|
|
#endif |
|
1215 |
|
|
1216 |
if (INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE) |
opt_complementary = "=1:ar"; /* one argument; -a assumes -r */ |
1217 |
die("bad inode size"); |
getopt32(argv, OPTION_STR); |
1218 |
#if ENABLE_FEATURE_MINIX2 |
argv += optind; |
1219 |
if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) |
device_name = argv[0]; |
|
die("bad v2 inode size"); |
|
|
#endif |
|
|
while (--argc != 0) { |
|
|
argv++; |
|
|
if (argv[0][0] != '-') { |
|
|
if (device_name) |
|
|
bb_show_usage(); |
|
|
device_name = argv[0]; |
|
|
} else { |
|
|
while (*++argv[0]) { |
|
|
switch (argv[0][0]) { |
|
|
case 'l': |
|
|
list = 1; |
|
|
break; |
|
|
case 'a': |
|
|
automatic = 1; |
|
|
repair = 1; |
|
|
break; |
|
|
case 'r': |
|
|
automatic = 0; |
|
|
repair = 1; |
|
|
break; |
|
|
case 'v': |
|
|
verbose = 1; |
|
|
break; |
|
|
case 's': |
|
|
show = 1; |
|
|
break; |
|
|
case 'm': |
|
|
warn_mode = 1; |
|
|
break; |
|
|
case 'f': |
|
|
force = 1; |
|
|
break; |
|
|
default: |
|
|
bb_show_usage(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
if (!device_name) |
|
|
bb_show_usage(); |
|
1220 |
|
|
1221 |
check_mount(); /* trying to check a mounted filesystem? */ |
check_mount(); /* trying to check a mounted filesystem? */ |
1222 |
if (repair && !automatic) { |
if (OPT_manual) { |
1223 |
if (!isatty(0) || !isatty(1)) |
if (!isatty(0) || !isatty(1)) |
1224 |
die("need terminal for interactive repairs"); |
die("need terminal for interactive repairs"); |
1225 |
} |
} |
1226 |
IN = xopen(device_name, repair ? O_RDWR : O_RDONLY); |
xmove_fd(xopen(device_name, OPT_repair ? O_RDWR : O_RDONLY), dev_fd); |
1227 |
|
|
1228 |
/*sync(); paranoia? */ |
/*sync(); paranoia? */ |
1229 |
read_superblock(); |
read_superblock(); |
1234 |
* flags and whether or not the -f switch was specified on the |
* flags and whether or not the -f switch was specified on the |
1235 |
* command line. |
* command line. |
1236 |
*/ |
*/ |
1237 |
printf("%s, "PROGRAM_VERSION"\n", applet_name); |
printf("%s: %s\n", applet_name, bb_banner); |
1238 |
|
|
1239 |
if (!(Super.s_state & MINIX_ERROR_FS) |
if (!(Super.s_state & MINIX_ERROR_FS) |
1240 |
&& (Super.s_state & MINIX_VALID_FS) && !force |
&& (Super.s_state & MINIX_VALID_FS) && !OPT_force |
1241 |
) { |
) { |
1242 |
if (repair) |
if (OPT_repair) |
1243 |
printf("%s is clean, check is skipped\n", device_name); |
printf("%s is clean, check is skipped\n", device_name); |
1244 |
return 0; |
return 0; |
1245 |
} else if (force) |
} else if (OPT_force) |
1246 |
printf("Forcing filesystem check on %s\n", device_name); |
printf("Forcing filesystem check on %s\n", device_name); |
1247 |
else if (repair) |
else if (OPT_repair) |
1248 |
printf("Filesystem on %s is dirty, needs checking\n", |
printf("Filesystem on %s is dirty, needs checking\n", |
1249 |
device_name); |
device_name); |
1250 |
|
|
1251 |
read_tables(); |
read_tables(); |
1252 |
|
|
1253 |
if (repair && !automatic) { |
if (OPT_manual) { |
1254 |
tcgetattr(0, &termios); |
tcgetattr(0, &sv_termios); |
1255 |
tmp = termios; |
tmp = sv_termios; |
1256 |
tmp.c_lflag &= ~(ICANON | ECHO); |
tmp.c_lflag &= ~(ICANON | ECHO); |
1257 |
tcsetattr(0, TCSANOW, &tmp); |
tcsetattr_stdin_TCSANOW(&tmp); |
1258 |
termios_set = 1; |
termios_set = 1; |
1259 |
} |
} |
1260 |
|
|
1266 |
check(); |
check(); |
1267 |
} |
} |
1268 |
|
|
1269 |
if (verbose) { |
if (OPT_verbose) { |
1270 |
int i, free_cnt; |
int i, free_cnt; |
1271 |
|
|
1272 |
for (i = 1, free_cnt = 0; i <= INODES; i++) |
for (i = 1, free_cnt = 0; i <= INODES; i++) |
1295 |
write_tables(); |
write_tables(); |
1296 |
printf("FILE SYSTEM HAS BEEN CHANGED\n"); |
printf("FILE SYSTEM HAS BEEN CHANGED\n"); |
1297 |
sync(); |
sync(); |
1298 |
} else if (repair) |
} else if (OPT_repair) |
1299 |
write_super_block(); |
write_superblock(); |
1300 |
|
|
1301 |
if (repair && !automatic) |
if (OPT_manual) |
1302 |
tcsetattr(0, TCSANOW, &termios); |
tcsetattr_stdin_TCSANOW(&sv_termios); |
1303 |
|
|
1304 |
if (changed) |
if (changed) |
1305 |
retcode += 3; |
retcode += 3; |