/* * 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 #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)") : "??");*/ } }