Ejemplo n.º 1
0
uint_32 MFS_Find_unused_cluster_from
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,      /*[IN] the drive on which to operate */
    uint_32                 cluster_number  /*[IN] first cluster number to search */   
    )
{
    uint_32      max_clusters,cluster;
    _mfs_error   error_code;
    uint_32      cluster_status;

#if MFSCFG_READ_ONLY_CHECK
    if (MFS_is_read_only (NULL, drive_ptr))
    {
        return CLUSTER_INVALID;
    }
#endif

    max_clusters = drive_ptr->LAST_CLUSTER;
    for ( cluster = cluster_number; cluster <= max_clusters; cluster++ )
    {
        error_code = MFS_get_cluster_from_fat(drive_ptr,cluster,&cluster_status);
        if ( error_code != MFS_NO_ERROR )
        {
            return(CLUSTER_INVALID);
        }
        else if ( cluster_status == CLUSTER_UNUSED )
        {
            drive_ptr->NEXT_FREE_CLUSTER = cluster;
            return(cluster);
        }
    }  

    for ( cluster = CLUSTER_MIN_GOOD; cluster < cluster_number; cluster++ )
    {
        error_code = MFS_get_cluster_from_fat(drive_ptr,cluster, &cluster_status);
        if ( error_code != MFS_NO_ERROR )
        {
            return(CLUSTER_INVALID);
        }
        else if ( cluster_status == CLUSTER_UNUSED )
        {
            drive_ptr->NEXT_FREE_CLUSTER = cluster;      
            return(cluster);
        }
    }  

    return(CLUSTER_INVALID);
}  
Ejemplo n.º 2
0
/*!
 * \brief
 *
 * Get an unused cluster number. Assumes that the FAT has been read
 * Assumes drive SEM is locked.
 *
 * \param[in] drive_ptr The drive on which to operate.
 * \param[in] cluster_number First cluster number to search.
 *
 * \return uint32_t Cluster_number, 0xffff means that none is available
 */
uint32_t MFS_Find_unused_cluster_from(
    MFS_DRIVE_STRUCT_PTR drive_ptr,
    uint32_t cluster_number)
{
    uint32_t max_clusters, cluster;
    _mfs_error error_code;
    uint32_t cluster_status;

    max_clusters = drive_ptr->LAST_CLUSTER;
    for (cluster = cluster_number; cluster <= max_clusters; cluster++)
    {
        error_code = MFS_get_cluster_from_fat(drive_ptr, cluster, &cluster_status);
        if (error_code != MFS_NO_ERROR)
        {
            return (CLUSTER_INVALID);
        }
        else if (cluster_status == CLUSTER_UNUSED)
        {
            drive_ptr->NEXT_FREE_CLUSTER = cluster;
            return (cluster);
        }
    }

    for (cluster = CLUSTER_MIN_GOOD; cluster < cluster_number; cluster++)
    {
        error_code = MFS_get_cluster_from_fat(drive_ptr, cluster, &cluster_status);
        if (error_code != MFS_NO_ERROR)
        {
            return (CLUSTER_INVALID);
        }
        else if (cluster_status == CLUSTER_UNUSED)
        {
            drive_ptr->NEXT_FREE_CLUSTER = cluster;
            return (cluster);
        }
    }

    return (CLUSTER_INVALID);
}
Ejemplo n.º 3
0
/*!
 * \brief Get number of free clusters on the disk.
 *
 * \param drive_ptr
 * \param free_clusters_ptr
 *
 * \return _mfs_error
 */
_mfs_error MFS_Get_disk_free_space_internal(
    MFS_DRIVE_STRUCT_PTR drive_ptr,
    uint32_t *free_clusters_ptr)
{
    uint32_t last_cluster;
    uint32_t k;
    uint32_t free_slots;
    _mfs_error error_code = MFS_NO_ERROR;
    uint32_t cluster_status;

    last_cluster = drive_ptr->LAST_CLUSTER;

    if (drive_ptr->FREE_COUNT == FSI_UNKNOWN)
    {
        free_slots = 0;

        for (k = CLUSTER_MIN_GOOD; k <= last_cluster; k++)
        {
            error_code = MFS_get_cluster_from_fat(drive_ptr, k, &cluster_status);
            if (error_code != MFS_NO_ERROR)
            {
                break;
            }
            else if (cluster_status == CLUSTER_UNUSED)
            {
                free_slots++;
            }
        }

        if (error_code == MFS_NO_ERROR)
        {
            drive_ptr->FREE_COUNT = free_slots;
        }
    }
    else
    {
        free_slots = drive_ptr->FREE_COUNT;
    }

    if (free_clusters_ptr != NULL)
    {
        *free_clusters_ptr = free_slots;
    }

    return error_code;
}
Ejemplo n.º 4
0
/*!
 * \brief Follow a chain of clusters and mark the entries as unused.
 *
 * \param[in] drive_ptr The drive on which to operate.
 * \param[in] cluster_number First cluster number to release.
 *
 * \return _mfs_error
 */
_mfs_error MFS_Release_chain(
    MFS_DRIVE_STRUCT_PTR drive_ptr,
    uint32_t cluster_number)
{
    uint32_t next_cluster;
    _mfs_error error_code;

    if ((cluster_number >= CLUSTER_MIN_GOOD) && (cluster_number <= drive_ptr->LAST_CLUSTER))
    {
        do
        {
            error_code = MFS_get_cluster_from_fat(drive_ptr, cluster_number, &next_cluster);
            if (error_code != MFS_NO_ERROR)
            {
                break;
            }
            else if (((next_cluster > drive_ptr->LAST_CLUSTER) || (next_cluster < CLUSTER_MIN_GOOD)) && (next_cluster != CLUSTER_EOF))
            {
                error_code = MFS_LOST_CHAIN;
                break;
            }

            error_code = MFS_Put_fat(drive_ptr, cluster_number, CLUSTER_UNUSED);
            if (error_code)
            {
                break;
            }

            /* Invalidation of data sectors of released chain here may certainly save some write operations but it is mostly a corner case */
            error_code = MFS_sector_cache_invalidate(drive_ptr, CLUSTER_TO_SECTOR(drive_ptr, cluster_number), drive_ptr->SECTORS_PER_CLUSTER);
            if (error_code)
            {
                break;
            }

            cluster_number = next_cluster;
        } while (cluster_number != CLUSTER_EOF);
    }
    else
    {
        error_code = MFS_NO_ERROR;
    }

    return (error_code);
}
Ejemplo n.º 5
0
/*!
 * \brief Get the number of bad clusters in the file system.
 *
 * \param drive_ptr
 * \param bad_clusters_ptr
 *
 * \return _mfs_error
 */
