⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rdcf2.c

📁 基于lpc2106和OV6620的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*-----------------------------------------------------------------------------          RDCF: A Reentrant DOS-Compatible File System, Version 2.0   Public Domain - No Restrictions on Use by Philip J. Erdelsky pje@acm.org                               January 15, 1993 Nov 11, 2005 -- Tom Walsh <tom@openharware.net>    Adapted for use under gcc + ARM + NewLib.-----------------------------------------------------------------------------*//* * Copyright 2006-2007  Anthony Rowe and Adam Goode * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//* #define _BIG_ENDIAN */#include "rdcf2.h"#include <string.h>#include <ctype.h>#include <stdio.h>#include <time.h>#include <sys/time.h>#include <sys/errno.h>#include <sys/fcntl.h>#define SECTOR_SIZE RDCF_SECTOR_SIZE#define ENTRIES_PER_SECTOR  (SECTOR_SIZE/sizeof(struct directory))#define NO_DIRECTORY_INDEX  0xFFFF/* Special values for first byte of name. */#define END_DIRECTORY     0x00#define DELETED_FILE      0xE5/* Special values for FAT entries. */#define EMPTY_CLUSTER            0#define RESERVED_CLUSTER_12_BIT  0xFF0#define LAST_CLUSTER_12_BIT      0xFF8#define LAST_CLUSTER_16_BIT      0xFFF8/* buffer status */enum buffer_status { EMPTY, CLEAN, DIRTY };/* additional mode bits */#define APPEND     (1<<6)#define WRITTEN    (1<<7)/*-----------------------------------------------------------------------------Layout of first sector when read into buffer[].  A simple structure would notbe portable because some words are not aligned on even addresses.-----------------------------------------------------------------------------*/#define BYTES_PER_SECTOR     (buffer[11]|buffer[12]<<8)#define SECTORS_PER_CLUSTER   buffer[13]#define RESERVED_SECTORS     (buffer[14]|buffer[15]<<8)#define NUMBER_OF_FATS        buffer[16]#define ROOT_ENTRIES         (buffer[17]|buffer[18]<<8)#define TOTAL_SECTORS        (buffer[19]|buffer[20]<<8)#define MEDIA_DESCRIPTOR      buffer[21]#define SECTORS_PER_FAT      (buffer[22]|buffer[23]<<8)#define SECTORS_PER_TRACK    (buffer[24]|buffer[25]<<8)#define HEADS                (buffer[26]|buffer[27]<<8)#define HIDDEN_SECTORS       (buffer[28]|buffer[29]<<8)/*-----------------------------------------------------------------------------The following functions and macros convert words and double words from "bigendian" to "little endian" form or vice-versa.-----------------------------------------------------------------------------*/#ifdef _BIG_ENDIANstatic void swap_two (uint8_t * p){  uint8_t x = p[0];  p[0] = p[1];  p[1] = x;}static void swap_four (uint8_t * p){  uint8_t x = p[0];  p[0] = p[3];  p[3] = x;  swap_two (p + 1);}#define convert_short(x) swap_two((uint8_t *)(&(x)))#define convert_long(x)  swap_four((uint8_t *)(&(x)))#endifstatic void rdcf_get_date_and_time (struct rdcf_date_and_time *p){  struct tm dateTime;  struct timeval temp;  time_t now;  if (gettimeofday (&temp, 0) == 0) {    // time is correct    now = temp.tv_sec;    localtime_r (&now, &dateTime);    p->hour = dateTime.tm_hour;    p->minute = dateTime.tm_min;    p->second = dateTime.tm_sec;    p->month = dateTime.tm_mon + 1;    p->day = dateTime.tm_mday;    p->year = dateTime.tm_year + 1900;  } else {    // time is incorrect, apply "the notorious 1-1-80 00:00:00"    p->hour = 0;    p->minute = 0;    p->second = 0;    p->month = 1;    p->day = 1;    p->year = 1980;  }}/*-----------------------------------------------------------------------------This function calls longjmp() to specify an error code and exit from the RDCFfunction originally called.-----------------------------------------------------------------------------*/static void error_exit (struct rdcf *f, int error){  longjmp (f->error, error);}/*-----------------------------------------------------------------------------These macros make the calls on access_sector() more readable.-----------------------------------------------------------------------------*/static void read_sector (struct rdcf *f, unsigned sector, void *buffer){  f->drive_error = f->ReadSector (sector, buffer);  if (f->drive_error != 0)    error_exit (f, ~EIO);}static void write_sector (struct rdcf *f, unsigned sector,                          const uint8_t * buffer){  f->drive_error = f->WriteSector (sector, buffer);  if (f->drive_error != 0)    error_exit (f, ~EIO);}/*-----------------------------------------------------------------------------This function writes the buffer in the FCB if it is marked as "dirty".-----------------------------------------------------------------------------*/static void flush_buffer (struct rdcf *f){  if (f->buffer_status == DIRTY) {    // here is where we keep from thrashing while doing FAT operations.    // if the sector to be written is in the first FAT table, then    // mirror the write to corresponding sector in second FAT.    write_sector (f, f->sector_in_buffer, f->buffer.buf);    if ((f->sector_in_buffer >= f->first_FAT_sector) &&        (f->sector_in_buffer <= f->first_FAT_sector + f->sectors_per_FAT)) {      // mirror.      write_sector (f, f->sector_in_buffer + f->sectors_per_FAT,                    f->buffer.buf);    }    f->buffer_status = CLEAN;  }}/*-----------------------------------------------------------------------------This function reads a sector into the buffer in the FCB, if it is not alreadythere.  If another sector is there, the buffer is first flushed.-----------------------------------------------------------------------------*/static void read_buffer (struct rdcf *f, unsigned sector){  if (f->buffer_status == EMPTY || sector != f->sector_in_buffer) {    flush_buffer (f);    read_sector (f, sector, f->buffer.buf);    f->sector_in_buffer = sector;    f->buffer_status = CLEAN;  }}/*-----------------------------------------------------------------------------This function checks to see if a cluster number is valid and declares an errorif it is not.-----------------------------------------------------------------------------*/static void check_cluster (struct rdcf *f, unsigned cluster){  if (cluster < 2 || cluster > f->maximum_cluster_number)    error_exit (f, ~ESPIPE);}/*-----------------------------------------------------------------------------This function returns the FAT entry for the specified cluster.Reads from first copy of FAT.-----------------------------------------------------------------------------*/static unsigned FAT_entry (struct rdcf *f, unsigned cluster){  check_cluster (f, cluster);  if (f->maximum_cluster_number < RESERVED_CLUSTER_12_BIT) {    unsigned byte_index = cluster + (cluster >> 1);    uint8_t p[2];    read_buffer (f, f->first_FAT_sector + byte_index / SECTOR_SIZE);    p[0] = f->buffer.buf[byte_index % SECTOR_SIZE];    byte_index++;    read_buffer (f, f->first_FAT_sector + byte_index / SECTOR_SIZE);    p[1] = f->buffer.buf[byte_index % SECTOR_SIZE];    return (cluster & 1) ? (p[1] << 4 | p[0] >> 4) : (p[0] | p[1]) << 8 &      0xF00;  }  else {    ushort x;    read_buffer (f, f->first_FAT_sector + cluster / (SECTOR_SIZE / 2));    x = f->buffer.fat[cluster % (SECTOR_SIZE / 2)];#ifdef _BIG_ENDIAN    convert_short (x);#endif    return x;  }}/*-----------------------------------------------------------------------------This function sets the FAT entry for the specified cluster to the specifiedvalue.  The 12-bit FAT entry always occupies two consecutive bytes, filling onebyte completely and filling only one nibble of the other byte.  Since thesebytes may be in different sectors, two separate calls on read_buffer() areused.  The one-sector caching implemented by read_buffer() prevents multipledisk accesses when both bytes are in the same sector.  Every copy of the FAT isupdated in the same way.-----------------------------------------------------------------------------*/static void set_FAT_entry (struct rdcf *f, unsigned cluster, unsigned x){  unsigned sector;  check_cluster (f, cluster);#ifdef _BIG_ENDIAN  if (f->maximum_cluster_number >= RESERVED_CLUSTER_12_BIT)    convert_short (x);#endif  sector = f->first_FAT_sector;  if (f->maximum_cluster_number < RESERVED_CLUSTER_12_BIT) {    unsigned byte_index = cluster + (cluster >> 1);    uint8_t *p;    read_buffer (f, sector + byte_index / SECTOR_SIZE);    p = f->buffer.buf + byte_index % SECTOR_SIZE;    *p = (cluster & 1) ? (*p & 0x0F) | (x << 4) : x;    f->buffer_status = DIRTY;    read_buffer (f, sector + (byte_index + 1) / SECTOR_SIZE);    p = f->buffer.buf + (byte_index + 1) % SECTOR_SIZE;    *p = (cluster & 1) ? x >> 4 : (*p & 0xF0) | (x >> 8);  }  else {    read_buffer (f, sector + cluster / (SECTOR_SIZE / 2));    f->buffer.fat[cluster % (SECTOR_SIZE / 2)] = x;  }  f->buffer_status = DIRTY;}/*-----------------------------------------------------------------------------This function checks the value of c (which is always in the range from 0 to255, inclusive). If it represents a character that cannot appear in a validfile name or extension, it bails out.-----------------------------------------------------------------------------*/static void check_file_character (struct rdcf *f, unsigned c){  static uint8_t table[32] = {    0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0xDC, 0x00, 0xFC,    0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x90,    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF  };  if (table[c >> 3] & 1 << (c & 7))    error_exit (f, ~EINVAL);}/*-----------------------------------------------------------------------------This function edits a file or directory spec into the name-extension form usedin the file directory entry.  It returns a pointer to the characterfollowing the last one of the spec.-----------------------------------------------------------------------------*/static const char *spec_to_name_extension (struct rdcf *f,                                           uint8_t * name_extension,                                           const uint8_t * spec){  unsigned i = 0;  unsigned c;  while ((c = (*spec++)) != 0 && c != RDCF_SLASH_CHAR && c != '.') {    check_file_character (f, c);    if (i < NAME_SIZE)      name_extension[i++] = toupper (c);  }  if (i == 0)    error_exit (f, ~EINVAL);  while (i < NAME_SIZE)    name_extension[i++] = ' ';  if (c == '.')    while ((c = (*spec++)) != 0 && c != RDCF_SLASH_CHAR) {      check_file_character (f, c);      if (i < NAME_SIZE + EXTENSION_SIZE)        name_extension[i++] = toupper (c);    }  while (i < NAME_SIZE + EXTENSION_SIZE)    name_extension[i++] = ' ';  return spec - 1;}/*-----------------------------------------------------------------------------This function edits the name-extension form used in a file entry to file spec.-----------------------------------------------------------------------------*/static void name_extension_to_spec (uint8_t * spec,                                    const uint8_t * name_extension){  unsigned i;  uint8_t *s = spec;  for (i = 0; i < NAME_SIZE && name_extension[i] != ' '; i++)    *s++ = name_extension[i];  if (name_extension[NAME_SIZE] != ' ') {    *s++ = '.';    for (i = NAME_SIZE;         i < NAME_SIZE + EXTENSION_SIZE && name_extension[i] != ' '; i++) {      *s++ = name_extension[i];    }  }  *s = 0;}/*-----------------------------------------------------------------------------This function calculates the number of the first sector in the specifiedcluster.-----------------------------------------------------------------------------*/static unsigned first_sector_in_cluster (struct rdcf *f, unsigned cluster){  check_cluster (f, cluster);  return f->first_data_sector + (cluster - 2) * f->sectors_per_cluster;}/*-----------------------------------------------------------------------------This function finds the directory entry referred to by f->directory_cluster andf->directory_index, reads it into f->buffer, and returns a pointer to it.-----------------------------------------------------------------------------*/static struct directory *find_directory (struct rdcf *f){  read_buffer (f, (f->directory_cluster == 0 ? f->first_directory_sector :                   first_sector_in_cluster (f, f->directory_cluster)) +               f->directory_index / ENTRIES_PER_SECTOR);  return &f->buffer.dir[f->directory_index % ENTRIES_PER_SECTOR];}/*-----------------------------------------------------------------------------This function updates a directory entry.  If the "delete_entry" parameter istrue (nonzero), it also marks the entry as deleted.-----------------------------------------------------------------------------*/static void update_directory_entry (struct rdcf *f, int delete_entry){  struct directory *d = find_directory (f);  if (f->file.attribute & RDCF_VOLUME || f->file.spec[0] == '.')    memcpy (d->name_extension, f->file.spec, NAME_SIZE + EXTENSION_SIZE);  else    spec_to_name_extension (f, d->name_extension, f->file.spec);  if (delete_entry)    d->name_extension[0] = DELETED_FILE;  d->attribute = f->file.attribute;  d->date = (f->file.date_and_time.year - 1980) << 9 |    f->file.date_and_time.month << 5 | f->file.date_and_time.day;  d->time = f->file.date_and_time.hour << 11 |    f->file.date_and_time.minute << 5 | f->file.date_and_time.second >> 1;  d->first_cluster = f->file.first_cluster;  d->size = f->file.size;  memset (d->reserved, 0, sizeof (d->reserved));#ifdef _BIG_ENDIAN  convert_short (d->date);  convert_short (d->time);  convert_short (d->first_cluster);  convert_long (d->size);#endif  f->buffer_status = DIRTY;}/*-----------------------------------------------------------------------------This function reads directory information into an FCB.-----------------------------------------------------------------------------*/static void read_directory_entry (struct rdcf *f){  struct directory *d = find_directory (f);  if (d->attribute & RDCF_VOLUME) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -