17 * - check hash table index
18 * - clear extents from free bitmap and make sure free bitmap is null
19 * - sanity check block size, sys block size, mirrors, etc
20 * - check that extent count is valid
21 * - check that terminator matches
22 * - make sure file sizes match up
25 int check_crc(u8
*blk
)
28 size_t hdr_size
= sizeof(struct omfs_header
);
29 struct omfs_inode
*oi
;
31 oi
= (struct omfs_inode
*) blk
;
33 crc
= crc_ccitt_msb(0, blk
+ hdr_size
,
34 swap_be32(oi
->head
.body_size
));
36 return (crc
== swap_be16(oi
->head
.crc
));
39 int check_header(u8
*blk
)
43 struct omfs_inode
*oi
;
45 oi
= (struct omfs_inode
*) blk
;
48 for (i
= 1; i
< OMFS_XOR_COUNT
; i
++)
51 return (xor == oi
->head
.check_xor
);
54 int check_sanity(check_context_t
*ctx
)
56 omfs_inode_t
*inode
= ctx
->current_inode
;
57 if (swap_be32(inode
->head
.body_size
) >
58 swap_be32(ctx
->omfs_info
->super
->sys_blocksize
))
61 // check device size here too.
65 int check_bitmap(check_context_t
*ctx
)
70 omfs_super_t
*super
= ctx
->omfs_info
->super
;
71 omfs_root_t
*root
= ctx
->omfs_info
->root
;
76 bsize
= (swap_be64(super
->num_blocks
) + 7) / 8;
77 first_blk
= swap_be64(root
->bitmap
) + (bsize
+
78 swap_be32(super
->blocksize
)-1) / swap_be32(super
->blocksize
);
80 for (i
=0; i
< first_blk
; i
++)
81 set_bit(ctx
->visited
, i
);
83 for (i
=0; i
< bsize
; i
++)
85 if (ctx
->bitmap
[i
] != ctx
->visited
[i
])
88 printf("Wrong bitmap byte at %d (%02x, %02x)\n", i
,
89 ctx
->bitmap
[i
], ctx
->visited
[i
]);
94 fix_problem(E_BITMAP
, ctx
);
99 void visit_extents(check_context_t
*ctx
)
101 struct omfs_extent
*oe
;
102 struct omfs_extent_entry
*entry
;
108 buf
= omfs_get_block(ctx
->omfs_info
->dev
,
109 ctx
->omfs_info
->super
, next
);
113 oe
= (struct omfs_extent
*) &buf
[OMFS_EXTENT_START
];
117 extent_count
= swap_be32(oe
->extent_count
);
119 next
= swap_be64(oe
->next
);
122 // ignore last entry as it is the terminator
123 for (; extent_count
> 1; extent_count
--)
125 u64 start
= swap_be64(entry
->cluster
);
127 for (i
=0; i
<swap_be64(entry
->blocks
); i
++)
128 set_bit(ctx
->visited
, start
+ i
);
133 set_bit(ctx
->visited
, last
);
134 set_bit(ctx
->visited
, last
+1);
140 buf
= omfs_get_block(ctx
->omfs_info
->dev
,
141 ctx
->omfs_info
->super
, next
);
144 oe
= (struct omfs_extent
*) &buf
[OMFS_EXTENT_CONT
];
151 int check_inode(check_context_t
*ctx
)
155 omfs_inode_t
*inode
= ctx
->current_inode
;
157 if (test_bit(ctx
->visited
, ctx
->block
))
159 fix_problem(E_LOOP
, ctx
);
162 for (i
=0; i
< swap_be32(ctx
->omfs_info
->super
->mirrors
); i
++)
163 set_bit(ctx
->visited
, ctx
->block
+ i
);
165 if (!check_sanity(ctx
))
167 fix_problem(E_INSANE
, ctx
);
170 if (!check_header((u8
*)inode
))
172 fix_problem(E_HEADER_XOR
, ctx
);
174 if (!check_crc((u8
*)inode
))
176 fix_problem(E_HEADER_CRC
, ctx
);
178 if (swap_be64(inode
->head
.self
) != ctx
->block
)
180 fix_problem(E_SELF_PTR
, ctx
);
183 if (swap_be64(inode
->parent
) != ctx
->parent
)
185 fix_problem(E_PARENT_PTR
, ctx
);
188 if (omfs_compute_hash(ctx
->omfs_info
, inode
->name
) != ctx
->hash
)
190 fix_problem(E_HASH_WRONG
, ctx
);
193 if (inode
->type
== OMFS_FILE
)
201 static int on_node(dirscan_t
*d
, dirscan_entry_t
*entry
, void *user
)
203 char *name
= escape(entry
->inode
->name
);
204 check_context_t
*ctx
= (check_context_t
*) user
;
206 printf("inode: %*c%s%c %llx %d %d %llx %llx\n",
207 entry
->level
*2, ' ', name
,
208 (entry
->inode
->type
== OMFS_DIR
) ? '/' : ' ',
209 swap_be64(entry
->inode
->head
.self
), entry
->hindex
,
210 swap_be16(entry
->inode
->head
.crc
),
211 entry
->parent
, entry
->block
);
214 ctx
->current_inode
= entry
->inode
;
215 ctx
->block
= entry
->block
;
216 ctx
->parent
= entry
->parent
;
217 ctx
->hash
= entry
->hindex
;
223 int check_fs(FILE *fp
)
235 if (omfs_read_super(fp
, &super
))
237 fix_problem(E_READ_SUPER
, 0);
240 if (omfs_read_root_block(fp
, &super
, &root
))
242 fix_problem(E_READ_ROOT
, 0);
246 ctx
.omfs_info
= &info
;
247 ctx
.bitmap
= omfs_get_bitmap(&info
);
248 bsize
= (swap_be64(info
.super
->num_blocks
) + 7) / 8;
249 ctx
.visited
= calloc(1, bsize
);
251 if (dirscan_begin(&info
, on_node
, &ctx
) != 0)
253 fix_problem(E_SCAN
, 0);