_mfs_error MFS_Bad_clusters(
    MFS_DRIVE_STRUCT_PTR drive_ptr,
    uint32_t *bad_clusters_ptr)
{
    uint32_t last_cluster;
    uint32_t k;
    uint32_t bad_slots;
    _mfs_error error_code;
    uint32_t cluster_status;

    if (bad_clusters_ptr == NULL)
    {
        return MFS_INVALID_POINTER;
    }

    bad_slots = 0;

    error_code = MFS_lock_and_enter(drive_ptr, 0);
    if (error_code != MFS_NO_ERROR)
    {
        return error_code;
    }

    last_cluster = drive_ptr->LAST_CLUSTER;

    for (k = CLUSTER_MIN_GOOD; k <= last_cluster; k++)
    {
        error_code = MFS_get_cluster_from_fat(drive_ptr, k, &cluster_status);
        if (error_code != MFS_NO_ERROR)
        {
            break;
        }
        else if (cluster_status == CLUSTER_BAD)
        {
            bad_slots++;
        }
    }

    *bad_clusters_ptr = bad_slots;

    MFS_leave_and_unlock(drive_ptr, 0);

    return error_code;
}
Ejemplo n.º 6
0
_mfs_error MFS_next_data_sector(
    MFS_DRIVE_STRUCT_PTR    drive_ptr,
    MFS_HANDLE_PTR          handle,
    uint32_t             *sector_index_ptr,
    uint32_t             *sector_number_ptr
    )
{
    _mfs_error  error = MFS_NO_ERROR;
    uint32_t     next_cluster;

    if ( handle->CURRENT_CLUSTER != CLUSTER_EOF )
    {
        (*sector_index_ptr)++;
        if ( *sector_index_ptr >= drive_ptr->BPB.SECTORS_PER_CLUSTER )
        {
            // New cluster
            error = MFS_get_cluster_from_fat(drive_ptr, handle->CURRENT_CLUSTER, &next_cluster);
            if ( error == MFS_NO_ERROR )
            {
                handle->PREVIOUS_CLUSTER = handle->CURRENT_CLUSTER;
                handle->CURRENT_CLUSTER = next_cluster;
                *sector_index_ptr = 0;

                if ( next_cluster == CLUSTER_EOF )
                {
                    error = MFS_EOF;
                }
            }
        }

        if ( error == MFS_NO_ERROR )
        {
            *sector_number_ptr = CLUSTER_TO_SECTOR(handle->CURRENT_CLUSTER) + *sector_index_ptr;
        }
    }
    else
    {
        error = MFS_EOF;
    }
    return error;
}
Ejemplo n.º 7
0
uint_32  MFS_Bad_clusters
    (
    MQX_FILE_PTR            mfs_fd_ptr  
    )
{
    MFS_DRIVE_STRUCT_PTR    drive_ptr;
    uint_32                 last_cluster;
    uint_32                 k;
    uint_32                 bad_slots;
    uint_32                 error_code;
    uint_32                 cluster_status;

    bad_slots = 0;


    error_code = MFS_lock_dos_disk( mfs_fd_ptr, &drive_ptr );
    if ( error_code != MFS_NO_ERROR )
    {
        return error_code;
    }

    last_cluster = drive_ptr->LAST_CLUSTER;

    for ( k = CLUSTER_MIN_GOOD; k <= last_cluster; k++ )
    {
        error_code = MFS_get_cluster_from_fat(drive_ptr, k, &cluster_status);
        if ( error_code != MFS_NO_ERROR )
        {
            break;
        }
        else if ( cluster_status == CLUSTER_BAD )
        {
            bad_slots++;
        }
    }  

    MFS_unlock(drive_ptr,FALSE);

    return(bad_slots);
}  
Ejemplo n.º 8
0
uint_32  MFS_Get_disk_free_space_internal
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,
    uint_32_ptr             error_ptr
    )
{
    uint_32  last_cluster, k, free_slots;
    uint_32  error_code = MFS_NO_ERROR;
    uint_32  cluster_status;

    last_cluster = drive_ptr->LAST_CLUSTER;

    if ( drive_ptr->FREE_COUNT == FSI_UNKNOWN )
    {
        free_slots = 0;

        for ( k = CLUSTER_MIN_GOOD; k <= last_cluster; k++ )
        {
            error_code = MFS_get_cluster_from_fat(drive_ptr, k, &cluster_status);
            if ( error_code != MFS_NO_ERROR )
            {
                break;
            }
            else if ( cluster_status == CLUSTER_UNUSED )
            {
                free_slots++;
            }
        }  
        drive_ptr->FREE_COUNT = free_slots;
    }
    else
    {
        free_slots = drive_ptr->FREE_COUNT;    
    }  

    MFS_set_error_and_return(error_ptr, error_code, free_slots);
}
Ejemplo n.º 9
0
_mfs_error MFS_Extend_chain
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,      /*[IN] the drive on which to operate */
    uint_32                 cluster_number, /*[IN] number of a cluster within the chain */
    uint_32                 num_clusters,   /*[IN] number of clusters to append to chain */   
    uint_32_ptr             added_cluster   /* [IN] pointer to the place where we should put the # of the first  new cluster. */
    )
{
    uint_32    next_cluster;
    _mfs_error error_code;
    boolean    extended;

#if MFSCFG_READ_ONLY_CHECK
    if (MFS_is_read_only (NULL, drive_ptr))
    {
        return MFS_DISK_IS_WRITE_PROTECTED;
    }
#endif

    extended = FALSE;
    error_code = MFS_NO_ERROR;

    if ( cluster_number < CLUSTER_MIN_GOOD || cluster_number > drive_ptr->LAST_CLUSTER )
    {
        error_code = MFS_INVALID_CLUSTER_NUMBER;
    }
    else if ( num_clusters )
    {
        /*
        ** Find the end of the chain
        */
        next_cluster = cluster_number;
        do
        {
            cluster_number = next_cluster;
            error_code = MFS_get_cluster_from_fat(drive_ptr,next_cluster, &next_cluster);
            if ( error_code != MFS_NO_ERROR )
            {
                return error_code;
            }
            else if ( (next_cluster > drive_ptr->LAST_CLUSTER || next_cluster < CLUSTER_MIN_GOOD) && next_cluster != CLUSTER_EOF )
            {
                return(MFS_LOST_CHAIN);
            }
        } while ( next_cluster != CLUSTER_EOF );

        /*
        ** Find a free cluster
        */
        next_cluster = MFS_Find_unused_cluster_from(drive_ptr, cluster_number+1);

        /*
        ** Check to see if the disk is not full.
        */
        if ( next_cluster == CLUSTER_INVALID )
        {
            return MFS_DISK_FULL;
        }

        /*
        ** Link the free cluster to the chain, at the end.
        */
        *added_cluster = next_cluster;
        error_code = MFS_Put_fat(drive_ptr,cluster_number, next_cluster);
        extended = TRUE;

        while ( --num_clusters && !error_code )
        {
            /*
            ** Find a free cluster
            */
            cluster_number = next_cluster;
            next_cluster = MFS_Find_unused_cluster_from(drive_ptr, cluster_number+1);
            /*
            ** Check to see if the disk is not full.
            */
            if ( next_cluster == CLUSTER_INVALID )
            {
                error_code = MFS_Put_fat(drive_ptr,cluster_number, CLUSTER_EOF);
                return MFS_DISK_FULL;
            }
            else
            {
                /*
                ** Link the free cluster to the chain, at the end.
                */
                error_code = MFS_Put_fat(drive_ptr,cluster_number, next_cluster);
            }  
        }  
        if ( extended && !error_code )
        {
            error_code = MFS_Put_fat(drive_ptr,next_cluster, CLUSTER_EOF);
        }
    }

    return(error_code);
}  
Ejemplo n.º 10
0
_mfs_error MFS_Add_cluster_to_chain
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,      /*[IN] the drive on which to operate */
    uint_32                 cluster_number, /*[IN] number of a cluster within the chain */
    uint_32_ptr             added_cluster   /*[IN] pointer to the place where we should put the # of the new cluster. */  
    )
{
    uint_32     next_cluster,free_cluster;
    _mfs_error  error_code;

#if MFSCFG_READ_ONLY_CHECK
    if (MFS_is_read_only (NULL, drive_ptr))
    {
        return MFS_DISK_IS_WRITE_PROTECTED;
    }
#endif

    if ( cluster_number < CLUSTER_MIN_GOOD || 
        cluster_number > drive_ptr->LAST_CLUSTER )
    {
        error_code = MFS_INVALID_CLUSTER_NUMBER;
    }
    else
    {
        free_cluster = MFS_Find_unused_cluster_from(drive_ptr, drive_ptr->NEXT_FREE_CLUSTER);

        /*
        ** Check to see if the disk is not full.
        */
        if ( free_cluster == CLUSTER_INVALID )
        {
            error_code = MFS_DISK_FULL;
        }
        else
        {
            /*
            ** Find the end of the chain
            */
            next_cluster = cluster_number;
            do
            {
                cluster_number = next_cluster;
                error_code = MFS_get_cluster_from_fat(drive_ptr,next_cluster, &next_cluster);
                if ( error_code != MFS_NO_ERROR )
                {
                    break;
                }
                else if ( next_cluster > drive_ptr->LAST_CLUSTER && next_cluster != CLUSTER_EOF )
                {
                    error_code = MFS_BAD_DISK_UNIT;
                    break;
                }
            } while ( next_cluster != CLUSTER_EOF );

            /*
            ** Link the free cluster to the chain, at the end.
            */
            if ( error_code == MFS_NO_ERROR )
            {
                error_code = MFS_Put_fat(drive_ptr,cluster_number, free_cluster);
                if ( error_code )
                {
                    return(error_code);
                }
                error_code = MFS_Put_fat(drive_ptr,free_cluster, CLUSTER_EOF);
                if ( error_code )
                {
                    return(error_code);
                }
                *added_cluster = free_cluster;
            }
        }  
    }  

    return(error_code);
}  
Ejemplo n.º 11
0
_mfs_error MFS_Release_chain
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,      /*[IN] the drive on which to operate */
    uint_32                 cluster_number  /*[IN] first cluster number to release */
    )
{
    uint_32    next_cluster,first_sector_in_cluster,last_sector_in_cluster;
    _mfs_error error_code;

#if MFSCFG_READ_ONLY_CHECK
    if (MFS_is_read_only (NULL, drive_ptr))
    {
        return MFS_DISK_IS_WRITE_PROTECTED;
    }
#endif

    if ( (cluster_number >= CLUSTER_MIN_GOOD) && (cluster_number <= drive_ptr->LAST_CLUSTER) )
    {
        do
        {
            error_code = MFS_get_cluster_from_fat(drive_ptr,cluster_number,&next_cluster);
            if ( error_code != MFS_NO_ERROR )
            {
                break;
            }
            else if ( ((next_cluster > drive_ptr->LAST_CLUSTER) || (next_cluster < CLUSTER_MIN_GOOD)) && (next_cluster != CLUSTER_EOF) )
            {
                error_code = MFS_LOST_CHAIN;
                break;
            }

            first_sector_in_cluster = CLUSTER_TO_SECTOR(cluster_number);
            last_sector_in_cluster = first_sector_in_cluster+ drive_ptr->BPB.SECTORS_PER_CLUSTER -1;

            // Check to see if the currently cached data sector is being deleted.
            if ( (drive_ptr->DATA_SECTOR_NUMBER >= first_sector_in_cluster) && (drive_ptr->DATA_SECTOR_NUMBER <= last_sector_in_cluster) )
            {
                error_code = MFS_Invalidate_data_sector(drive_ptr);

                if ( error_code != MFS_NO_ERROR )
                {
                    return error_code;
                }
            }

            error_code = MFS_Put_fat(drive_ptr,cluster_number, CLUSTER_UNUSED);
            if ( error_code )
            {
                break;
            }
            cluster_number = next_cluster;
        } while ( cluster_number != CLUSTER_EOF );
        error_code = MFS_Write_back_fat(drive_ptr);
    }
    else
    {
        error_code = MFS_NO_ERROR;
    }  

    return(error_code);
}  
Ejemplo n.º 12
0
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  MFS_Write_device_sector
* Returned Value   :  error_code
* Comments  :
*     Reads or writes consecutive clusters.
*END*---------------------------------------------------------------------*/
_mfs_error MFS_Write_device_sector
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,
    uint_32                 sector_number,  /*[IN] sector number to read/write from/to file system medium */
    char_ptr                buffer_ptr      /*[IN/OUT] address of where data is to be stored/written */
    )
{
    uint_32    new_cluster_number, next_cluster, bad_cluster_number;
    uint_32    i;
    uint_32    retries, attempts;
    uint_32    new_sector_number, no_of_sectors;
    char_ptr   temp_buffer_ptr;
    int_32     num, expect_num, shifter, seek_loc, tmp;
    _mfs_error error;

#if MFSCFG_READ_ONLY_CHECK
    if (MFS_is_read_only (NULL, drive_ptr))
    {
        return MFS_DISK_IS_WRITE_PROTECTED;
    }
#endif

    error = MFS_NO_ERROR;

    MFS_LOG(printf("MFS_Write_device_sector %d\n", sector_number));

    if ( sector_number > drive_ptr->BPB.MEGA_SECTORS )
    {
        return(MFS_SECTOR_NOT_FOUND);
    }

    attempts = 0;
    /* Lock device */
    ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_LOCK, &drive_ptr->DRV_NUM);

    if ( drive_ptr->BLOCK_MODE )
    {
        shifter    = 0;
        seek_loc   = sector_number;
        expect_num = 1;
    }
    else
    {
        shifter    = drive_ptr->SECTOR_POWER;
        seek_loc   = sector_number << shifter;
        expect_num = 1 << shifter;
    }  

    MFS_device_write_internal(drive_ptr, seek_loc, buffer_ptr, &expect_num,  &buffer_ptr, shifter);

    if ( expect_num > 0 )
    {
        error = drive_ptr->DEV_FILE_PTR->ERROR;
#if MFSCFG_MAX_CLUSTER_REMAP_ATTEMPTS
        /*
        ** Check to see if the write failed due to a bad sector. If so, 
        ** rewrite cluster by cluster until we find bad cluster, then move 
        ** it.
        */
        temp_buffer_ptr = buffer_ptr;
        if ( drive_ptr->BLOCK_MODE )
        {
            expect_num = drive_ptr->BPB.SECTORS_PER_CLUSTER;
        }
        else
        {
            expect_num = drive_ptr->CLUSTER_SIZE_BYTES;
        }  
        tmp = expect_num;

        for ( i = 0; i < no_of_clusters; i++ )
        {
            MFS_device_write_internal(drive_ptr, seek_loc, temp_buffer_ptr, &expect_num, &buffer_ptr, shifter);

            if ( expect_num > 0 )
            {
                error_code = drive_ptr->DEV_FILE_PTR->ERROR;
                ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_UNLOCK, &drive_ptr->DRV_NUM);
                bad_cluster_number = cluster_number + i;
                error_code = MFS_get_cluster_from_fat(drive_ptr, bad_cluster_number, &next_cluster);
                if ( error_code != MFS_NO_ERROR )
                {
                    /* 
                    ** This is done so that the unlock at end of function
                    ** works properly
                    */
                    ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_LOCK, &drive_ptr->DRV_NUM);
                    break;
                }

                retries = MFSCFG_MAX_CLUSTER_REMAP_ATTEMPTS;

                while ( (error_code != MFS_NO_ERROR) && retries-- )
                {
                    /*
                    ** Mark old cluster BAD 
                    */
                    error_code = MFS_Put_fat(drive_ptr, bad_cluster_number, CLUSTER_BAD);
                    if ( error_code )
                    {
                        break;
                    }

                    /*
                    ** Find available fat, update old FAT as invalid, 
                    ** update new fat, and write new cluster.
                    */
                    new_cluster_number = MFS_Find_unused_cluster_from(drive_ptr, bad_cluster_number);
                    if ( new_cluster_number ==  CLUSTER_INVALID )
                    {
                        /*
                        ** No more clusters
                        */
                        return MFS_DISK_FULL;
                    }

                    new_sector_number = drive_ptr->DATA_START_SECTOR + ((uint_32)(new_cluster_number - CLUSTER_MIN_GOOD)) * drive_ptr->BPB.SECTORS_PER_CLUSTER;

                    ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_LOCK, &drive_ptr->DRV_NUM);

                    expect_num = tmp;

                    MFS_device_write_internal(drive_ptr, new_sector_number << shifter, temp_buffer_ptr, &expect_num, &buffer_ptr, shifter);

                    if ( expect_num > 0 )
                    {
                        error_code = drive_ptr->DEV_FILE_PTR->ERROR;
                    }

                    ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_UNLOCK, &(drive_ptr->DRV_NUM));
                    bad_cluster_number = new_cluster_number;
                }  

                if ( error_code != MFS_NO_ERROR )
                {
                    return MFS_WRITE_FAULT;
                }

                /*
                ** update chain, 
                */
                error_code = MFS_Put_fat(drive_ptr, new_cluster_number, next_cluster);
                if ( error_code )
                {
                    return(error_code);
                }

                if ( handle->PREVIOUS_CLUSTER )
                {
                    error_code = MFS_Put_fat(drive_ptr,handle->PREVIOUS_CLUSTER, new_cluster_number );
                    if ( error_code )
                    {
                        return(error_code);
                    }
                }
                else
                {
                    clustod(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER, new_cluster_number);
                }  
                handle->PREVIOUS_CLUSTER = new_cluster_number;
                ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_LOCK, &drive_ptr->DRV_NUM);
            }
            else
            {
                handle->PREVIOUS_CLUSTER = cluster_number+i;
            }  
            temp_buffer_ptr += drive_ptr->CLUSTER_SIZE_BYTES;
            sector_number   += drive_ptr->BPB.SECTORS_PER_CLUSTER;
        }  
