Ignore:
Timestamp:
Jul 24, 2015, 3:10:48 PM (9 years ago)
Author:
guerin
Message:

fat32: implement _fat_opendir, _fat_closedir, _fat_readdir

File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/giet_fat32/fat32.c

    r654 r658  
    31313131//  -3  : "File not open"
    31323132/////////////////////////////////////////////////////////////////////////////////
    3133 int _fat_file_info( unsigned int            fd_id,
    3134                     struct fat_file_info_s* info )
     3133int _fat_file_info( unsigned int     fd_id,
     3134                    fat_file_info_t* info )
    31353135{
    31363136    if ( _fat.initialised != FAT_INITIALISED )
     
    32093209
    32103210    // check count & seek versus file size
    3211     if ( count + seek > inode->size )
     3211    if ( count + seek > inode->size && !inode->is_dir )
    32123212    {
    32133213        _spin_lock_release( &_fat.fat_lock );
     
    41794179}  // end _fat_mkdir()
    41804180
     4181
     4182
     4183
     4184///////////////////////////////////////////////////////////////////////////////
     4185// This function implements the giet_fat_opendir() system call.
     4186// The semantic is similar to the UNIX opendir() function.
     4187// If the specified directory does not exist, an error is returned.
     4188// It allocates a file descriptor to the calling task, for the directory
     4189// identified by "pathname". If several tasks try to open the same directory,
     4190// each task obtains a private file descriptor.
     4191// A node name cannot be larger than 31 characters.
     4192///////////////////////////////////////////////////////////////////////////////
     4193// Returns file descriptor for the directory index on success
     4194// Returns a negative value on error:
     4195//   -1  :  "FAT not initialized"
     4196//   -2  :  "path to parent not found"
     4197//   -3  :  "one name in path too long"
     4198//   -4  :  "directory not found"
     4199//   -9  :  "file descriptor array full"
     4200//   -11 :  "not a directory"
     4201///////////////////////////////////////////////////////////////////////////////
     4202extern int _fat_opendir( char* pathname )
     4203{
     4204    int fd_id = _fat_open( pathname, O_RDONLY );
     4205
     4206    if ( fd_id < 0 )
     4207        return fd_id;
     4208
     4209    if ( !_fat.fd[fd_id].inode->is_dir )
     4210    {
     4211        _printf("\n[FAT ERROR] in _fat_opendir() : <%s> is not a directory\n",
     4212                pathname );
     4213        return -11;
     4214    }
     4215
     4216    return fd_id;
     4217}
     4218
     4219
     4220
     4221
     4222/////////////////////////////////////////////////////////////////////////////////
     4223// This function implements the "giet_fat_closedir()" system call.
     4224// Same behavior as _fat_close(), no check for directory.
     4225/////////////////////////////////////////////////////////////////////////////////
     4226// Returns 0 on success.
     4227// Returns negative value on error:
     4228//  -1  : "FAT not initialized"
     4229//  -2  : "Illegal file descriptor"
     4230//  -3  : "File not open"
     4231//  -4  : "Cannot update DATA regions"
     4232/////////////////////////////////////////////////////////////////////////////////
     4233extern int _fat_closedir( unsigned int fd_id )
     4234{
     4235    return _fat_close( fd_id );
     4236}
     4237
     4238
     4239
     4240
     4241/////////////////////////////////////////////////////////////////////////////////
     4242// This function implements the "giet_fat_readdir()" system call.
     4243// It reads one directory entry from the file descriptor opened by
     4244// "giet_fat_opendir()" and writes its info to the "entry" argument.
     4245// This includes the cluster, size, is_dir and name info for each entry.
     4246/////////////////////////////////////////////////////////////////////////////////
     4247// Returns 0 on success, or 1 if there are no more entries.
     4248// Returns a negative value on error:
     4249//  -1  : "FAT not initialized"
     4250//  -2  : "illegal file descriptor"
     4251//  -3  : "file not open"
     4252//  -4  : "not a directory"
     4253//  -5  : "can't read entry"
     4254/////////////////////////////////////////////////////////////////////////////////
     4255extern int _fat_readdir( unsigned int  fd_id,
     4256                         fat_dirent_t* entry )
     4257{
     4258    unsigned int  lfn   = 0;            // lfn entries count
     4259    unsigned int  attr;                 // ATTR field value
     4260    unsigned int  ord;                  // ORD field value
     4261    char          lfn1[16];             // temporary buffer for string in LFN1
     4262    char          lfn2[16];             // temporary buffer for string in LFN2
     4263    char          lfn3[16];             // temporary buffer for string in LFN3
     4264    unsigned char buf[DIR_ENTRY_SIZE];  // raw entry buffer
     4265    fat_file_info_t info;
     4266
     4267    // check for directory
     4268    int ret = _fat_file_info( fd_id, &info );
     4269    if (ret < 0)
     4270    {
     4271        return ret;
     4272    }
     4273    else if ( !info.is_dir )
     4274    {
     4275        _printf("\n[FAT ERROR] in _fat_readdir() : not a directory\n" );
     4276        return -4;
     4277    }
     4278
     4279    while ( 1 )
     4280    {
     4281        if ( _fat_read( fd_id, &buf, sizeof(buf) ) != sizeof(buf) )
     4282        {
     4283            _printf("\n[FAT ERROR] in _fat_readdir() : can't read entry\n" );
     4284            return -5;
     4285        }
     4286
     4287        attr = _read_entry( DIR_ATTR, buf, 0 );
     4288        ord  = _read_entry( LDIR_ORD, buf, 0 );
     4289
     4290        if (ord == NO_MORE_ENTRY)               // no more entry in directory => stop
     4291        {
     4292            // seek back to this entry
     4293            _spin_lock_acquire( &_fat.fat_lock );
     4294            _fat.fd[fd_id].seek -= DIR_ENTRY_SIZE;
     4295            _spin_lock_release( &_fat.fat_lock );
     4296
     4297            return 1;
     4298        }
     4299        else if ( ord == FREE_ENTRY )           // free entry => skip
     4300        {
     4301            continue;
     4302        }
     4303        else if ( attr == ATTR_LONG_NAME_MASK ) // LFN entry => get partial names
     4304        {
     4305            unsigned int seq = ord & 0x3;
     4306            lfn = (seq > lfn) ? seq : lfn;
     4307            if      ( seq == 1 ) _get_name_from_long( buf, lfn1 );
     4308            else if ( seq == 2 ) _get_name_from_long( buf, lfn2 );
     4309            else if ( seq == 3 ) _get_name_from_long( buf, lfn3 );
     4310            continue;
     4311        }
     4312        else                                    // NORMAL entry => stop
     4313        {
     4314            break;
     4315        }
     4316    }
     4317
     4318    // TODO handle is_vid
     4319    entry->cluster = (_read_entry( DIR_FST_CLUS_HI, buf, 1 ) << 16) |
     4320                     (_read_entry( DIR_FST_CLUS_LO, buf, 1 )      ) ;
     4321    entry->size    = (_read_entry( DIR_FILE_SIZE  , buf, 1 )      ) ;
     4322    entry->is_dir  = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY);
     4323
     4324    if      ( lfn == 0 )
     4325    {
     4326        _get_name_from_short( buf, entry->name );
     4327    }
     4328    else if ( lfn == 1 )
     4329    {
     4330        _strcpy( entry->name     , lfn1 );
     4331    }
     4332    else if ( lfn == 2 )
     4333    {
     4334        _strcpy( entry->name     , lfn1 );
     4335        _strcpy( entry->name + 13, lfn2 );
     4336    }
     4337    else if ( lfn == 3 )
     4338    {
     4339        _strcpy( entry->name     , lfn1 );
     4340        _strcpy( entry->name + 13, lfn2 );
     4341        _strcpy( entry->name + 26, lfn3 );
     4342    }
     4343
     4344    return 0;
     4345}
    41814346
    41824347
Note: See TracChangeset for help on using the changeset viewer.