📄 fsckino.c
字号:
* ino_recptr - input - pointer to an fsck inode record describing * the current inode * * RETURNS: * success: FSCK_OK * failure: something else */int get_path(uint32_t inode_idx, uint32_t parent_inonum, char **addr_path_addr, struct fsck_inode_record *ino_recptr){ int gip_rc = FSCK_OK; uint32_t inode_inonum; uint32_t this_parent_inonum; int bytes_used; int this_name_length = 0; int length_in_UniChars; UniChar uniname[256]; char *path_ptr; int path_idx; int path_completed = 0; uint32_t parent_idx; struct fsck_inode_record *parent_inorecptr; int aggregate_inode = 0; int alloc_ifnull = 0; *addr_path_addr = NULL; bytes_used = sizeof (char); path_idx = JFS_PATH_MAX - 1; agg_recptr->path_buffer[path_idx] = '\0'; path_ptr = &(agg_recptr->path_buffer[path_idx]); /* change the inode index to an inode number */ inode_inonum = (uint32_t) inode_idx; /* the first parent must be given since the object may not be a * directory */ this_parent_inonum = parent_inonum; if (inode_idx == 2) { /* it's the root directory */ path_completed = -1; path_idx--; path_ptr--; agg_recptr->path_buffer[path_idx] = agg_recptr->delim_char; } while ((!path_completed) && (gip_rc == FSCK_OK)) { gip_rc = direntry_get_objnam(this_parent_inonum, inode_inonum, &length_in_UniChars, uniname); uniname[length_in_UniChars] = 0; if (gip_rc != FSCK_OK) { /* didn't get the name */ path_completed = -1; if (path_idx != (JFS_PATH_MAX - 1)) { /* we got part of the path */ /* remove the foreslash from the * beginning of the path we have at this * beginning as now assembled it implies * that the unconnected dir parent is * connected to the fileset root directory. */ path_ptr++; } break; } this_name_length = Unicode_String_to_UTF8_String((uint8_t *) Str_Name, uniname, 256); Str_Name[this_name_length] = '\0'; if ((bytes_used + this_name_length + sizeof (char)) > JFS_PATH_MAX) { /* the path is beyond the legal length */ path_completed = -1; if (path_idx == (JFS_PATH_MAX - 1)) { /* the very first segment * is too long to be valid */ gip_rc = FSCK_FAILED_DIRENTRYBAD; } else { /* we got part of the path */ /* remove the foreslash from the * beginning of the path we have at * this point since as now assembled * it implies that the unconnected dir * parent is connected to the fileset * root directory. */ path_ptr++; } break; } bytes_used += this_name_length; path_idx -= this_name_length; path_ptr -= this_name_length; Str_Name_len = this_name_length; memcpy((void *) path_ptr, (void *) &Str_Name, Str_Name_len); bytes_used += sizeof (char); path_idx--; path_ptr--; agg_recptr->path_buffer[path_idx] = agg_recptr->delim_char; /* * assume that we'll find a parent dir for the * path segment just copied into the path buffer. */ if (this_parent_inonum == ROOT_I) { path_completed = -1; break; } /* haven't gotten up to root yet */ parent_idx = (uint32_t) this_parent_inonum; inode_inonum = this_parent_inonum; gip_rc = get_inorecptr(aggregate_inode, alloc_ifnull, parent_idx, &parent_inorecptr); if ((gip_rc == FSCK_OK) && (parent_inorecptr == NULL)) gip_rc = FSCK_INTERNAL_ERROR_21; if (gip_rc != FSCK_OK) break; this_parent_inonum = parent_inorecptr->parent_inonum; if ((this_parent_inonum == 0) || (parent_inorecptr->selected_to_rls) || (!(parent_inorecptr->in_use)) || (parent_inorecptr->inode_type == metadata_inode)) { path_completed = -1; /* remove the foreslash from the beginning * of the path we have at this point since * as now assembled it implies that the * unconnected dir parent is connected to * the fileset root directory. */ path_ptr++; } } if (gip_rc == FSCK_OK) /* indicate where to find the 1st char of the path just * assembled */ *addr_path_addr = path_ptr; return (gip_rc);}/***************************************************************************** * NAME: in_inode_data_check * * FUNCTION: Verify that the fields in the current inode which describe * inline data (that is, storage within the inode itself) do * not overlap. * * PARAMETERS: * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * NOTES: The data regarding inline data for the inode is stored in * the global aggregate record, fields in the this_inode record. * * RETURNS: * success: FSCK_OK * failure: something else */int in_inode_data_check(struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr){ int iidc_rc = FSCK_OK; int16_t size16; struct dinode an_inode; /* * if in-inode data (or description of data) overflows * this then the EA can NOT be inline */ size16 = sizeof (an_inode.di_inlinedata); if (agg_recptr->this_inode.in_inode_data_length > size16) { /* extra long inline data */ if (agg_recptr->this_inode.ea_inline) { /* conflict */ inorecptr->selected_to_rls = 1; inorecptr->inline_data_err = 1; inorecptr->clr_ea_fld = 1; agg_recptr->corrections_needed = 1; fsck_send_msg(fsck_INOINLINECONFLICT, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_longdata_and_otherinline); } if (agg_recptr->this_inode.acl_inline) { /* conflict */ inorecptr->selected_to_rls = 1; inorecptr->inline_data_err = 1; inorecptr->clr_acl_fld = 1; agg_recptr->corrections_needed = 1; fsck_send_msg(fsck_INOINLINECONFLICT, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_longdata_and_otherinline); } } else { if (agg_recptr->this_inode.ea_inline && agg_recptr->this_inode.acl_inline) { /* conflict */ inorecptr->clr_ea_fld = 1; inorecptr->clr_acl_fld = 1; agg_recptr->corrections_needed = 1; fsck_send_msg(fsck_INOINLINECONFLICT, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_longdata_and_otherinline); } } return (iidc_rc);}/***************************************************************************** * NAME: inode_is_in_use * * FUNCTION: Determine whether the specified inode is currently being * used to represent a file system object. * * PARAMETERS: * inode_ptr - input - pointer to the current inode * inode_num - input - ordinal number of the inode in the internal * JFS format * * RETURNS: * 0: if inode is not in use * 1: if inode is in use */int inode_is_in_use(struct dinode *inode_ptr, uint32_t inode_num){ int iiiu_result; int ixpxd_unequal = 0; ixpxd_unequal = memcmp((void *) &(inode_ptr->di_ixpxd), (void *) &(agg_recptr->ino_ixpxd), sizeof (pxd_t)); iiiu_result = ((inode_ptr->di_inostamp == agg_recptr->inode_stamp) && (inode_ptr->di_number == inode_num) && (inode_ptr->di_fileset == agg_recptr->ino_fsnum) && (!ixpxd_unequal) && (inode_ptr->di_nlink != 0)); return (iiiu_result);}/***************************************************************************** * NAME: parent_count * * FUNCTION: Count the number of directory entries fsck has observed which * refer to the specified inode. * * PARAMETERS: * this_inorec - input - pointer to an fsck inode record describing the * current inode * * RETURNS: * the number of parent directories observed for the inode */int parent_count(struct fsck_inode_record *this_inorec){ int pc_result = 0; struct fsck_inode_ext_record *this_ext; if (this_inorec->parent_inonum != 0) { pc_result++; } this_ext = this_inorec->ext_rec; while (this_ext != NULL) { /* extension records to check */ if (this_ext->ext_type == parent_extension) { pc_result++; } this_ext = this_ext->next; } return (pc_result);}/***************************************************************************** * NAME: record_valid_inode * * FUNCTION: Record, in the fsck workspace block map, all aggregate blocks * allocated to the specified inode. The inode structures have * already been validated, no error checking is done. * * PARAMETERS: * inoptr - input - pointer to the current inode * inoidx - input - ordinal number of the inode as an integer * inorecptr - input - pointer to an fsck inode record describing the * current inode * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK * failure: something else */int record_valid_inode(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr){ int rvi_rc = FSCK_OK; int64_t first_fsblk, last_fsblk; uint32_t num_fsblks; dxd_t *dxd_ptr; /* * record the extent (if any) containing the EA */ if (inoptr->di_ea.flag == DXD_EXTENT) { /* there is an ea to record */ dxd_ptr = &(inoptr->di_ea); first_fsblk = addressDXD(dxd_ptr); num_fsblks = lengthDXD(dxd_ptr); last_fsblk = first_fsblk + num_fsblks - 1; extent_record(first_fsblk, last_fsblk); agg_recptr->this_inode.all_blks += num_fsblks; agg_recptr->blocks_this_fset += num_fsblks; } /* * record the extent (if any) containing the ACL */ if (inoptr->di_acl.flag == DXD_EXTENT) { /* there is an acl to record */ dxd_ptr = &(inoptr->di_acl); first_fsblk = addressDXD(dxd_ptr); num_fsblks = lengthDXD(dxd_ptr); last_fsblk = first_fsblk + num_fsblks - 1; extent_record(first_fsblk, last_fsblk); agg_recptr->this_inode.all_blks += num_fsblks; agg_recptr->blocks_this_fset += num_fsblks; } /* * record the extents (if any) described as data */ process_valid_data(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_RECORD); return (rvi_rc);}/***************************************************************************** * NAME: release_inode * * FUNCTION: Release all aggregate blocks allocated to the specified inode. * Reset the link count, in the inode on the device, to zero * to make it available for reuse. * * PARAMETERS: * inoidx - input - ordinal number of the inode as an integer * ino_recptr - input - pointer to an fsck inode record describing the * current inode * inoptr - input - pointer to the current inode * * RETURNS: * success: FSCK_OK * failure: something else */int release_inode(uint32_t inoidx, struct fsck_inode_record *ino_recptr, struct dinode *inoptr){ int ri_rc = FSCK_OK; struct dinode *this_inode; int aggregate_inode = 0; /* going for fileset inodes only */ int which_it = 0; /* in release 1 there is only fileset 0 */ struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; msg_info_ptr->msg_inopfx = fsck_fset_inode; msg_info_ptr->msg_inonum = inoidx; if (ino_recptr->inode_type == directory_inode) { msg_info_ptr->msg_inotyp = fsck_directory; } else if (ino_recptr->inode_type == symlink_inode) { msg_info_ptr->msg_inotyp = fsck_symbolic_link; } else if (ino_recptr->inode_type == char_special_inode) { msg_info_ptr->msg_inotyp = fsck_char_special; } else if (ino_recptr->inode_type == block_special_inode) { msg_info_ptr->msg_inotyp = fsck_block_special; } else if (ino_recptr->inode_type == FIFO_inode) { msg_info_ptr->msg_inotyp = fsck_FIFO; } else if (ino_recptr->inode_type == SOCK_inode) { msg_info_ptr->msg_inotyp = fsck_SOCK; } else { /* a regular file */ msg_info_ptr->msg_inotyp = fsck_file; } if (ino_recptr->in_use) { /* the inode is 'in use' */ ri_rc = inode_get(aggregate_inode, which_it, inoidx, &this_inode); if (ri_rc == FSCK_OK) { /* inode read successfully */ this_inode->di_nlink = 0; ri_rc = inode_put(this_inode); if ((ri_rc == FSCK_OK) && (!ino_recptr->ignore_alloc_blks)) { ri_rc = unrecord_valid_inode(this_inode, inoidx, ino_recptr, msg_info_ptr); } } } return (ri_rc);}/***************************************************************************** * NAME: unrecord_valid_inode * * FUNCTION: Unrecord, in the fsck workspace block map, all aggregate blocks * allocated to the specified inode. The inode structures have * already been validated, no error checking is done. * * PARAMETERS: * inoptr - input - pointer to the current inode * inoidx - input - ordinal number of the inode as an integer * inorecptr - input - pointer to an fsck inode record describing * the current inode * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -