Beispiel #1
0
void MFS_Delete_handles
    (
    MFS_DRIVE_STRUCT_PTR      drive_ptr,    /*[IN] the drive on which to operate */
    char_ptr                  filename,     /*[IN]  the filename to be erased.*/
    uint_32                   cluster       /*[IN]  the first cluster of the file to be erased*/
    )
{
    MFS_HANDLE_PTR   next_handle;

    next_handle = (MFS_HANDLE_PTR) _queue_head(&(drive_ptr->HANDLE_LIST));
    while ( next_handle )
    {
        if ( clustoh(next_handle->DIR_ENTRY.HFIRST_CLUSTER,
            next_handle->DIR_ENTRY.LFIRST_CLUSTER) == cluster )
        {
            /*
            ** Although the starting clusters match (same file),
            ** a name comparison is needed in the case the file is 0 length
            ** (in which case the starting cluster is 0)
            */
            if ( !memcmp (next_handle->DIR_ENTRY.NAME, filename, 11) )
            {
                *next_handle->DIR_ENTRY.NAME = '\0';
            }
        }
        next_handle = (MFS_HANDLE_PTR) _queue_next(&drive_ptr->HANDLE_LIST, (QUEUE_ELEMENT_STRUCT_PTR) next_handle);
    }  
}  
void  *MFS_Create_file
    (
        MFS_DRIVE_STRUCT_PTR drive_ptr,
        unsigned char       attr,       /*[IN] attribute for created file*/
        char                *pathname,   /*[IN] directory and filename of the file to be created */
        _mfs_error_ptr      error_ptr   /*[IN/OUT] error code is written to this address */
    )
{
    MFS_HANDLE_PTR          handle;
    MFS_HANDLE_PTR          next_handle;
    MFS_DIR_ENTRY_PTR       dir_entry_ptr;
    TIME_STRUCT             time;
    DATE_STRUCT             clk_time;
    uint32_t                 dir_cluster;
    uint32_t                 dir_index;
    char                    access;
    _mfs_error              error_code, saved_code = 0;

    if ( (pathname == NULL) || (*pathname == '\0') )
    {
        *error_ptr = MFS_INVALID_PARAMETER;
        return( NULL );
    }

#if MFSCFG_READ_ONLY_CHECK
    if (MFS_is_read_only (drive_ptr))
    {
        *error_ptr = MFS_DISK_IS_WRITE_PROTECTED;
        return NULL;
    }
#endif

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

    handle = NULL;

    attr &= (MFS_ATTR_READ_ONLY | MFS_ATTR_HIDDEN_FILE | MFS_ATTR_SYSTEM_FILE | MFS_ATTR_ARCHIVE | MFS_ATTR_VOLUME_NAME);
    attr |= MFS_ATTR_ARCHIVE;
    access = (attr & MFS_ATTR_READ_ONLY) ? MFS_ACCESS_READ_ONLY : MFS_ACCESS_READ_WRITE;
    dir_entry_ptr =  MFS_Create_entry_slave(drive_ptr, attr, pathname, &dir_cluster, &dir_index, &error_code, TRUE);

    if ( (dir_entry_ptr != NULL) && !(attr & MFS_ATTR_VOLUME_NAME) )
    {
        handle = MFS_Get_handle(drive_ptr,dir_entry_ptr);
        if ( handle != NULL )
        {
            handle->DIR_CLUSTER = dir_cluster;
            handle->DIR_INDEX = dir_index;
            handle->ACCESS = access;
            handle->CURRENT_CLUSTER = 0;
            handle->PREVIOUS_CLUSTER = 0;

            /*
            ** If file exists, overwrite and set size to 0
            */
            if ( error_code == MFS_FILE_EXISTS )
            {
                _time_get(&time);
                _time_to_date(&time, &clk_time);
                NORMALIZE_DATE(&clk_time);
                saved_code = MFS_Release_chain(drive_ptr, clustoh(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER));
                if ( saved_code == MFS_NO_ERROR || saved_code == MFS_LOST_CHAIN )
                {
                    clustod(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER, 0);
                    mqx_htodl(handle->DIR_ENTRY.FILE_SIZE, 0L);
                    mqx_htodc(handle->DIR_ENTRY.ATTRIBUTE, attr);
                    mqx_htods(handle->DIR_ENTRY.TIME, PACK_TIME(clk_time));
                    mqx_htods(handle->DIR_ENTRY.DATE, PACK_DATE(clk_time));
                    error_code = MFS_Update_entry(drive_ptr, handle);

                    /*
                    ** If the same file is already open, mark it as 'freshly
                    ** truncated' so reads and writes don't clobber any data.
                    */
                    if ( error_code == MFS_NO_ERROR )
                    {
                        next_handle =  (MFS_HANDLE_PTR) _queue_head(&drive_ptr->HANDLE_LIST);
                        while ( next_handle )
                        {
                            if ( next_handle->DIR_CLUSTER == dir_cluster && next_handle->DIR_INDEX == dir_index )
                            {
                                next_handle->CURRENT_CLUSTER = 0;
                                next_handle->PREVIOUS_CLUSTER = 0;
                            }
                            next_handle =  (MFS_HANDLE_PTR) _queue_next(&drive_ptr->HANDLE_LIST, (QUEUE_ELEMENT_STRUCT_PTR) next_handle);
                        }  
                    }
                }
            }

            /*
            ** No need to update the disk image if we didn't change anything.
            */
            if ( (mqx_dtohc(handle->DIR_ENTRY.ATTRIBUTE) != attr) && (error_code == MFS_NO_ERROR) )
            {
                mqx_htodc(handle->DIR_ENTRY.ATTRIBUTE, attr);
                error_code = MFS_Update_entry(drive_ptr, handle);
            }

        }
        else
        {
            error_code = MFS_INSUFFICIENT_MEMORY;
        }  
    }

    MFS_unlock(drive_ptr,FALSE);

    if ( error_code == MFS_NO_ERROR && saved_code == MFS_LOST_CHAIN )
    {
        *error_ptr = saved_code;
    }
    else
    {
        *error_ptr = error_code; 
    }  

    return((void *)handle);
}  
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  MFS_Find_directory
* Returned Value   :  starting_cluster of the specified directory
* Comments  :  Search through the file structure to find the specified
*  directory.  Will search either from the current directory or from the
*  root directory.  Returns the starting cluster number of the specified
*  directory.  If the specified directory cannot be found, then 
*  CLUSTER_INVALID  is returned.
*
*END*---------------------------------------------------------------------*/
uint32_t MFS_Find_directory
    (
    MFS_DRIVE_STRUCT_PTR  drive_ptr,    /*[IN] drive context */
    char              *path_ptr,     /*[IN] specific directory to search for */
    uint32_t               first_cluster /*[IN] start searching in this cluster, used for a relative search*/
    )
{
    MFS_DIR_ENTRY_PTR     dir_entry_ptr;
    char              *directory;
    uint32_t               current_cluster;
    uint32_t               dir_index;
    _mfs_error            error_code;
    bool               flag;
    uint32_t               prev_cluster = CLUSTER_INVALID; 
    unsigned char                 attribute;


    if ( MFS_alloc_path(&directory)!= MFS_NO_ERROR )
    {
        return( CLUSTER_INVALID );
    }

    if ( *path_ptr == '\\' || *path_ptr == '/' )
    {
        current_cluster = ROOT_CLUSTER(drive_ptr);
        path_ptr++;
    }
    else
    {
        current_cluster = first_cluster;
    }  

    while ( path_ptr )
    {
        if ( *path_ptr )
        {
            path_ptr = MFS_Parse_next_filename(path_ptr, directory);

            if ( !MFS_lfn_dirname_valid(directory) )
            {
                current_cluster = CLUSTER_INVALID;
                break;
            }

            flag = FALSE;
            if ( current_cluster == 0 )  flag = TRUE;
            if ( drive_ptr->FAT_TYPE == MFS_FAT32 )
            {
                if ( current_cluster == drive_ptr->BPB32.ROOT_CLUSTER )
                {
                    flag = TRUE;
                }
            }

            if ( flag )
            {
                /*
                ** Special treatment for '.' and '..' in root directory
                */
                dir_index = MFS_Is_dot_directory(directory);
                if ( dir_index == 1 )
                {
                    /* Return the value of the root cluster */
                    MFS_free_path(directory);
                    return ROOT_CLUSTER(drive_ptr);
                }
                else if ( dir_index == 2 )
                {
                    MFS_free_path(directory);
                    return(CLUSTER_INVALID);
                }
            }

            dir_index = 0;

            dir_entry_ptr = MFS_Find_directory_entry( drive_ptr, directory,
                &current_cluster, &dir_index,  &prev_cluster, (~ATTR_EXCLUSIVE),  
                &error_code);

            if ( dir_entry_ptr == NULL )
            {
                current_cluster = CLUSTER_INVALID;
                break;
            }
            else
            {
                attribute = mqx_dtohc(dir_entry_ptr->ATTRIBUTE);

                if ( attribute & MFS_ATTR_DIR_NAME )
                {
                    current_cluster = clustoh(dir_entry_ptr->HFIRST_CLUSTER, dir_entry_ptr->LFIRST_CLUSTER);
                    if ( current_cluster == 0 && drive_ptr->FAT_TYPE == MFS_FAT32 )
                    {
                        current_cluster = drive_ptr->BPB32.ROOT_CLUSTER;
                    }
                }
                else
                {
                    // Found an entry, but it is not a directory
                    MFS_free_path(directory);
                    return(CLUSTER_INVALID);
                }
            }  
        }
        else
        {
            break;
        }  
    }  
    MFS_free_path(directory);

    return(current_cluster);
}  
_mfs_error MFS_Remove_subdir
    (
        MFS_DRIVE_STRUCT_PTR drive_ptr,
        
        char                *pathname     /*[IN] pathname of the directory to be removed */
    )
{
    _mfs_error              error_code, saved_error = 0;
    uint32_t                 dir_cluster, parent_cluster, dir_index;
    MFS_DIR_ENTRY_PTR       dir_entry_ptr;
    uint32_t                 prev_cluster= CLUSTER_INVALID; 
    uint32_t                 parent_prev_cluster= CLUSTER_INVALID; 

    if ( (pathname == NULL) || (*pathname == '\0') )
    {
        return MFS_INVALID_PARAMETER;
    }

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

    dir_entry_ptr = MFS_Find_entry_on_disk (drive_ptr, pathname, &error_code, &parent_cluster, &dir_index,  &parent_prev_cluster);  

    if ( dir_entry_ptr )
    {
        if ( mqx_dtohc(dir_entry_ptr->ATTRIBUTE) & MFS_ATTR_DIR_NAME )
        {
            dir_cluster = clustoh(dir_entry_ptr->HFIRST_CLUSTER, dir_entry_ptr->LFIRST_CLUSTER);
            if ( dir_cluster != drive_ptr->CUR_DIR_CLUSTER )
            {
                dir_index = 2;  /* Skip over '.' and '..' */
                dir_entry_ptr = MFS_Find_directory_entry (drive_ptr, NULL, &dir_cluster, &dir_index, &prev_cluster, MFS_ATTR_ANY, &error_code);  
                if ( dir_entry_ptr == NULL && !error_code )
                {
                    dir_index = 0;
                    dir_entry_ptr = MFS_Find_entry_on_disk (drive_ptr, pathname, &error_code, &parent_cluster, &dir_index, &parent_prev_cluster);
                    if ( dir_entry_ptr )
                    {
                        *dir_entry_ptr->NAME = MFS_DEL_FILE;
                        drive_ptr->DIR_SECTOR_DIRTY = TRUE;
                        error_code = MFS_remove_lfn_entries(drive_ptr, parent_cluster, dir_index, parent_prev_cluster); 
                        if ( !error_code )
                        {
                            saved_error = MFS_Release_chain(drive_ptr, dir_cluster);
                        }
                    }
                }
                else if ( dir_entry_ptr != NULL && !error_code )
                {
                    error_code = MFS_FILE_EXISTS;
                }
            }
            else
            {
                error_code = MFS_ATTEMPT_TO_REMOVE_CURRENT_DIR;
            }  
        }
        else
        {
            error_code = MFS_WRITE_FAULT;
        }  
    }
    else
    {
        error_code = MFS_PATH_NOT_FOUND;
    }  

    MFS_unlock(drive_ptr,TRUE);

    if ( saved_error == MFS_LOST_CHAIN && error_code == MFS_NO_ERROR )
    {
        error_code = saved_error;
    }

    return(error_code);
}  
uint32_t MFS_Write
    (
        MFS_HANDLE_PTR handle,
        
        MFS_DRIVE_STRUCT_PTR drive_ptr,
      
        uint32_t            num_bytes,      /*[IN] number of bytes to be written */ 

        char                *buffer_address, /*[IN/OUT] bytes are written from this buffer */

        _mfs_error_ptr      error_ptr       /*[IN/OUT] error code is written to this address */
    )
{
    uint32_t                 bytes_written;
    uint32_t                 copy_size;
    uint32_t                 cluster_offset;
    uint32_t                 sector_number, sector_index;
    uint32_t                 sector_offset;
    uint32_t                 whole_sectors;
    uint32_t                 cont_sectors;
    uint32_t                 proc_sectors;
    _mfs_error              error, temp_error;
    uint32_t                 file_size;
    uint32_t                 next_cluster;
    bool                 need_hwread;
    uint32_t                 location;
    uint32_t                 num_zeros;
    uint32_t                 zeros_written;
    uint32_t                 zero_size;

#if MFSCFG_READ_ONLY_CHECK
    if (MFS_is_read_only (drive_ptr))
    {
        MFS_set_error_and_return(error_ptr,MFS_DISK_IS_WRITE_PROTECTED,0);
    }
#endif

    if ( buffer_address == NULL )
    {
        MFS_set_error_and_return(error_ptr,MFS_INVALID_PARAMETER,0);
    }

    if ( num_bytes == 0 )
    {
        MFS_set_error_and_return(error_ptr,MFS_NO_ERROR,0);
    }

    error = MFS_lock_dos_disk( drive_ptr );
    if ( error != MFS_NO_ERROR )
    {
        MFS_set_error_and_return(error_ptr,error,0);
    }

    if ( handle->ACCESS == MFS_ACCESS_READ_ONLY )
    {
        MFS_unlock(drive_ptr,FALSE);
        MFS_set_error_and_return(error_ptr,MFS_ACCESS_DENIED,0);
    }

    /*
    ** Setup the current cluster. If this is the first time writing to the file, a cluster needs to be added.
    */
    if ( handle->CURRENT_CLUSTER == 0 )
    {
        handle->PREVIOUS_CLUSTER = 0;
        handle->CURRENT_CLUSTER = clustoh(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER);
        if ( handle->CURRENT_CLUSTER==0 )
        {
            next_cluster = MFS_Find_unused_cluster_from(drive_ptr,drive_ptr->NEXT_FREE_CLUSTER);
            if ( next_cluster != CLUSTER_INVALID )
            {
                clustod(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER, next_cluster);
                handle->TOUCHED = 1;

                error = MFS_Put_fat(drive_ptr, next_cluster, CLUSTER_EOF);
                if ( error == MFS_NO_ERROR )
                {
                    handle->CURRENT_CLUSTER = next_cluster;
                }
                else
                {
                    MFS_unlock(drive_ptr,FALSE);
                    MFS_set_error_and_return(error_ptr,error,0);
                }
            }
            else
            {
                MFS_unlock(drive_ptr,FALSE);
                MFS_set_error_and_return(error_ptr,MFS_DISK_FULL,0);
            }
        }
    }
    else if ( handle->CURRENT_CLUSTER == CLUSTER_EOF )
    {
        error = MFS_Add_cluster_to_chain(drive_ptr, handle->PREVIOUS_CLUSTER, &handle->CURRENT_CLUSTER);
        if ( MFS_NO_ERROR != error )
        {
            MFS_unlock(drive_ptr,FALSE);
            MFS_set_error_and_return(error_ptr,error,0);
        }
    }
    else if ( handle->CURRENT_CLUSTER > drive_ptr->LAST_CLUSTER )
    {
        MFS_unlock(drive_ptr,FALSE);
        MFS_set_error_and_return(error_ptr,MFS_DISK_FULL,0);
    }

    /* Make sure location (local variable) never points behind the end of file */
    file_size = mqx_dtohl(handle->DIR_ENTRY.FILE_SIZE);
    location = (handle->LOCATION > file_size) ? file_size : handle->LOCATION;

    /* Calculate sector number and offsets within cluster and sector */
    cluster_offset = OFFSET_WITHIN_CLUSTER(location);
    sector_index = CLUSTER_OFFSET_TO_SECTOR(cluster_offset);
    sector_number = CLUSTER_TO_SECTOR(handle->CURRENT_CLUSTER) + sector_index;
    sector_offset = OFFSET_WITHIN_SECTOR(location);

    /* Calculate possible gap to fill in by zeros if writing behind the end of file */
    num_zeros = handle->LOCATION - location;

    zeros_written = 0;
    bytes_written = 0;

    /* Write zeros to fill in gap if LOCATION points behind the end of file */
    while (zeros_written < num_zeros)
    {
        /* If offset is non-zero, then reading the data is required */
        error = MFS_Read_data_sector(drive_ptr, handle, sector_number, sector_offset != 0);
        if ( error != MFS_NO_ERROR )
            break;

        /* Zero the buffer  */
        zero_size = min(num_zeros-zeros_written, drive_ptr->BPB.SECTOR_SIZE-sector_offset);
        _mem_zero(&drive_ptr->DATA_SECTOR_PTR[sector_offset], zero_size);
        drive_ptr->DATA_SECTOR_DIRTY = TRUE;

        if ( drive_ptr->WRITE_CACHE_POLICY == MFS_WRITE_THROUGH_CACHE )
        {
            error = MFS_Flush_data_sector_buffer(drive_ptr);
            if ( error != MFS_NO_ERROR )
                break;
        }

        zeros_written += zero_size;
        sector_offset += zero_size;

        /*
        ** Check to see if we need to advance to the next sector, which has
        ** the side effect of increasing the cluster number if required.
        */
        if ( sector_offset >= drive_ptr->BPB.SECTOR_SIZE )
        {
            temp_error = MFS_next_data_sector(drive_ptr, handle, &sector_index, &sector_number);
            if (temp_error == MFS_EOF)
            {
                /* Always allocate new cluster, there is something to be written for sure */
                error = MFS_Add_cluster_to_chain(drive_ptr, handle->PREVIOUS_CLUSTER, &handle->CURRENT_CLUSTER);
                if ( MFS_NO_ERROR == error )
                {
                    sector_number = CLUSTER_TO_SECTOR(handle->CURRENT_CLUSTER);
                    sector_index = 0;
                }

            }
            else
            {
                error = temp_error;
            }
            sector_offset = 0;
        }
    }

    /* Write partial sector if sector_offset is non-zero */
    if ((sector_offset != 0) && (error == MFS_NO_ERROR))
    {
        /* Offset is non-zero, reading the data is required */
        error = MFS_Read_data_sector(drive_ptr, handle, sector_number, TRUE);

        if (error == MFS_NO_ERROR)
        {
            /* The requested lenght of data may span the sector to it's end  */
            copy_size = min(num_bytes, drive_ptr->BPB.SECTOR_SIZE-sector_offset);

            _mem_copy(buffer_address, &drive_ptr->DATA_SECTOR_PTR[sector_offset], copy_size);
            drive_ptr->DATA_SECTOR_DIRTY = TRUE;

            if (drive_ptr->WRITE_CACHE_POLICY == MFS_WRITE_THROUGH_CACHE)
            {
                error = MFS_Flush_data_sector_buffer(drive_ptr);
            }

            if (error == MFS_NO_ERROR)
            {
                bytes_written = copy_size;

                /*
                ** Check to see if we need to advance to the next sector, which has
                ** the side effect of increasing the cluster number if required.
                */
                if ((sector_offset + bytes_written) >= drive_ptr->BPB.SECTOR_SIZE)
                {
                    temp_error = MFS_next_data_sector(drive_ptr, handle, &sector_index, &sector_number);
                    /* Only an error if we are not done writing and can't extend the chain */
                    if (bytes_written < num_bytes)
                    {
                        if (temp_error == MFS_EOF)
                        {
                            /* Allocate new cluster */
                            error = MFS_Add_cluster_to_chain(drive_ptr, handle->PREVIOUS_CLUSTER, &handle->CURRENT_CLUSTER);
                            /* Update sector_number and index unconditionally - if there was an error the value is never used anyways. */
                            sector_number = CLUSTER_TO_SECTOR(handle->CURRENT_CLUSTER);
                            sector_index = 0;
                        }
                        else
                        {
                            error = temp_error;
                        }
                    }
                }
            }
        }
    }

    /* Check whether the application buffer is properly aligned */
    if ((((uint32_t)buffer_address+bytes_written) & drive_ptr->ALIGNMENT_MASK) == 0)
    {
        /* Yes, use zero copy approach */
        whole_sectors = (num_bytes - bytes_written) >> drive_ptr->SECTOR_POWER;
        while ((whole_sectors > 0) && (error == MFS_NO_ERROR))
        {
            cont_sectors = drive_ptr->BPB.SECTORS_PER_CLUSTER - sector_index;
            if (cont_sectors > whole_sectors)
                cont_sectors = whole_sectors;

            error = MFS_Write_device_sectors(drive_ptr, sector_number, cont_sectors, MFSCFG_MAX_WRITE_RETRIES, buffer_address+bytes_written, &proc_sectors);

            if (proc_sectors > 0)
            {
                bytes_written += proc_sectors * drive_ptr->BPB.SECTOR_SIZE;
                whole_sectors -= proc_sectors;

                /* Advance to next unprocessed sector */
                sector_index += proc_sectors - 1;
                temp_error = MFS_next_data_sector(drive_ptr, handle, &sector_index, &sector_number);
                /* Go on only if we are not done writing yet */
                if ((error == MFS_NO_ERROR) && (bytes_written < num_bytes))
                {
                    if (temp_error == MFS_EOF)
                    {
                        /* Allocate new cluster */
                        error = MFS_Add_cluster_to_chain(drive_ptr, handle->PREVIOUS_CLUSTER, &handle->CURRENT_CLUSTER);
                        /* Update sector_number and index unconditionally - if there was an error the value is never used anyways. */
                        sector_number = CLUSTER_TO_SECTOR(handle->CURRENT_CLUSTER);
                        sector_index = 0;

                    }
                    else
                    {
                        error = temp_error;
                    }
                }
            }
        }
    }
Beispiel #6
0
_mfs_error  MFS_Delete_file
    (
    MQX_FILE_PTR            mfs_fd_ptr, /*[IN] the MFS device on which to operate */
    char_ptr                pathname    /*[IN] directory and file name of the file to delete */
    )
{
    MFS_DRIVE_STRUCT_PTR    drive_ptr;
    MFS_DIR_ENTRY_PTR       dir_entry_ptr;
    _mfs_error              error_code, saved_code = 0;
    uint_32                 dir_cluster, dir_index;
    uint_32                 first_cluster;
    uint_32                 prev_cluster= CLUSTER_INVALID; 


    if ( (pathname == NULL) || (*pathname == '\0') )
    {
        return MFS_INVALID_PARAMETER;
    }

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

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

    dir_entry_ptr = MFS_Find_entry_on_disk(drive_ptr, pathname, &error_code, &dir_cluster, &dir_index, &prev_cluster); 

    if ( dir_entry_ptr != NULL )
    {
        if ( dtohc(dir_entry_ptr->ATTRIBUTE) & (MFS_ATTR_DIR_NAME | MFS_ATTR_VOLUME_NAME | MFS_ATTR_READ_ONLY) )
        {
            error_code = MFS_ACCESS_DENIED;
        }
        else
        {
            first_cluster = clustoh(dir_entry_ptr->HFIRST_CLUSTER, dir_entry_ptr->LFIRST_CLUSTER);

            if ( first_cluster )
            {
                saved_code = MFS_Release_chain(drive_ptr, first_cluster);

                if ( saved_code != MFS_LOST_CHAIN && saved_code != MFS_NO_ERROR )
                {
                    MFS_unlock(drive_ptr,TRUE);
                    return(saved_code);
                }
            }
            /*
            ** Mark all open files with the same name as erased
            */
            MFS_Delete_handles(drive_ptr, dir_entry_ptr->NAME, first_cluster);

            *dir_entry_ptr->NAME = MFS_DEL_FILE; 
            drive_ptr->DIR_SECTOR_DIRTY = TRUE;

            error_code = MFS_remove_lfn_entries(drive_ptr,dir_cluster,dir_index, prev_cluster);  
        } 
    }
    MFS_unlock(drive_ptr,TRUE);

    if ( saved_code == MFS_LOST_CHAIN && error_code == MFS_NO_ERROR )
    {
        error_code = saved_code;
    }

    return(error_code);
} 
Beispiel #7
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;
            }
        }  
