Example #1
0
static int
fatfs_find(fatfs_dirsearch_t *ds)
{
    int err;

    CYG_TRACE1(TFS, "find path='%s'", ds->path);
    
    // Short circuit empty paths
    if (*(ds->path) == '\0')
        return ENOERR;
    
    // Iterate down directory tree until we find the object we want
    for(;;)
    {
        err = find_entry(ds);
        
        if (err != ENOERR)
            return err;
        
        if (ds->last)
        {
            CYG_TRACE0(TFS, "entry found");
            return ENOERR;
        }

        // Update dirsearch object to search next directory
        ds->dir   = ds->node;
        ds->path += ds->namelen;
        
        // Skip dirname separators
        if (*(ds->path) == '/') ds->path++;
        
        CYG_TRACE1(TFS, "find path to go='%s'", ds->path);
    }
}
Example #2
0
externC cyg_uint32
hal_arch_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data)
{
    CYG_TRACE1(true, "Interrupt: %d", vector);

    CYG_FAIL("Spurious Interrupt!!!");
    return 0;
}
Example #3
0
void
fatfs_node_ref(fatfs_disk_t *disk, fatfs_node_t *node)
{
    CYG_CHECK_DATA_PTRC(disk);
    CYG_CHECK_DATA_PTRC(node);
    CYG_TRACE2(TNC, "node='%s' refcnt=%d", node->dentry.filename, node->refcnt);
    
    node->refcnt++;    
    if (1 == node->refcnt)
    {
        // First reference - move node from dead to live list

        CYG_TRACE1(TNC, "node='%s' to live list", node->dentry.filename);
        
        node_list_remove(&disk->dead_nlist, node);
        node_list_head_add(&disk->live_nlist, node);
    }

    SANITY_CHECK();
}
Example #4
0
fatfs_node_t*
fatfs_node_alloc(fatfs_disk_t *disk, fatfs_dir_entry_t *dentry)
{
    fatfs_node_t *node;

    CYG_CHECK_DATA_PTRC(disk);
    CYG_CHECK_DATA_PTRC(dentry);
 
    node = node_pool_alloc(disk);
        
    if (NULL == node)
    {
        CYG_TRACE2(TNC, "getting node from dead list (size=%d keep=%d)",
                        node_list_get_size(&disk->dead_nlist), DLIST_KEEP_NUM);
        
        if (node_list_get_size(&disk->dead_nlist) <= DLIST_KEEP_NUM)
            return NULL;
        
        node = node_list_tail_get(&disk->dead_nlist);
        if (NULL == node)
            return NULL;
        
        CYG_TRACE1(TNC, "recycling node='%s'", node->dentry.filename); 

        node_list_remove(&disk->dead_nlist, node);
        if (!node_hash_remove(&disk->node_hash, node))
            CYG_ASSERT(false, "node not in hash");
    }     

    // Init new node    
    node->dentry = *dentry;
    node->refcnt = 0;

    node_list_head_add(&disk->dead_nlist, node);
    if (!node_hash_add(&disk->node_hash, node))
        CYG_ASSERT(false, "node already in hash");

    SANITY_CHECK();

    return node;
}
Example #5
0
void
fatfs_node_unref(fatfs_disk_t *disk, fatfs_node_t *node)
{
    CYG_CHECK_DATA_PTRC(disk);
    CYG_CHECK_DATA_PTRC(node);
    CYG_TRACE2(TNC, "node='%s' refcnt=%d", node->dentry.filename, node->refcnt);
    CYG_ASSERT(node->refcnt > 0, "node->refcnt <= 0");

    node->refcnt--;
    if (0 == node->refcnt)
    {
        // No more references - move node from live to dead list

        CYG_TRACE1(TNC, "node='%s' to dead list", node->dentry.filename);

        node_list_remove(&disk->live_nlist, node);
        node_list_head_add(&disk->dead_nlist, node);
    }

    SANITY_CHECK();
}
Example #6
0
externC cyg_uint32
hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data)
{
    CYG_TRACE1(true, "Interrupt: %d", vector);

#ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
#ifdef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT
#ifdef CYGDBG_HAL_CTRLC_ISR
    // then see if it is an incoming character interrupt and break
    // into the stub ROM if the char is a ^C.
    if ( CYGDBG_HAL_CTRLC_ISR( vector, data ) )
        return 1; // interrupt handled
#endif
#endif
#endif

    diag_printf("Spurious Interrupt!!! - vector: %d, data: %x\n", vector, 
                data);
    CYG_FAIL("Spurious Interrupt!!!");
    return 0;
}
Example #7
0
static int
fatfs_fo_close(struct CYG_FILE_TAG *fp)
{    
    fatfs_disk_t  *disk  = (fatfs_disk_t *) fp->f_mte->data;
    fatfs_fd_t    *fd    = (fatfs_fd_t *)   fp->f_data;
    fatfs_node_t  *node  = fd->node;
    int            err   = ENOERR;

    CYG_TRACE1(TFO, "close fp=%p", fp);

    // Write file attributes to disk, unreference 
    // the file node and free its private data

    if (node != disk->root)
        err = fatfs_write_dir_entry(disk, &node->dentry);

    fatfs_node_unref(disk, node);    

    free_fatfs_fd(fd);
    
    return err;
}
Example #8
0
static int 
find_entry(fatfs_dirsearch_t *ds)
{
    const char  *name     = ds->path;
    const char  *n        = name;
    char         namelen  = 0;
    int          err;
    
    if( !S_ISDIR(ds->dir->dentry.mode) )
    {
        CYG_TRACE1(TFS, "entry '%s' not dir", ds->dir->dentry.filename);
        return ENOTDIR;
    }
    
    // Isolate the next element of the path name
    while (*n != '\0' && *n != '/')
        n++, namelen++;

    // If we terminated on a NUL, set last flag
    if (*n == '\0')
        ds->last = true;

    // Update name in dirsearch object
    ds->name    = name;
    ds->namelen = namelen;

    err = find_direntry(ds);
    if (err != ENOERR)
        return err;

    CYG_TRACE2(TFS, "entry '%s' %s", name, (ds->node ? "found" : "not found"));
    
    if (ds->node != NULL)
       return ENOERR;
    else
       return ENOENT; 
}
Example #9
0
static int 
fatfs_open(cyg_mtab_entry *mte,
           cyg_dir         dir, 
           const char     *name,
           int             mode,  
           cyg_file       *file)
{
    fatfs_disk_t       *disk = (fatfs_disk_t *) mte->data;
    fatfs_node_t       *node = NULL;
    fatfs_fd_t         *fd;
    fatfs_dirsearch_t   ds;
    int                 err;

    CYG_TRACE5(TFS, "open mte=%p dir=%p name='%s' mode=%d file=%p", 
                    mte, dir, name, mode, file);

    init_dirsearch(&ds, disk, (fatfs_node_t *) dir, name);

    err = fatfs_find(&ds);

    if (err == ENOENT)
    {
        if (ds.last && (mode & O_CREAT))
        {
            fatfs_dir_entry_t new_file_dentry;
            
            // No node there, if the O_CREAT bit is set then we must
            // create a new one. The dir and name fields of the dirsearch
            // object will have been updated so we know where to put it.

            CYG_TRACE1(TFS, "creating new file '%s'", name); 

            err = fatfs_create_file(disk, 
                                    &ds.dir->dentry, 
                                    ds.name, 
                                    ds.namelen, 
                                    &new_file_dentry);
            if (err != ENOERR)
                return err;

            node = fatfs_node_alloc(disk, &new_file_dentry);
            if (NULL == node)
                return EMFILE;
           
            // Update directory times
            ds.dir->dentry.atime =
            ds.dir->dentry.mtime = cyg_timestamp();
            
            err = ENOERR;
        }
    }
    else if (err == ENOERR)
    {
        // The node exists. If the O_CREAT and O_EXCL bits are set, we
        // must fail the open

        if ((mode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
            err = EEXIST;
        else
            node = ds.node;
    }

    if (err == ENOERR && (mode & O_TRUNC))
    {
        // If the O_TRUNC bit is set we must clean out the file data
        CYG_TRACE0(TFS, "truncating file"); 
        fatfs_trunc_file(disk, &node->dentry);
    }

    if (err != ENOERR)
        return err;
    
    if (S_ISDIR(node->dentry.mode))
        return EISDIR;

#ifdef CYGCFG_FS_FAT_USE_ATTRIBUTES
    // if the file is read only and is opened for writing
    // fail with permission error
    if (S_FATFS_ISRDONLY(node->dentry.attrib) && (mode & O_WRONLY))
        return EACCES;
#endif // CYGCFG_FS_FAT_USE_ATTRIBUTES

    // Allocate file object private data and
    // make a reference to this file node

    fd = alloc_fatfs_fd(disk, node);
    if (NULL == fd)
        return EMFILE;

    fatfs_node_ref(disk, node);

    // Initialize the file object

    if (mode & O_APPEND)
        fatfs_setpos(disk, &node->dentry, &fd->pos, node->dentry.size);  
    
    file->f_flag   |= mode & CYG_FILE_MODE_MASK;
    file->f_type    = CYG_FILE_TYPE_FILE;
    file->f_ops     = &fatfs_fileops;
    file->f_offset  = (mode & O_APPEND) ? node->dentry.size : 0;
    file->f_data    = (CYG_ADDRWORD) fd;
    file->f_xops    = 0;

    return ENOERR;
}
Example #10
0
static int 
fatfs_mount(cyg_fstab_entry *fste, cyg_mtab_entry *mte)
{
    cyg_io_handle_t     dev_h;
    fatfs_disk_t       *disk;
    fatfs_dir_entry_t   root_dentry;
    Cyg_ErrNo           err;

    CYG_TRACE2(TFS, "mount fste=%p mte=%p", fste, mte);

    init_fatfs_fds();
    
    CYG_TRACE1(TFS, "looking up disk device '%s'", mte->devname);
    
    err = cyg_io_lookup(mte->devname, &dev_h);
    if (err != ENOERR)
        return err;

    disk = (fatfs_disk_t *)malloc(sizeof(fatfs_disk_t));
    if (NULL == disk)
        return ENOMEM;
        
    CYG_TRACE0(TFS, "initializing block cache"); 

    disk->bcache_mem = (cyg_uint8 *)malloc(CYGNUM_FS_FAT_BLOCK_CACHE_MEMSIZE);
    if (NULL == disk->bcache_mem)
    {
        free(disk);
        return ENOMEM;
    }
    // FIXME: get block size from disk device
    err = cyg_blib_io_create(dev_h, disk->bcache_mem, 
            CYGNUM_FS_FAT_BLOCK_CACHE_MEMSIZE, 512, &disk->blib);
    if (err != ENOERR)
    {
        free(disk->bcache_mem);
        free(disk);
        return err;
    }
    
    disk->dev_h = dev_h;

    CYG_TRACE0(TFS, "initializing disk");
    
    err = fatfs_init(disk);
    if (err != ENOERR)
    {
        cyg_blib_delete(&disk->blib);
        free(disk->bcache_mem);
        free(disk);
        return err;
    }
   
#if TFS    
    print_disk_info(disk);
#endif

    CYG_TRACE0(TFS, "initializing node cache");

    fatfs_node_cache_init(disk);
    
    CYG_TRACE0(TFS, "initializing root node");
    
    fatfs_get_root_dir_entry(disk, &root_dentry);
    
    disk->root = fatfs_node_alloc(disk, &root_dentry);

    fatfs_node_ref(disk, disk->root);
    
    mte->root = (cyg_dir)disk->root;
    mte->data = (CYG_ADDRWORD)disk;

    CYG_TRACE0(TFS, "disk mounted");

    return ENOERR;
}
Example #11
0
static int
find_direntry(fatfs_dirsearch_t *ds)
{
    fatfs_dir_entry_t  dentry;
    fatfs_data_pos_t   pos;
    int                err;

    CYG_TRACE1(TFS, "searching for dir entry '%s'", ds->name);

    // Check for '.' 

    if (!strncmp(".", ds->name, ds->namelen))
    {
        ds->node = ds->dir;
        return ENOERR;
    }
   
    // Check the cache
    
    ds->node = fatfs_node_find(ds->disk, 
                               ds->name, 
                               ds->namelen, 
                               ds->dir->dentry.cluster);

    if (ds->node != NULL)
    {
        // Dir entry found in cache
        
        CYG_TRACE0(TFS, "dir entry found in cache");

        fatfs_node_touch(ds->disk, ds->node);
        return ENOERR;
    }

    // Dir entry not in cache - search the current dir

    fatfs_initpos(ds->disk, &ds->dir->dentry, &pos);

    while (true)
    {  
        // Read next dir entry 
        
        err = fatfs_read_dir_entry(ds->disk, &ds->dir->dentry, &pos, &dentry);
        if (err != ENOERR)
            return (err == EEOF ? ENOERR : err);

        // Compare filenames
    
        if ('\0' == dentry.filename[ds->namelen] &&
               0 == strncasecmp(dentry.filename, ds->name, ds->namelen))
        {
            // Dir entry found - allocate new node and return

            CYG_TRACE0(TFS, "dir entry found");
            
            if (0 == strncmp(ds->name, "..", ds->namelen)) 
            {
                fatfs_dir_entry_t _dentry;
                fatfs_data_pos_t  _pos;
 
                if (0 == dentry.cluster) 
                {
                    ds->node = ds->disk->root;
                    return ENOERR;
                }
             
                fatfs_initpos(ds->disk, &dentry, &_pos);
                while (true)
                {
                    err = fatfs_read_dir_entry(ds->disk, &dentry, &_pos, &_dentry);
                    if (err != ENOERR)
                        return err;
                    if (0 == strcmp(".", _dentry.filename))
                        break;
                }
 
                ds->node = fatfs_node_find(ds->disk, 
                                           _dentry.filename, 
                                           strlen(_dentry.filename),
                                           _dentry.parent_cluster); 
                
                if (NULL != ds->node)
                    fatfs_node_touch(ds->disk, ds->node);
                else 
                    ds->node = fatfs_node_alloc(ds->disk, &_dentry);
                                
                if (NULL == ds->node)
                    return EMFILE;
                                
                return ENOERR;
            }
            else 
                ds->node = fatfs_node_alloc(ds->disk, &dentry);

            if (NULL == ds->node)
                return EMFILE;

            return ENOERR;
        }
    }
}