📄 fsckdtre.c
字号:
/* * Copyright (C) International Business Machines Corp., 2000-2004 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <config.h>#include <string.h>/* defines and includes common among the fsck.jfs modules */#include "xfsckint.h"/* * for inline unicode functions */#include "jfs_byteorder.h"#include "jfs_unicode.h"#include "jfs_filsys.h"#include "devices.h"#include "unicode_to_utf8.h"/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */extern struct superblock *sb_ptr;/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */extern struct fsck_agg_record *agg_recptr;/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For directory entry processing * * defined in xchkdsk.c */extern uint32_t key_len[2];extern UniChar key[2][JFS_NAME_MAX];extern UniChar ukey[2][JFS_NAME_MAX];extern int32_t Uni_Name_len;extern UniChar Uni_Name[JFS_NAME_MAX];/* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */#define LEFT_KEY_LOWER -1#define KEYS_MATCH 0#define LEFT_KEY_HIGHER 1struct fsck_Dtree_info { dtroot_t *dtr_ptr; dtpage_t *dtp_ptr; pxd_t *pxd_ptr; int8_t *dtstbl; int16_t last_dtidx; int16_t freelist_first_dtidx; int16_t freelist_count; struct dtslot *slots; int8_t slot_map[DTPAGEMAXSLOT]; int64_t ext_addr; uint32_t ext_length; struct dtreeQelem *this_Qel; struct dtreeQelem *next_Qel; int64_t last_node_addr; int8_t last_level; int8_t leaf_level; int8_t leaf_seen; int16_t max_slotidx; int16_t this_key_idx; int16_t last_key_idx; uint32_t key_len[2]; UniChar key[2][JFS_NAME_MAX];};int direntry_get_objnam_node(uint32_t, int8_t *, struct dtslot *, int, int *, UniChar *, int8_t *);int dTree_binsrch_internal_page(struct fsck_Dtree_info *, UniChar *, uint32_t, int8_t, int8_t *, int8_t *, int8_t *, struct fsck_inode_record *);int dTree_binsrch_leaf(struct fsck_Dtree_info *, UniChar *, uint32_t, int8_t, int8_t *, int8_t *, int8_t *, int8_t *, struct fsck_inode_record *);int dTree_key_compare(UniChar *, uint8_t, UniChar *, uint8_t, int *);int dTree_key_compare_leaflvl(UniChar *, uint8_t, UniChar *, uint8_t, int8_t *);int dTree_key_compare_prntchld(struct fsck_Dtree_info *, UniChar *, uint8_t, UniChar *, uint8_t, int8_t *);int dTree_key_compare_samelvl(UniChar *, uint8_t, UniChar *, uint8_t, int8_t *);int dTree_key_extract(struct fsck_Dtree_info *, int, UniChar *, uint32_t *, int8_t, int8_t, struct fsck_inode_record *);int dTree_key_extract_cautiously(struct fsck_Dtree_info *, int, UniChar *, uint32_t *, int8_t, int8_t, struct fsck_inode_record *);int dTree_key_extract_record(struct fsck_Dtree_info *, int, UniChar *, uint32_t *, int8_t, int8_t, struct fsck_inode_record *);int dTree_key_to_upper(UniChar *, UniChar *, int32_t);int dTree_node_first_key(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int);int dTree_node_first_in_level(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int);int dTree_node_last_in_level(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int);int dTree_node_not_first_in_level(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int);int dTree_node_not_last_in_level(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int);int dTree_node_size_check(struct fsck_Dtree_info *, int8_t, int8_t, int8_t, struct fsck_inode_record *, struct fsck_ino_msg_info *, int);int dTree_process_internal_slots(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int);int dTree_process_leaf_slots(struct fsck_Dtree_info *, struct fsck_inode_record *, struct dinode *, struct fsck_ino_msg_info *, int);int dTree_verify_slot_freelist(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int);int process_valid_dir_node(int8_t *, struct dtslot *, int, struct fsck_inode_record *, struct fsck_ino_msg_info *, int);/* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV *//***************************************************************************** * NAME: direntry_add * * FUNCTION: Add an entry to a directory. * * PARAMETERS: * parent_inoptr - input - pointer to the directory inode, in an * fsck buffer, to which the entry should * be added. * child_inonum - input - inode number to put in the new directory * entry. * child_name - input - pointer to the file name to put in the * new directory entry. * * RETURNS: * success: FSCK_OK * failure: something else */int direntry_add(struct dinode *parent_inoptr, uint32_t child_inonum, UniChar * child_name){ int ad_rc = FSCK_OK; struct component_name uniname_struct; uniname_struct.namlen = UniStrlen(child_name); uniname_struct.name = child_name; ad_rc = fsck_dtInsert(parent_inoptr, &uniname_struct, &child_inonum); if (ad_rc == FSCK_OK) { ad_rc = inode_put(parent_inoptr); } else { if (ad_rc < 0) { fsck_send_msg(fsck_INTERNALERROR, FSCK_INTERNAL_ERROR_60, ad_rc, child_inonum, parent_inoptr->di_number); ad_rc = FSCK_INTERNAL_ERROR_60; } else { if (ad_rc == FSCK_BLKSNOTAVAILABLE) { fsck_send_msg(fsck_CANTRECONINSUFSTG, 3); } } } return (ad_rc);}/***************************************************************************** * NAME: direntry_get_inonum * * FUNCTION: Get the inode number for the file whose name is given. * * PARAMETERS: * parent_inonum - input - the inode number of a directory containing * an entry for the inode whose name is * desired. * obj_name_length - input - the length of the file name in mixed case * obj_name - input - pointer to the file name in mixed case * obj_NAME_length - input - the length of the file name in upper case * obj_NAME - input - pointer to the file name in upper case * found_inonum - input - pointer to a variable in which to return * the inode number stored in the (found) entry * * NOTES: A case insensitive search is conducted. * * RETURNS: * success: FSCK_OK * failure: something else */int direntry_get_inonum(uint32_t parent_inonum, int obj_name_length, UniChar * obj_name, int obj_NAME_length, UniChar * obj_NAME, uint32_t * found_inonum){ int gdi_rc = FSCK_OK; struct dinode *root_inoptr; int is_aggregate = 0; int alloc_ifnull = 0; int which_table = FILESYSTEM_I; struct dtslot *slot_ptr; int8_t entry_found; struct fsck_inode_record *root_inorecptr; gdi_rc = inode_get(is_aggregate, which_table, ROOT_I, &root_inoptr); if (gdi_rc == FSCK_OK) { /* got the root inode */ gdi_rc = get_inorecptr(is_aggregate, alloc_ifnull, ROOT_I, &root_inorecptr); if ((gdi_rc == FSCK_OK) && (root_inorecptr == NULL)) { gdi_rc = FSCK_INTERNAL_ERROR_46; } else if (gdi_rc == FSCK_OK) { gdi_rc = dTree_search(root_inoptr, obj_name, obj_name_length, obj_NAME, obj_NAME_length, &slot_ptr, &entry_found, root_inorecptr); } if ((gdi_rc == FSCK_OK) && (entry_found)) { *found_inonum = ((struct ldtentry *) slot_ptr)->inumber; } } return (gdi_rc);}/***************************************************************************** * NAME: direntry_get_objnam * * FUNCTION: Find the file name for the given inode number in the given * directory inode. * * PARAMETERS: * parent_inonum - input - the inode number of the directory * containing an entry for the object * obj_inonum - input - the inode number of the object for * which the file name is desired * found_name_length - input - pointer to a variable in which to return * the length of the object name * found_name - input - pointer to a buffer in which to return * the object name * * RETURNS: * success: FSCK_OK * failure: something else */int direntry_get_objnam(uint32_t parent_inonum, uint32_t obj_inonum, int *found_name_length, UniChar * found_name){ int dgon_rc = FSCK_OK; int is_aggregate = 0; int which_it = FILESYSTEM_I; /* in release 1 there's exactly 1 fileset */ uint32_t parent_inoidx; struct dinode *parent_inoptr; dtpage_t *leaf_ptr; int64_t leaf_offset; int8_t dir_inline; int8_t dir_rootleaf; dtroot_t *dtroot_ptr; int8_t *dtstbl; struct dtslot *slots; int last_dtidx; int8_t entry_found; /* assume no match will be found */ *found_name_length = 0; parent_inoidx = (uint32_t) parent_inonum; dgon_rc = inode_get(is_aggregate, which_it, parent_inoidx, &parent_inoptr); if (dgon_rc != FSCK_OK) { /* but we read it before! */ /* this is fatal */ dgon_rc = FSCK_FAILED_CANTREAD_DIRNOW; } else { /* got the parent inode */ dgon_rc = find_first_dir_leaf(parent_inoptr, &leaf_ptr, &leaf_offset, &dir_inline, &dir_rootleaf); if (dgon_rc != FSCK_OK) { /* we already verified the dir! */ dgon_rc = FSCK_FAILED_DIRGONEBAD; } else { /* we found and read the first leaf */ if (dir_rootleaf) { /* rootleaf directory tree */ dtroot_ptr = (dtroot_t *) & (parent_inoptr->di_btroot); dtstbl = (int8_t *) & (dtroot_ptr->header.stbl[0]); slots = &(dtroot_ptr->slot[0]); last_dtidx = dtroot_ptr->header.nextindex - 1; dgon_rc = direntry_get_objnam_node(obj_inonum, dtstbl, slots, last_dtidx, found_name_length, found_name, &entry_found); } else { /* it's a separate node and probably first in a chain */ /* try the first leaf */ dtstbl = (int8_t *) & (leaf_ptr-> slot[leaf_ptr->header. stblindex]); slots = &(leaf_ptr->slot[0]); last_dtidx = leaf_ptr->header.nextindex - 1; dgon_rc = direntry_get_objnam_node(obj_inonum, dtstbl, slots, last_dtidx, found_name_length, found_name, &entry_found); /* try the remaining leaves */ while ((dgon_rc == FSCK_OK) && (!entry_found) && (leaf_ptr->header.next != 0)) { dgon_rc = dnode_get(leaf_ptr->header.next, BYTESPERPAGE, &leaf_ptr); if (dgon_rc != FSCK_OK) { /* this is fatal */ dgon_rc = FSCK_FAILED_READ_NODE4; } else { /* got the sibling leaf node */ dtstbl = (int8_t *) & (leaf_ptr-> slot [leaf_ptr-> header. stblindex]); slots = &(leaf_ptr->slot[0]); last_dtidx = leaf_ptr->header.nextindex - 1; dgon_rc = direntry_get_objnam_node (obj_inonum, dtstbl, slots, last_dtidx, found_name_length, found_name, &entry_found); } } } } } if ((dgon_rc == FSCK_OK) && (!entry_found)) { /* * but we saw this entry earlier! */ dgon_rc = FSCK_FAILED_DIRENTRYGONE; } return (dgon_rc);}/***************************************************************************** * NAME: direntry_get_objnam_node * * FUNCTION: Find the file name, in the given directory leaf node, of the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -