Exemple #1
0
/* allocate a DirEntry in the directory `dirEntry'
 * its address in filesystem is returned in addr
 */
int allocateDirEntry(DirEntry *dirEntry,ULONG * value_addr) {
    int result = _traverse(dirEntry,traverse_availableDirEntry,value_addr);
    /* result == 1 means all clusters of dirEntry were searched
     * which means we can not found a available entry
     * allocate a new cluster to get one
     */
    if( result == 1 ) {
#ifdef DEBUG
        printf("No available Dir Entry in current cluster !\n");
#endif
        /* search the last cluster in the FAT chain
         * allocate a new cluster and append it to the last cluster
         */
        ULONG startCluster = getDirClusterNum(dirEntry);
        ULONG last = getLastCluster(startCluster);
        ULONG newCluster = allocateCluster();
        if( newCluster == 0 )
            report_exit("Not enough space!\n");

        FAT[last] = newCluster;
        FAT[newCluster] = EOD;
        updateAllFat();
        /* allocate the first dir entry in the cluster */
        *value_addr = (cluster2sector( newCluster ) * bps);
    }
#ifdef DEBUG
    printf("Allocated dirEntry address: 0x%08x\n",(int)*value_addr);
#endif
    return 1;
}
Exemple #2
0
int fat_blockread(int fd, void *buffer)
{
    uint32_t    block;
    uint32_t    temp;
    fhandle_t *handle = fd_handles[fd];   
    
    if ( (fd > MAX_FILES) || (fd < 0) ) // if not valid index
        return (uint32_t) -1;           // return failure
    
    if (handle == NULL)                 // if slot is not in use
        return (uint32_t) -1;           // return failure

    if (handle->foffset > handle->highwater)
    {
        return 0;
    }
    
    block = cluster2sector(handle->cluster);    // get the start block

    temp = handle->foffset % bytes_per_cluster;        // for later use

    // add local block within a cluster 
    block += temp / bytes_per_sector;

    TRACE_FAT("blockread: %ld\n",block);

    // read the data
    sd_readsector(block, buffer, 0, 0);
    /*handle->foffset += bytes_per_sector;*/ 
    handle->foffset += bytes_per_sector - (handle->foffset%bytes_per_sector);

    if (handle->foffset % bytes_per_cluster == 0)      // cluster boundary
    {
        // need to get a new cluster
        handle->cluster = fat_nextcluster(handle->cluster); // follow FAT chain
        //if (fd->cluster == -1)                        // if we're at end of chain
        //{
            //break;                                // we're finished, there is no more data
        //}
    }

    return bytes_per_sector;
}
Exemple #3
0
/*
 * traverse all cluster belonged to the DirEntry de,
 * pass the cluster read to func for processing
 * set a value `value_addr' to indicate the stop address
 */
int _traverse(DirEntry * de,int (*func)(unsigned char *,int,ULONG *),
              ULONG * value_addr) {
    int result=0;
    ULONG base_sector,dir_cluster;
    ULONG nRemain = de->DIR_FileSize;
    dir_cluster = getDirClusterNum(de);

    if( nRemain == 0 ) {
        /* for a Directory DirEntry.size= 0
         * set to INF to keep the traverse going*/
        if( de->DIR_Attr & ATTR_DIR ) nRemain = INF;
        /* some normal file may have size=0,no allocated cluster for it */
        else return 1;
    }

    /* traverse the FAT chain */
    ULONG stopat,len=0;
    do {
        base_sector = data_secNum + spc*(dir_cluster-2);
        /* read the whole cluster */
        len = read_sectors(base_sector,buffer,spc);
#ifdef DEBUG
        printf("Cluster : %lu\n",dir_cluster);
        printf("Sector : %lu\n",base_sector);
        printf("Read:   %lu\nRemain: %lu\n",len,nRemain);
#endif
        /* pass the buffer content to func for processing
         * NOTE: result=1 means keep traversing
         * result=0 means stop traversing, and stopat point to
         * the stop position in buffer
         * */
        if(nRemain<len) result = func(buffer,nRemain,&stopat);
        else result = func(buffer,len,&stopat);
        if( result == 0 ) {
            *value_addr = (cluster2sector(dir_cluster)*bps + stopat);
            break;
        }

        nRemain -= len;
        dir_cluster=FAT[dir_cluster];
    } while( dir_cluster < END_MARK );
    return result;
}
Exemple #4
0
/**
 * Read specific number of bytes from file
 * 
 * \param fd File handle
 * \param buffer Buffer to store data
 * \param len Number of bytes to read
 * \return Number of bytes successful read.
 * 
 */
