Beispiel #1
0
_mfs_error MFS_Flush_caches
    (
    MFS_DRIVE_STRUCT_PTR  drive_ptr
    )
{
#if MFSCFG_READ_ONLY
    return MFS_NO_ERROR;
#else
    _mfs_error        error_code, return_code = MFS_NO_ERROR;

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

    return_code = MFS_Flush_directory_sector_buffer(drive_ptr);
    error_code = MFS_Flush_data_sector_buffer(drive_ptr);
    if ( return_code == MFS_NO_ERROR ) return_code = error_code;
    error_code = MFS_Flush_fat_cache(drive_ptr);
    if ( return_code == MFS_NO_ERROR ) return_code = error_code;

    return(return_code);
#endif   
}  
Beispiel #2
0
/*!
 * \brief Unmounts the filesystem.
 *
 * This function brings filesystem on drive to consistent state by flushing
 * all cached data and releases data structures.
 *
 * \param drive_ptr
 *
 * \return int Error code.
 */
int MFS_Unmount_drive_internal(
    MFS_DRIVE_STRUCT_PTR drive_ptr)
{
    int result = MFS_NO_ERROR;

#if !MFSCFG_READ_ONLY
    if (drive_ptr->FAT_TYPE == MFS_FAT32)
    {
        if (!MFS_is_read_only(drive_ptr))
        {
            FILESYSTEM_INFO_DISK_PTR fsinfo_ptr;
            result = MFS_sector_map(drive_ptr, drive_ptr->FS_INFO, (void **)&fsinfo_ptr, MFS_MAP_MODE_OVERWRITE, 0);
            if (result == MFS_NO_ERROR)
            {
                mqx_htodl(fsinfo_ptr->LEAD_SIG, FSI_LEADSIG);
                mqx_htodl(fsinfo_ptr->STRUCT_SIG, FSI_STRUCTSIG);
                mqx_htodl(fsinfo_ptr->FREE_COUNT, drive_ptr->FREE_COUNT);
                mqx_htodl(fsinfo_ptr->NEXT_FREE, drive_ptr->NEXT_FREE_CLUSTER);
                mqx_htodl(fsinfo_ptr->TRAIL_SIG, FSI_TRAILSIG);

                result = MFS_sector_unmap(drive_ptr, drive_ptr->FS_INFO, 1);
            }
        }
    }
#endif

    return result;
}
Beispiel #3
0
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  MFS_Write_back_directory_sector_buffer
* Returned Value   :  MFS error code
* Comments  :
*   Write the sector buffer back to the disk.
*   Assumes the semaphore is already obtained.
*END*---------------------------------------------------------------------*/
_mfs_error MFS_Write_back_directory_sector_buffer
    (
    MFS_DRIVE_STRUCT_PTR  drive_ptr
    )
{
#if MFSCFG_READ_ONLY
    return MFS_NO_ERROR;
#else
    _mfs_error   error_code = MFS_NO_ERROR;

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

    MFS_LOG(printf("MFS_Write_back_directory_sector_buffer"));
    drive_ptr->DIR_SECTOR_DIRTY = TRUE;
    if ( drive_ptr->WRITE_CACHE_POLICY==MFS_WRITE_THROUGH_CACHE )
    {
        error_code = MFS_Flush_directory_sector_buffer(drive_ptr);
    }

    return(error_code);
#endif

}  
Beispiel #4
0
_mfs_error MFS_Flush_data_sector_buffer
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr     /*[IN] the drive on which to operate */
    )
{
#if MFSCFG_READ_ONLY
    return MFS_NO_ERROR;
#else
    _mfs_error   error_code = MFS_NO_ERROR;

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

    if ( drive_ptr->DATA_SECTOR_DIRTY )
    {
        error_code = MFS_Write_device_sector(drive_ptr,drive_ptr->DATA_SECTOR_NUMBER,drive_ptr->DATA_SECTOR_PTR);

        if ( error_code == MFS_NO_ERROR )
        {
            drive_ptr->DATA_SECTOR_DIRTY=FALSE;
        }
    }

    return error_code;
#endif
}  
Beispiel #5
0
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  MFS_Flush_directory_sector_buffer
* Returned Value   :  MFS error code
* Comments  :
*   Write the sector buffer back to the disk.
*   Assumes the semaphore is already obtained.
*END*---------------------------------------------------------------------*/
_mfs_error MFS_Flush_directory_sector_buffer
    (
    MFS_DRIVE_STRUCT_PTR  drive_ptr
    )
{
#if MFSCFG_READ_ONLY
    return MFS_NO_ERROR;
#else
    _mfs_error   error_code= MFS_NO_ERROR;

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

    if ( drive_ptr->DIR_SECTOR_DIRTY )
    {
        error_code = MFS_Write_device_sector(drive_ptr,drive_ptr->DIR_SECTOR_NUMBER,drive_ptr->DIR_SECTOR_PTR);
        drive_ptr->DIR_SECTOR_DIRTY = FALSE;
    }

    return(error_code);
#endif
}  
Beispiel #6
0
_mfs_error  MFS_Clear_cluster
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,  /*[IN] the drive on which to operate */
    uint_32                 cluster     /*[IN]  the # of the cluster to clear*/
    )
{
    uint_32      sector,i;
    _mfs_error   error_code;

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

    error_code = MFS_Flush_directory_sector_buffer(drive_ptr);
    sector = CLUSTER_TO_SECTOR(cluster);

    _mem_zero(drive_ptr->DIR_SECTOR_PTR, drive_ptr->BPB.SECTOR_SIZE);
    for ( i = 0; ((i<drive_ptr->BPB.SECTORS_PER_CLUSTER) && (error_code==MFS_NO_ERROR));i++ )
    {
        error_code = MFS_Write_device_sector(drive_ptr,sector+i,drive_ptr->DIR_SECTOR_PTR);
    } 
    drive_ptr->DIR_SECTOR_NUMBER = sector;
    return(error_code);
}  
Beispiel #7
0
_mfs_error MFS_Set_file_attributes
    (
    MQX_FILE_PTR            mfs_fd_ptr,  
    char _PTR_              pathname,       /*[IN] pathname of the specific file */
    uchar_ptr               attribute_ptr   /*[IN] attribute of file */
    )
{
    MFS_DRIVE_STRUCT_PTR    drive_ptr;
    MFS_DIR_ENTRY_PTR       dir_entry_ptr;
    _mfs_error              error_code;
    uint_32                 dir_cluster, dir_index;
    uchar                   at, attrib;
    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;
    }
    attrib = *attribute_ptr;
    attrib &= MFS_ATTR_ARCHIVE | MFS_ATTR_READ_ONLY | MFS_ATTR_HIDDEN_FILE | MFS_ATTR_SYSTEM_FILE;
    dir_entry_ptr = MFS_Find_entry_on_disk(drive_ptr, pathname, &error_code, &dir_cluster, &dir_index, &prev_cluster);  
    if ( error_code == MFS_NO_ERROR )
    {
        at = dtohc(dir_entry_ptr->ATTRIBUTE);
        if ( at != *attribute_ptr )
        {
            /*
            ** The volume-label and the directory-name are mutually exclusive.
            ** The volume-label cannot act as a directory-name. Check whether
            ** you are trying to set the attributes to a volume.
            */
            if ( ! ((at & MFS_ATTR_VOLUME_NAME) || (*attribute_ptr & MFS_ATTR_VOLUME_NAME)) )
            {
                htodc(dir_entry_ptr->ATTRIBUTE, *attribute_ptr);
                drive_ptr->DIR_SECTOR_DIRTY = TRUE;
            }
            else
            {
                error_code = MFS_ACCESS_DENIED;
            }  
        }
    }

    MFS_unlock(drive_ptr,TRUE);

    return(error_code);
}  
Beispiel #8
0
void MFS_Decrement_free_clusters(MFS_DRIVE_STRUCT_PTR drive_ptr)
{
#if MFSCFG_READ_ONLY_CHECK
    if (MFS_is_read_only (NULL, drive_ptr))
    {
        return;
    }
#endif
    if ( drive_ptr->FREE_COUNT != FSI_UNKNOWN )
    {
        drive_ptr->FREE_COUNT--;
    }
}
Beispiel #9
0
_mfs_error MFS_Flush_fat_cache
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr   /*[IN] the drive on which to operate */
    )
{
#if MFSCFG_READ_ONLY
    return MFS_NO_ERROR;
#else
    _mfs_error  error_code;
    uint_32     fat_size,fat,i;

    error_code = MFS_NO_ERROR;

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

    if ( drive_ptr->FAT_CACHE_DIRTY )
    {
        if ( drive_ptr->FAT_TYPE == MFS_FAT32 )
        {
            fat_size = drive_ptr->BPB32.FAT_SIZE;
        }
        else
        {
            fat_size = drive_ptr->BPB.SECTORS_PER_FAT;
        }  

        /* Backup all copies of fat */
        for ( fat=0; (fat<drive_ptr->BPB.NUMBER_OF_FAT) && (error_code==MFS_NO_ERROR); fat++ )
        {
            for ( i=0; (i<drive_ptr->FAT_CACHE_SIZE) && (error_code==MFS_NO_ERROR); i++ )
            {
                error_code = MFS_Write_device_sector(drive_ptr, 
                    drive_ptr->FAT_START_SECTOR + drive_ptr->FAT_CACHE_START + i + (fat * fat_size), 
                    (pointer) &drive_ptr->FAT_CACHE_PTR[drive_ptr->BPB.SECTOR_SIZE*i]);
            }
        }  

        if ( error_code == MFS_NO_ERROR )
        {
            drive_ptr->FAT_CACHE_DIRTY = FALSE;
        }
    }

    return(error_code);
#endif
}  
Beispiel #10
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);
}  
Beispiel #11
0
/*!
 * \brief
 *
 * Verifies that the drive is mounted and possibly checks other preconditions.
 * The function assumes that the drive is locked.
 *
 * \param drive_ptr
 * \param mode
 *
 * \return _mfs_error
 */
