Changeset 508

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

reformat

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • 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