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);
}  
_mfs_error MFS_Find_first_file
    (
        MFS_DRIVE_STRUCT_PTR drive_ptr,

        unsigned char       attribute,      /*[IN] type of file to find, Search attributes */
        char                *pathname,       /*[IN] optionally the directory and filename to search for */
        MFS_SEARCH_DATA_PTR transfer_ptr    /*[IN] address of search data block into which the results of the search are put */
    )
{
    MFS_INTERNAL_SEARCH_PTR internal_search_ptr;
    char                *temp_dirname;
    char                *temp_filename;
    uint32_t                 current_cluster;
    _mfs_error              error_code;
    uint32_t                 i;
    char                    c;

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

    if ( transfer_ptr == NULL )
    {
        return MFS_INVALID_MEMORY_BLOCK_ADDRESS;
    }

    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;
    }

    _mem_zero(transfer_ptr, sizeof (MFS_SEARCH_DATA));
    transfer_ptr->DRIVE_PTR = drive_ptr;

    MFS_Parse_pathname(temp_dirname, temp_filename, pathname);

    current_cluster = drive_ptr->CUR_DIR_CLUSTER;
    current_cluster = MFS_Find_directory(drive_ptr, temp_dirname, current_cluster);

    if ( current_cluster == CLUSTER_INVALID )
    {
        error_code = MFS_PATH_NOT_FOUND;
    }
    else
    {
        /*
        ** The internal search is only initialised if the directory exists.
        */
        internal_search_ptr = &transfer_ptr->INTERNAL_SEARCH_DATA;
        internal_search_ptr->CURRENT_CLUSTER = current_cluster;
        internal_search_ptr->PREV_CLUSTER = CLUSTER_INVALID;  
        internal_search_ptr->DIR_ENTRY_INDEX = 0;

        MFS_Expand_wildcard(temp_filename, internal_search_ptr->FILENAME);   
        internal_search_ptr->FULLNAME = temp_filename;

        i = _strnlen(pathname, PATHNAME_SIZE + FILENAME_SIZE + 1);
        c = pathname[--i];
        while ( (c != '\\') && (c != '/') && (c != ':') && i )
        {
            i--;         
            c = pathname[i];
        }  
        if ( i || c == '\\' || c == '/' )
        {
            i++;
        }

        internal_search_ptr->SRC_PTR = pathname + i;
        internal_search_ptr->ATTRIBUTE = attribute;
        error_code = MFS_Find_next_slave(drive_ptr, transfer_ptr);
    }  

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

    return(error_code);
}  
_mfs_error MFS_Change_current_dir
    (
        MFS_DRIVE_STRUCT_PTR drive_ptr,
        
        char               *pathname     /*[IN] pathname of the directory to become the current dir */
    )
{
    uint32_t                 dir_cluster;
    uint16_t                 length;
    _mfs_error              error_code;
    char                *directory;
    char                *temp_cur;
    register char       *src, *dest, *dest_start;

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

    error_code = MFS_alloc_2paths(&directory,&temp_cur);
    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(directory);
        MFS_free_path(temp_cur);
        return error_code;
    }

    dir_cluster = drive_ptr->CUR_DIR_CLUSTER;
    dir_cluster = MFS_Find_directory(drive_ptr, pathname, dir_cluster);

    if ( dir_cluster != CLUSTER_INVALID )
    {
        src = pathname;
        dest = temp_cur;

        if ( *src == '\\' || *src == '/' )
        {
            temp_cur[0] = '\\';
            temp_cur[1] = '\0';
            src++;
        }
        else
        {
            strcpy (temp_cur, drive_ptr->CURRENT_DIR);
            dest = temp_cur + strlen(temp_cur) - 1;
        }  
        dest_start = temp_cur;

        length = strlen(dest_start);

        while ( src )
        {
            if ( *src )
            {
                src = MFS_Parse_next_filename(src, directory);
                if ( src != NULL )
                {
                    MFS_strupr(directory);
                }
                if ( directory[0] == '.' && directory[1] == '.' )
                {
                    if ( dest != dest_start )
                    {
                        while ( dest != dest_start && *dest != '\\' )
                        {
                            dest--;
                        }  
                        /* Erase the previous backslash, unless it is the
                        ** first (root directory).
                        */
                        if ( dest != dest_start )
                        {
                            *dest-- = '\0';
                        }
                        else
                        {
                            *(dest+1) = '\0';
                        }  
                    }
                    else
                    {
                        /*
                        ** The check for underflow is redundant, because the path
                        ** has been found already.
                        */
                        error_code = MFS_PATH_NOT_FOUND;
                        break;
                    }  
                }
                else if ( directory[0] && directory[0] != '.' )
                {
                    if ( *dest != '\\' )
                    {
                        *(++dest) = '\\';
                        length++;
                    }
                    length += strlen(directory);
                    if ( length < sizeof (drive_ptr->CURRENT_DIR) )
                    {
                        strcpy (++dest, directory);
                        dest = temp_cur + length - 1;
                    }
                    else
                    {
                        error_code = MFS_INVALID_LENGTH_IN_DISK_OPERATION;
                        break;
                    }  
                }
            }
            else
            {
                break;
            }  
        }  
        if ( error_code == MFS_NO_ERROR )
        {
            strcpy (drive_ptr->CURRENT_DIR, dest_start);
            drive_ptr->CUR_DIR_CLUSTER = dir_cluster;
        }
    }
    else
    {
        error_code = MFS_PATH_NOT_FOUND;
    }  

    MFS_free_path(directory);
    MFS_free_path(temp_cur);
    MFS_unlock(drive_ptr,FALSE);

    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);
}  
Beispiel #5
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);
}