_mfs_error MFS_enter(
    MFS_DRIVE_STRUCT_PTR drive_ptr,
    int mode)
{
    if (!drive_ptr->DOS_DISK)
    {
        return MFS_NOT_A_DOS_DISK;
    }

    if ((mode & MFS_ENTER_READWRITE) && MFS_is_read_only(drive_ptr))
    {
        return MFS_DISK_IS_WRITE_PROTECTED;
    }

    return MFS_NO_ERROR;
}
Beispiel #12
0
_mfs_error MFS_Update_entry
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,  /*[IN] the drive on which to operate */
    MFS_HANDLE_PTR          handle      /*[IN] Update this file */
    )
{
    uint_32              dir_index;
    uint_32              dir_cluster;
    _mfs_error           error_code = MFS_NO_ERROR;
    MFS_DIR_ENTRY_PTR    dir_entry_ptr;
    uint_32              prev_cluster; 

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

    if ( handle == NULL )
    {
        error_code = MFS_INVALID_HANDLE;
    }
    else
    {
        dir_cluster =  handle->DIR_CLUSTER;
        dir_index   =  handle->DIR_INDEX;

        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 )
        {
            error_code = MFS_FILE_NOT_FOUND;
        }
        else
        {
            _mem_copy(&handle->DIR_ENTRY, dir_entry_ptr, sizeof(MFS_DIR_ENTRY));
            drive_ptr->DIR_SECTOR_DIRTY = TRUE;
        }  

    }  

    return(error_code);
}  
Beispiel #13
0
_mfs_error MFS_Invalidate_data_sector
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr   /*[IN] the drive on which to operate */
    )
{
#if MFSCFG_READ_ONLY
    return MFS_NO_ERROR;
#else

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

    drive_ptr->DATA_SECTOR_NUMBER = MAX_UINT_32;
    drive_ptr->DATA_SECTOR_DIRTY=FALSE;
    return MFS_NO_ERROR;
#endif
}  
Beispiel #14
0
int32_t  MFS_Close_file
    (
        MFS_HANDLE_PTR handle,
        MFS_DRIVE_STRUCT_PTR drive_ptr
    )
{
    TIME_STRUCT             time;
    DATE_STRUCT             clk_time;
    _mfs_error              error_code;

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

#if !MFSCFG_READ_ONLY
#if MFSCFG_READ_ONLY_CHECK
    if (MFS_is_read_only (drive_ptr))
    {
        error_code = MFS_DISK_IS_WRITE_PROTECTED;
    }
#endif    
    if ((handle->TOUCHED) && (error_code == MFS_NO_ERROR))
    {
        _time_get(&time);
        _time_to_date(&time, &clk_time);
        NORMALIZE_DATE(&clk_time);
        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);
    }
