예제 #1
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);
}  
예제 #2
0
_mfs_error MFS_Get_volume
    (
        MFS_DRIVE_STRUCT_PTR drive_ptr,

        char                *volume_name /*[OUT] name of the volune */
    )
{
    MFS_DIR_ENTRY_PTR          dir_entry_ptr;
    _mfs_error                 error_code;
    uint32_t                    vol_cluster, vol_index, i;
    char                   *disk_vol_name;
    uint32_t                    prev_cluster= CLUSTER_INVALID; 

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

    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 )
        {
            disk_vol_name = dir_entry_ptr->NAME;
            for ( i = 0 ; i < SFILENAME_SIZE - 1; i++ )
            {
                *volume_name++ = *disk_vol_name++;
            }  
        }
        *volume_name = '\0'; 
    }

    MFS_unlock(drive_ptr,FALSE);   
    return( error_code );
}  
예제 #3
0
_mfs_error MFS_Get_volume
    (
    MQX_FILE_PTR            mfs_fd_ptr, /*[IN] pointer to the file struct returned by fopen("MFS...:",..); */
    char_ptr                volume_name /*[OUT] name of the volune */
    )
{
    MFS_DRIVE_STRUCT_PTR       drive_ptr;
    MFS_DIR_ENTRY_PTR          dir_entry_ptr;
    _mfs_error                 error_code;
    uint_32                    vol_cluster, vol_index, i;
    char_ptr                   disk_vol_name;
    uint_32                    prev_cluster= CLUSTER_INVALID; 

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

    error_code = MFS_lock_dos_disk(mfs_fd_ptr, &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 )
        {
            disk_vol_name = dir_entry_ptr->NAME;
            for ( i = 0 ; i < SFILENAME_SIZE - 1; i++ )
            {
                *volume_name++ = *disk_vol_name++;
            }  
        }
        *volume_name = '\0'; 
    }

    MFS_unlock(drive_ptr,FALSE);   
    return( error_code );
}  
예제 #4
0
_mfs_error MFS_Find_next_slave
    (
    MFS_DRIVE_STRUCT_PTR  drive_ptr,    /*[IN] drive context */
    void     *search_next_ptr           /*[IN] address of search data block indicating the current criteria and the results 
                                        ** of the last search results of this search are placed in this data block */
    )
{
    MFS_SEARCH_DATA_PTR        transfer_ptr;
    MFS_INTERNAL_SEARCH_PTR    internal_search_ptr;
    MFS_DIR_ENTRY_PTR          dir_entry_ptr;
    _mfs_error                 error_code;
    uint32_t                    len;
    bool                    found;
    bool                    match_all;
    bool                    eightdotthree = FALSE;
    char                   *lfn;
    char                       sname[SFILENAME_SIZE+1]; 
    uint32_t                    dotfile = 0;
    MFS_DIR_ENTRY  saved_dir_entry;  

    transfer_ptr = (MFS_SEARCH_DATA_PTR) search_next_ptr;
    error_code = MFS_NO_ERROR;
    found = FALSE;

    if ( transfer_ptr )
    {
        internal_search_ptr = &transfer_ptr->INTERNAL_SEARCH_DATA;

        if ( MFS_alloc_path(&lfn)!= MFS_NO_ERROR )
        {
            return MFS_INSUFFICIENT_MEMORY;
        }

        match_all = MFS_Check_search_string_for_all(internal_search_ptr->SRC_PTR);
        if ( !match_all )
        {
            dotfile = MFS_Is_dot_directory(internal_search_ptr->SRC_PTR);
            if ( dotfile == 0 )
            {
                eightdotthree = MFS_Check_search_string_for_8dot3( internal_search_ptr->SRC_PTR);
            }
        }
        do
        {
            dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, NULL, &internal_search_ptr->CURRENT_CLUSTER, &internal_search_ptr->DIR_ENTRY_INDEX,
                &internal_search_ptr->PREV_CLUSTER, internal_search_ptr->ATTRIBUTE & (~ATTR_EXCLUSIVE), &error_code);

            if ( dir_entry_ptr == NULL && !error_code )
            {
                error_code = MFS_FILE_NOT_FOUND;
                break;
            }

            if ( internal_search_ptr->CURRENT_CLUSTER == CLUSTER_INVALID )
            {
                error_code = MFS_FILE_NOT_FOUND;
                break;
            }

            if ( dir_entry_ptr == NULL )
            {
                break;
            }
            saved_dir_entry=*dir_entry_ptr; 

            /* Make sure the entry is not an LFN entry */
            if ( *dir_entry_ptr->ATTRIBUTE != MFS_ATTR_LFN )
            {
                MFS_Compress_nondotfile (dir_entry_ptr->NAME, sname);

                if ( match_all )
                {
                    found = TRUE;
                }
                else
                {
                    if ( dotfile != 0 )
                    {
                        if ( dotfile == 1 )
                        {
                            found = internal_search_ptr->FULLNAME[0] == dir_entry_ptr->NAME[0];
                        }
                        else if ( dotfile == 2 )
                        {
                            found = (internal_search_ptr->FULLNAME[0] == dir_entry_ptr->NAME[0]) &&
                                    (internal_search_ptr->FULLNAME[1] == dir_entry_ptr->NAME[1]);
                        }
                        else
                        {
                            found = FALSE; /* This shouldn't happen */
                        }
                    }
                    else if ( eightdotthree )
                    {
                        found = MFS_Wildcard_match(internal_search_ptr->FILENAME, dir_entry_ptr->NAME);
                    }
                    else
                    {
                        if ( MFS_get_lfn_dir_cluster(drive_ptr, search_next_ptr, sname, lfn) == MFS_NO_ERROR )
                        {
                            found = MFS_lfn_match(internal_search_ptr->SRC_PTR, lfn, 0);
                        }
                        else
                        {
                            found = MFS_lfn_match(internal_search_ptr->SRC_PTR, sname, 0);
                        }  
                    }  
                }  
            }

            if ( !error_code )
            {
                error_code = MFS_Increment_dir_index(drive_ptr, &internal_search_ptr->CURRENT_CLUSTER,
                    &internal_search_ptr->DIR_ENTRY_INDEX, &internal_search_ptr->PREV_CLUSTER);  
            }

        } while ( (error_code == MFS_NO_ERROR) && (found  == FALSE) );

        if ( error_code == MFS_NO_ERROR )
        {
            transfer_ptr->ATTRIBUTE = mqx_dtohc(saved_dir_entry.ATTRIBUTE);
            transfer_ptr->TIME      = mqx_dtohs(saved_dir_entry.TIME);
            transfer_ptr->DATE      = mqx_dtohs(saved_dir_entry.DATE);
            transfer_ptr->FILE_SIZE = mqx_dtohl(saved_dir_entry.FILE_SIZE);

            /* Transfer the filename */
            len = _strnlen(sname,13);
            if ( sname[len-1] == '.' )
            {
                sname[len-1] = '\0';
            }
            strncpy(transfer_ptr->NAME, sname, 13);
        }

        MFS_free_path((void *)lfn);
    }
    else
    {
        error_code = MFS_INVALID_MEMORY_BLOCK_ADDRESS;
    }  

    return(error_code);
}  
예제 #5
0
MFS_DIR_ENTRY_PTR MFS_Find_entry_on_disk
    (
    MFS_DRIVE_STRUCT_PTR    drive_ptr,          /*[IN] drive context */
    char               *pathname,           /*[IN] pathname of the file */
    _mfs_error_ptr             error_ptr,       /*[IN/OUT] resulting error code is written to this address*/
    uint32_t             *dir_cluster_ptr,    /*[OUT] the cluster in which the dir entry is located */
    uint32_t             *dir_index_ptr,      /*[OUT] the index within the dir cluster where the entry is located */
    uint32_t             *prev_cluster_ptr    /*[OUT] the cluster previous to dir cluster */    
    )
{
    MFS_DIR_ENTRY_PTR    dir_entry_ptr;
    char             *temp_dirname;
    char             *temp_filename;
    uint32_t              first_cluster;

    *error_ptr = MFS_alloc_2paths(&temp_dirname,&temp_filename);
    if ( *error_ptr != MFS_NO_ERROR )
    {
        return( NULL );
    }

    *error_ptr = MFS_NO_ERROR;
    dir_entry_ptr = NULL;

    if ( pathname )
    {
        MFS_Parse_pathname(temp_dirname, temp_filename, pathname);

        /*
        ** Is this a relative or an absolute file search ?
        */
        if ( *pathname == '\\' || *pathname == '/' )
        {
            first_cluster = ROOT_CLUSTER(drive_ptr);
        }
        else
        {
            first_cluster = drive_ptr->CUR_DIR_CLUSTER;
        }  

        /* first_cluster will now store the current_cluster # */
        first_cluster = MFS_Find_directory(drive_ptr, temp_dirname, first_cluster);
        *prev_cluster_ptr = CLUSTER_INVALID; 

        if ( first_cluster == CLUSTER_INVALID )
        {
            *error_ptr = MFS_PATH_NOT_FOUND;
        }
        else
        {
            *dir_index_ptr = 0;
            *dir_cluster_ptr = first_cluster;
            /*
            ** Checking for the superset of filename chars will allow
            ** finding something like \mydir\..
            */
            if ( !MFS_lfn_dirname_valid(temp_filename) )
            {
                dir_entry_ptr = NULL;
                *error_ptr = MFS_INVALID_PARAMETER;
            }
            else
            {
                dir_entry_ptr = MFS_Find_directory_entry(drive_ptr, temp_filename,
                    dir_cluster_ptr, dir_index_ptr, prev_cluster_ptr, MFS_ATTR_ANY, error_ptr);  
                if ( dir_entry_ptr == NULL && !*error_ptr )
                {
                    *error_ptr = MFS_FILE_NOT_FOUND;
                }
            }  
        }  
    }
    else
    {
        *error_ptr = MFS_INVALID_PARAMETER;
    }  
    MFS_free_path(temp_dirname);
    MFS_free_path(temp_filename);

    return(dir_entry_ptr);
}  
예제 #6
0
/*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);
}  
예제 #7
0
_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 );
}  
예제 #8
0
_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);
}  
예제 #9
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);
}  
예제 #10
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);
}