blob: b6c4092f5ece7eee8f0a66e653d3b5015f8efdd6 [file]
/*
* 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)") : "??");*/
}
}