#endif

    MFS_Free_handle(drive_ptr, handle);
    MFS_unlock(drive_ptr,TRUE);

    return(int32_t) error_code;
}  
Beispiel #15
0
_mfs_error MFS_Write_back_fat
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr
    )
{

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

    if ( drive_ptr->FAT_CACHE_POLICY == MFS_WRITE_THROUGH_CACHE )
    {
        return( MFS_Flush_fat_cache(drive_ptr) );
    }
    else
    {
        return( MFS_NO_ERROR );
    } 
}  
Beispiel #16
0
int_32 MFS_Close_Device
    (
    MQX_FILE_PTR             fd_ptr /* [IN] the MFS file handle for the device being closed */
    )
{
    MFS_DRIVE_STRUCT_PTR      drive_ptr;
    FILESYSTEM_INFO_DISK_PTR  fsinfo_ptr;
    int_32                    result = MFS_NO_ERROR;

#if !MFSCFG_READ_ONLY
#if MFSCFG_READ_ONLY_CHECK
    if (MFS_is_read_only (fd_ptr, NULL))
    {
        result = MFS_DISK_IS_WRITE_PROTECTED;
    }
#endif
    if (result != MFS_DISK_IS_WRITE_PROTECTED)
    {
        result = _io_ioctl(fd_ptr, IO_IOCTL_FLUSH_OUTPUT, NULL); 
    }
#endif

    MFS_lock(fd_ptr, &drive_ptr);

#if !MFSCFG_READ_ONLY
    if (result != MFS_DISK_IS_WRITE_PROTECTED)
    {
        MFS_Flush_caches(drive_ptr);
    }
#endif

    if ( _queue_is_empty(&drive_ptr->HANDLE_LIST) )
    {
        if ( drive_ptr->FAT_TYPE == MFS_FAT32 )
        {
#if !MFSCFG_READ_ONLY
            if (result != MFS_DISK_IS_WRITE_PROTECTED)
            {
                fsinfo_ptr = (FILESYSTEM_INFO_DISK_PTR)drive_ptr->DATA_SECTOR_PTR;
                if ( fsinfo_ptr != NULL )
                {
                    htodl(fsinfo_ptr->LEAD_SIG,   FSI_LEADSIG);
                    htodl(fsinfo_ptr->STRUCT_SIG, FSI_STRUCTSIG);
                    htodl(fsinfo_ptr->FREE_COUNT, drive_ptr->FREE_COUNT);
                    htodl(fsinfo_ptr->NEXT_FREE,  drive_ptr->NEXT_FREE_CLUSTER);
                    htodl(fsinfo_ptr->TRAIL_SIG,  FSI_TRAILSIG);

                    MFS_Write_device_sector(drive_ptr, FSINFO_SECTOR, (char_ptr)fsinfo_ptr);
                }
            }
#endif
        }

        MFS_free_drive_data(drive_ptr, TRUE);

        drive_ptr->MFS_FILE_PTR = NULL;
        result = MFS_NO_ERROR;
    }
    else
    {
    	/* liutest add for get unclose handle */
    	MFS_HANDLE_PTR          next_handle;
        next_handle =  (MFS_HANDLE_PTR) _queue_head(&drive_ptr->HANDLE_LIST);
          while ( next_handle )
          {
        	  printf("unclose handle 0x%X\n",(uint_32)next_handle);
               next_handle =  (MFS_HANDLE_PTR) _queue_next(&drive_ptr->HANDLE_LIST, (QUEUE_ELEMENT_STRUCT_PTR) next_handle);
          }  
          
        result = MFS_SHARING_VIOLATION;
        /* MFS_free_drive_data(drive_ptr, TRUE);

         drive_ptr->MFS_FILE_PTR = NULL;
         result = MFS_NO_ERROR;*/
    }  

    MFS_unlock(drive_ptr,FALSE);

    return result;

}  
void  *MFS_Create_temp_file
    (
        MFS_DRIVE_STRUCT_PTR drive_ptr,
        
        
        unsigned char       attr,           /*[IN] attribute to be given to the file when it is created */
        char                *pathname,       /*[IN] provides the directory path where the file is to be created,
                                            **[OUT] the file name is appended to the directory name */
        _mfs_error_ptr      error_ptr    /*[OUT] Pointer for the MFS ERROR CODE location */
    )
{
    MFS_HANDLE_PTR       handle;
    MFS_DIR_ENTRY_PTR       dir_entry_ptr;
    _mfs_error              error_code;
    uint32_t                 dir_cluster, dir_index;
    uint16_t                 trial;
    char                *last_char;
    uint16_t                 pathlen;
    unsigned char                   access;
    char                *temp_file;

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

    trial = 0;
    error_code = MFS_FILE_NOT_FOUND;
    handle = NULL;

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

    *error_ptr  = MFS_alloc_path(&temp_file);
    if ( *error_ptr )
    {
        return( NULL );
    }

    *error_ptr = MFS_lock_dos_disk( drive_ptr );
    if ( *error_ptr != MFS_NO_ERROR )
    {
        MFS_free_path(temp_file);
        return 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_cluster = drive_ptr->CUR_DIR_CLUSTER;
    dir_cluster = MFS_Find_directory(drive_ptr, pathname, dir_cluster);

    if ( dir_cluster == CLUSTER_INVALID )
    {
        error_code = MFS_PATH_NOT_FOUND;
    }
    else
    {
        pathlen = strlen (pathname);
        last_char = pathname + pathlen;
        if ( pathlen )
        {
            last_char--;
        }

        do
        {
            sprintf(temp_file, (*last_char == '\\' || *last_char == '/' || pathlen == 0) ?
                "%sTMP%05.5lu.@@@" : "%s\\TMP%05.5lu.@@@", pathname, (uint32_t) trial);
            dir_entry_ptr = MFS_Create_entry_slave(drive_ptr, attr, temp_file, &dir_cluster, &dir_index, &error_code, FALSE);
            trial++;
        } while ( (error_code == MFS_FILE_EXISTS) && (trial < MFSCFG_FIND_TEMP_TRIALS) );

        if ( error_code == MFS_NO_ERROR )
        {
            handle = MFS_Get_handle(drive_ptr,dir_entry_ptr);
            if ( handle )
            {
                _mem_copy (temp_file, pathname, strlen(temp_file) + 1);
                handle->DIR_CLUSTER = dir_cluster;
                handle->DIR_INDEX = dir_index;
                handle->ACCESS = access;
                handle->CURRENT_CLUSTER = 0;
                handle->PREVIOUS_CLUSTER = 0;
            }
            else
            {
                error_code = MFS_INSUFFICIENT_MEMORY;
            }  
        }
    }  

    MFS_free_path(temp_file);
    MFS_unlock(drive_ptr,FALSE);

    if ( error_ptr )
    {
        *error_ptr = error_code;
    }

    return((void *) handle);
}  
Beispiel #18
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 #19
0
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  MFS_Write_device_sectors
* Returned Value   :  error_code
* Comments  :
*     Reads or writes consecutive sectors.
*END*---------------------------------------------------------------------*/
_mfs_error MFS_Write_device_sectors
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,
    uint_32                 sector_number,  /*[IN] first sector to read/write from/to file system medium */
    uint_32                 sector_count,   /*[IN] number of sectors to read/write from/to file system medium */
    uint_32                 max_retries,    /*[IN] number of retries of the same low level operation if it fails */ 
    char_ptr                buffer_ptr,     /*[IN/OUT] address of where data is to be stored/written */
    uint_32_ptr             processed       /*[OUT] number of sector successfully processed */
    )
{
    uint_32    attempts;
    int_32     num, expect_num, seek_loc, shifter;
    char_ptr   data_ptr;
    _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);
    }

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

    fseek(drive_ptr->DEV_FILE_PTR, seek_loc, IO_SEEK_SET);

    data_ptr = buffer_ptr;
    attempts = 0;
    while ( expect_num > 0 && attempts <= max_retries)
    {
        num = write(drive_ptr->DEV_FILE_PTR, data_ptr, expect_num);
        if ( num == IO_ERROR )
        {
            error = IO_ERROR_WRITE;
            break;
        }
        if ( num > 0 )
        {
            expect_num -= num;
            data_ptr += num << (drive_ptr->SECTOR_POWER - shifter);
            attempts = 0; /* there is a progress, reset attempts counter */
        }
        attempts++;
    }  

    if ( expect_num > 0 )
    {
        error = drive_ptr->DEV_FILE_PTR->ERROR;
    }
    else if (drive_ptr->READBACK_SECTOR_PTR) 
    {
        fseek(drive_ptr->DEV_FILE_PTR, seek_loc, IO_SEEK_SET);
        
        data_ptr = buffer_ptr;        
        expect_num = sector_count << shifter;
        while ( expect_num > 0 )
        {
            num = read(drive_ptr->DEV_FILE_PTR, drive_ptr->READBACK_SECTOR_PTR, 1<<shifter);
            if ( num != (1<<shifter) )
            {
                error = drive_ptr->DEV_FILE_PTR->ERROR;
                break;
            } 
            if ( memcmp(data_ptr, drive_ptr->READBACK_SECTOR_PTR, drive_ptr->BPB.SECTOR_SIZE) != 0 ) 
            {
                error = IO_ERROR_WRITE;
                break;
            }
            expect_num -= num;
            data_ptr += num << (drive_ptr->SECTOR_POWER - shifter);
        }
    }    
    
    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;

        case MFS_NO_ERROR:
            /* Ensure that error code is always set if less than requested data was written */
            if ( expect_num > 0 ) error = MFS_WRITE_FAULT;
            break;

        default:
            break;
    }  

    if (processed)
        *processed = ((sector_count<<shifter) - expect_num) >> shifter;  
        
    return error;
}  
Beispiel #20
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);
}  
Beispiel #21
0
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 #22
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);
}  
Beispiel #23
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);
}  
_mfs_error  MFS_Create_subdir
    (
        MFS_DRIVE_STRUCT_PTR drive_ptr,
        
        char                *pathname    /*[IN] pathname of the directory to be created */
    )
{
    MFS_DIR_ENTRY_PTR       dir_entry_ptr;
    uint32_t                 dir_cluster;
    uint32_t                 parent_cluster;
    uint32_t                 free_cluster;
    uint32_t                 dir_index;
    _mfs_error              error_code;
    char                *temp_dirname;
    char                *temp_filename;

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

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

    error_code = MFS_alloc_2paths(&temp_dirname,&temp_filename);
    if ( error_code != MFS_NO_ERROR )
    {
        return( error_code );
    }
    error_code = MFS_lock_dos_disk( drive_ptr );
    if ( error_code != MFS_NO_ERROR )
    {
        MFS_free_path(temp_dirname);
        MFS_free_path(temp_filename);
        return error_code;
    }

    MFS_Parse_pathname (temp_dirname, temp_filename, pathname);
    dir_cluster = drive_ptr->CUR_DIR_CLUSTER;
    parent_cluster = MFS_Find_directory (drive_ptr, temp_dirname, dir_cluster);

    dir_cluster = parent_cluster;
    if ( MFS_is_valid_lfn(temp_filename) )
    {
        if ( dir_cluster != CLUSTER_INVALID )
        {
            /*
            ** We'll obtain a cluster for the new directory first. If we
            ** cannot create the directory afterwards, it is easier to re-free
            ** the cluster than to remove the new entry.
            */
            free_cluster = MFS_Find_unused_cluster_from(drive_ptr, drive_ptr->NEXT_FREE_CLUSTER);
            if ( free_cluster != CLUSTER_INVALID )
            {
                error_code = MFS_Clear_cluster(drive_ptr, free_cluster);
                if ( error_code )
                {
                    MFS_unlock(drive_ptr,TRUE);
                    MFS_free_path(temp_dirname);
                    MFS_free_path(temp_filename);
                    return( error_code );
                }
                error_code = MFS_Put_fat(drive_ptr, free_cluster, CLUSTER_EOF);
                dir_entry_ptr = MFS_Create_directory_entry(drive_ptr, temp_filename, MFS_ATTR_DIR_NAME, &dir_cluster, &dir_index, &error_code);
                if ( error_code == MFS_NO_ERROR )
                {
                    clustod(dir_entry_ptr->HFIRST_CLUSTER, dir_entry_ptr->LFIRST_CLUSTER, free_cluster);
                    drive_ptr->DIR_SECTOR_DIRTY = TRUE;

                    /*
                    ** We shall now create the "." and ".." entries.
                    */
                    dir_cluster = free_cluster;
                    dir_entry_ptr = MFS_Create_directory_entry(drive_ptr,".",  MFS_ATTR_DIR_NAME, &dir_cluster, &dir_index, &error_code);
                    if ( error_code == MFS_NO_ERROR )
                    {
                        clustod(dir_entry_ptr->HFIRST_CLUSTER,  dir_entry_ptr->LFIRST_CLUSTER, free_cluster);
                        drive_ptr->DIR_SECTOR_DIRTY = TRUE;
                        dir_entry_ptr = MFS_Create_directory_entry(drive_ptr,"..", MFS_ATTR_DIR_NAME, &dir_cluster, &dir_index, &error_code);

                        if ( error_code == MFS_NO_ERROR )
                        {
                            if ( drive_ptr->FAT_TYPE == MFS_FAT32 )
                            {
                                if ( drive_ptr->BPB32.ROOT_CLUSTER == parent_cluster )
                                {
                                    /* 
                                    ** Even though the FAT32 root sector can be 
                                    ** anywhere, it is identified as 0 when referenced 
                                    ** through a directory entry
                                    */          
                                    parent_cluster = 0;
                                }
                            }
                            clustod(dir_entry_ptr->HFIRST_CLUSTER, dir_entry_ptr->LFIRST_CLUSTER, parent_cluster);
                            drive_ptr->DIR_SECTOR_DIRTY = TRUE;
                        }
                    }
                }
                else
                {
                    MFS_Put_fat(drive_ptr, free_cluster, CLUSTER_UNUSED);
                }  
            }
            else
            {
                error_code = MFS_DISK_FULL;
            }  
        }
        else
        {
            error_code = MFS_PATH_NOT_FOUND;
        }  
    }
    else if ( MFS_lfn_dirname_valid(temp_filename) )
    {
        if ( dir_cluster )
        {
            error_code = MFS_FILE_EXISTS;
        }
        else
        {
            error_code = MFS_CANNOT_CREATE_DIRECTORY;
        }  
    }
    else
    {
        error_code = MFS_INVALID_PARAMETER;
    }  

    MFS_free_path(temp_dirname);
    MFS_free_path(temp_filename);
    MFS_unlock(drive_ptr,TRUE);

    return(error_code);
}  
_mfs_error MFS_Set_volume
    (
        MFS_DRIVE_STRUCT_PTR drive_ptr,

        char                *volume_name /*[IN] name to use for the volune */
    )
{
    MFS_DIR_ENTRY_PTR          dir_entry_ptr;
    _mfs_error                 error_code;
    uint32_t                    vol_cluster, vol_index;
    uint32_t                    prev_cluster= CLUSTER_INVALID; 

    if ( volume_name == NULL )
    {
        return( MFS_INVALID_PARAMETER );
    }

    if ( *volume_name == '\0' )
    {
        return( MFS_INVALID_PARAMETER );
    }

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

    error_code = MFS_lock_dos_disk(drive_ptr);

    if ( !error_code )
    {
        vol_cluster = ROOT_CLUSTER(drive_ptr);
        vol_index = 0;
        dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, NULL, &vol_cluster, &vol_index, &prev_cluster, MFS_ATTR_VOLUME_NAME, &error_code); 

        if ( dir_entry_ptr )
        {
            MFS_Expand_dotfile(volume_name, dir_entry_ptr->NAME);
            *dir_entry_ptr->ATTRIBUTE = MFS_ATTR_VOLUME_NAME;
            drive_ptr->DIR_SECTOR_DIRTY = TRUE;

        }
        else if ( !error_code )
        {
            vol_cluster = ROOT_CLUSTER(drive_ptr);
            vol_index = 0;
            dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &vol_cluster, &vol_index, &prev_cluster, MFS_ATTR_ANY, &error_code); 
            if ( dir_entry_ptr )
            {
                MFS_Expand_dotfile(volume_name, dir_entry_ptr->NAME);
                *dir_entry_ptr->ATTRIBUTE = MFS_ATTR_VOLUME_NAME;
                drive_ptr->DIR_SECTOR_DIRTY = TRUE;
            }
        }
    }

    MFS_unlock(drive_ptr,TRUE);
    return( error_code );
}  
Beispiel #26
0
MFS_DIR_ENTRY_PTR MFS_Create_directory_entry
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,  /*[IN] the drive on which to operate */
    char_ptr        filename_ptr,       /*[IN] pointer to the file's name */
    char            attribute,          /*[IN] attribute to be assigned to the file */
    uint_32_ptr     dir_cluster_ptr,    /*[IN/OUT] indicates cluster in which the entry was put.*/
    uint_32_ptr     dir_index_ptr,      /*[IN/OUT] index of the location of new file within the directory */
    uint_32_ptr     error_ptr           /*[IN/OUT] error_return_address */
    )
{
    MFS_DIR_ENTRY_PTR     dir_entry_ptr, dir_entry_ptr1;
    MFS_DIR_ENTRY_PTR     temp_entry_ptr;
    TIME_STRUCT           time;
    DATE_STRUCT           clk_time;
    uint_32               dir_index, saved_index, temp_index;
    uint_32               entry_cluster, saved_cluster, temp_cluster;
    uint_32               needed_entries, i;
    int_32                length;
    boolean               found_all = FALSE;
    char                  temp_name[SFILENAME_SIZE+1], short_name[SFILENAME_SIZE+1];  
    uchar                 checksum = 0;
    uint_32               prev_cluster= CLUSTER_INVALID, saved_prev_cluster, temp_prev_cluster; 

    dir_entry_ptr = NULL;
    entry_cluster = *dir_cluster_ptr;
    dir_index = 0;

    /*
    ** Check for duplicate file
    */
    if ( filename_ptr == NULL )
    {
        *error_ptr = MFS_INVALID_PARAMETER;
    }
    else if ( *filename_ptr == '\0' )
    {
        *error_ptr = MFS_FILE_NOT_FOUND;
    }
#if MFSCFG_READ_ONLY_CHECK
    else if (MFS_is_read_only (NULL, drive_ptr))
    {
        *error_ptr = MFS_DISK_IS_WRITE_PROTECTED;
    }
#endif
    else if ( (dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, filename_ptr,
        &entry_cluster, &dir_index, &prev_cluster, MFS_ATTR_ANY, error_ptr)) != NULL )
    {
        *error_ptr = MFS_FILE_EXISTS;
    }
    else
    {
        /*
        ** Search for an empty slot
        */

        dir_index = 0;
        dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, attribute, error_ptr); 


        if ( MFS_Dirname_valid(filename_ptr) )
        {
            found_all = TRUE;
        }

        if ( dir_entry_ptr ==  NULL && !*error_ptr )
        {
            found_all = TRUE;
        }

        /* 
        ** Save it now because we might not go into the while loop
        ** If we don't go into while, we lose original values when these 
        ** variables are restored after the while loop
        */
        saved_cluster = entry_cluster;
        saved_index = dir_index;

        while ( !found_all )
        {
            /* Calculate the amount of extra entries needed for LFN's */
            saved_cluster = entry_cluster;
            saved_index = dir_index;

            for ( needed_entries = (strlen(filename_ptr) + 12) / 13;  needed_entries >= 1 && !found_all; needed_entries-- )
            {
                *error_ptr = MFS_Increment_dir_index(drive_ptr, &entry_cluster, &dir_index, NULL);  
                if ( entry_cluster == CLUSTER_EOF && !*error_ptr )
                {
                    /* This means the LFN will span a cluster. */
                    found_all = TRUE;
                    break;
                }
                temp_index = dir_index;
                temp_cluster = entry_cluster;
                temp_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, MFS_ATTR_ANY,error_ptr); 
                if ( *error_ptr )
                {
                    return NULL;
                }
                if ( !temp_entry_ptr )
                {
                    found_all = TRUE;
                    dir_entry_ptr = NULL;
                    break;
                }
                else if ( dir_index == temp_index && temp_cluster == entry_cluster )
                {
                    continue;
                }
                else
                {
                    break;
                }        
            }  

            if ( needed_entries == 0 )
            {
                found_all = TRUE;
            }

            if ( found_all )
            {
                dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &saved_cluster, &saved_index, &saved_prev_cluster, MFS_ATTR_ANY,error_ptr); 
            }
        }  

        entry_cluster = saved_cluster;
        dir_index = saved_index;


        if ( dir_entry_ptr ==  NULL && !*error_ptr )
        {
            /*
            ** Empty spot not found... get a new cluster and use the first entry.
            */
            dir_index = 0;
            if ( entry_cluster == 0 )
            {
                *error_ptr = MFS_ROOT_DIR_FULL;
                return(NULL);
            }
            else
            {
                *error_ptr = MFS_Add_cluster_to_chain(drive_ptr, entry_cluster, &entry_cluster);
                if ( *error_ptr == MFS_NO_ERROR )
                {
                    *error_ptr = MFS_Clear_cluster(drive_ptr, entry_cluster);
                    if ( *error_ptr )
                    {
                        return(NULL);
                    }
                    dir_entry_ptr = (pointer) drive_ptr->DIR_SECTOR_PTR;
                    *error_ptr = MFS_Write_back_fat(drive_ptr);
                    if ( *error_ptr )
                    {
                        return(NULL);
                    }
                }
            }  
        }
    }  

    if ( *error_ptr == MFS_NO_ERROR )
    {
        /* At this point we have one of the following cases 
        **
        ** 1. We have a normal 8.3 filename and an empty slot for it
        ** 2. We have a LFN, and a slot which has enough consecutive free slots
        **    to store the LFN, followed by the actual entry
        */

        /* If the file is a normal 8.3 file */
        if ( MFS_Dirname_valid(filename_ptr) )
        {
            _mem_zero(dir_entry_ptr, sizeof (MFS_DIR_ENTRY));            
            htodc(dir_entry_ptr->ATTRIBUTE, attribute);
            MFS_Expand_dotfile(filename_ptr, dir_entry_ptr->NAME);

            _time_get(&time);
            _time_to_date(&time, &clk_time);
            NORMALIZE_DATE(&clk_time);
            htods(dir_entry_ptr->TIME, PACK_TIME(clk_time));
            htods(dir_entry_ptr->DATE, PACK_DATE(clk_time));   
            drive_ptr->DIR_SECTOR_DIRTY = TRUE;
        }
        else
        {
            /* Case where the file is a LFN */   
            length = strlen(filename_ptr);

            /* Get the 8.3 name and calculate the checksum */
            temp_index = 0;
            temp_cluster = *dir_cluster_ptr;
            *error_ptr = MFS_lfn_to_sfn(filename_ptr, temp_name);

            if ( !*error_ptr )
            {
                do
                {
                    dir_entry_ptr1 = MFS_Find_directory_entry(drive_ptr, temp_name, &temp_cluster, &temp_index, &temp_prev_cluster, MFS_ATTR_ANY, error_ptr); 
                    if ( !*error_ptr && dir_entry_ptr1 != NULL )
                    {
                        MFS_increment_lfn(temp_name);
                        temp_index = 0;       
                    }
                } while ( !*error_ptr && dir_entry_ptr1 != NULL );
                dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, attribute, error_ptr); 

                /*
                ** The memory should be cleared after finding the directory entry.
                */
                _mem_zero(dir_entry_ptr, sizeof (MFS_DIR_ENTRY));

                /* Setup the final slot */
                ((MFS_LNAME_ENTRY_PTR) dir_entry_ptr)->ID |= MFS_LFN_END;
                drive_ptr->DIR_SECTOR_DIRTY = TRUE;

                MFS_Expand_dotfile(temp_name,short_name);
                checksum = MFS_lfn_checksum(short_name);
            }

            while ( length && !*error_ptr )
            {
                i = length - ((length -1) % 13 + 1);
                *error_ptr = MFS_lfn_name_to_entry(filename_ptr + i, (MFS_LNAME_ENTRY_PTR) dir_entry_ptr);

                /* Set the entry number, the checksum value and the attribute */
                ((MFS_LNAME_ENTRY_PTR) dir_entry_ptr)->ID |= (length + 12) / 13;
                ((MFS_LNAME_ENTRY_PTR) dir_entry_ptr)->ALIAS_CHECKSUM= checksum;
                ((MFS_LNAME_ENTRY_PTR) dir_entry_ptr)->ATTR = MFS_ATTR_LFN;
                drive_ptr->DIR_SECTOR_DIRTY = TRUE;

                length -= (length - i);
                if ( length < 0 )
                {
                    length = 0;
                }

                if ( length && !*error_ptr )
                {

                    dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, attribute, error_ptr); 
                    if ( dir_entry_ptr ==  NULL && !*error_ptr )
                    {
                        /* No empty spots... We need to get a new cluster */
                        dir_index = 0; 
                        if ( entry_cluster == 0 )
                        {
                            *error_ptr = MFS_ROOT_DIR_FULL; 
                            return(NULL); 
                        }
                        else
                        {
                            *error_ptr = MFS_Add_cluster_to_chain( drive_ptr, entry_cluster, &entry_cluster); 
                            if ( *error_ptr == MFS_NO_ERROR )
                            {
                                *error_ptr = MFS_Clear_cluster(drive_ptr, entry_cluster); 
                                if ( *error_ptr )
                                {
                                    return(NULL); 
                                }
                                dir_entry_ptr = (pointer) drive_ptr->DIR_SECTOR_PTR; 
                                *error_ptr = MFS_Write_back_fat(drive_ptr); 
                                if ( *error_ptr )
                                {
                                    return(NULL); 
                                }
                            }
                        }   
                    }
                    _mem_zero(dir_entry_ptr, sizeof (MFS_DIR_ENTRY));
                    drive_ptr->DIR_SECTOR_DIRTY = TRUE;
                }
            }  

            /* LFN is written, so write the actual entry */
            if ( !*error_ptr )
            {
                dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, "", &entry_cluster, &dir_index, &prev_cluster, attribute, error_ptr); 
                if ( dir_entry_ptr == NULL && !*error_ptr )
                {
                    dir_index = 0; 
                    if ( entry_cluster == 0 )
                    {
                        *error_ptr = MFS_ROOT_DIR_FULL; 
                        return(NULL); 
                    }
                    else
                    {
                        *error_ptr = MFS_Add_cluster_to_chain( drive_ptr, entry_cluster, &entry_cluster); 
                        if ( *error_ptr == MFS_NO_ERROR )
                        {
                            *error_ptr =  MFS_Clear_cluster(drive_ptr, entry_cluster); 
                            if ( *error_ptr )
                            {
                                return(NULL); 
                            }
                            dir_entry_ptr = (pointer) drive_ptr->DIR_SECTOR_PTR; 
                            *error_ptr = MFS_Write_back_fat(drive_ptr); 
                            if ( *error_ptr )
                            {
                                return(NULL); 
                            }
                        }
                    }   
                }

                _mem_zero(dir_entry_ptr, sizeof (MFS_DIR_ENTRY));
                htodc(dir_entry_ptr->ATTRIBUTE, attribute);
                MFS_Expand_dotfile(temp_name, dir_entry_ptr->NAME);

                _time_get(&time);
                _time_to_date(&time, &clk_time);
                NORMALIZE_DATE(&clk_time);
                htods(dir_entry_ptr->TIME, PACK_TIME(clk_time));
                htods(dir_entry_ptr->DATE, PACK_DATE(clk_time));   
                drive_ptr->DIR_SECTOR_DIRTY = TRUE;
            }
        }  

        if ( *error_ptr )
        {
            return(NULL);
        }
    }

    *dir_cluster_ptr = entry_cluster;
    *dir_index_ptr = dir_index;
    return(dir_entry_ptr);
}  
void  *MFS_Create_new_file
    (
        MFS_DRIVE_STRUCT_PTR drive_ptr,
        
        unsigned char       attr,           /*[IN] attribute to be given to the new file */
        char                *pathname,       /*[IN] directory and file name to be given to the new file */
        _mfs_error_ptr      error_ptr    /*[IN/OUT] error code is written to this address */
    )
{
    MFS_HANDLE_PTR          handle;
    MFS_DIR_ENTRY_PTR       dir_entry_ptr;
    uint32_t                 dir_cluster, dir_index;
    _mfs_error              error_code;
    char                    access;

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

    handle = NULL;
    error_code = MFS_NO_ERROR;

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

    }

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

    attr &= (MFS_ATTR_READ_ONLY | MFS_ATTR_HIDDEN_FILE | MFS_ATTR_SYSTEM_FILE | MFS_ATTR_ARCHIVE);
    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, FALSE);

    if ( error_code == MFS_NO_ERROR && dir_entry_ptr != NULL )
    {
        handle = MFS_Get_handle(drive_ptr,dir_entry_ptr);

        if ( handle )
        {
            handle->ACCESS = access;
            handle->DIR_CLUSTER = dir_cluster;
            handle->DIR_INDEX = dir_index;
            handle->CURRENT_CLUSTER = 0;
            handle->PREVIOUS_CLUSTER = 0;
        }
        else
        {
            error_code = MFS_INSUFFICIENT_MEMORY;
        }  
    }

    MFS_unlock(drive_ptr,FALSE);

    if ( error_ptr )
    {
        *error_ptr = error_code;
    }

    return((void *)handle);
}  
Beispiel #28
0
MFS_DIR_ENTRY_PTR MFS_Create_entry_slave
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,      /*[IN] the drive on which to operate */
    uchar                    attr,          /*[IN] attribute to be given to the new file */
    char_ptr                 pathname,      /*[IN] directory and file name to be given to the new file */
    uint_32_ptr              cluster_ptr,   /*[OUT] cluster # in the directory where the entry was created */
    uint_32_ptr              index_ptr,     /*[OUT] index # in the directory where the entry was created*/
    _mfs_error_ptr           error_ptr,     /*[IN/OUT] error code is written to this address */
    boolean                  overwrite      /*[IN]  if TRUE, we will overwrite an existing entry w/the same name */
    )
{
    MFS_DIR_ENTRY_PTR   dir_entry_ptr;
    char_ptr            temp_dirname;
    char_ptr            temp_filename;
    uchar               at;
    uint_32             dir_cluster;
    uint_32             dir_index;
    uint_32             vol_cluster,
        vol_index;
    _mfs_error          error_code;
    uint_32             prev_cluster; 

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

    dir_index   = 0;
    dir_cluster = drive_ptr->CUR_DIR_CLUSTER;
    dir_entry_ptr = NULL;

    error_code = MFS_alloc_2paths(&temp_dirname,&temp_filename);
    if ( error_code )
    {
        return( NULL );
    }

    error_code = MFS_Parse_pathname(temp_dirname, temp_filename, pathname);
    if ( error_code == MFS_NO_ERROR )
    {
        dir_cluster = MFS_Find_directory(drive_ptr, temp_dirname, dir_cluster);

        if ( dir_cluster == CLUSTER_INVALID )
        {
            error_code = MFS_PATH_NOT_FOUND;
        }
        else
        {
            if ( MFS_is_valid_lfn(temp_filename) )
            {
                if ( attr & MFS_ATTR_VOLUME_NAME )
                {
                    /*
                    ** If creating a volume label, it must be in the root
                    ** directory.
                    */
                    if ( dir_cluster == 0 )
                    {
                        vol_cluster = 0;
                        vol_index   = 0;
                        dir_entry_ptr =  MFS_Find_directory_entry(drive_ptr, NULL, &vol_cluster, 
                            &vol_index, &prev_cluster, MFS_ATTR_VOLUME_NAME, &error_code); 
                        if ( dir_entry_ptr )
                        {
                            error_code = MFS_ALREADY_ASSIGNED;
                        }
                    }
                    else
                    {
                        error_code = MFS_ACCESS_DENIED;
                    }  
                }

                if ( error_code == MFS_NO_ERROR )
                {
                    dir_entry_ptr = MFS_Create_directory_entry(drive_ptr, temp_filename, attr, &dir_cluster, &dir_index, &error_code);

                    /* if dir_entry_ptr == NULL
                    ** we couldn't create a new entry. 
                    ** if not NULL, it may be a brand new entry (MFS_NO_ERROR) or
                    ** an old one (MFS_FILE_EXISTS)
                    */

                    if ( dir_entry_ptr != NULL )
                    {
                        at = dtohc(dir_entry_ptr->ATTRIBUTE);

                        if ( (error_code != MFS_NO_ERROR) && (overwrite == FALSE) )
                        {
                            dir_entry_ptr = NULL;
                        }
                        else if ( (error_code == MFS_FILE_EXISTS) && ((at & MFS_ATTR_DIR_NAME) != (attr & MFS_ATTR_DIR_NAME)) 
                            || ((at & MFS_ATTR_VOLUME_NAME) !=  (attr & MFS_ATTR_VOLUME_NAME)) )
                        {
                            error_code = MFS_WRITE_FAULT;
                            dir_entry_ptr = NULL;
                        }
                        else if ( at & MFS_ATTR_READ_ONLY && error_code != 
                            MFS_NO_ERROR )
                        {
                            /*
                            ** If not freshly created
                            */
                            error_code = MFS_ACCESS_DENIED;
                            dir_entry_ptr = NULL;
                        }
                    }
                    *cluster_ptr = dir_cluster;
                    *index_ptr   = dir_index;
                }
            }
            else
            {
                error_code = MFS_INVALID_PARAMETER;
                dir_entry_ptr = NULL;
            }  
        }  
    }

    if ( error_ptr )
    {
        *error_ptr = error_code;
    }

    MFS_free_path(temp_filename);
    MFS_free_path(temp_dirname);

    return(dir_entry_ptr);
}  
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);
}  
Beispiel #30
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);
}