Пример #1
0
/**
 * @brief Searches for free space region starting at the end of the volume.
 * @param[in] jp job parameters structure.
 * @param[in] min_lcn minimum LCN of region.
 * @param[in] min_length minimum length of region, in clusters.
 * @param[out] max_length length of the biggest region found.
 * @note In case of termination request returns NULL immediately.
 */
winx_volume_region *find_last_free_region(udefrag_job_parameters *jp,
        ULONGLONG min_lcn,ULONGLONG min_length,ULONGLONG *max_length)
{
    winx_volume_region *rgn;
    ULONGLONG time = winx_xtime();

    if(max_length) *max_length = 0;
    if(jp->free_regions){
        for(rgn = jp->free_regions->prev; rgn; rgn = rgn->prev){
            if(jp->termination_router((void *)jp)) break;
            if(rgn->lcn < min_lcn) break;
            if(max_length){
                if(rgn->length > *max_length)
                    *max_length = rgn->length;
            }
            if(rgn->length >= min_length){
                jp->p_counters.searching_time += winx_xtime() - time;
                return rgn;
            }
            if(rgn->prev == jp->free_regions->prev) break;
        }
    }
    jp->p_counters.searching_time += winx_xtime() - time;
    return NULL;
}
Пример #2
0
/**
 * @brief Searches for best matching free space region.
 * @param[in] jp job parameters structure.
 * @param[in] start_lcn a point which divides disk into two parts (see below).
 * @param[in] min_length minimal accepted length of the region, in clusters.
 * @param[in] preferred_position one of the FIND_MATCHING_RGN_xxx constants:
 * FIND_MATCHING_RGN_FORWARD - region after the start_lcn preferred
 * FIND_MATCHING_RGN_BACKWARD - region before the start_lcn preferred
 * FIND_MATCHING_RGN_ANY - any region accepted
 * @note In case of termination request returns
 * NULL immediately.
 */
winx_volume_region *find_matching_free_region(udefrag_job_parameters *jp,
    ULONGLONG start_lcn, ULONGLONG min_length, int preferred_position)
{
    winx_volume_region *rgn, *rgn_matching;
    ULONGLONG length;
    ULONGLONG time = winx_xtime();
    
    rgn_matching = NULL, length = 0;
    for(rgn = jp->free_regions; rgn; rgn = rgn->next){
        if(jp->termination_router((void *)jp)){
            jp->p_counters.searching_time += winx_xtime() - time;
            return NULL;
        }
        if(preferred_position == FIND_MATCHING_RGN_BACKWARD \
          && rgn->lcn > start_lcn)
            if(rgn_matching != NULL)
                break;
        if(rgn->length >= min_length){
            if(length == 0 || rgn->length < length){
                rgn_matching = rgn;
                length = rgn->length;
                if(length == min_length \
                  && preferred_position != FIND_MATCHING_RGN_FORWARD)
                    break;
            }
        }
        if(rgn->next == jp->free_regions) break;
    }
    jp->p_counters.searching_time += winx_xtime() - time;
    return rgn_matching;
}
Пример #3
0
/**
 * @brief Searches for well known locked files
 * and applies their dispositions to the map.
 * @details Resets f->disp structure of locked files.
 */
static void redraw_well_known_locked_files(udefrag_job_parameters *jp)
{
    winx_file_info *f;
    ULONGLONG time;
    ULONGLONG n = 0;

    winx_dbg_print_header(0,0,I"searching for well known locked files...");
    time = winx_xtime();
    
    for(f = jp->filelist; f; f = f->next){
        if(f->disp.blockmap){ /* otherwise nothing to redraw */
            if(is_well_known_locked_file(f,jp)){
                if(!is_file_locked(f,jp)){
                    /* possibility of this case should be reduced */
                    dtrace("file wasn't locked: %ws",f->path);
                } else {
                    itrace("locked file DETECTED:  %ws",f->path);
                    n ++;
                }
            }
        }
        if(f->next == jp->filelist) break;
    }

    itrace("%I64u locked files found",n);
    winx_dbg_print_header(0,0,I"well known locked files search completed in %I64u ms",
        winx_xtime() - time);
}
Пример #4
0
/**
 * @brief Saves fragmentation report on the volume.
 * @return Zero for success, negative value otherwise.
 */
int save_fragmentation_report(udefrag_job_parameters *jp)
{
    int result = 0;
    ULONGLONG time;

    winx_dbg_print_header(0,0,I"*");
    winx_dbg_print_header(0,0,I"report saving started");
    if(jp->job_type != ANALYSIS_JOB)
        dbg_print_file_counters(jp);
    
    if(jp->udo.disable_reports)
        return 0;
    
    time = winx_xtime();

    result = save_lua_report(jp);
    
    winx_dbg_print_header(0,0,I"report saved in %I64u ms",
        winx_xtime() - time);
    return result;
}
Пример #5
0
/**
 * @brief Searches for largest free space region.
 * @note In case of termination request returns
 * NULL immediately.
 */
winx_volume_region *find_largest_free_region(udefrag_job_parameters *jp)
{
    winx_volume_region *rgn, *rgn_largest;
    ULONGLONG length;
    ULONGLONG time = winx_xtime();
    
    rgn_largest = NULL, length = 0;
    for(rgn = jp->free_regions; rgn; rgn = rgn->next){
        if(jp->termination_router((void *)jp)){
            jp->p_counters.searching_time += winx_xtime() - time;
            return NULL;
        }
        if(rgn->length > length){
            rgn_largest = rgn;
            length = rgn->length;
        }
        if(rgn->next == jp->free_regions) break;
    }
    jp->p_counters.searching_time += winx_xtime() - time;
    return rgn_largest;
}
Пример #6
0
/**
 * @brief Performs a volume analysis.
 * @return Zero for success, negative value otherwise.
 */
int analyze(udefrag_job_parameters *jp)
{
    ULONGLONG time;
    int result;
    
    time = start_timing("analysis",jp);
    jp->pi.current_operation = VOLUME_ANALYSIS;
    
    /* update volume information */
    result = get_volume_information(jp);
    if(result < 0)
        return result;
    
    /* scan volume for free space areas */
    if(get_free_space_layout(jp) < 0)
        return (-1);
    
    /* redraw mft zone in light magenta */
    get_mft_zones_layout(jp);
    
    /* search for files */
    if(find_files(jp) < 0)
        return (-1);
    
    /* redraw well known locked files in green */
    redraw_well_known_locked_files(jp);

    /* produce list of fragmented files */
    produce_list_of_fragmented_files(jp);
    (void)check_fragmentation_level(jp); /* for debugging */

    result = check_requested_action(jp);
    if(result < 0)
        return result;
    
    jp->p_counters.analysis_time = winx_xtime() - time;
    stop_timing("analysis",time,jp);
    return 0;
}
Пример #7
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;
}