📄 node_formats.c
字号:
switch (get_type (&ih->ih_key)) { case TYPE_DIRECT: return get_ih_item_len (ih); case TYPE_INDIRECT: return I_UNFM_NUM(ih) * blocksize;// - get_ih_free_space (ih); case TYPE_STAT_DATA: case TYPE_DIRENTRY: return 0; } reiserfs_warning (stderr, "get_bytes_number: called for wrong type of item %h", ih); return 0;}int check_item_f (reiserfs_filsys_t * fs, struct item_head * ih, char * item);/* ih_key, ih_location and ih_item_len seem correct, check other fields */static int does_ih_look_correct (struct item_head * ih){ int ih_key_format; int key_key_format; /* key format from item_head */ ih_key_format = get_ih_key_format (ih); if (ih_key_format != KEY_FORMAT_1 && ih_key_format != KEY_FORMAT_2) return 0; /* key format calculated on key */ key_key_format = key_format (&ih->ih_key); if (is_stat_data_ih (ih)) { /* for stat data we can not find key format from a key itself, so look at the item length */ if (get_ih_item_len (ih) == SD_SIZE) key_key_format = KEY_FORMAT_2; else if (get_ih_item_len (ih) == SD_V1_SIZE) key_key_format = KEY_FORMAT_1; else return 0; } if (key_key_format != ih_key_format) return 0; /* we do not check ih_format.fsck_need as fsck might change it. So, debugreiserfs -p will have to dump it */ return 1;}/* check item length, ih_free_space for pure 3.5 format, unformatted node pointers */static int is_bad_indirect (reiserfs_filsys_t * fs, struct item_head * ih, char * item, check_unfm_func_t check_unfm_func){ unsigned int i; __u32 * ind = (__u32 *)item; if (get_ih_item_len (ih) % UNFM_P_SIZE) return 1; for (i = 0; i < I_UNFM_NUM (ih); i ++) { if (!ind [i]) continue; if (check_unfm_func && check_unfm_func (fs, d32_get (ind, i))) return 1; } if (fs->fs_format == REISERFS_FORMAT_3_5) { /* check ih_free_space for 3.5 format only */ if (get_ih_free_space (ih) > fs->fs_blocksize - 1) return 1; } return 0;}static const struct { hashf_t func; char * name;} hashes[] = {{0, "not set"}, {keyed_hash, "\"tea\""}, {yura_hash, "\"rupasov\""}, {r5_hash, "\"r5\""}}; #define HASH_AMOUNT (sizeof (hashes) / sizeof (hashes [0]))int known_hashes (void){ return HASH_AMOUNT;}#define good_name(hashfn,name,namelen,deh_offset) \(hash_value (hashfn, name, namelen) == GET_HASH_VALUE (deh_offset))/* this also sets hash function */int is_properly_hashed (reiserfs_filsys_t * fs, char * name, int namelen, __u32 offset){ unsigned int i; if (namelen == 1 && name[0] == '.') { if (offset == DOT_OFFSET) return 1; return 0; } if (namelen == 2 && name[0] == '.' && name[1] == '.') { if (offset == DOT_DOT_OFFSET) return 1; return 0; } if (hash_func_is_unknown (fs)) { /* try to find what hash function the name is sorted with */ for (i = 1; i < HASH_AMOUNT; i ++) { if (good_name (hashes [i].func, name, namelen, offset)) { if (!hash_func_is_unknown (fs)) { /* two or more hash functions give the same value for this name */ fprintf (stderr, "Detecting hash code: could not detect hash with name \"%.*s\"\n", namelen, name); reiserfs_hash (fs) = 0; return 1; } /* set hash function */ reiserfs_hash(fs) = hashes [i].func; } } if (hash_func_is_unknown (fs)) { return 0; } } if (good_name (reiserfs_hash(fs), name, namelen, offset)) return 1; return 0;}int find_hash_in_use (char * name, int namelen, __u32 offset, unsigned int code_to_try_first){ unsigned int i; if (!namelen || !name[0]) return UNSET_HASH; if (code_to_try_first) { if (good_name (hashes [code_to_try_first].func, name, namelen, offset)) return code_to_try_first; } for (i = 1; i < HASH_AMOUNT; i ++) { if (i == code_to_try_first) continue; if (good_name (hashes [i].func, name, namelen, offset)) return i; } /* not matching hash found */ return UNSET_HASH;}char * code2name(unsigned int code) { if (code >= HASH_AMOUNT || code < 0) return 0; return hashes [code].name;}int func2code (hashf_t func){ unsigned int i; for (i = 0; i < HASH_AMOUNT; i ++) if (func == hashes [i].func) return i; reiserfs_panic ("func2code: no hashes matches this function\n"); return 0;}hashf_t code2func(unsigned int code) { if (code >= HASH_AMOUNT) { reiserfs_warning (stderr, "code2func: wrong hash code %d.\n" "Using default %s hash function\n", code, code2name (DEFAULT_HASH)); code = DEFAULT_HASH; } return hashes [code].func;}hashf_t name2func (char * hash) { unsigned int i; for (i = 0; i < HASH_AMOUNT; i ++) if (!strcmp (hash, hashes [i].name)) return hashes [i].func; return 0;}int dir_entry_bad_location (struct reiserfs_de_head * deh, struct item_head * ih, int first){ if (get_deh_location (deh) < DEH_SIZE * get_ih_entry_count (ih)) return 1; if (get_deh_location (deh) >= get_ih_item_len (ih)) return 1; if (!first && get_deh_location (deh) >= get_deh_location (deh - 1)) return 1; return 0;}/* the only corruption which is not considered fatal - is hash mismatching. If bad_dir is set - directory item having such names is considered bad */static int is_bad_directory (reiserfs_filsys_t * fs, struct item_head * ih, char * item, int bad_dir){ int i; int namelen; struct reiserfs_de_head * deh = (struct reiserfs_de_head *)item; __u32 prev_offset = 0; __u16 prev_location = get_ih_item_len (ih); for (i = 0; i < get_ih_entry_count (ih); i ++, deh ++) { if (get_deh_location (deh) >= prev_location) return 1; prev_location = get_deh_location (deh); namelen = name_in_entry_length (ih, deh, i); if (namelen > (int)REISERFS_MAX_NAME_LEN(fs->fs_blocksize)) return 1; if (get_deh_offset (deh) <= prev_offset) return 1; prev_offset = get_deh_offset (deh); /* check hash value */ if (!is_properly_hashed (fs, 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;}/* used by debugreisrefs -p only yet */int is_it_bad_item (reiserfs_filsys_t * fs, struct item_head * ih, char * item, check_unfm_func_t check_unfm, int bad_dir){ int retval;/* if (!does_key_look_correct (fs, &ih->ih_key)) return 1; if (!does_ih_look_correct (ih)) return 1;*/ if (!does_ih_look_correct (ih)) return 1; if (is_stat_data_ih (ih) || is_direct_ih (ih)) return 0; if (is_direntry_ih (ih)) { retval = is_bad_directory (fs, ih, item, bad_dir); /* if (retval) reiserfs_warning (stderr, "is_bad_directory %H\n", ih);*/ return retval; } if (is_indirect_ih (ih)) { retval = is_bad_indirect (fs, ih, item, check_unfm); /* if (retval) reiserfs_warning (stderr, "is_bad_indirect %H\n", ih);*/ return retval; } return 1;}/* prepare new or old stat data for the new directory */void make_dir_stat_data (int blocksize, int key_format, __u32 dirid, __u32 objectid, struct item_head * ih, void * sd){ memset (ih, 0, IH_SIZE); set_key_dirid (&ih->ih_key, dirid); set_key_objectid (&ih->ih_key, objectid); set_key_offset_v1 (&ih->ih_key, SD_OFFSET); set_key_uniqueness (&ih->ih_key, 0); set_ih_key_format (ih, key_format); set_ih_free_space (ih, MAX_US_INT); if (key_format == KEY_FORMAT_2) { struct stat_data *sd_v2 = (struct stat_data *)sd; set_ih_item_len (ih, SD_SIZE); set_sd_v2_mode (sd_v2, S_IFDIR + 0755); set_sd_v2_nlink (sd_v2, 2); set_sd_v2_uid (sd_v2, 0); set_sd_v2_gid (sd_v2, 0); set_sd_v2_size (sd_v2, EMPTY_DIR_SIZE); set_sd_v2_atime (sd_v2, time(NULL)); sd_v2->sd_ctime = sd_v2->sd_mtime = sd_v2->sd_atime; /* all le */ set_sd_v2_rdev (sd_v2, 0); set_sd_v2_blocks (sd_v2, dir_size2st_blocks (EMPTY_DIR_SIZE)); }else{ struct stat_data_v1 *sd_v1 = (struct stat_data_v1 *)sd; set_ih_item_len (ih, SD_V1_SIZE); set_sd_v1_mode(sd_v1, S_IFDIR + 0755); set_sd_v1_nlink(sd_v1, 2); set_sd_v1_uid (sd_v1, 0); set_sd_v1_gid (sd_v1, 0); set_sd_v1_size(sd_v1, EMPTY_DIR_SIZE_V1); set_sd_v1_atime(sd_v1, time(NULL)); sd_v1->sd_ctime = sd_v1->sd_mtime = sd_v1->sd_atime; /* all le */ set_sd_v1_blocks(sd_v1, dir_size2st_blocks(EMPTY_DIR_SIZE_V1)); set_sd_v1_first_direct_byte(sd_v1, NO_BYTES_IN_DIRECT_ITEM); }}static void _empty_dir_item (int format, char * body, __u32 dirid, __u32 objid, __u32 par_dirid, __u32 par_objid){ struct reiserfs_de_head * deh; __u16 state; memset (body, 0, (format == KEY_FORMAT_2 ? EMPTY_DIR_SIZE : EMPTY_DIR_SIZE_V1)); deh = (struct reiserfs_de_head *)body; /* direntry header of "." */ set_deh_offset (deh, DOT_OFFSET); set_deh_dirid (deh, dirid); set_deh_objectid (deh, objid); state = (1 << DEH_Visible2); set_deh_state (deh, state); /* direntry header of ".." */ set_deh_offset (deh + 1, DOT_DOT_OFFSET); /* key of ".." for the root directory */ set_deh_dirid (deh + 1, par_dirid); set_deh_objectid (deh + 1, par_objid); set_deh_state (deh + 1, state); if (format == KEY_FORMAT_2) { set_deh_location (deh, EMPTY_DIR_SIZE - ROUND_UP (strlen ("."))); set_deh_location (deh + 1, get_deh_location (deh) - ROUND_UP (strlen (".."))); } else { set_deh_location (deh, EMPTY_DIR_SIZE_V1 - strlen (".")); set_deh_location (deh + 1, get_deh_location (deh) - strlen ("..")); } /* copy ".." and "." */ memcpy (body + get_deh_location (deh), ".", 1); memcpy (body + get_deh_location (deh + 1), "..", 2); }void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid, __u32 par_dirid, __u32 par_objid){ _empty_dir_item (KEY_FORMAT_1, body, dirid, objid, par_dirid, par_objid);}void make_empty_dir_item (char * body, __u32 dirid, __u32 objid, __u32 par_dirid, __u32 par_objid){ _empty_dir_item (KEY_FORMAT_2, body, dirid, objid, par_dirid, par_objid);}/* for every item call common action and an action corresponding to item type */void for_every_item (struct buffer_head * bh, item_head_action_t action, item_action_t * actions){ int i; struct item_head * ih; item_action_t iaction; ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) { if (action) action (ih); iaction = actions[get_type (&ih->ih_key)]; if (iaction) iaction (bh, ih); }}#if __BYTE_ORDER == __LITTLE_ENDIAN# define get_key_offset_v2(key) (__u64)((key->u.k2_offset_v2.k_offset))# define set_key_offset_v2(key,val) (void)(key->u.k2_offset_v2.k_offset = (val))# define get_key_type_v2(key) (__u16)((key->u.k2_offset_v2.k_type))# define set_key_type_v2(key,val) (void)(key->u.k2_offset_v2.k_type = (val))#elif __BYTE_ORDER == __BIG_ENDIANtypedef union { struct offset_v2 offset_v2; __u64 linear;} __attribute__ ((__packed__)) offset_v2_esafe_overlay;static inline __u64 get_key_offset_v2 (const struct key *key){ offset_v2_esafe_overlay tmp = *(offset_v2_esafe_overlay *) (&(key->u.k2_offset_v2)); tmp.linear = le64_to_cpu( tmp.linear );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -