/** * @brief Removes a file block from * the binary tree of all file blocks. * @return Zero for success, * negative value otherwise. */ int remove_block_from_file_blocks_tree(udefrag_job_parameters *jp, winx_blockmap *block) { struct file_block *fb; struct file_block b; if(block == NULL) return (-1); if(jp->file_blocks == NULL) return (-1); b.file = NULL; b.block = block; fb = prb_delete(jp->file_blocks,&b); if(fb == NULL){ /* the following debugging output indicates either a bug, or file system inconsistency */ etrace("failed for %p: VCN = %I64u, LCN = %I64u, LEN = %I64u", block, block->vcn, block->lcn, block->length); /* if block does not exist in tree, we have nothing to cleanup */ return 0; } winx_free(fb); return 0; }
/** * @brief Searches for the first movable file block * after the specified cluster on the volume. * @param[in] jp job parameters. * @param[in,out] min_lcn pointer to variable containing * minimum LCN - file blocks below it will be ignored. * @param[in] flags one of SKIP_xxx flags defined in udefrag.h * @param[out] first_file pointer to variable receiving information * about the file the first block belongs to. * @return Pointer to the first block. NULL indicates failure. */ winx_blockmap *find_first_block(udefrag_job_parameters *jp, ULONGLONG *min_lcn, int flags, winx_file_info **first_file) { winx_file_info *found_file; winx_blockmap *first_block; winx_blockmap b; struct file_block fb, *item; struct prb_traverser t; int movable_file; ULONGLONG tm = winx_xtime(); if(min_lcn == NULL || first_file == NULL) return NULL; found_file = NULL; first_block = NULL; b.lcn = *min_lcn; fb.block = &b; prb_t_init(&t,jp->file_blocks); item = prb_t_insert(&t,jp->file_blocks,&fb); if(item == &fb){ /* block at min_lcn not found */ item = prb_t_next(&t); if(prb_delete(jp->file_blocks,&fb) == NULL){ etrace("cannot remove block from the tree"); winx_flush_dbg_log(0); /* 'cause error is critical */ } } if(item){ found_file = item->file; first_block = item->block; } while(!jp->termination_router((void *)jp)){ if(found_file == NULL) break; if(flags & SKIP_PARTIALLY_MOVABLE_FILES){ movable_file = can_move_entirely(found_file,jp); } else { movable_file = can_move(found_file,jp); } if(is_file_locked(found_file,jp)) movable_file = 0; if(movable_file){ if(jp->is_fat && is_directory(found_file) && first_block == found_file->disp.blockmap){ /* skip first fragments of FAT directories */ } else { /* desired block found */ *min_lcn = first_block->lcn + 1; /* the current block will be skipped later anyway in this case */ *first_file = found_file; jp->p_counters.searching_time += winx_xtime() - tm; return first_block; } } /* skip current block */ *min_lcn = *min_lcn + 1; /* and go to the next one */ item = prb_t_next(&t); if(item == NULL) break; found_file = item->file; first_block = item->block; } *first_file = NULL; jp->p_counters.searching_time += winx_xtime() - tm; return NULL; }
/** * @brief Removes file from the list of fragmented files. */ void truncate_fragmented_files_list(winx_file_info *f,udefrag_job_parameters *jp) { if(!prb_delete(jp->fragmented_files,(void *)f)) etrace("%ws is not found in the tree",f->path); }