Beispiel #8
0
uint32_t  MFS_Read
    (
    MFS_HANDLE_PTR          handle, /*[IN] file handle upon which the action is to be taken */
    MFS_DRIVE_STRUCT_PTR    drive_ptr,
    uint32_t                num_bytes,      /*[IN] number of bytes to be read */
    char                    *buffer_address, /*[IN/OUT] bytes are read into this buffer */
    _mfs_error_ptr          error_ptr       /*[IN/OUT] error code is written to this address */
    )
{
    uint32_t                 location;
    uint32_t                 bytes_read;
    uint32_t                 bytes_left_in_file;
    uint32_t                 copy_size;
    uint32_t                 cluster_offset;
    uint32_t                 sector_number, sector_index;
    uint32_t                 sector_offset;
    uint32_t                 whole_sectors;
    uint32_t                 cont_sectors;
    uint32_t                 proc_sectors;
    _mfs_error               error, temp_error;
    bool                     eof_reached;
    uint32_t                 file_size;

    if ( num_bytes == 0 )
    {
        MFS_set_error_and_return(error_ptr,MFS_NO_ERROR,0);
    }

    if ( buffer_address == NULL )
    {
        MFS_set_error_and_return(error_ptr,MFS_INVALID_PARAMETER,0);
    }

    error = MFS_lock_dos_disk(drive_ptr);
    if ( error != MFS_NO_ERROR )
    {
        MFS_set_error_and_return(error_ptr,error,0);
    }

    if ( handle->ACCESS != MFS_ACCESS_READ_ONLY &&
        handle->ACCESS != MFS_ACCESS_READ_WRITE )
    {
        MFS_unlock(drive_ptr,FALSE);
        MFS_set_error_and_return(error_ptr,MFS_ACCESS_DENIED,0);
    }


    if ( handle->CURRENT_CLUSTER == 0 )
    {
        handle->PREVIOUS_CLUSTER = 0;
        handle->CURRENT_CLUSTER = clustoh(handle->DIR_ENTRY.HFIRST_CLUSTER, handle->DIR_ENTRY.LFIRST_CLUSTER);
    }
    else if ( handle->CURRENT_CLUSTER == CLUSTER_EOF )
    {
        MFS_unlock(drive_ptr,FALSE);
        MFS_set_error_and_return(error_ptr,MFS_EOF,0);
    }


    bytes_read = 0;
    eof_reached = FALSE;
    location = handle->LOCATION;

    /*
    ** Can't read past file size
    */
    file_size = mqx_dtohl(handle->DIR_ENTRY.FILE_SIZE);
    if ( location > file_size )
    {
        location = file_size;
    }
    bytes_left_in_file = file_size - location;
    if ( num_bytes > bytes_left_in_file )
    {
        eof_reached = TRUE;
        num_bytes = bytes_left_in_file;
    }

    if ( bytes_left_in_file )
    {
        /*
        ** Read the number of bytes from the current file
        ** position to the end of the current cluster
        */
        cluster_offset = OFFSET_WITHIN_CLUSTER(location);
        sector_index = CLUSTER_OFFSET_TO_SECTOR(cluster_offset);
        sector_number = CLUSTER_TO_SECTOR(handle->CURRENT_CLUSTER) + sector_index;
        sector_offset = OFFSET_WITHIN_SECTOR(location);

        /* Read partial sector if sector_offet is non-zero */
        if (sector_offset != 0)
        {
            error = MFS_Read_data_sector(drive_ptr, handle, sector_number, TRUE);
            if ( error == MFS_NO_ERROR )
            {
                /* The requested lenght of data may span the sector to it's end  */
                copy_size = min(num_bytes, drive_ptr->BPB.SECTOR_SIZE-sector_offset);

                _mem_copy(&drive_ptr->DATA_SECTOR_PTR[sector_offset], buffer_address, copy_size);
                bytes_read=copy_size;

                /*
                ** Check to see if we need to advance to the next sector, which has
                ** the side effect of increasing the cluster number if required.
                */
                if ( (sector_offset+bytes_read) >= drive_ptr->BPB.SECTOR_SIZE )
                {
                    temp_error = MFS_next_data_sector(drive_ptr, handle, &sector_index, &sector_number);
                    /* Only an error if we are not done reading */
                    if ( bytes_read<num_bytes )
                    {
                        error = temp_error;
                    }
                }
            }
        }

        /* Check whether the application buffer is properly aligned */
        if ((((uint32_t)buffer_address+bytes_read) & drive_ptr->ALIGNMENT_MASK) == 0)
        {
            /* Yes, use zero copy approach */
            whole_sectors = (num_bytes - bytes_read) >> drive_ptr->SECTOR_POWER;
            while ((whole_sectors > 0) && (error == MFS_NO_ERROR))
            {
                cont_sectors = drive_ptr->BPB.SECTORS_PER_CLUSTER - sector_index;
                if (cont_sectors > whole_sectors)
                    cont_sectors = whole_sectors;

                error = MFS_Read_device_sectors(drive_ptr, sector_number, cont_sectors, MFSCFG_MAX_READ_RETRIES, buffer_address+bytes_read, &proc_sectors);

                if (proc_sectors > 0)
                {
                    bytes_read += proc_sectors * drive_ptr->BPB.SECTOR_SIZE;
                    whole_sectors -= proc_sectors;

                    /* Advance to next unprocessed sector */
                    sector_index += proc_sectors - 1;
                    temp_error = MFS_next_data_sector(drive_ptr, handle, &sector_index, &sector_number);
                    /* Only an error if we are not done reading */
                    if ((error==MFS_NO_ERROR) && (bytes_read<num_bytes))
                    {
                        error = temp_error;
                    }
                }
            }
        }
        else
        {