#endif
    }

    /* Unlock device under MFS */
    ioctl(drive_ptr->DEV_FILE_PTR, IO_IOCTL_DEV_UNLOCK, &drive_ptr->DRV_NUM);

    switch ( error )
    {
        case IO_ERROR_WRITE_PROTECTED:
            error = MFS_DISK_IS_WRITE_PROTECTED;
            break;

        case IO_ERROR_WRITE:
            error = MFS_WRITE_FAULT;
            break;

        case IO_ERROR_WRITE_ACCESS:
            error = MFS_SECTOR_NOT_FOUND;
            break;

        case IO_ERROR_READ:
            error = MFS_READ_FAULT;
            break;

        case IO_ERROR_READ_ACCESS:
            error = MFS_SECTOR_NOT_FOUND;
            break;

        default:
            break;
    }  

    return(error);
}  
Ejemplo n.º 13
0
/*!
 * \brief Find a free cluster, follow a chain and add it to the chain.
 *
 * \param[in] drive_ptr The drive on which to operate.
 * \param[in] cluster_number Number of a cluster within the chain.
 * \param[in] num_clusters Number of clusters to append to chain.
 * \param[in] added_cluster Pointer to the place where we should put the # of the first  new cluster.
 *
 * \return _mfs_error
 */
_mfs_error MFS_Extend_chain(
    MFS_DRIVE_STRUCT_PTR drive_ptr,
    uint32_t cluster_number,
    uint32_t num_clusters,
    uint32_t *added_cluster)
{
    uint32_t next_cluster;
    uint32_t extended;
    _mfs_error error_code;

    if (cluster_number < CLUSTER_MIN_GOOD || cluster_number > drive_ptr->LAST_CLUSTER)
    {
        return MFS_INVALID_CLUSTER_NUMBER;
    }

    if (num_clusters <= 0)
    {
        return MFS_NO_ERROR;
    }

    /* Find the end of the chain */
    next_cluster = cluster_number;
    do
    {
        cluster_number = next_cluster;
        error_code = MFS_get_cluster_from_fat(drive_ptr, cluster_number, &next_cluster);
        if (error_code != MFS_NO_ERROR)
        {
            return error_code;
        }
        else if ((next_cluster > drive_ptr->LAST_CLUSTER || next_cluster < CLUSTER_MIN_GOOD) && next_cluster != CLUSTER_EOF)
        {
            return MFS_LOST_CHAIN;
        }
    } while (next_cluster != CLUSTER_EOF);

    extended = 0;

    while (num_clusters)
    {
        /* Find a free cluster */
        next_cluster = MFS_Find_unused_cluster_from(drive_ptr, cluster_number + 1);

        /* Check to see if the disk is not full */
        if (next_cluster == CLUSTER_INVALID)
        {
            break; /* Condition handled after the loop */
        }

        /* Link the free cluster to the chain, at the end */
        error_code = MFS_Put_fat(drive_ptr, cluster_number, next_cluster);
        if (error_code != MFS_NO_ERROR)
        {
            return error_code;
        }

        if (extended == 0 && added_cluster != NULL)
        {
            *added_cluster = next_cluster;
        }

        extended++;
        cluster_number = next_cluster;
        num_clusters--;
    }

    /* If the chain was extended, write EOF to it's last link */
    if (extended)
    {
        error_code = MFS_Put_fat(drive_ptr, cluster_number, CLUSTER_EOF);
    }

    if (num_clusters && !error_code)
    {
        error_code = MFS_DISK_FULL;
    }

    return error_code;
}
Ejemplo n.º 14
0
uint32_t MFS_Move_file_pointer
    (
    MFS_HANDLE_PTR          handle,
    MFS_DRIVE_STRUCT_PTR    drive_ptr,
    _mfs_error_ptr          error_ptr /*[IN/OUT] resulting error code is written to this address*/
    )
{
    uint32_t                 position_after_seek, position_before_seek;
    uint32_t                 current_cluster,
                            previous_cluster,
                            first_cluster,
                            skip_clusters,
                            k;
    _mfs_error              error_code;


    error_code = MFS_lock_dos_disk( drive_ptr );
    if ( error_code != MFS_NO_ERROR )
    {
        if ( error_ptr != NULL )
        {
            *error_ptr = error_code;
        }
        return 0;
    }

    position_after_seek = handle->LOCATION;

    MFS_LOG(printf("seek to %d\n",position_after_seek));

    /*
    ** Cannot move ahead of the beginning of the file; force beginning.
    */
    if ( error_code == MFS_NO_ERROR )
    {

        /*
        ** There are four cases
        **
        ** 1) Seeking to beginning of file (position_after_seek=0, cluster=0)
        ** 2) No change in position (position_after_seek==position_before_seek)
        ** 2) Seeking ahead of current file pointer
        ** 3) Seeking behind current file pointer
        */
        /*
        ** Cannot move beyond the end of file !
        */
        if ( position_after_seek> mqx_dtohl(handle->DIR_ENTRY.FILE_SIZE) )     // + 1
        {
            position_after_seek = mqx_dtohl(handle->DIR_ENTRY.FILE_SIZE);  //  - 1
            error_code = MFS_EOF;
        }

        current_cluster = 0;
        previous_cluster = 0;
        first_cluster = clustoh(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER);
        MFS_LOG(printf("first_cluster =  %d\n",first_cluster));

        /*
        ** Set the current_cluster correctly.
        ** If we're moving ahead, don't start from the beginning.
        */
        position_before_seek = CLUSTER_BOUNDARY(handle->SAVED_POSITION);

        if ( handle->CURRENT_CLUSTER==0 )
        {
            handle->CURRENT_CLUSTER = first_cluster;
            handle->PREVIOUS_CLUSTER = 0;
            position_before_seek = 0;
        }

        if ( position_after_seek == 0 )
        {
            current_cluster = first_cluster;
            previous_cluster = 0;
        }
        else if ( position_after_seek == position_before_seek )
        {
            current_cluster  = handle->CURRENT_CLUSTER;
            previous_cluster = handle->PREVIOUS_CLUSTER;
        }
        else
        {
            if ( position_after_seek < position_before_seek )
            {
                position_before_seek = 0;
                current_cluster = first_cluster;
                previous_cluster = 0;
            }
            else
            {
                current_cluster  = handle->CURRENT_CLUSTER;
                previous_cluster = handle->PREVIOUS_CLUSTER;
            }  

            MFS_LOG(printf("current cluster =  %d\n",current_cluster));

            if ( current_cluster && (current_cluster!=CLUSTER_EOF) )
            {
                /*
                ** How many clusters do we need to skip?
                */
                skip_clusters = (position_after_seek - position_before_seek) >> drive_ptr->CLUSTER_POWER_BYTES;
                for ( k = 0; k < skip_clusters; k++ )
                {
                    previous_cluster = current_cluster;

                    error_code = MFS_get_cluster_from_fat(drive_ptr, previous_cluster, &current_cluster);
                    if ( error_code != MFS_NO_ERROR )
                    {
                        break;
                    }
                    if ( current_cluster==CLUSTER_EOF )
                    {
                        error_code = MFS_EOF;
                        break;
                    }
                    else if ( (current_cluster < CLUSTER_MIN_GOOD) || (current_cluster > drive_ptr->LAST_CLUSTER) )
                    {
                        error_code = MFS_BAD_DISK_UNIT;
                        break;
                    }
                    MFS_LOG(printf("skip, current cluster =  %d\n",current_cluster));
                }  
            }
            else
            {
                error_code = MFS_EOF;
            }
        }  
Ejemplo n.º 15
0
_mfs_error  MFS_Increment_dir_index
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,  /*[IN] the drive on which to operate */
    uint_32_ptr    cluster_ptr,         /*[IN/OUT]  the initial/next cluster # */
    uint_32_ptr    index_ptr,           /*[IN/OUT]  the initial/next index */
    uint_32_ptr    prev_cluster_ptr     /*[IN/OUT]  the prev cluster # */
    )
{
    uint_32        index;
    uint_32        cluster;
    _mfs_error     error_code;

    error_code = MFS_NO_ERROR;
    index   = *index_ptr;
    cluster = *cluster_ptr;

    index++;

    if ( !(index & (drive_ptr->ENTRIES_PER_SECTOR-1)) )
    {
        /*
        ** if the index count LSB's wrapped to 0 (new sector)
        */
        if ( cluster != 0 )
        {
            if ( INDEX_TO_SECTOR (index) >= drive_ptr->BPB.SECTORS_PER_CLUSTER )
            {
                /*
                ** If we are over the size of a cluster
                */

                error_code = MFS_get_cluster_from_fat(drive_ptr,cluster, &cluster);
                if ( error_code == MFS_NO_ERROR )
                {
                    index = 0;
                }
            }
        }
        else
        {
            if ( index >= drive_ptr->BPB.ROOT_ENTRIES )
            {
                index = 0;
                cluster = CLUSTER_INVALID;
            }
        }  
    }

    if ( (cluster != *cluster_ptr) && (cluster != CLUSTER_INVALID) )
    {
        if ( prev_cluster_ptr != NULL )
        {
            *prev_cluster_ptr = *cluster_ptr;
        }
    }

    *index_ptr   = index;
    *cluster_ptr = cluster;

    return(error_code);
}