int fat_read(int fd, char *buffer, int len)
{
    uint16_t    nbytes;
    uint32_t    block;
    uint16_t    dcount;
    uint16_t    loffset;
    fhandle_t   *handle = fd_handles[fd]; 

    TRACE_FAT("fat_read %d,%08x,%d\n",fd,buffer,len);
    
    if ( (fd > MAX_FILES) || (fd < 0) ) // if not valid index
        return -1;           // return failure
    
    if (handle == NULL)                 // if slot is not in use
        return -1;           // return failure


    // limit max read to size of file
    if (len > (handle->highwater - handle->foffset) )
        len = handle->highwater - handle->foffset;

    dcount = len;

    TRACE_FAT("fat_read\n");

    while (dcount)
    {
        loffset = handle->foffset % bytes_per_sector; // local offset within a block 
        block = cluster2sector(handle->cluster);    // get the start block

        // add local block within a cluster 
        block += (handle->foffset % bytes_per_cluster) / bytes_per_sector;

        // limit to max one block
        nbytes = dcount < bytes_per_sector ? dcount : bytes_per_sector;

        //limit to remaining bytes in a block
        if (nbytes > (bytes_per_sector - loffset) )
            nbytes = bytes_per_sector - loffset;

        // read the data
        sd_read_n(block, loffset, nbytes, (uint8_t*) buffer);

        // bump buffer pointer
        buffer += nbytes;

        handle->foffset += nbytes;
        dcount -= nbytes;

        if (handle->foffset % bytes_per_cluster == 0)      // cluster boundary
        {
            // need to get a new cluster
            handle->cluster = fat_nextcluster(handle->cluster); // follow FAT chain
            if (handle->cluster == -1)                      // if we're at end of chain
            {
                break;                              // we're finished, there is no more data
            }
        }
    }
    TRACE_FAT("fat_read return %d\n",len - dcount);
    return len - dcount;
}
Exemple #5
0
/**
 * Scan through directory entries to find the given file or directory
 * 
 * \param ff_data FatFind helper structure
 * \return Error code
 * 
 */
static int ff_scan(fatffdata_t * ff_data)
{
    uint16_t i,j, eindex;
    uint16_t sectoroffset, entryoffset, maxsector;
    uint32_t cluster;
    uint32_t sector;
    uint8_t match,longmatch;
    char matchspace[13];
    fatdirentry_t *de;
    uint8_t n;
    uint8_t nameoffset;

    eindex  = ff_data->ff_offset;
    cluster = ff_data->ff_cluster;

    sectoroffset = eindex / (bytes_per_sector/sizeof(fatdirentry_t));
    entryoffset  = eindex % (bytes_per_sector/sizeof(fatdirentry_t));

    if (isFAT32 == 0 && cluster == root_dir_cluster ) // if not FAT32 and this is the root dir
        maxsector = root_dir_sectors;                 // set max sector count for root dir
    else
        maxsector = sectors_per_cluster;

    longmatch = 0;
    // loop until entry found or end of list
    while (1)                               
    {
        sector = cluster2sector(cluster);

        for (i=sectoroffset;i<maxsector;i++)
        {
            readsector(sector+i, (uint8_t*) sector_buffer);      // request a sector
            de = (fatdirentry_t *) sector_buffer;
            de += entryoffset;

            for (j=entryoffset;j<bytes_per_sector/sizeof(fatdirentry_t);j++)  // 32 entries per sector 
            {

                if (*de->deName == SLOT_EMPTY)
                {
                    return -1;
                }

                if (*de->deName != SLOT_DELETED)
                {
                    if ((de->deAttributes & ATTR_LONG_FILENAME) == ATTR_LONG_FILENAME)
                    {
                        // found long name entry

                        if ( ((struct winentry *)de)->weCnt & WIN_LAST )            // first part of a long name
                            memset(ff_data->ff_name,0,sizeof(ff_data->ff_name));    // clear name

                        // piece together a fragment of the long name
                        // and place it at the correct spot
                        nameoffset = ((((struct winentry *)de)->weCnt & WIN_CNT)-1) * WIN_CHARS;

                        for (n=0;n<5;n++)
                            ff_data->ff_name[nameoffset+n] = ((struct winentry *)de)->wePart1[n*2];
                        for (n=0;n<6;n++)
                            ff_data->ff_name[nameoffset+5+n] = ((struct winentry *)de)->wePart2[n*2];
                        for (n=0;n<2;n++)
                            ff_data->ff_name[nameoffset+11+n] = ((struct winentry *)de)->wePart3[n*2];

                        if ( (((struct winentry *)de)->weCnt & WIN_CNT) == 1 )  // long name complete
                        {
                            // set match flag
                            longmatch = szWildMatch8(ff_data->ff_search, ff_data->ff_name);
                        }
                    }
                    else
                    {
                        // found short name entry, determine a match 
                        dos2str(matchspace,(char*)de->deName,(char*)de->deExtension);
                        match = szWildMatch8(ff_data->ff_search, matchspace);

                        // special!
                        // skip the single dot entry
                        if (strcmp(matchspace,".") != 0)
                        {
                            if ((match || longmatch) && ((de->deAttributes & ATTR_VOLUME) == 0))
                            {
                                // found
                                ff_data->ff_cluster = cluster;
                                ff_data->ff_offset = eindex;    // save index of file
                                memcpy(&ff_data->ff_de,de,sizeof(fatdirentry_t));
                                if (!longmatch)
                                {
                                    strcpy(ff_data->ff_name, matchspace);
                                }
                                return 0;
                            }
                        }
                    }

                }//if !SLOT_DELETED

                eindex++;
                de++;   // next entry
            }//for (j=entryoffset

            entryoffset = 0;
        }//for (i=sectoroffset

        sectoroffset = 0;
        cluster = fat_nextcluster(cluster);
 
        if (cluster == 0)   // if end of chain
        {
            TRACE_FAT("ff_scan end of chain\n");
            return -1;
        }
        eindex = 0;
    }//while

}