167 lines
4.7 KiB
C
167 lines
4.7 KiB
C
/*
|
|
* Copyright 2000-2004 by Hans Reiser, licensing governed by
|
|
* reiserfsprogs/README
|
|
*/
|
|
|
|
/* length of the directory entry in directory item. This define calculates
|
|
length of i-th directory entry using directory entry locations from dir
|
|
entry head. When it calculates length of 0-th directory entry, it uses
|
|
length of whole item in place of entry location of the non-existent
|
|
following entry in the calculation. See picture above.*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include "reiserfs/libreiserfs.h"
|
|
|
|
// NOTE: this is not name length. This is length of whole entry
|
|
int reiserfs_direntry_entry_len (reiserfs_ih_t * ih,
|
|
reiserfs_deh_t * deh,
|
|
int pos_in_item)
|
|
{
|
|
if (pos_in_item)
|
|
return (reiserfs_deh_get_loc (deh - 1) - reiserfs_deh_get_loc (deh));
|
|
return (reiserfs_ih_get_len (ih) - reiserfs_deh_get_loc (deh));
|
|
}
|
|
|
|
|
|
int reiserfs_direntry_name_len (reiserfs_ih_t * ih,
|
|
reiserfs_deh_t * deh,
|
|
int pos_in_item)
|
|
{
|
|
int len, i;
|
|
char * name;
|
|
|
|
len = reiserfs_direntry_entry_len (ih, deh, pos_in_item);
|
|
name = reiserfs_deh_name (deh, pos_in_item);
|
|
|
|
// name might be padded with 0s
|
|
i = 0;
|
|
while (name[i] && i < len)
|
|
i++;
|
|
|
|
return i;
|
|
}
|
|
|
|
int reiserfs_direntry_entry_estimate (char * name, int key_format) {
|
|
if (key_format == KEY_FORMAT_2)
|
|
return MISC_ROUND_UP (strlen(name));
|
|
else if (key_format == KEY_FORMAT_1)
|
|
return strlen(name);
|
|
|
|
return -1;
|
|
}
|
|
|
|
/* the only corruption which is not considered fatal - is hash mismatching. If
|
|
bad_dir is set - directory item having such names is considered bad */
|
|
int reiserfs_direntry_check (reiserfs_filsys_t * fs,
|
|
reiserfs_ih_t * ih,
|
|
char * item,
|
|
int bad_dir)
|
|
{
|
|
int i;
|
|
int namelen;
|
|
reiserfs_deh_t * deh = (reiserfs_deh_t *)item;
|
|
__u32 prev_offset = 0;
|
|
__u16 prev_location = reiserfs_ih_get_len (ih);
|
|
|
|
for (i = 0; i < reiserfs_ih_get_entries (ih); i ++, deh ++) {
|
|
if (reiserfs_deh_get_loc (deh) >= prev_location)
|
|
return 1;
|
|
prev_location = reiserfs_deh_get_loc (deh);
|
|
|
|
namelen = reiserfs_direntry_name_len (ih, deh, i);
|
|
if (namelen > REISERFS_NAME_MAX)
|
|
return 1;
|
|
|
|
if (reiserfs_deh_get_off (deh) <= prev_offset)
|
|
return 1;
|
|
prev_offset = reiserfs_deh_get_off (deh);
|
|
|
|
/* check hash value */
|
|
if (!reiserfs_hash_correct (&fs->hash,
|
|
item + prev_location,
|
|
namelen, prev_offset))
|
|
{
|
|
if (bad_dir)
|
|
/* make is_bad_leaf to not insert whole leaf. Node will be
|
|
marked not-insertable and put into tree item by item in
|
|
pass 2 */
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int reiserfs_direntry_loc_check (reiserfs_deh_t * deh,
|
|
reiserfs_ih_t * ih,
|
|
int first)
|
|
{
|
|
if (reiserfs_deh_get_loc (deh) <
|
|
REISERFS_DEH_SIZE * reiserfs_ih_get_entries (ih))
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (reiserfs_deh_get_loc (deh) >= reiserfs_ih_get_len (ih))
|
|
return 1;
|
|
|
|
if (!first) {
|
|
if (reiserfs_deh_get_loc (deh) >= reiserfs_deh_get_loc (deh - 1))
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void reiserfs_direntry_print (FILE * fp, reiserfs_filsys_t * fs,
|
|
reiserfs_bh_t * bh, reiserfs_ih_t * ih)
|
|
{
|
|
int i;
|
|
int namelen;
|
|
reiserfs_deh_t * deh;
|
|
char * name;
|
|
/* static char namebuf [80];*/
|
|
|
|
if (!reiserfs_ih_dir (ih))
|
|
return;
|
|
|
|
/*printk ("\n%2%-25s%-30s%-15s%-15s%-15s\n", " Name", "length",
|
|
"Object key", "Hash", "Gen number", "Status"); */
|
|
|
|
reiserfs_warning (fp, "%3s: %-25s%s%-22s%-12s%s\n", "###", "Name",
|
|
"length", " Object key", " Hash", "Gen number");
|
|
|
|
deh = reiserfs_deh (bh, ih);
|
|
for (i = 0; i < reiserfs_ih_get_entries (ih); i ++, deh ++) {
|
|
if (reiserfs_direntry_loc_check (deh, ih, i == 0 ? 1 : 0)) {
|
|
reiserfs_warning (fp, "%3d: wrong entry location %u, deh_offset %u\n",
|
|
i, reiserfs_deh_get_loc (deh), reiserfs_deh_get_off (deh));
|
|
continue;
|
|
}
|
|
if (i && reiserfs_direntry_loc_check (deh - 1, ih, ((i - 1) == 0) ? 1 : 0))
|
|
/* previous entry has bad location so we can not calculate entry
|
|
length */
|
|
namelen = 25;
|
|
else
|
|
namelen = reiserfs_direntry_name_len (ih, deh, i);
|
|
|
|
name = reiserfs_deh_name (deh, i);
|
|
reiserfs_warning (fp, "%3d: \"%-25.*s\"(%3d)%20K%12d%5d, loc %u, "
|
|
"state %x %s\n", i, namelen, name, namelen,
|
|
(reiserfs_key_t *)&(deh->deh2_dir_id),
|
|
OFFSET_HASH (reiserfs_deh_get_off (deh)),
|
|
OFFSET_GEN (reiserfs_deh_get_off (deh)),
|
|
reiserfs_deh_get_loc (deh), reiserfs_deh_get_state (deh),
|
|
reiserfs_hash_name (reiserfs_hash_find (
|
|
name, namelen, reiserfs_deh_get_off (deh),
|
|
fs ? reiserfs_sb_get_hash (fs->fs_ondisk_sb) :
|
|
UNSET_HASH)));
|
|
|
|
/*fs ? (reiserfs_hash_correct (&fs->hash, name,
|
|
namelen, deh_offset (deh)) ? "" : "(BROKEN)") : "??");*/
|
|
}
|
|
}
|