Rcpp::List Commit::parent_list() { BEGIN_RCPP Rcpp::List v; unsigned int c = parent_count(); for (int i=0; i<c; ++i) { v.push_back(parent(i)); } return v; END_RCPP }
/***************************************************************************** * NAME: check_link_counts * * FUNCTION: Count links from child directories to their parents. * * Verify that the link count stored in each in-use inode * matches the number of links fsck observed for the inode. * * PARAMETERS: none * * NOTES: * * RETURNS: * success: FSCK_OK * failure: something else */ retcode_t check_link_counts ( ) { retcode_t clc_rc = FSCK_OK; inoidx_t ino_idx; int num_parents; int invalid_count_seen = 0; int low_stored_count_seen = 0; char user_reply; fsck_inode_extptr this_ext; fsck_inode_recptr this_inorec; fsck_inode_recptr parent_inorec; int done_looking = 0; int aggregate_inode = 0; int alloc_ifnull = 0; struct fsck_ino_msg_info ino_msg_info; fsck_msg_info_ptr msg_info_ptr; msg_info_ptr = &ino_msg_info; msg_info_ptr->msg_inopfx = fsck_fset_inode; /* all fileset owned */ /* * count links from child directories to their parents * * (These can't be counted when the parent-child relationship * is observed because that observation occurs while processing * the parent and until the child is processed we don't know * whether the child is a directory or not.) */ clc_rc = get_inorecptr_first( aggregate_inode, &ino_idx, &this_inorec ); while( (clc_rc == FSCK_OK) && (this_inorec != NULL) ) { if( (this_inorec->in_use) && (!this_inorec->selected_to_rls) && (!this_inorec->ignore_alloc_blks) && (this_inorec->inode_type == directory_inode) ) { /* * inode is in use, not being released, and * is type directory */ this_inorec->link_count++; /* for the self entry */ if( (this_inorec->parent_inonum == ROOT_I) && (agg_recptr->rootdir_rebuilt) ) { /* * special case: if the parent is root and root was * rebuilt, then don't increment parent */ if( this_inorec->inonum == ROOT_I ) { /* * special case: if this IS the root, then it's link from itself * to itself DOES count */ this_inorec->link_count++; } } else if( this_inorec->parent_inonum != (ino_t) 0 ) { /* * not an orphan */ clc_rc = get_inorecptr( aggregate_inode, alloc_ifnull, this_inorec->parent_inonum, &parent_inorec ); if( (clc_rc != FSCK_OK) || (parent_inorec == NULL) ) { clc_rc = FSCK_INTERNAL_ERROR_13; sprintf( message_parm_0, "%ld", clc_rc ); /* @F1 */ msgprms[0] = message_parm_0; /* @F1 */ msgprmidx[0] = 0; /* @F1 */ sprintf( message_parm_1, "%ld", ino_idx ); /* @F1 */ msgprms[1] = message_parm_1; /* @F1 */ msgprmidx[1] = 0; /* @F1 */ sprintf( message_parm_2, "%ld", this_inorec->parent_inonum ); /* @F1 */ msgprms[2] = message_parm_2; /* @F1 */ msgprmidx[2] = 0; /* @F1 */ sprintf( message_parm_3, "%ld", 0 ); /* @F1 */ msgprms[3] = message_parm_3; /* @F1 */ msgprmidx[3] = 0; /* @F1 */ fsck_send_msg( fsck_INTERNALERROR, 0, 4 ); /* @F1 */ } else { parent_inorec->link_count++; /* * handle the first (and usually the only) * parent. */ } if( (clc_rc == FSCK_OK) && (this_inorec->ext_rec != NULL) ) { /* * there might be more parents */ num_parents = parent_count( this_inorec ); if( num_parents > 1 ) { /* directory with illegal links */ this_inorec->unxpctd_prnts = 1; agg_recptr->corrections_needed = 1; /* * Create an extension record for the parent inode number * now stored in the child inode record. * When we traverse the aggregate on-disk we'll copy the * stored value into this field of the inode record for * use when displaying paths to the inode. */ clc_rc = get_inode_extension( &this_ext ); if( clc_rc == FSCK_OK ) { /* got extension record */ this_ext->ext_type = parent_extension; this_ext->inonum = this_inorec->parent_inonum; this_ext->next = this_inorec->ext_rec; this_inorec->ext_rec = this_ext; this_inorec->parent_inonum = 0; this_ext = this_ext->next; /* already counted the first * one, back when it was in the * workspace inode record itself */ while ( (clc_rc == FSCK_OK) && (this_ext != NULL) ) { /* exten records to check */ if( this_ext->ext_type == parent_extension ) { clc_rc = get_inorecptr( aggregate_inode, alloc_ifnull, this_ext->inonum, &parent_inorec ); if( (clc_rc != FSCK_OK) || (parent_inorec == NULL) ) { clc_rc = FSCK_INTERNAL_ERROR_14; sprintf( message_parm_0, "%ld", clc_rc ); /* @F1 */ msgprms[0] = message_parm_0; /* @F1 */ msgprmidx[0] = 0; /* @F1 */ sprintf( message_parm_1, "%ld", ino_idx ); /* @F1 */ msgprms[1] = message_parm_1; /* @F1 */ msgprmidx[1] = 0; /* @F1 */ sprintf( message_parm_2, "%ld", this_ext->inonum ); /* @F1 */ msgprms[2] = message_parm_2; /* @F1 */ msgprmidx[2] = 0; /* @F1 */ sprintf( message_parm_3, "%ld", 0 ); /* @F1 */ msgprms[3] = message_parm_3; /* @F1 */ msgprmidx[3] = 0; /* @F1 */ fsck_send_msg( fsck_INTERNALERROR, 0, 4 ); /* @F1 */ } else { parent_inorec->link_count++; } } this_ext = this_ext->next; } /* end while exten records to check */ } /* end got extension record */ } /* end directory with illegal links */ } /* end there might be more parents */ } /* end not an orphan */ } /* end inode is in use and is type directory */ if( clc_rc == FSCK_OK ) { clc_rc = get_inorecptr_next( aggregate_inode, &ino_idx, &this_inorec ); } } /* end while */ /* * verify that stored link counts match observed link counts * * We have added each observed link and subtracted the stored * count. If the stored count is correct the result is 0. */ if( clc_rc == FSCK_OK ) { /* no fatal errors */ clc_rc = get_inorecptr_first( aggregate_inode, &ino_idx, &this_inorec ); while( (clc_rc == FSCK_OK) && (this_inorec != NULL) && (!done_looking) ) { if( (this_inorec->in_use) && (!this_inorec->selected_to_rls) && (!this_inorec->ignore_alloc_blks) ) { /* * inode is in use and not being released */ if( this_inorec->link_count != 0 ) { /* stored * link count doesn't match fsck's observations */ if( this_inorec->parent_inonum == 0 ) { /* inode is an orphan */ this_inorec->crrct_link_count = 1; } else { /* not an orphan */ this_inorec->crrct_link_count = 1; if( this_inorec->link_count > 0 ) { low_stored_count_seen = 1; } invalid_count_seen = 1; msgprms[0] = message_parm_0; msgprmidx[0] = msg_info_ptr->msg_inopfx; sprintf( message_parm_1, "%ld", ino_idx ); msgprms[1] = message_parm_1; msgprmidx[1] = 0; fsck_send_msg( fsck_BADINOLKCT, 0, 2 ); } /* end else not an orphan */ } /* end stored link count doesn't match fsck's observations */ } /* end inode is in use and not being released */ if( clc_rc == FSCK_OK ) { clc_rc = get_inorecptr_next( aggregate_inode, &ino_idx, &this_inorec ); } } /* end while */ if( (clc_rc == FSCK_OK) && (invalid_count_seen) ) { if( agg_recptr->processing_readwrite ) { /* we can fix this */ agg_recptr->corrections_approved = 1; fsck_send_msg( fsck_WILLFIXLINKCTS, 0, 0 ); } /* end we can fix this */ else { /* no write access */ if( low_stored_count_seen ) { agg_recptr->ag_dirty = 1; } /* end if low_stored_count_seen */ /* * reset all link counts (in the fsck workspace) to * zero so that we won't accidentally correct them * while doing link count adjustments. * * (Link count adjustments are side effects of approved * repairs. For example, if a directory inode is * released, the link count of its parent directory * is decremented.) */ clc_rc = get_inorecptr_first( aggregate_inode, &ino_idx, &this_inorec ); while( (clc_rc == FSCK_OK) && (this_inorec != NULL) ) { if( this_inorec->in_use ) { /* inode in use */ this_inorec->crrct_link_count = 0; this_inorec->link_count = 0; } /* end inode in use */ clc_rc = get_inorecptr_next( aggregate_inode, &ino_idx, &this_inorec ); } /* end while */ fsck_send_msg( fsck_BADLINKCTS, 0, 0 ); } /* end no write access */ } /* end if invalid_count_seen */ } /* end no fatal errors */ return( clc_rc ); } /* end of check_link_counts () */