Changeset 508

Show
Ignore:
Timestamp:
04/15/07 19:07:43 (3 years ago)
Author:
goodea
Message:

reformat

Location:
trunk/hal/lpc2106-cmucam3
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • trunk/hal/lpc2106-cmucam3/rdcf2.c

    r346 r508  
    5757/* buffer status */ 
    5858 
    59 enum buffer_status {EMPTY, CLEAN, DIRTY}; 
     59enum buffer_status { EMPTY, CLEAN, DIRTY }; 
    6060 
    6161/* additional mode bit */ 
     
    8787#ifdef _BIG_ENDIAN 
    8888 
    89 static void swap_two(uint8_t *p) 
    90 { 
    91         uint8_t x = p[0]; 
    92         p[0] = p[1]; 
    93         p[1] = x; 
    94 } 
    95  
    96 static void swap_four(uint8_t *p) 
    97 { 
    98         uint8_t x = p[0]; 
    99         p[0] = p[3]; 
    100         p[3] = x; 
    101         swap_two(p+1); 
    102 } 
    103  
    104   #define convert_short(x) swap_two((uint8_t *)(&(x))) 
    105   #define convert_long(x)  swap_four((uint8_t *)(&(x))) 
     89static void swap_two (uint8_t * p) 
     90{ 
     91  uint8_t x = p[0]; 
     92  p[0] = p[1]; 
     93  p[1] = x; 
     94} 
     95 
     96static void swap_four (uint8_t * p) 
     97{ 
     98  uint8_t x = p[0]; 
     99  p[0] = p[3]; 
     100  p[3] = x; 
     101  swap_two (p + 1); 
     102} 
     103 
     104#define convert_short(x) swap_two((uint8_t *)(&(x))) 
     105#define convert_long(x)  swap_four((uint8_t *)(&(x))) 
    106106 
    107107#endif 
    108108 
    109 static void rdcf_get_date_and_time(struct rdcf_date_and_time *p) 
    110 { 
    111         struct tm dateTime; 
    112         struct timeval  temp; 
    113         time_t now; 
    114  
    115         gettimeofday(&temp, 0); 
    116         now = temp.tv_sec; 
    117         localtime_r(&now, &dateTime); 
    118                 // time is correct. 
    119         p->hour = dateTime.tm_hour; 
    120         p->minute = dateTime.tm_min; 
    121         p->second = dateTime.tm_sec; 
    122         p->month = dateTime.tm_mon+1; 
    123         p->day = dateTime.tm_mday; 
    124         p->year = dateTime.tm_year+1900; 
     109static void rdcf_get_date_and_time (struct rdcf_date_and_time *p) 
     110{ 
     111  struct tm dateTime; 
     112  struct timeval temp; 
     113  time_t now; 
     114 
     115  gettimeofday (&temp, 0); 
     116  now = temp.tv_sec; 
     117  localtime_r (&now, &dateTime); 
     118  // time is correct. 
     119  p->hour = dateTime.tm_hour; 
     120  p->minute = dateTime.tm_min; 
     121  p->second = dateTime.tm_sec; 
     122  p->month = dateTime.tm_mon + 1; 
     123  p->day = dateTime.tm_mday; 
     124  p->year = dateTime.tm_year + 1900; 
    125125} 
    126126 
     
    130130-----------------------------------------------------------------------------*/ 
    131131 
    132 static void error_exit(struct rdcf *f, int error) 
    133 { 
    134   longjmp(f->error, error); 
     132static void error_exit (struct rdcf *f, int error) 
     133{ 
     134  longjmp (f->error, error); 
    135135} 
    136136 
     
    141141static void read_sector (struct rdcf *f, unsigned sector, void *buffer) 
    142142{ 
    143         f->drive_error = f->ReadSector(sector, buffer); 
    144         if (f->drive_error != 0) error_exit(f, ~EIO); 
    145 } 
    146  
    147 static void write_sector (struct rdcf *f, unsigned sector, const uint8_t *buffer) 
    148 { 
    149         f->drive_error = f->WriteSector(sector, buffer); 
    150         if (f->drive_error != 0) error_exit(f, ~EIO); 
    151 } 
    152          
     143  f->drive_error = f->ReadSector (sector, buffer); 
     144  if (f->drive_error != 0) 
     145    error_exit (f, ~EIO); 
     146} 
     147 
     148static void write_sector (struct rdcf *f, unsigned sector, 
     149                          const uint8_t * buffer) 
     150{ 
     151  f->drive_error = f->WriteSector (sector, buffer); 
     152  if (f->drive_error != 0) 
     153    error_exit (f, ~EIO); 
     154} 
     155 
    153156/*----------------------------------------------------------------------------- 
    154157This function writes the buffer in the FCB if it is marked as "dirty". 
    155158-----------------------------------------------------------------------------*/ 
    156159 
    157 static void flush_buffer(struct rdcf *f) 
    158 { 
    159         if (f->buffer_status == DIRTY) { 
    160                         // here is where we keep from thrashing while doing FAT operations. 
    161                         // if the sector to be written is in the first FAT table, then 
    162                         // mirror the write to corresponding sector in second FAT. 
    163                 write_sector(f, f->sector_in_buffer, f->buffer.buf); 
    164                 if ((f->sector_in_buffer >= f->first_FAT_sector) && 
    165                                 (f->sector_in_buffer <= f->first_FAT_sector+f->sectors_per_FAT)) { 
    166                                 // mirror. 
    167                         write_sector(f, f->sector_in_buffer+f->sectors_per_FAT, f->buffer.buf); 
    168                 } 
    169                 f->buffer_status = CLEAN; 
    170         } 
     160static void flush_buffer (struct rdcf *f) 
     161{ 
     162  if (f->buffer_status == DIRTY) { 
     163    // here is where we keep from thrashing while doing FAT operations. 
     164    // if the sector to be written is in the first FAT table, then 
     165    // mirror the write to corresponding sector in second FAT. 
     166    write_sector (f, f->sector_in_buffer, f->buffer.buf); 
     167    if ((f->sector_in_buffer >= f->first_FAT_sector) && 
     168        (f->sector_in_buffer <= f->first_FAT_sector + f->sectors_per_FAT)) { 
     169      // mirror. 
     170      write_sector (f, f->sector_in_buffer + f->sectors_per_FAT, 
     171                    f->buffer.buf); 
     172    } 
     173    f->buffer_status = CLEAN; 
     174  } 
    171175} 
    172176 
     
    176180-----------------------------------------------------------------------------*/ 
    177181 
    178 static void read_buffer(struct rdcf *f, unsigned sector) 
    179 { 
    180         if (f->buffer_status == EMPTY || sector != f->sector_in_buffer) { 
    181                 flush_buffer(f); 
    182                 read_sector(f, sector, f->buffer.buf); 
    183                 f->sector_in_buffer = sector; 
    184                 f->buffer_status = CLEAN; 
    185         } 
     182static void read_buffer (struct rdcf *f, unsigned sector) 
     183{ 
     184  if (f->buffer_status == EMPTY || sector != f->sector_in_buffer) { 
     185    flush_buffer (f); 
     186    read_sector (f, sector, f->buffer.buf); 
     187    f->sector_in_buffer = sector; 
     188    f->buffer_status = CLEAN; 
     189  } 
    186190} 
    187191 
     
    191195-----------------------------------------------------------------------------*/ 
    192196 
    193 static void check_cluster(struct rdcf *f, unsigned cluster) 
    194 { 
    195         if (cluster < 2 || cluster > f->maximum_cluster_number) 
    196                 error_exit(f, ~ESPIPE); 
     197static void check_cluster (struct rdcf *f, unsigned cluster) 
     198{ 
     199  if (cluster < 2 || cluster > f->maximum_cluster_number) 
     200    error_exit (f, ~ESPIPE); 
    197201} 
    198202 
     
    202206-----------------------------------------------------------------------------*/ 
    203207 
    204 static unsigned FAT_entry(struct rdcf *f, unsigned cluster) 
    205 { 
    206         check_cluster(f, cluster); 
    207         if (f->maximum_cluster_number < RESERVED_CLUSTER_12_BIT) { 
    208                 unsigned byte_index = cluster + (cluster>>1); 
    209                 uint8_t p[2]; 
    210                 read_buffer(f, f->first_FAT_sector + byte_index/SECTOR_SIZE); 
    211                 p[0] = f->buffer.buf[byte_index%SECTOR_SIZE]; 
    212                 byte_index++; 
    213                 read_buffer(f, f->first_FAT_sector + byte_index/SECTOR_SIZE); 
    214                 p[1] = f->buffer.buf[byte_index%SECTOR_SIZE]; 
    215                 return (cluster&1) ? (p[1]<<4 | p[0]>>4) : (p[0] | p[1])<<8&0xF00; 
    216         } else { 
    217                 ushort x; 
    218                 read_buffer(f, f->first_FAT_sector + cluster/(SECTOR_SIZE/2)); 
    219                 x = f->buffer.fat[cluster%(SECTOR_SIZE/2)]; 
    220                 #ifdef _BIG_ENDIAN 
    221                 convert_short(x); 
    222                 #endif 
    223                 return x; 
    224         } 
     208static unsigned FAT_entry (struct rdcf *f, unsigned cluster) 
     209{ 
     210  check_cluster (f, cluster); 
     211  if (f->maximum_cluster_number < RESERVED_CLUSTER_12_BIT) { 
     212    unsigned byte_index = cluster + (cluster >> 1); 
     213    uint8_t p[2]; 
     214    read_buffer (f, f->first_FAT_sector + byte_index / SECTOR_SIZE); 
     215    p[0] = f->buffer.buf[byte_index % SECTOR_SIZE]; 
     216    byte_index++; 
     217    read_buffer (f, f->first_FAT_sector + byte_index / SECTOR_SIZE); 
     218    p[1] = f->buffer.buf[byte_index % SECTOR_SIZE]; 
     219    return (cluster & 1) ? (p[1] << 4 | p[0] >> 4) : (p[0] | p[1]) << 8 & 
     220      0xF00; 
     221  } 
     222  else { 
     223    ushort x; 
     224    read_buffer (f, f->first_FAT_sector + cluster / (SECTOR_SIZE / 2)); 
     225    x = f->buffer.fat[cluster % (SECTOR_SIZE / 2)]; 
     226#ifdef _BIG_ENDIAN 
     227    convert_short (x); 
     228#endif 
     229    return x; 
     230  } 
    225231} 
    226232 
     
    235241-----------------------------------------------------------------------------*/ 
    236242 
    237 static void set_FAT_entry(struct rdcf *f, unsigned cluster, unsigned x) 
    238 { 
    239         unsigned sector; 
    240         check_cluster(f, cluster); 
     243static void set_FAT_entry (struct rdcf *f, unsigned cluster, unsigned x) 
     244{ 
     245  unsigned sector; 
     246  check_cluster (f, cluster); 
    241247#ifdef _BIG_ENDIAN 
    242         if (f->maximum_cluster_number >= RESERVED_CLUSTER_12_BIT) 
    243                 convert_short(x); 
     248  if (f->maximum_cluster_number >= RESERVED_CLUSTER_12_BIT) 
     249    convert_short (x); 
    244250#endif 
    245         sector = f->first_FAT_sector; 
    246         if (f->maximum_cluster_number < RESERVED_CLUSTER_12_BIT) { 
    247                 unsigned byte_index = cluster + (cluster>>1); 
    248                 uint8_t *p; 
    249                 read_buffer(f, sector + byte_index/SECTOR_SIZE); 
    250                 p = f->buffer.buf + byte_index%SECTOR_SIZE; 
    251                 *p = (cluster&1) ? (*p & 0x0F) | (x<<4) : x; 
    252                 f->buffer_status = DIRTY; 
    253                 read_buffer(f, sector + (byte_index+1)/SECTOR_SIZE); 
    254                 p = f->buffer.buf + (byte_index+1)%SECTOR_SIZE; 
    255                 *p = (cluster&1) ? x>>4 : (*p&0xF0) | (x>>8); 
    256         } else { 
    257                 read_buffer(f, sector + cluster/(SECTOR_SIZE/2)); 
    258                 f->buffer.fat[cluster%(SECTOR_SIZE/2)] = x; 
    259         } 
    260         f->buffer_status = DIRTY; 
     251  sector = f->first_FAT_sector; 
     252  if (f->maximum_cluster_number < RESERVED_CLUSTER_12_BIT) { 
     253    unsigned byte_index = cluster + (cluster >> 1); 
     254    uint8_t *p; 
     255    read_buffer (f, sector + byte_index / SECTOR_SIZE); 
     256    p = f->buffer.buf + byte_index % SECTOR_SIZE; 
     257    *p = (cluster & 1) ? (*p & 0x0F) | (x << 4) : x; 
     258    f->buffer_status = DIRTY; 
     259    read_buffer (f, sector + (byte_index + 1) / SECTOR_SIZE); 
     260    p = f->buffer.buf + (byte_index + 1) % SECTOR_SIZE; 
     261    *p = (cluster & 1) ? x >> 4 : (*p & 0xF0) | (x >> 8); 
     262  } 
     263  else { 
     264    read_buffer (f, sector + cluster / (SECTOR_SIZE / 2)); 
     265    f->buffer.fat[cluster % (SECTOR_SIZE / 2)] = x; 
     266  } 
     267  f->buffer_status = DIRTY; 
    261268} 
    262269 
     
    267274-----------------------------------------------------------------------------*/ 
    268275 
    269 static void check_file_character(struct rdcf *f, unsigned c) 
    270 { 
    271         static uint8_t table[32] = { 
    272                 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0xDC, 0x00, 0xFC, 
    273                 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x90, 
    274                 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
    275                 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 
    276         }; 
    277         if (table[c>>3] & 1<<(c&7)) error_exit(f, ~EINVAL); 
     276static void check_file_character (struct rdcf *f, unsigned c) 
     277{ 
     278  static uint8_t table[32] = { 
     279    0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0xDC, 0x00, 0xFC, 
     280    0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x90, 
     281    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     282    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 
     283  }; 
     284  if (table[c >> 3] & 1 << (c & 7)) 
     285    error_exit (f, ~EINVAL); 
    278286} 
    279287 
     
    284292-----------------------------------------------------------------------------*/ 
    285293 
    286 static const char *spec_to_name_extension(struct rdcf *f, 
    287         uint8_t *name_extension, const uint8_t *spec) 
    288 { 
    289         unsigned i = 0; 
    290         unsigned c; 
    291         while ((c=(*spec++))!=0 && c!=RDCF_SLASH_CHAR && c!='.') { 
    292                 check_file_character(f,c); 
    293                 if (i<NAME_SIZE) name_extension[i++] = toupper(c); 
    294         } 
    295         if (i==0) error_exit(f, ~EINVAL); 
    296         while (i<NAME_SIZE) name_extension[i++] = ' '; 
    297         if (c=='.') while ((c=(*spec++))!=0 && c!=RDCF_SLASH_CHAR) { 
    298                 check_file_character(f,c); 
    299                 if (i<NAME_SIZE+EXTENSION_SIZE) name_extension[i++] = toupper(c); 
    300         } 
    301         while (i<NAME_SIZE+EXTENSION_SIZE) name_extension[i++] = ' '; 
    302         return spec-1; 
     294static const char *spec_to_name_extension (struct rdcf *f, 
     295                                           uint8_t * name_extension, 
     296                                           const uint8_t * spec) 
     297{ 
     298  unsigned i = 0; 
     299  unsigned c; 
     300  while ((c = (*spec++)) != 0 && c != RDCF_SLASH_CHAR && c != '.') { 
     301    check_file_character (f, c); 
     302    if (i < NAME_SIZE) 
     303      name_extension[i++] = toupper (c); 
     304  } 
     305  if (i == 0) 
     306    error_exit (f, ~EINVAL); 
     307  while (i < NAME_SIZE) 
     308    name_extension[i++] = ' '; 
     309  if (c == '.') 
     310    while ((c = (*spec++)) != 0 && c != RDCF_SLASH_CHAR) { 
     311      check_file_character (f, c); 
     312      if (i < NAME_SIZE + EXTENSION_SIZE) 
     313        name_extension[i++] = toupper (c); 
     314    } 
     315  while (i < NAME_SIZE + EXTENSION_SIZE) 
     316    name_extension[i++] = ' '; 
     317  return spec - 1; 
    303318} 
    304319 
     
    307322-----------------------------------------------------------------------------*/ 
    308323 
    309 static void name_extension_to_spec(uint8_t *spec, const uint8_t *name_extension) 
    310 { 
    311         unsigned i; 
    312         uint8_t *s = spec; 
    313         for (i=0; i<NAME_SIZE && name_extension[i]!=' '; i++) 
    314                 *s++ = name_extension[i]; 
    315         if (name_extension[NAME_SIZE]!=' ') { 
    316                 *s++ = '.'; 
    317                 for (i=NAME_SIZE; 
    318                                 i<NAME_SIZE+EXTENSION_SIZE && name_extension[i]!=' '; i++) { 
    319                         *s++ = name_extension[i]; 
    320                 } 
    321         } 
    322         *s = 0; 
     324static void name_extension_to_spec (uint8_t * spec, 
     325                                    const uint8_t * name_extension) 
     326{ 
     327  unsigned i; 
     328  uint8_t *s = spec; 
     329  for (i = 0; i < NAME_SIZE && name_extension[i] != ' '; i++) 
     330    *s++ = name_extension[i]; 
     331  if (name_extension[NAME_SIZE] != ' ') { 
     332    *s++ = '.'; 
     333    for (i = NAME_SIZE; 
     334         i < NAME_SIZE + EXTENSION_SIZE && name_extension[i] != ' '; i++) { 
     335      *s++ = name_extension[i]; 
     336    } 
     337  } 
     338  *s = 0; 
    323339} 
    324340 
     
    328344-----------------------------------------------------------------------------*/ 
    329345 
    330 static unsigned first_sector_in_cluster(struct rdcf *f, unsigned cluster) 
    331 { 
    332         check_cluster(f, cluster); 
    333         return f->first_data_sector + (cluster-2) * f->sectors_per_cluster; 
     346static unsigned first_sector_in_cluster (struct rdcf *f, unsigned cluster) 
     347{ 
     348  check_cluster (f, cluster); 
     349  return f->first_data_sector + (cluster - 2) * f->sectors_per_cluster; 
    334350} 
    335351 
     
    339355-----------------------------------------------------------------------------*/ 
    340356 
    341 static struct directory *find_directory(struct rdcf *f) 
    342 { 
    343         read_buffer(f, (f->directory_cluster == 0 ? f->first_directory_sector : 
    344                 first_sector_in_cluster(f, f->directory_cluster)) + 
    345                 f->directory_index/ENTRIES_PER_SECTOR); 
    346         return &f->buffer.dir[f->directory_index%ENTRIES_PER_SECTOR]; 
    347 } 
    348   
     357static struct directory *find_directory (struct rdcf *f) 
     358{ 
     359  read_buffer (f, (f->directory_cluster == 0 ? f->first_directory_sector : 
     360                   first_sector_in_cluster (f, f->directory_cluster)) + 
     361               f->directory_index / ENTRIES_PER_SECTOR); 
     362  return &f->buffer.dir[f->directory_index % ENTRIES_PER_SECTOR]; 
     363} 
     364 
    349365/*----------------------------------------------------------------------------- 
    350366This function updates a directory entry.  If the "delete_entry" parameter is 
     
    352368-----------------------------------------------------------------------------*/ 
    353369 
    354 static void update_directory_entry(struct rdcf *f, int delete_entry) 
    355 { 
    356         struct directory *d = find_directory(f); 
    357         if (f->file.attribute & RDCF_VOLUME || f->file.spec[0] == '.') 
    358                 memcpy(d->name_extension, f->file.spec, NAME_SIZE+EXTENSION_SIZE); 
    359         else 
    360                 spec_to_name_extension(f, d->name_extension, f->file.spec); 
    361         if (delete_entry) d->name_extension[0] = DELETED_FILE; 
    362         d->attribute = f->file.attribute; 
    363         d->date = (f->file.date_and_time.year-1980)<<9 | 
    364         f->file.date_and_time.month<<5 | f->file.date_and_time.day; 
    365         d->time = f->file.date_and_time.hour<<11 | 
    366         f->file.date_and_time.minute<<5 | f->file.date_and_time.second>>1; 
    367         d->first_cluster = f->file.first_cluster; 
    368         d->size = f->file.size; 
    369         memset(d->reserved, 0, sizeof(d->reserved)); 
     370static void update_directory_entry (struct rdcf *f, int delete_entry) 
     371{ 
     372  struct directory *d = find_directory (f); 
     373  if (f->file.attribute & RDCF_VOLUME || f->file.spec[0] == '.') 
     374    memcpy (d->name_extension, f->file.spec, NAME_SIZE + EXTENSION_SIZE); 
     375  else 
     376    spec_to_name_extension (f, d->name_extension, f->file.spec); 
     377  if (delete_entry) 
     378    d->name_extension[0] = DELETED_FILE; 
     379  d->attribute = f->file.attribute; 
     380  d->date = (f->file.date_and_time.year - 1980) << 9 | 
     381    f->file.date_and_time.month << 5 | f->file.date_and_time.day; 
     382  d->time = f->file.date_and_time.hour << 11 | 
     383    f->file.date_and_time.minute << 5 | f->file.date_and_time.second >> 1; 
     384  d->first_cluster = f->file.first_cluster; 
     385  d->size = f->file.size; 
     386  memset (d->reserved, 0, sizeof (d->reserved)); 
    370387#ifdef _BIG_ENDIAN 
    371         convert_short(d->date); 
    372         convert_short(d->time); 
    373         convert_short(d->first_cluster); 
    374         convert_long(d->size); 
     388  convert_short (d->date); 
     389  convert_short (d->time); 
     390  convert_short (d->first_cluster); 
     391  convert_long (d->size); 
    375392#endif 
    376         f->buffer_status = DIRTY; 
     393  f->buffer_status = DIRTY; 
    377394} 
    378395 
     
    381398-----------------------------------------------------------------------------*/ 
    382399 
    383 static void read_directory_entry(struct rdcf *f) 
    384 { 
    385         struct directory *d = find_directory(f); 
    386         if (d->attribute&RDCF_VOLUME) { 
    387                 memcpy(f->file.spec, d->name_extension, NAME_SIZE+EXTENSION_SIZE); 
    388                 f->file.spec[NAME_SIZE+EXTENSION_SIZE] = 0; 
    389         } else 
    390                 name_extension_to_spec(f->file.spec, d->name_extension); 
    391         f->file.attribute = d->attribute; 
    392         { 
    393                 ushort date = d->date; 
     400static void read_directory_entry (struct rdcf *f) 
     401{ 
     402  struct directory *d = find_directory (f); 
     403  if (d->attribute & RDCF_VOLUME) { 
     404    memcpy (f->file.spec, d->name_extension, NAME_SIZE + EXTENSION_SIZE); 
     405    f->file.spec[NAME_SIZE + EXTENSION_SIZE] = 0; 
     406  } 
     407  else 
     408    name_extension_to_spec (f->file.spec, d->name_extension); 
     409  f->file.attribute = d->attribute; 
     410  { 
     411    ushort date = d->date; 
    394412#ifdef _BIG_ENDIAN 
    395                 convert_short(date); 
     413    convert_short (date); 
    396414#endif 
    397                 f->file.date_and_time.year = (date>>9)+1980; 
    398                 f->file.date_and_time.month = date>>5&0xF; 
    399                 f->file.date_and_time.day = date&0x1F; 
    400         } 
    401         { 
    402                 ushort aTime = d->time; 
     415    f->file.date_and_time.year = (date >> 9) + 1980; 
     416    f->file.date_and_time.month = date >> 5 & 0xF; 
     417    f->file.date_and_time.day = date & 0x1F; 
     418  } 
     419  { 
     420    ushort aTime = d->time; 
    403421#ifdef _BIG_ENDIAN 
    404                 convert_short(time); 
     422    convert_short (time); 
    405423#endif 
    406                 f->file.date_and_time.hour = aTime>>11; 
    407                 f->file.date_and_time.minute = aTime>>5&0x3F; 
    408                 f->file.date_and_time.second = aTime<<1&0x1F<<1; 
    409         } 
    410         f->file.first_cluster = d->first_cluster; 
    411         f->file.size = d->size; 
     424    f->file.date_and_time.hour = aTime >> 11; 
     425    f->file.date_and_time.minute = aTime >> 5 & 0x3F; 
     426    f->file.date_and_time.second = aTime << 1 & 0x1F << 1; 
     427  } 
     428  f->file.first_cluster = d->first_cluster; 
     429  f->file.size = d->size; 
    412430#ifdef _BIG_ENDIAN 
    413         convert_short(f->file.first_cluster); 
    414         convert_long(f->file.size); 
     431  convert_short (f->file.first_cluster); 
     432  convert_long (f->file.size); 
    415433#endif 
    416434} 
     
    435453-----------------------------------------------------------------------------*/ 
    436454 
    437 static int find_file_in_directory_or_find_volume(struct rdcf *f, 
    438         const uint8_t *name_extension) 
    439 { 
    440         unsigned empty_cluster = 2; 
    441         unsigned empty_index = NO_DIRECTORY_INDEX; 
    442         unsigned number_of_directory_entries = f->directory_cluster == 0 ? 
    443                 (f->first_data_sector - f->first_directory_sector)*ENTRIES_PER_SECTOR : 
    444                 ENTRIES_PER_SECTOR*f->sectors_per_cluster; 
    445         f->directory_first_cluster = f->directory_cluster; 
    446         while (1) { 
    447                 for (f->directory_index = 0; 
    448                                 f->directory_index < number_of_directory_entries; f->directory_index++) { 
    449                         struct directory *d = find_directory(f); 
    450                         if ((d->name_extension[0] == DELETED_FILE || 
    451                                         d->name_extension[0] == END_DIRECTORY) && 
    452                                         empty_index == NO_DIRECTORY_INDEX) { 
    453                                 empty_cluster = f->directory_cluster; 
    454                                 empty_index = f->directory_index; 
    455                         } 
    456                         if (d->name_extension[0] == END_DIRECTORY) break; 
    457                         if ((name_extension == NULL && 
    458                                         (d->name_extension[0] != DELETED_FILE && d->attribute & RDCF_VOLUME)) || 
    459                                         (name_extension != NULL && 
    460                                         (memcmp(d->name_extension, name_extension, NAME_SIZE+EXTENSION_SIZE) 
    461                                         == 0 && (d->attribute&RDCF_VOLUME) == 0))) { 
    462                                 read_directory_entry(f); 
    463                                 return 1; 
    464                         } 
    465                 } 
    466                 if (f->directory_index < number_of_directory_entries || 
    467                                 f->directory_cluster == 0) { 
    468                         break; 
    469                 } 
    470                 { 
    471                         unsigned x = FAT_entry(f, f->directory_cluster); 
    472                         if (x >= f->last_cluster_mark) break; 
    473                         f->directory_cluster = x; 
    474                 } 
    475         } 
    476         f->directory_index = empty_index; 
    477         if (f->directory_index != NO_DIRECTORY_INDEX) 
    478                 f->directory_cluster = empty_cluster; 
    479         if (name_extension != NULL) 
    480                 name_extension_to_spec(f->file.spec, name_extension); 
    481         return 0; 
     455static int find_file_in_directory_or_find_volume (struct rdcf *f, 
     456                                                  const uint8_t * 
     457                                                  name_extension) 
     458{ 
     459  unsigned empty_cluster = 2; 
     460  unsigned empty_index = NO_DIRECTORY_INDEX; 
     461  unsigned number_of_directory_entries = f->directory_cluster == 0 ? 
     462    (f->first_data_sector - f->first_directory_sector) * ENTRIES_PER_SECTOR : 
     463    ENTRIES_PER_SECTOR * f->sectors_per_cluster; 
     464  f->directory_first_cluster = f->directory_cluster; 
     465  while (1) { 
     466    for (f->directory_index = 0; 
     467         f->directory_index < number_of_directory_entries; 
     468         f->directory_index++) { 
     469      struct directory *d = find_directory (f); 
     470      if ((d->name_extension[0] == DELETED_FILE || 
     471           d->name_extension[0] == END_DIRECTORY) && 
     472          empty_index == NO_DIRECTORY_INDEX) { 
     473        empty_cluster = f->directory_cluster; 
     474        empty_index = f->directory_index; 
     475      } 
     476      if (d->name_extension[0] == END_DIRECTORY) 
     477        break; 
     478      if ((name_extension == NULL && 
     479           (d->name_extension[0] != DELETED_FILE 
     480            && d->attribute & RDCF_VOLUME)) || (name_extension != NULL 
     481                                                && 
     482                                                (memcmp 
     483                                                 (d->name_extension, 
     484                                                  name_extension, 
     485                                                  NAME_SIZE + EXTENSION_SIZE) 
     486                                                 == 0 
     487                                                 && (d-> 
     488                                                     attribute & RDCF_VOLUME) 
     489                                                 == 0))) { 
     490        read_directory_entry (f); 
     491        return 1; 
     492      } 
     493    } 
     494    if (f->directory_index < number_of_directory_entries || 
     495        f->directory_cluster == 0) { 
     496      break; 
     497    } 
     498    { 
     499      unsigned x = FAT_entry (f, f->directory_cluster); 
     500      if (x >= f->last_cluster_mark) 
     501        break; 
     502      f->directory_cluster = x; 
     503    } 
     504  } 
     505  f->directory_index = empty_index; 
     506  if (f->directory_index != NO_DIRECTORY_INDEX) 
     507    f->directory_cluster = empty_cluster; 
     508  if (name_extension != NULL) 
     509    name_extension_to_spec (f->file.spec, name_extension); 
     510  return 0; 
    482511} 
    483512 
     
    494523-----------------------------------------------------------------------------*/ 
    495524 
    496 static int find_file(struct rdcf *f, const char *spec) 
    497 { 
    498                 /* start with root directory */ 
    499         f->directory_cluster = 0; 
    500         while (1) { 
    501                 int found; 
    502                 uint8_t name_extension[NAME_SIZE+EXTENSION_SIZE]; 
    503                         /* scan name and extension */ 
    504                 spec = spec_to_name_extension(f, name_extension, spec); 
    505                         /* look it up in directory */ 
    506                 found = find_file_in_directory_or_find_volume(f, name_extension); 
    507                         /* if this is the end of the file specification, return */ 
    508                 if (*spec == 0) return found; 
    509                         /* otherwise, the name and extension were a subdirectory in the path */ 
    510                 if (!found || (f->file.attribute&RDCF_DIRECTORY) == 0) 
    511                         error_exit(f, ~EISDIR); 
    512                 f->directory_cluster = f->file.first_cluster; 
    513                         /* skip over the \ after the subdirectory */ 
    514                 spec++; 
    515         } 
     525static int find_file (struct rdcf *f, const char *spec) 
     526{ 
     527  /* start with root directory */ 
     528  f->directory_cluster = 0; 
     529  while (1) { 
     530    int found; 
     531    uint8_t name_extension[NAME_SIZE + EXTENSION_SIZE]; 
     532    /* scan name and extension */ 
     533    spec = spec_to_name_extension (f, name_extension, spec); 
     534    /* look it up in directory */ 
     535    found = find_file_in_directory_or_find_volume (f, name_extension); 
     536    /* if this is the end of the file specification, return */ 
     537    if (*spec == 0) 
     538      return found; 
     539    /* otherwise, the name and extension were a subdirectory in the path */ 
     540    if (!found || (f->file.attribute & RDCF_DIRECTORY) == 0) 
     541      error_exit (f, ~EISDIR); 
     542    f->directory_cluster = f->file.first_cluster; 
     543    /* skip over the \ after the subdirectory */ 
     544    spec++; 
     545  } 
    516546} 
    517547 
     
    520550-----------------------------------------------------------------------------*/ 
    521551 
    522 static void read_file_system_information(struct rdcf *f) 
    523 { 
    524         f->first_FAT_sector = DriveDesc.FirstFatSector; 
    525         f->sectors_per_FAT = DriveDesc.SectorsPerFAT; 
    526         f->sectors_per_cluster = DriveDesc.SectorsPerCluster; 
    527         f->first_directory_sector = DriveDesc.RootDirSector; 
    528         f->first_data_sector = DriveDesc.DataStartSector; 
    529         f->maximum_cluster_number = 
    530                 ((DriveDesc.MaxDataSector - DriveDesc.DataStartSector) / 
    531                 DriveDesc.SectorsPerCluster) + 1; 
    532         f->last_cluster_mark = 
    533                 f->maximum_cluster_number < RESERVED_CLUSTER_12_BIT ? 
    534                 LAST_CLUSTER_12_BIT : LAST_CLUSTER_16_BIT; 
     552static void read_file_system_information (struct rdcf *f) 
     553{ 
     554  f->first_FAT_sector = DriveDesc.FirstFatSector; 
     555  f->sectors_per_FAT = DriveDesc.SectorsPerFAT; 
     556  f->sectors_per_cluster = DriveDesc.SectorsPerCluster; 
     557  f->first_directory_sector = DriveDesc.RootDirSector; 
     558  f->first_data_sector = DriveDesc.DataStartSector; 
     559  f->maximum_cluster_number = 
     560    ((DriveDesc.MaxDataSector - DriveDesc.DataStartSector) / 
     561     DriveDesc.SectorsPerCluster) + 1; 
     562  f->last_cluster_mark = 
     563    f->maximum_cluster_number < RESERVED_CLUSTER_12_BIT ? 
     564    LAST_CLUSTER_12_BIT : LAST_CLUSTER_16_BIT; 
    535565} 
    536566 
     
    542572#ifdef RDCF_MULTIPLE_DRIVE 
    543573#error "multiple drives has not been implemented!" 
    544 static char *get_drive(struct rdcf *f, char *spec) 
    545 { 
    546         if (spec[0] != 0 && spec[1] == ':') { 
    547                 if (isalpha(spec[0])) f->drive = toupper(spec[0])-'A'; 
    548                 else error_exit(f, ~EINVAL); 
    549                 return spec + 2; 
    550         } 
    551         error_exit(f, ~EINVAL); 
     574static char *get_drive (struct rdcf *f, char *spec) 
     575{ 
     576  if (spec[0] != 0 && spec[1] == ':') { 
     577    if (isalpha (spec[0])) 
     578      f->drive = toupper (spec[0]) - 'A'; 
     579    else 
     580      error_exit (f, ~EINVAL); 
     581    return spec + 2; 
     582  } 
     583  error_exit (f, ~EINVAL); 
    552584} 
    553585#endif 
     
    559591-----------------------------------------------------------------------------*/ 
    560592 
    561 static const char * initialize_fcb(struct rdcf *f, const char * spec) 
    562 { 
    563         f->buffer_status = EMPTY; 
    564         f->first_possibly_empty_cluster = 2; 
    565         read_file_system_information(f); 
    566         return spec; 
     593static const char *initialize_fcb (struct rdcf *f, const char *spec) 
     594{ 
     595  f->buffer_status = EMPTY; 
     596  f->first_possibly_empty_cluster = 2; 
     597  read_file_system_information (f); 
     598  return spec; 
    567599} 
    568600 
     
    572604-----------------------------------------------------------------------------*/ 
    573605 
    574 static void check_write_access(struct rdcf *f) 
    575 { 
    576         if (f->file.attribute & (RDCF_READ_ONLY+RDCF_HIDDEN+RDCF_SYSTEM)) 
    577                 error_exit(f, ~EACCES); 
     606static void check_write_access (struct rdcf *f) 
     607{ 
     608  if (f->file.attribute & (RDCF_READ_ONLY + RDCF_HIDDEN + RDCF_SYSTEM)) 
     609    error_exit (f, ~EACCES); 
    578610} 
    579611 
     
    582614-----------------------------------------------------------------------------*/ 
    583615 
    584 static void release_FAT_entries(struct rdcf *f) 
    585 { 
    586         unsigned j; 
    587         j = f->file.first_cluster; 
    588         if (j != EMPTY_CLUSTER) { 
    589                 while (j < f->last_cluster_mark && j) { 
    590                         unsigned k = FAT_entry(f,j); 
    591                         if (j < f->first_possibly_empty_cluster) { 
    592                           f->first_possibly_empty_cluster = j; 
    593                         } 
    594                         set_FAT_entry(f,j,EMPTY_CLUSTER); 
    595                         j = k; 
    596                 } 
    597         } 
    598         f->mode |= WRITTEN; 
     616static void release_FAT_entries (struct rdcf *f) 
     617{ 
     618  unsigned j; 
     619  j = f->file.first_cluster; 
     620  if (j != EMPTY_CLUSTER) { 
     621    while (j < f->last_cluster_mark && j) { 
     622      unsigned k = FAT_entry (f, j); 
     623      if (j < f->first_possibly_empty_cluster) { 
     624        f->first_possibly_empty_cluster = j; 
     625      } 
     626      set_FAT_entry (f, j, EMPTY_CLUSTER); 
     627      j = k; 
     628    } 
     629  } 
     630  f->mode |= WRITTEN; 
    599631} 
    600632 
     
    605637-----------------------------------------------------------------------------*/ 
    606638 
    607 static unsigned add_new_cluster(struct rdcf *f, unsigned cluster, 
    608         unsigned first_possibly_empty_cluster) 
    609 { 
    610 unsigned new_cluster; 
    611         for (new_cluster = first_possibly_empty_cluster; 
    612                         new_cluster <= f->maximum_cluster_number; new_cluster++) { 
    613                 if (FAT_entry(f, new_cluster)==EMPTY_CLUSTER) break; 
    614         } 
    615         if (new_cluster > f->maximum_cluster_number) return EMPTY_CLUSTER; 
    616         if (cluster != EMPTY_CLUSTER) set_FAT_entry(f, cluster, new_cluster); 
    617         set_FAT_entry(f, new_cluster, f->last_cluster_mark); 
    618         return new_cluster; 
     639static unsigned add_new_cluster (struct rdcf *f, unsigned cluster, 
     640                                 unsigned first_possibly_empty_cluster) 
     641{ 
     642  unsigned new_cluster; 
     643  for (new_cluster = first_possibly_empty_cluster; 
     644       new_cluster <= f->maximum_cluster_number; new_cluster++) { 
     645    if (FAT_entry (f, new_cluster) == EMPTY_CLUSTER) 
     646      break; 
     647  } 
     648  if (new_cluster > f->maximum_cluster_number) 
     649    return EMPTY_CLUSTER; 
     650  if (cluster != EMPTY_CLUSTER) 
     651    set_FAT_entry (f, cluster, new_cluster); 
     652  set_FAT_entry (f, new_cluster, f->last_cluster_mark); 
     653  return new_cluster; 
    619654} 
    620655 
     
    623658-----------------------------------------------------------------------------*/ 
    624659 
    625 static void clear_cluster(struct rdcf *f, unsigned cluster) 
    626 { 
    627         unsigned count = f->sectors_per_cluster; 
    628         unsigned sector = first_sector_in_cluster(f, cluster); 
    629         flush_buffer(f); 
    630         f->buffer_status = EMPTY; 
    631         memset(f->buffer.buf, 0, SECTOR_SIZE); 
    632         do write_sector(f, sector++, f->buffer.buf); while (--count != 0); 
     660static void clear_cluster (struct rdcf *f, unsigned cluster) 
     661{ 
     662  unsigned count = f->sectors_per_cluster; 
     663  unsigned sector = first_sector_in_cluster (f, cluster); 
     664  flush_buffer (f); 
     665  f->buffer_status = EMPTY; 
     666  memset (f->buffer.buf, 0, SECTOR_SIZE); 
     667  do 
     668    write_sector (f, sector++, f->buffer.buf); 
     669  while (--count != 0); 
    633670} 
    634671 
     
    638675-----------------------------------------------------------------------------*/ 
    639676 
    640 static void lengthen_directory_if_necessary(struct rdcf *f) 
    641 { 
    642         if (f->directory_index == NO_DIRECTORY_INDEX) { 
    643                 if (f->directory_cluster == 0) error_exit(f, ~ENOSPC); 
    644                 f->directory_cluster = add_new_cluster(f, f->directory_cluster, 2); 
    645                 if (f->directory_cluster == 0) error_exit(f, ~ENOSPC); 
    646                 f->directory_index = 0; 
    647                 clear_cluster(f, f->directory_cluster); 
    648         } 
     677static void lengthen_directory_if_necessary (struct rdcf *f) 
     678{ 
     679  if (f->directory_index == NO_DIRECTORY_INDEX) { 
     680    if (f->directory_cluster == 0) 
     681      error_exit (f, ~ENOSPC); 
     682    f->directory_cluster = add_new_cluster (f, f->directory_cluster, 2); 
     683    if (f->directory_cluster == 0) 
     684      error_exit (f, ~ENOSPC); 
     685    f->directory_index = 0; 
     686    clear_cluster (f, f->directory_cluster); 
     687  } 
    649688} 
    650689 
     
    658697    (RDCF_ARCHIVE+RDCF_HIDDEN+RDCF_READ_ONLY+RDCF_SYSTEM) 
    659698 
    660 int rdcf_close(struct rdcf *f) 
    661 { 
    662         if ((f->result=setjmp(f->error)) != 0) return f->result; 
    663         if (f->mode & WRITTEN) { 
    664                 f->buffer_status = EMPTY; 
    665                 f->file.attribute |= RDCF_ARCHIVE; 
    666                 rdcf_get_date_and_time(&f->file.date_and_time); 
    667                         // do not allow empty files. 
    668                 update_directory_entry(f, (f->file.size) ? 0 : 1); 
    669                 flush_buffer(f); 
    670         } 
    671         return 0; 
    672 } 
    673  
    674 int rdcf_delete(struct rdcf *f, const char *spec) 
    675 { 
    676         if ((f->result=setjmp(f->error)) != 0) return f->result; 
    677         spec = initialize_fcb(f, spec); 
    678         if (*spec == 0) /* delete volume label */ { 
    679                 if (!find_file_in_directory_or_find_volume(f, NULL)) 
    680                         error_exit(f, ~ENOENT); 
    681         } else if (!find_file(f, spec)) 
    682                 error_exit(f, ~ENOENT); 
    683                 /* check to see that a directory is empty before deleting it */ 
    684         else if (f->file.attribute & RDCF_DIRECTORY) { 
    685                 unsigned cluster = f->file.first_cluster; 
    686                 while (cluster != EMPTY_CLUSTER && cluster < f->last_cluster_mark) { 
    687                         unsigned sector = first_sector_in_cluster(f, cluster); 
    688                         unsigned sector_count = f->sectors_per_cluster; 
    689                         unsigned next_cluster = FAT_entry(f, cluster); 
    690                         do { 
    691                                 unsigned entry_count = ENTRIES_PER_SECTOR; 
    692                                 uint8_t *p = f->buffer.buf; 
    693                                 read_buffer(f, sector); 
    694                                 do { 
    695                                         unsigned c = *p; 
    696                                         if (c == END_DIRECTORY) break; 
    697                                         if (c != DELETED_FILE && c != '.') error_exit(f, ~EACCES); 
    698                                         p += sizeof(struct directory); 
    699                                 } while (--entry_count != 0); 
    700                                 if (entry_count != 0) break; 
    701                         } while (--sector_count != 0); 
    702                         cluster = next_cluster; 
    703                 } 
    704         } else check_write_access(f); 
    705         release_FAT_entries(f); 
    706         update_directory_entry(f, 1); 
    707         flush_buffer(f); 
    708         return 0; 
    709 } 
    710  
    711 int rdcf_rename(struct rdcf *f, const char *old_spec, const char *new_spec) 
    712 { 
    713         uint8_t name_extension[NAME_SIZE+EXTENSION_SIZE]; 
    714         if ((f->result=setjmp(f->error)) != 0) return f->result; 
    715         old_spec = initialize_fcb(f, old_spec); 
    716         if (!find_file(f, old_spec)) error_exit(f, ~ENOENT); 
    717         if (f->file.attribute & (RDCF_HIDDEN+RDCF_SYSTEM)) 
    718                 error_exit(f, ~EACCES); 
    719         spec_to_name_extension(f, name_extension, new_spec); 
    720         f->directory_cluster = f->directory_first_cluster; 
    721         if (find_file_in_directory_or_find_volume(f, name_extension)) 
    722                 error_exit(f, ~ENOENT); 
    723         find_file(f, old_spec); 
    724         name_extension_to_spec(f->file.spec, name_extension); 
    725         update_directory_entry(f, 0); 
    726         flush_buffer(f); 
    727         return 0; 
    728 } 
    729  
    730 int rdcf_open(struct rdcf *f, const char *spec, unsigned mode) 
    731 { 
    732         int found; 
    733         if ((f->result=setjmp(f->error)) != 0) return f->result; 
    734                 // make sure it is not open on another stream. 
    735         f->mode = 0; 
    736         found = find_file(f, initialize_fcb(f, spec)); 
    737         if (found && f->file.attribute&RDCF_DIRECTORY) 
    738                 error_exit(f, ~EISDIR); 
    739                 // see how to open the file. 
    740         if (mode & _FTRUNC && found) { 
    741                         // simply empty the file of clusters. 
    742                 if (found) { 
    743                         check_write_access(f); 
    744                         release_FAT_entries(f); 
    745                         flush_buffer(f); 
    746                 } else lengthen_directory_if_necessary(f); 
    747                 f->file.first_cluster = EMPTY_CLUSTER; 
    748                 f->file.size = 0L; 
    749         } 
    750                 // create new dir entry if mode is not purely read: "r" 
    751         if (!found && (mode & 0x3)) { 
    752                 f->file.attribute = RDCF_ARCHIVE; 
    753                 rdcf_get_date_and_time(&f->file.date_and_time); 
    754                 f->mode |= WRITTEN; 
    755                 f->file.first_cluster = EMPTY_CLUSTER; 
    756                 f->file.size = 0L; 
    757                 update_directory_entry(f, 0); 
    758                 flush_buffer(f); 
    759         } 
    760         if ((mode & 0x3) == 0) { 
    761                         // open for reading. 
    762                 f->mode |= RDCF_READ; 
    763                 if (!found) error_exit(f, ~ENOENT); 
    764         } else { 
    765                         // open for writing or 
    766                 f->mode |= RDCF_WRITE; 
    767                         // open for read write. 
    768                 if ((mode & 0x3) == 2) f->mode |= RDCF_READ; 
    769                 check_write_access(f); 
    770         } 
    771         f->last_cluster = EMPTY_CLUSTER; 
    772         f->position = 0; 
    773         f->cluster = f->file.first_cluster; 
    774         if (mode & _FAPPEND) { 
    775                         // seek to end of file. 
    776                 if ((found = rdcf_seek(f, f->file.size)) != 0) return found; 
    777         } 
    778         return 0; 
     699int rdcf_close (struct rdcf *f) 
     700{ 
     701  if ((f->result = setjmp (f->error)) != 0) 
     702    return f->result; 
     703  if (f->mode & WRITTEN) { 
     704    f->buffer_status = EMPTY; 
     705    f->file.attribute |= RDCF_ARCHIVE; 
     706    rdcf_get_date_and_time (&f->file.date_and_time); 
     707    // do not allow empty files. 
     708    update_directory_entry (f, (f->file.size) ? 0 : 1); 
     709    flush_buffer (f); 
     710  } 
     711  return 0; 
     712} 
     713 
     714int rdcf_delete (struct rdcf *f, const char *spec) 
     715{ 
     716  if ((f->result = setjmp (f->error)) != 0) 
     717    return f->result; 
     718  spec = initialize_fcb (f, spec); 
     719  if (*spec == 0) {             /* delete volume label */ 
     720    if (!find_file_in_directory_or_find_volume (f, NULL)) 
     721      error_exit (f, ~ENOENT); 
     722  } 
     723  else if (!find_file (f, spec)) 
     724    error_exit (f, ~ENOENT); 
     725  /* check to see that a directory is empty before deleting it */ 
     726  else if (f->file.attribute & RDCF_DIRECTORY) { 
     727    unsigned cluster = f->file.first_cluster; 
     728    while (cluster != EMPTY_CLUSTER && cluster < f->last_cluster_mark) { 
     729      unsigned sector = first_sector_in_cluster (f, cluster); 
     730      unsigned sector_count = f->sectors_per_cluster; 
     731      unsigned next_cluster = FAT_entry (f, cluster); 
     732      do { 
     733        unsigned entry_count = ENTRIES_PER_SECTOR; 
     734        uint8_t *p = f->buffer.buf; 
     735        read_buffer (f, sector); 
     736        do { 
     737          unsigned c = *p; 
     738          if (c == END_DIRECTORY) 
     739            break; 
     740          if (c != DELETED_FILE && c != '.') 
     741            error_exit (f, ~EACCES); 
     742          p += sizeof (struct directory); 
     743        } while (--entry_count != 0); 
     744        if (entry_count != 0) 
     745          break; 
     746      } while (--sector_count != 0); 
     747      cluster = next_cluster; 
     748    } 
     749  } 
     750  else 
     751    check_write_access (f); 
     752  release_FAT_entries (f); 
     753  update_directory_entry (f, 1); 
     754  flush_buffer (f); 
     755  return 0; 
     756} 
     757 
     758int rdcf_rename (struct rdcf *f, const char *old_spec, const char *new_spec) 
     759{ 
     760  uint8_t name_extension[NAME_SIZE + EXTENSION_SIZE]; 
     761  if ((f->result = setjmp (f->error)) != 0) 
     762    return f->result; 
     763  old_spec = initialize_fcb (f, old_spec); 
     764  if (!find_file (f, old_spec)) 
     765    error_exit (f, ~ENOENT); 
     766  if (f->file.attribute & (RDCF_HIDDEN + RDCF_SYSTEM)) 
     767    error_exit (f, ~EACCES); 
     768  spec_to_name_extension (f, name_extension, new_spec); 
     769  f->directory_cluster = f->directory_first_cluster; 
     770  if (find_file_in_directory_or_find_volume (f, name_extension)) 
     771    error_exit (f, ~ENOENT); 
     772  find_file (f, old_spec); 
     773  name_extension_to_spec (f->file.spec, name_extension); 
     774  update_directory_entry (f, 0); 
     775  flush_buffer (f); 
     776  return 0; 
     777} 
     778 
     779int rdcf_open (struct rdcf *f, const char *spec, unsigned mode) 
     780{ 
     781  int found; 
     782  if ((f->result = setjmp (f->error)) != 0) 
     783    return f->result; 
     784  // make sure it is not open on another stream. 
     785  f->mode = 0; 
     786  found = find_file (f, initialize_fcb (f, spec)); 
     787  if (found && f->file.attribute & RDCF_DIRECTORY) 
     788    error_exit (f, ~EISDIR); 
     789  // see how to open the file. 
     790  if (mode & _FTRUNC && found) { 
     791    // simply empty the file of clusters. 
     792    if (found) { 
     793      check_write_access (f); 
     794      release_FAT_entries (f); 
     795      flush_buffer (f); 
     796    } 
     797    else 
     798      lengthen_directory_if_necessary (f); 
     799    f->file.first_cluster = EMPTY_CLUSTER; 
     800    f->file.size = 0L; 
     801  } 
     802  // create new dir entry if mode is not purely read: "r" 
     803  if (!found && (mode & 0x3)) { 
     804    f->file.attribute = RDCF_ARCHIVE; 
     805    rdcf_get_date_and_time (&f->file.date_and_time); 
     806    f->mode |= WRITTEN; 
     807    f->file.first_cluster = EMPTY_CLUSTER; 
     808    f->file.size = 0L; 
     809    update_directory_entry (f, 0); 
     810    flush_buffer (f); 
     811  } 
     812  if ((mode & 0x3) == 0) { 
     813    // open for reading. 
     814    f->mode |= RDCF_READ; 
     815    if (!found) 
     816      error_exit (f, ~ENOENT); 
     817  } 
     818  else { 
     819    // open for writing or 
     820    f->mode |= RDCF_WRITE; 
     821    // open for read write. 
     822    if ((mode & 0x3) == 2) 
     823      f->mode |= RDCF_READ; 
     824    check_write_access (f); 
     825  } 
     826  f->last_cluster = EMPTY_CLUSTER; 
     827  f->position = 0; 
     828  f->cluster = f->file.first_cluster; 
     829  if (mode & _FAPPEND) { 
     830    // seek to end of file. 
     831    if ((found = rdcf_seek (f, f->file.size)) != 0) 
     832      return found; 
     833  } 
     834  return 0; 
    779835} 
    780836 
     
    786842 * 
    787843***************************************************************/ 
    788 int rdcf_read(struct rdcf *f, void *buf, int count) 
    789 { 
    790         uint32_t size = f->file.size; 
    791         unsigned unread_bytes = count; 
    792         uint32_t position = f->position; 
    793         char *buffer = buf; 
    794         if ((f->result=setjmp(f->error)) != 0) return f->result; 
    795         if ((f->mode & RDCF_READ) == 0) error_exit(f, ~EBADFD); 
    796         f->buffer_status = EMPTY; 
    797         while (unread_bytes>0) { 
    798                 unsigned n = unread_bytes; 
    799                 unsigned rest_of_sector = SECTOR_SIZE - position%SECTOR_SIZE; 
    800                 unsigned sector; 
    801                 if (size<position+n) n = size-position; 
    802                 if (n==0) break; 
    803                 sector = first_sector_in_cluster(f, f->cluster) + 
    804                         (position/SECTOR_SIZE)%f->sectors_per_cluster; 
    805                 if (n>rest_of_sector) n = rest_of_sector; 
    806                 if (position%SECTOR_SIZE==0 && n==SECTOR_SIZE) 
    807                         read_sector(f, sector, buffer); 
    808                 else /* read a partial sector */ { 
    809                         read_buffer(f, sector); 
    810                         memcpy(buffer, &f->buffer.buf[position%SECTOR_SIZE], n); 
    811                 } 
    812                 buffer += n; 
    813                 position += n; 
    814                 unread_bytes -= n; 
    815                 if (position%(f->sectors_per_cluster*SECTOR_SIZE)==0 && position<size) { 
    816                         unsigned next_cluster = FAT_entry(f, f->cluster); 
    817                         if (next_cluster >= f->last_cluster_mark) f->last_cluster = f->cluster; 
    818                         f->cluster = next_cluster; 
    819                 } 
    820         } 
    821         f->position = position; 
    822         return f->result = count - unread_bytes; 
    823 } 
    824  
    825  
    826 int rdcf_seek(struct rdcf *f, uint32_t offset) 
    827 { 
    828         unsigned i, cluster; 
    829         if ((f->result=setjmp(f->error)) != 0) return f->result; 
    830         if (offset>f->file.size) error_exit(f, ~ESPIPE); 
    831         f->buffer_status = EMPTY; 
    832         cluster = f->file.first_cluster; 
    833         for (i=offset/(f->sectors_per_cluster*SECTOR_SIZE); i>0; i--) { 
    834                 unsigned new_cluster = FAT_entry(f, cluster); 
    835                 if (new_cluster >= f->last_cluster_mark) f->last_cluster = cluster; 
    836                 cluster = new_cluster; 
    837         } 
    838         f->cluster = cluster; 
    839         f->position = offset; 
    840         return 0; 
    841 } 
    842  
    843 static int real_rdcf_write(struct rdcf *f, const uint8_t *buf, int count) 
    844 { 
    845         uint32_t size = f->file.size; 
    846         uint32_t position = f->position; 
    847         unsigned unwritten_bytes = count; 
    848         const char *buffer = buf; 
    849         if ((f->result=setjmp(f->error)) != 0) return f->result; 
    850         f->buffer_status = EMPTY; 
    851         if ((f->mode & RDCF_WRITE) == 0) error_exit(f, ~EBADFD); 
    852         while (unwritten_bytes>0) { 
    853                 unsigned sector; 
    854                 unsigned n = unwritten_bytes; 
    855                 unsigned rest_of_sector = SECTOR_SIZE - position%SECTOR_SIZE; 
    856                 if (n>rest_of_sector) n = rest_of_sector; 
    857                 if (f->cluster == EMPTY_CLUSTER || f->cluster >= f->last_cluster_mark) { 
    858                         unsigned new_cluster = 
    859                                 add_new_cluster(f, f->last_cluster, f->first_possibly_empty_cluster); 
    860                         if (new_cluster == EMPTY_CLUSTER) break; 
    861                         f->first_possibly_empty_cluster = new_cluster+1; 
    862                         f->cluster = f->last_cluster = new_cluster; 
    863                         if (f->file.first_cluster==EMPTY_CLUSTER) 
    864                         f->file.first_cluster = new_cluster; 
    865                 } 
    866                 sector = first_sector_in_cluster(f, f->cluster) + 
    867                         (position/SECTOR_SIZE)%f->sectors_per_cluster; 
    868                 if (position%SECTOR_SIZE==0 && 
    869                                 (n==SECTOR_SIZE || position+n>=size)) { 
    870                         write_sector(f, sector, buffer); 
    871                 } else /* write a partial sector */ { 
    872                         read_buffer(f, sector); 
    873                         memcpy(&f->buffer.buf[position%SECTOR_SIZE], buffer, n); 
    874                         f->buffer_status = DIRTY; 
    875                 } 
    876                 buffer += n; 
    877                 position += n; 
    878                 unwritten_bytes -= n; 
    879                 if (position>size) size = position; 
    880                 if (position%(f->sectors_per_cluster*SECTOR_SIZE)==0) { 
    881                         unsigned next_cluster = FAT_entry(f, f->cluster); 
    882                         if (next_cluster >= f->last_cluster_mark) 
    883                                 f->last_cluster = f->cluster; 
    884                         f->cluster = next_cluster; 
    885                 } 
    886         } 
    887         flush_buffer(f); 
    888         f->position = position; 
    889         f->file.size = size; 
    890         f->mode |= WRITTEN; 
     844int rdcf_read (struct rdcf *f, void *buf, int count) 
     845{ 
     846  uint32_t size = f->file.size; 
     847  unsigned unread_bytes = count; 
     848  uint32_t position = f->position; 
     849  char *buffer = buf; 
     850  if ((f->result = setjmp (f->error)) != 0) 
     851    return f->result; 
     852  if ((f->mode & RDCF_READ) == 0) 
     853    error_exit (f, ~EBADFD); 
     854  f->buffer_status = EMPTY; 
     855  while (unread_bytes > 0) { 
     856    unsigned n = unread_bytes; 
     857    unsigned rest_of_sector = SECTOR_SIZE - position % SECTOR_SIZE; 
     858    unsigned sector; 
     859    if (size < position + n) 
     860      n = size - position; 
     861    if (n == 0) 
     862      break; 
     863    sector = first_sector_in_cluster (f, f->cluster) + 
     864      (position / SECTOR_SIZE) % f->sectors_per_cluster; 
     865    if (n > rest_of_sector) 
     866      n = rest_of_sector; 
     867    if (position % SECTOR_SIZE == 0 && n == SECTOR_SIZE) 
     868      read_sector (f, sector, buffer); 
     869    else {                      /* read a partial sector */ 
     870 
     871      read_buffer (f, sector); 
     872      memcpy (buffer, &f->buffer.buf[position % SECTOR_SIZE], n); 
     873    } 
     874    buffer += n; 
     875    position += n; 
     876    unread_bytes -= n; 
     877    if (position % (f->sectors_per_cluster * SECTOR_SIZE) == 0 
     878        && position < size) { 
     879      unsigned next_cluster = FAT_entry (f, f->cluster); 
     880      if (next_cluster >= f->last_cluster_mark) 
     881        f->last_cluster = f->cluster; 
     882      f->cluster = next_cluster; 
     883    } 
     884  } 
     885  f->position = position; 
     886  return f->result = count - unread_bytes; 
     887} 
     888 
     889 
     890int rdcf_seek (struct rdcf *f, uint32_t offset) 
     891{ 
     892  unsigned i, cluster; 
     893  if ((f->result = setjmp (f->error)) != 0) 
     894    return f->result; 
     895  if (offset > f->file.size) 
     896    error_exit (f, ~ESPIPE); 
     897  f->buffer_status = EMPTY; 
     898  cluster = f->file.first_cluster; 
     899  for (i = offset / (f->sectors_per_cluster * SECTOR_SIZE); i > 0; i--) { 
     900    unsigned new_cluster = FAT_entry (f, cluster); 
     901    if (new_cluster >= f->last_cluster_mark) 
     902      f->last_cluster = cluster; 
     903    cluster = new_cluster; 
     904  } 
     905  f->cluster = cluster; 
     906  f->position = offset; 
     907  return 0; 
     908} 
     909 
     910static int real_rdcf_write (struct rdcf *f, const uint8_t * buf, int count) 
     911{ 
     912  uint32_t size = f->file.size; 
     913  uint32_t position = f->position; 
     914  unsigned unwritten_bytes = count; 
     915  const char *buffer = buf; 
     916  if ((f->result = setjmp (f->error)) != 0) 
     917    return f->result; 
     918  f->buffer_status = EMPTY; 
     919  if ((f->mode & RDCF_WRITE) == 0) 
     920    error_exit (f, ~EBADFD); 
     921  while (unwritten_bytes > 0) { 
     922    unsigned sector; 
     923    unsigned n = unwritten_bytes; 
     924    unsigned rest_of_sector = SECTOR_SIZE - position % SECTOR_SIZE; 
     925    if (n > rest_of_sector) 
     926      n = rest_of_sector; 
     927    if (f->cluster == EMPTY_CLUSTER || f->cluster >= f->last_cluster_mark) { 
     928      unsigned new_cluster = 
     929        add_new_cluster (f, f->last_cluster, f->first_possibly_empty_cluster); 
     930      if (new_cluster == EMPTY_CLUSTER) 
     931        break; 
     932      f->first_possibly_empty_cluster = new_cluster + 1; 
     933      f->cluster = f->last_cluster = new_cluster; 
     934      if (f->file.first_cluster == EMPTY_CLUSTER) 
     935        f->file.first_cluster = new_cluster; 
     936    } 
     937    sector = first_sector_in_cluster (f, f->cluster) + 
     938      (position / SECTOR_SIZE) % f->sectors_per_cluster; 
     939    if (position % SECTOR_SIZE == 0 && 
     940        (n == SECTOR_SIZE || position + n >= size)) { 
     941      write_sector (f, sector, buffer); 
     942    } 
     943    else {                      /* write a partial sector */ 
     944 
     945      read_buffer (f, sector); 
     946      memcpy (&f->buffer.buf[position % SECTOR_SIZE], buffer, n); 
     947      f->buffer_status = DIRTY; 
     948    } 
     949    buffer += n; 
     950    position += n; 
     951    unwritten_bytes -= n; 
     952    if (position > size) 
     953      size = position; 
     954    if (position % (f->sectors_per_cluster * SECTOR_SIZE) == 0) { 
     955      unsigned next_cluster = FAT_entry (f, f->cluster); 
     956      if (next_cluster >= f->last_cluster_mark) 
     957        f->last_cluster = f->cluster; 
     958      f->cluster = next_cluster; 
     959    } 
     960  } 
     961  flush_buffer (f); 
     962  f->position = position; 
     963  f->file.size = size; 
     964  f->mode |= WRITTEN; 
    891965#ifdef RDCF_FLUSH_DIR_AFTER_WRITE 
    892         rdcf_get_date_and_time(&f->file.date_and_time); 
    893                 // do not allow empty files. 
    894         update_directory_entry(f, (f->file.size) ? 0 : 1); 
    895         flush_buffer(f); 
     966  rdcf_get_date_and_time (&f->file.date_and_time); 
     967  // do not allow empty files. 
     968  update_directory_entry (f, (f->file.size) ? 0 : 1); 
     969  flush_buffer (f); 
    896970#endif 
    897         return f->result = count-unwritten_bytes; 
    898 } 
    899  
    900 int rdcf_write(struct rdcf *f, const void *buf, int count) 
    901 {// traps write() and ensures no dangling FAT chains. 
    902 int     result; 
    903         result = real_rdcf_write(f, buf, count); 
    904                 // uhoh, something really bad happened! 
    905                 // flush buffer and close the handle. 
    906         if (result <= 0) { 
    907                 rdcf_close(f); 
    908         } 
    909         return result; 
    910 } 
    911  
    912 int rdcf_flush_directory(struct rdcf *f) 
    913 { 
    914         if ((f->result=setjmp(f->error)) != 0) return f->result; 
    915         rdcf_get_date_and_time(&f->file.date_and_time); 
    916                 // do not allow empty files. 
    917         update_directory_entry(f, (f->file.size) ? 0 : 1); 
    918         flush_buffer(f); 
    919         return 0; 
     971  return f->result = count - unwritten_bytes; 
     972} 
     973 
     974int rdcf_write (struct rdcf *f, const void *buf, int count) 
     975{                               // traps write() and ensures no dangling FAT chains. 
     976  int result; 
     977  result = real_rdcf_write (f, buf, count); 
     978  // uhoh, something really bad happened! 
     979  // flush buffer and close the handle. 
     980  if (result <= 0) { 
     981    rdcf_close (f); 
     982  } 
     983  return result; 
     984} 
     985 
     986int rdcf_flush_directory (struct rdcf *f) 
     987{ 
     988  if ((f->result = setjmp (f->error)) != 0) 
     989    return f->result; 
     990  rdcf_get_date_and_time (&f->file.date_and_time); 
     991  // do not allow empty files. 
     992  update_directory_entry (f, (f->file.size) ? 0 : 1); 
     993  flush_buffer (f); 
     994  return 0; 
    920995} 
    921996 
    922997#if 0 
    923 int rdcf_attribute(struct rdcf *f, const char *spec, unsigned attribute) 
    924 { 
    925         if ((f->result=setjmp(f->error)) != 0) return f->result; 
    926         if (!find_file(f, initialize_fcb(f, spec)) || 
    927                         f->file.attribute & RDCF_DIRECTORY) { 
    928                 error_exit(f, ~ENOENT); 
    929         } 
    930         f->file.attribute = (f->file.attribute & ~CHANGEABLE_ATTRIBUTES) | 
    931                 (attribute & CHANGEABLE_ATTRIBUTES); 
    932         update_directory_entry(f, 0); 
    933         flush_buffer(f); 
    934         return 0; 
    935 } 
    936  
    937 int rdcf_date_and_time(struct rdcf *f, const char *spec, 
    938         struct rdcf_date_and_time *p) 
    939 { 
    940         if ((f->result=setjmp(f->error)) != 0) return f->result; 
    941         spec = initialize_fcb(f, spec); 
    942         if (*spec == 0) { 
    943                 f->directory_cluster = 0; 
    944                 if (!find_file_in_directory_or_find_volume(f, NULL)) 
    945                         error_exit(f, ~ENOENT); 
    946                 } else { 
    947                         if (!find_file(f, spec)) error_exit(f, ~ENOENT); 
    948         } 
    949         f->file.date_and_time = *p; 
    950         if ((f->file.attribute & (RDCF_DIRECTORY+RDCF_VOLUME)) == 0) { 
    951                 check_write_access(f); 
    952                 f->file.attribute |= RDCF_ARCHIVE; 
    953         } 
    954         update_directory_entry(f, 0); 
    955         if (f->file.attribute & RDCF_DIRECTORY) update_dot_and_dot_dot(f); 
    956         flush_buffer(f); 
    957         return 0; 
    958 } 
    959  
    960 int rdcf_directory(struct rdcf *f, const char *spec) 
    961 { 
    962                 /* uint8_t name_extension[NAME_SIZE+EXTENSION_SIZE]; ??? */ 
    963         if ((f->result=setjmp(f->error)) != 0) return f->result; 
    964         if (find_file(f, initialize_fcb(f, spec))) error_exit(f, ~EISDIR); 
    965                 /* spec_to_name_extension(f, name_extension, f->file.spec); ??? */ 
    966                 /* name_extension_to_spec(f->file.spec, name_extension); ??? */ 
    967                 /* determine whether there is enough free space for directory */ 
    968         { 
    969                 unsigned cluster = 2; 
    970                 unsigned required_clusters = 
    971                 f->directory_index == NO_DIRECTORY_INDEX ? 2 : 1; 
    972                 for (cluster = 2; required_clusters != 0; cluster++) { 
    973                         if (cluster > f->maximum_cluster_number) error_exit(f, ~ENOSPC); 
    974                         if (FAT_entry(f, cluster)==EMPTY_CLUSTER) required_clusters--; 
    975                 } 
    976         } 
    977         lengthen_directory_if_necessary(f); 
    978         f->file.attribute = RDCF_DIRECTORY; 
    979         f->file.first_cluster = add_new_cluster(f, EMPTY_CLUSTER, 2); 
    980         clear_cluster(f, f->file.first_cluster); 
    981         f->file.size = 0L; 
    982         rdcf_get_date_and_time(&f->file.date_and_time); 
    983         update_directory_entry(f, 0); 
    984         update_dot_and_dot_dot(f); 
    985         flush_buffer(f); 
    986         return 0; 
    987 } 
    988  
    989 long int rdcf_free_space(struct rdcf *f 
     998int rdcf_attribute (struct rdcf *f, const char *spec, unsigned attribute) 
     999{ 
     1000  if ((f->result = setjmp (f->error)) != 0) 
     1001    return f->result; 
     1002  if (!find_file (f, initialize_fcb (f, spec)) || 
     1003      f->file.attribute & RDCF_DIRECTORY) { 
     1004    error_exit (f, ~ENOENT); 
     1005  } 
     1006  f->file.attribute = (f->file.attribute & ~CHANGEABLE_ATTRIBUTES) | 
     1007    (attribute & CHANGEABLE_ATTRIBUTES); 
     1008  update_directory_entry (f, 0); 
     1009  flush_buffer (f); 
     1010  return 0; 
     1011} 
     1012 
     1013int rdcf_date_and_time (struct rdcf *f, const char *spec, 
     1014                        struct rdcf_date_and_time *p) 
     1015{ 
     1016  if ((f->result = setjmp (f->error)) != 0) 
     1017    return f->result; 
     1018  spec = initialize_fcb (f, spec); 
     1019  if (*spec == 0) { 
     1020    f->directory_cluster = 0; 
     1021    if (!find_file_in_directory_or_find_volume (f, NULL)) 
     1022      error_exit (f, ~ENOENT); 
     1023  } 
     1024  else { 
     1025    if (!find_file (f, spec)) 
     1026      error_exit (f, ~ENOENT); 
     1027  } 
     1028  f->file.date_and_time = *p; 
     1029  if ((f->file.attribute & (RDCF_DIRECTORY + RDCF_VOLUME)) == 0) { 
     1030    check_write_access (f); 
     1031    f->file.attribute |= RDCF_ARCHIVE; 
     1032  } 
     1033  update_directory_entry (f, 0); 
     1034  if (f->file.attribute & RDCF_DIRECTORY) 
     1035    update_dot_and_dot_dot (f); 
     1036  flush_buffer (f); 
     1037  return 0; 
     1038} 
     1039 
     1040int rdcf_directory (struct rdcf *f, const char *spec) 
     1041{ 
     1042  /* uint8_t name_extension[NAME_SIZE+EXTENSION_SIZE]; ??? */ 
     1043  if ((f->result = setjmp (f->error)) != 0) 
     1044    return f->result; 
     1045  if (find_file (f, initialize_fcb (f, spec))) 
     1046    error_exit (f, ~EISDIR); 
     1047  /* spec_to_name_extension(f, name_extension, f->file.spec); ??? */ 
     1048  /* name_extension_to_spec(f->file.spec, name_extension); ??? */ 
     1049  /* determine whether there is enough free space for directory */ 
     1050  { 
     1051    unsigned cluster = 2; 
     1052    unsigned required_clusters = 
     1053      f->directory_index == NO_DIRECTORY_INDEX ? 2 : 1; 
     1054    for (cluster = 2; required_clusters != 0; cluster++) { 
     1055      if (cluster > f->maximum_cluster_number) 
     1056        error_exit (f, ~ENOSPC); 
     1057      if (FAT_entry (f, cluster) == EMPTY_CLUSTER) 
     1058        required_clusters--; 
     1059    } 
     1060  } 
     1061  lengthen_directory_if_necessary (f); 
     1062  f->file.attribute = RDCF_DIRECTORY; 
     1063  f->file.first_cluster = add_new_cluster (f, EMPTY_CLUSTER, 2); 
     1064  clear_cluster (f, f->file.first_cluster); 
     1065  f->file.size = 0L; 
     1066  rdcf_get_date_and_time (&f->file.date_and_time); 
     1067  update_directory_entry (f, 0); 
     1068  update_dot_and_dot_dot (f); 
     1069  flush_buffer (f); 
     1070  return 0; 
     1071} 
     1072 
     1073long int rdcf_free_space (struct rdcf *f 
    9901074#ifdef RDCF_MULTIPLE_DRIVE 
    991         , char *spec 
     1075                          , char *spec 
    9921076#endif 
    993 ) 
    994 { 
    995         unsigned cluster; 
    996         unsigned number_of_empty_clusters = 0; 
    997         if ((f->result=setjmp(f->error)) != 0) return (long)(f->result); 
     1077  ) 
     1078{ 
     1079  unsigned cluster; 
     1080  unsigned number_of_empty_clusters = 0; 
     1081  if ((f->result = setjmp (f->error)) != 0) 
     1082    return (long) (f->result); 
    9981083#ifndef RDCF_MULTIPLE_DRIVE 
    999         initialize_fcb(f, NULL); 
     1084  initialize_fcb (f, NULL); 
    10001085#else 
    1001         if (*initialize_fcb(f, spec) != 0) error_exit(f, ~EINVAL); 
     1086  if (*initialize_fcb (f, spec) != 0) 
     1087    error_exit (f, ~EINVAL); 
    10021088#endif 
    1003         for (cluster = 2; cluster <= f->maximum_cluster_number; cluster++) { 
    1004                 if (FAT_entry(f, cluster) == EMPTY_CLUSTER) number_of_empty_clusters++; 
    1005         } 
    1006         f->file.size = (uint32_t) number_of_empty_clusters * 
    1007         (f->sectors_per_cluster * SECTOR_SIZE); 
    1008         return (long)(f->file.size); 
    1009 } 
    1010  
    1011 int rdcf_get_file_information(struct rdcf *f, const char *spec, unsigned idx) 
    1012 { 
    1013         if ((f->result=setjmp(f->error)) != 0) return f->result; 
    1014         find_entry(f, spec, idx); 
    1015         read_directory_entry(f); 
    1016         return f->result = f->file.spec[0] == DELETED_FILE ? ENOENT : 
    1017                 f->file.spec[0] == 0 ? ENOSPC : 0; 
    1018 } 
    1019  
    1020 int rdcf_next_file_information(struct rdcf *f) 
    1021 { 
    1022         if ((f->result=setjmp(f->error)) != 0) return f->result; 
    1023         f->directory_index++; 
    1024         if (f->directory_cluster == 0) { 
    1025                 if (f->directory_index >= 
    1026                                 (f->first_data_sector - f->first_directory_sector)*ENTRIES_PER_SECTOR) { 
    1027                         error_exit(f, ~ENOSPC); 
    1028                 } 
    1029         } else { 
    1030                 if (f->directory_index >= ENTRIES_PER_SECTOR*f->sectors_per_cluster) { 
    1031                         f->directory_cluster = FAT_entry(f, f->directory_cluster); 
    1032                         if (f->directory_cluster >= f->last_cluster_mark) 
    1033                         error_exit(f, ~ENOSPC); 
    1034                         f->directory_index = 0; 
    1035                 } 
    1036         } 
    1037         read_directory_entry(f); 
    1038         return f->result = f->file.spec[0] == DELETED_FILE ? ENOENT : 
    1039                 f->file.spec[0] == 0 ? ENOSPC : 0; 
     1089  for (cluster = 2; cluster <= f->maximum_cluster_number; cluster++) { 
     1090    if (FAT_entry (f, cluster) == EMPTY_CLUSTER) 
     1091      number_of_empty_clusters++; 
     1092  } 
     1093  f->file.size = (uint32_t) number_of_empty_clusters * 
     1094    (f->sectors_per_cluster * SECTOR_SIZE); 
     1095  return (long) (f->file.size); 
     1096} 
     1097 
     1098int rdcf_get_file_information (struct rdcf *f, const char *spec, unsigned idx) 
     1099{ 
     1100  if ((f->result = setjmp (f->error)) != 0) 
     1101    return f->result; 
     1102  find_entry (f, spec, idx); 
     1103  read_directory_entry (f); 
     1104  return f->result = f->file.spec[0] == DELETED_FILE ? ENOENT : 
     1105    f->file.spec[0] == 0 ? ENOSPC : 0; 
     1106} 
     1107 
     1108int rdcf_next_file_information (struct rdcf *f) 
     1109{ 
     1110  if ((f->result = setjmp (f->error)) != 0) 
     1111    return f->result; 
     1112  f->directory_index++; 
     1113  if (f->directory_cluster == 0) { 
     1114    if (f->directory_index >= 
     1115        (f->first_data_sector - 
     1116         f->first_directory_sector) * ENTRIES_PER_SECTOR) { 
     1117      error_exit (f, ~ENOSPC); 
     1118    } 
     1119  } 
     1120  else { 
     1121    if (f->directory_index >= ENTRIES_PER_SECTOR * f->sectors_per_cluster) { 
     1122      f->directory_cluster = FAT_entry (f, f->directory_cluster); 
     1123      if (f->directory_cluster >= f->last_cluster_mark) 
     1124        error_exit (f, ~ENOSPC); 
     1125      f->directory_index = 0; 
     1126    } 
     1127  } 
     1128  read_directory_entry (f); 
     1129  return f->result = f->file.spec[0] == DELETED_FILE ? ENOENT : 
     1130    f->file.spec[0] == 0 ? ENOSPC : 0; 
    10401131} 
    10411132 
     
    10451136-----------------------------------------------------------------------------*/ 
    10461137 
    1047 static void update_dot_and_dot_dot(struct rdcf *f) 
    1048 { 
    1049         f->directory_cluster = f->file.first_cluster; 
    1050         f->directory_index = 0; 
    1051         memset(f->file.spec, ' ', NAME_SIZE+EXTENSION_SIZE); 
    1052         f->file.spec[0] = '.'; 
    1053         update_directory_entry(f, 0); 
    1054         f->file.first_cluster = f->directory_first_cluster; 
    1055         f->directory_index = 1; 
    1056         f->file.spec[1] = '.'; 
    1057         update_directory_entry(f, 0); 
     1138static void update_dot_and_dot_dot (struct rdcf *f) 
     1139{ 
     1140  f->directory_cluster = f->file.first_cluster; 
     1141  f->directory_index = 0; 
     1142  memset (f->file.spec, ' ', NAME_SIZE + EXTENSION_SIZE); 
     1143  f->file.spec[0] = '.'; 
     1144  update_directory_entry (f, 0); 
     1145  f->file.first_cluster = f->directory_first_cluster; 
     1146  f->directory_index = 1; 
     1147  f->file.spec[1] = '.'; 
     1148  update_directory_entry (f, 0); 
    10581149} 
    10591150 
     
    10651156-----------------------------------------------------------------------------*/ 
    10661157 
    1067 static void find_entry(struct rdcf *f, const char *spec, unsigned idx) 
    1068 { 
    1069         spec = initialize_fcb(f, spec); 
    1070         if (*spec == 0) { 
    1071                 if (idx >= 
    1072                                 (f->first_data_sector - f->first_directory_sector)*ENTRIES_PER_SECTOR) { 
    1073                         error_exit(f, ~ENOSPC); 
    1074                 } 
    1075                 f->directory_first_cluster = f->directory_cluster = 0; 
    1076         } else { 
    1077                 if (!find_file(f, spec) || (f->file.attribute&RDCF_DIRECTORY) == 0) 
    1078                         error_exit(f, ~ENOENT); 
    1079                 f->directory_first_cluster = f->directory_cluster = f->file.first_cluster; 
    1080                 while (idx >= ENTRIES_PER_SECTOR*f->sectors_per_cluster) { 
    1081                         f->directory_cluster = FAT_entry(f, f->directory_cluster); 
    1082                         if (f->directory_cluster >= f->last_cluster_mark) 
    1083                                 error_exit(f, ~ENOSPC); 
    1084                         idx -= ENTRIES_PER_SECTOR*f->sectors_per_cluster; 
    1085                 } 
    1086         } 
    1087         f->directory_index = idx; 
     1158static void find_entry (struct rdcf *f, const char *spec, unsigned idx) 
     1159{ 
     1160  spec = initialize_fcb (f, spec); 
     1161  if (*spec == 0) { 
     1162    if (idx >= 
     1163        (f->first_data_sector - 
     1164         f->first_directory_sector) * ENTRIES_PER_SECTOR) { 
     1165      error_exit (f, ~ENOSPC); 
     1166    } 
     1167    f->directory_first_cluster = f->directory_cluster = 0; 
     1168  } 
     1169  else { 
     1170    if (!find_file (f, spec) || (f->file.attribute & RDCF_DIRECTORY) == 0) 
     1171      error_exit (f, ~ENOENT); 
     1172    f->directory_first_cluster = f->directory_cluster = f->file.first_cluster; 
     1173    while (idx >= ENTRIES_PER_SECTOR * f->sectors_per_cluster) { 
     1174      f->directory_cluster = FAT_entry (f, f->directory_cluster); 
     1175      if (f->directory_cluster >= f->last_cluster_mark) 
     1176        error_exit (f, ~ENOSPC); 
     1177      idx -= ENTRIES_PER_SECTOR * f->sectors_per_cluster; 
     1178    } 
     1179  } 
     1180  f->directory_index = idx; 
    10881181} 
    10891182 
     
    10911184 
    10921185// vi:nowrap: 
    1093  
  • trunk/hal/lpc2106-cmucam3/rdcf2.h

    r372 r508  
    4747//#define RDCF_FLUSH_DIR_AFTER_WRITE 
    4848//#define _BIG_ENDIAN 
    49 //#define RDCF_SLASH_CHAR                       '\\' 
     49//#define RDCF_SLASH_CHAR                       '\\' 
    5050#define RDCF_SLASH_CHAR                 '/' 
    5151 
     
    5454 ******************************************************/ 
    5555 
    56 struct rdcf_date_and_time 
    57 { 
     56struct rdcf_date_and_time { 
    5857  uint8_t second; 
    5958  uint8_t minute; 
     
    6463}; 
    6564 
    66 struct rdcf_file_information 
    67 { 
     65struct rdcf_file_information { 
    6866  uint8_t spec[13]; 
    6967  uint8_t attribute; 
     
    8381#define NAME_SIZE       8 
    8482#define EXTENSION_SIZE  3 
    85 struct directory 
    86 { 
    87   uint8_t name_extension[NAME_SIZE+EXTENSION_SIZE]; 
     83struct directory { 
     84  uint8_t name_extension[NAME_SIZE + EXTENSION_SIZE]; 
    8885  uint8_t attribute; 
    8986  uint8_t reserved[10]; 
     
    9592 
    9693union IO_BUFFER { 
    97   struct directory dir[RDCF_SECTOR_SIZE / sizeof(struct directory)]; 
    98   uint16_t fat[RDCF_SECTOR_SIZE/2]; 
     94  struct directory dir[RDCF_SECTOR_SIZE / sizeof (struct directory)]; 
     95  uint16_t fat[RDCF_SECTOR_SIZE / 2]; 
    9996  uint8_t buf[RDCF_SECTOR_SIZE]; 
    10097}; 
     
    10299/* FCB (File Control Block) */ 
    103100 
    104 struct rdcf 
    105 { 
     101struct rdcf { 
    106102  /* values that must be initialized by the calling program */ 
    107   union  IO_BUFFER buffer; 
     103  union IO_BUFFER buffer; 
    108104  // hardware access. 
    109   bool (*ReadSector)(uint32_t sector, uint8_t * buf); 
    110   bool (*WriteSector)(uint32_t sector, const uint8_t * buf); 
     105    bool (*ReadSector) (uint32_t sector, uint8_t * buf); 
     106    bool (*WriteSector) (uint32_t sector, const uint8_t * buf); 
    111107  /* file information */ 
    112108  struct rdcf_file_information file; 
     
    179175/* prototypes for functions defined in RDCF */ 
    180176 
    181 int rdcf_open(struct rdcf *, const char *, unsigned); 
    182 int rdcf_close(struct rdcf *); 
    183 int rdcf_write(struct rdcf *, const void *, int); 
    184 int rdcf_read(struct rdcf *, void *, int); 
    185 int rdcf_seek(struct rdcf *, uint32_t); 
    186 int rdcf_flush_directory(struct rdcf *); 
    187 int rdcf_delete(struct rdcf *, const char *); 
    188 int rdcf_rename(struct rdcf *, const char *, const char *); 
     177int rdcf_open (struct rdcf *, const char *, unsigned); 
     178int rdcf_close (struct rdcf *); 
     179int rdcf_write (struct rdcf *, const void *, int); 
     180int rdcf_read (struct rdcf *, void *, int); 
     181int rdcf_seek (struct rdcf *, uint32_t); 
     182int rdcf_flush_directory (struct rdcf *); 
     183int rdcf_delete (struct rdcf *, const char *); 
     184int rdcf_rename (struct rdcf *, const char *, const char *); 
    189185 
    190186#if 0 
    191 int rdcf_directory(struct rdcf *, const char *); 
    192 int rdcf_get_file_information(struct rdcf *, const char *, unsigned); 
    193 int rdcf_next_file_information(struct rdcf *); 
    194 int rdcf_date_and_time(struct rdcf *, const char *, struct rdcf_date_and_time *); 
    195 int rdcf_attribute(struct rdcf *, const char *, unsigned); 
    196 int rdcf_get_volume(struct rdcf *); 
    197 long rdcf_free_space(struct rdcf *); 
     187int rdcf_directory (struct rdcf *, const char *); 
     188int rdcf_get_file_information (struct rdcf *, const char *, unsigned); 
     189int rdcf_next_file_information (struct rdcf *); 
     190int rdcf_date_and_time (struct rdcf *, const char *, 
     191                        struct rdcf_date_and_time *); 
     192int rdcf_attribute (struct rdcf *, const char *, unsigned); 
     193int rdcf_get_volume (struct rdcf *); 
     194long rdcf_free_space (struct rdcf *); 
    198195#endif 
    199196