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

📄 fat_sup.c

📁 A FAT filesystem library in C. Very easy to add to any embedded system.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  FAT general support * *  Copyright(C) 2001 *  Camilo Alejandro Arboleda * *  The contents of this file are distributed under the GNU General *  Public License version 2. * *  As a special exception, when this code is included in the RTEMS *  operating system, linking other files with RTEMS objects including *  this code does not cause the resulting executable application to *  be covered by the GNU General Public License. This exception does *  not however invalidate any other reasons why the executable file might *  be covered by the GNU General Public License. */#include <sys/types.h>         /* for mkdir */#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <dirent.h>#include <rtems.h>#include <rtems/libio.h>#include "fat.h"#include "mtd.h"extern rtems_filesystem_location_info_t rtems_filesystem_current;extern rtems_filesystem_location_info_t rtems_filesystem_root;extern int rtems_libio_is_file_open(void  *node_access);extern void strlwr(char *);#ifndef set_errno_and_return_minus_one#define set_errno_and_return_minus_one( _error ) \  do { errno = (_error); return -1; } while(0)#endif#define rtems_filesystem_is_separator( _ch ) \   ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0'))#define fat_is_not_valid_char( c ) \   (((c < 'A') || (c > 'Z')) && ((c < 'a') || (c > 'z')) && ((c < '0') || (c >'9')) && (c!='.'))#define fat_is_valid_char( c ) \   (((c >= 'A') && (c =< 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <='9')) || (c=='.'))#define upchar( c ) ( ((c >= 'a') && (c <= 'z')) ? (c-0x20):(c))#define lowchar( c ) ( ((c >= 'A') && (c <= 'Z')) ? (c+0x20):(c))                                            #define SECTORSIZE 512extern FAT_jnode_t *fat_root_dir;extern FAT_jnode_t *fat_tail;/* Adds a node to open nodes chain */voidadd_node(FAT_jnode_t *node){   fat_tail->next = node;   node->next = NULL;   node->back = fat_tail;   if (node->parent)      node->parent->reference++;   fat_tail = node;}/* Removes a node from open nodes chain */voiddel_node(FAT_jnode_t *node){   FAT_jnode_t *index;   FAT_jnode_t *parent = node->parent;   index = fat_root_dir;   if (node->reference > 0) return;   while (index->next) {      if (index->next == node) {	 index->next = node->next;	 if (index->next) {            index->next->back = index;	 } else {            fat_tail = index;	 }	 free(node);         return;      }      index = index->next;   }   if (parent) {      parent->reference--;      if (parent->reference <= 0) {         del_node(parent);      }   }}/* Reads a block from FAT area */voidread_fat_block(int cluster, fat_geom_t *geom){   unsigned char buffer[SECTORSIZE * 2];   unsigned offset2;   int i;   int fd = geom->fd;   geom->fat_cache.offset = cluster;   switch (geom->type) {   case 0x04:   case 0x06: /* FAT 16 */      if (geom->fat_cache.entries == NULL) {         geom->fat_cache.entries = calloc(256,sizeof(unsigned short));         if (!geom->fat_cache.entries)            exit(1); /* Error */         geom->fat_cache.size = 256;      }      offset2 = geom->bytes_per_sect + (cluster * 2);      lseek( fd, offset2, SEEK_SET );      read( fd, buffer, geom->bytes_per_sect );      for (i = 0;i < geom->fat_cache.size; i++)         geom->fat_cache.entries[i] = * (unsigned short*)(buffer + i*2);      break;   case 0x01: /* FAT 12 */      if (geom->fat_cache.entries == NULL) {         geom->fat_cache.size = geom->sectors_per_fat * SECTORSIZE;         geom->fat_cache.entries = calloc(geom->fat_cache.size,sizeof(unsigned char));         if (!geom->fat_cache.entries)            exit(1); /* Error */         lseek(fd, SECTORSIZE, SEEK_SET);         read(fd,geom->fat_cache.entries,geom->fat_cache.size);      }      break;   default:      break;   }}/* Search one free cluster in disk */unsignedsearch_free_cluster(fat_geom_t *geom){   fat_block_t *fat_block = &(geom->fat_cache);   unsigned o2,t1, t2, cluster;   /* FAT 12 */   if (geom->type == 0x01) {      for (cluster = 2; cluster < geom->fat_entries ; cluster++) {         o2 = (cluster / 2) * 3;         t1 = *(unsigned *)( ((char *)fat_block->entries) + o2) & 0xfff;         t2 = (*(unsigned *)( ((char *)fat_block->entries) + o2) & 0xfff000) >> 12;         if (t1 == 0)            return cluster;         cluster++;         if (t2 == 0)            return cluster;      } /* end for */      return -1;   }   return -1;}/* */voidsave_fat( fat_geom_t *geom){   fat_block_t *fat_block = &(geom->fat_cache);   unsigned offset = 0;   unsigned offset2 = 0;   unsigned fat_size;   unsigned mask = 1;   int fd = geom->fd;   fat_size = SECTORSIZE * geom->sectors_per_fat;   if (geom->type == 0x01) {      offset = SECTORSIZE;      while (mask) {         if (fat_block->changed & mask ) {            /* Write first fat */            lseek(fd, offset, SEEK_SET);            write(fd, ((char *)fat_block->entries) + offset2, SECTORSIZE);            if (geom->total_FATs > 1) {               /* Write second fat */               lseek(fd, offset+fat_size, SEEK_SET);               write(fd, ((char *)fat_block->entries) + offset2, SECTORSIZE);            }         }         offset += SECTORSIZE;         offset2 += SECTORSIZE;         fat_block->changed &= ~mask; /* set as no changed */         mask <<= 1; /* Next sector */      }   } else {      if (!fat_block->changed) return;      offset = geom->bytes_per_sect + (fat_block->offset * 2);      lseek(fd, offset, SEEK_SET);      write(fd, fat_block->entries, 256);      if (geom->total_FATs > 1) {         lseek(fd, offset+fat_size, SEEK_SET);         write(fd, fat_block->entries, 256);      }      fat_block->changed = 0;   }};/* Changes the value of fat entry "cluster" with "new_value" */voidupdate_cluster(unsigned cluster, unsigned new_value, fat_geom_t *geom){   fat_block_t *fat_block = &(geom->fat_cache);   unsigned o2,t1, bit1,bit2;   unsigned tmp_offset;   if (geom->type == 0x01) {      /* FAT 12 */      o2 = (cluster / 2) * 3;      t1 = *(unsigned *)( ((char *)fat_block->entries) + o2);      if (cluster & 0x01) {         new_value &= 0x00000fff;         new_value <<= 12;         t1 &= 0xff000fff;         t1 |= new_value;      } else {         new_value &= 0x00000fff;         t1 &= 0xfffff000;         t1 |= new_value;      }      *(unsigned *)( ((char *)fat_block->entries) + o2) = t1;      bit1 = 1 << (o2 / SECTORSIZE);      bit2 = 1 << ( (o2 + 3) / SECTORSIZE);      fat_block->changed |= (bit1 | bit2);   } else {      /* FAT 16 */      if ( fat_block->offset <= cluster &&        (fat_block->offset + 256) > cluster ) {         fat_block->entries[cluster-fat_block->offset] = new_value;      } else {         if (fat_block->changed)            save_fat( geom);         tmp_offset = cluster - cluster % 256;         read_fat_block(tmp_offset,geom);         fat_block->entries[cluster-fat_block->offset] = new_value;      }      fat_block->changed = 1;   }}/* Add a new cluster to a chain */voidadd_cluster(unsigned last_cluster, unsigned new_cluster, fat_geom_t *geom){   /* Make last_cluster point new cluster */   update_cluster(last_cluster,new_cluster, geom);   /* Make new_cluster last cluster in chain */   update_cluster(new_cluster,0xfff, geom);}/* Search the next cluster in a cluster chain */unsignedsearch_next_cluster(int cluster, fat_geom_t *geom){   unsigned tmp_offset;   unsigned o2;   unsigned t1;   fat_block_t *fat_block = &(geom->fat_cache);   /* FAT 12 */   if (geom->type == 0x01) {      o2 = (cluster / 2) * 3;      if (cluster & 0x01)         t1 = (*(unsigned *)( ((char *)fat_block->entries) + o2) & 0xfff000) >> 12;      else         t1 = *(unsigned *)( ((char *)fat_block->entries) + o2) & 0xfff;      if (t1 > 0xff0) t1 |= 0xf000;      return t1;   }   /* FAT 16 */   if ( fat_block->offset <= cluster &&        (fat_block->offset + 256) > cluster ) {      return fat_block->entries[cluster-fat_block->offset];   }   tmp_offset = cluster - cluster % 256;   read_fat_block(tmp_offset,geom);   return fat_block->entries[cluster-fat_block->offset];}/* Find the cluster correspondig to current cluster */intfind_cluster(FAT_jnode_t *node, int offset, unsigned *cluster){   int new_cluster = node->current_cluster;   int offset2 = node->cache_offset - node->cache_offset % node->geometry->cluster_size;   *cluster = node->current_cluster;   offset &= 0xfffffe00;   if ( (offset < node->cache_offset) || (node->cache_offset < 0) ) {      /* Previous cluster or no cluster at all */      *cluster = node->st_ino;      offset2 = 0;   }   while ( (offset2+node->geometry->cluster_size) <= offset ) {      new_cluster = search_next_cluster(*cluster, node->geometry);      if (new_cluster > 0xfff0) return -1; /*  */      *cluster = new_cluster;      offset2 += node->geometry->cluster_size;   }   return *cluster;}/* Reads a block from disk */intread_root_block(FAT_jnode_t *node, fat_geom_t *geom, int offset){   int disk_offset;   int fd = geom->fd;   /* check block alignment */   if ( (offset & 0x1ff) != 0 ) return -1;   disk_offset = geom->root_dir_offset + offset;   if (disk_offset >= geom->data_offset) return -1;   lseek(fd,disk_offset,SEEK_SET);   read(fd,node->cache,SECTORSIZE);   node->current_cluster = 0;   node->cache_offset  = offset - offset % SECTORSIZE;   return 0;}/* Reads a block from disk */intread_block(FAT_jnode_t *node, fat_geom_t *geom, int offset){   int cluster = node->current_cluster;   int offset2 = node->cache_offset - node->cache_offset % geom->cluster_size;   int disk_offset;   int fd = geom->fd;   /* check block alignment */   if ( (offset & 0x1ff) != 0 ) return -1;   if ( (offset < node->cache_offset) || (node->cache_offset < 0) ) {      /* Previous cluster or no cluster at all */      cluster = node->st_ino;      offset2 = 0;   }   while ( (offset2+geom->cluster_size) <= offset ) {      cluster = search_next_cluster(cluster, geom);/*      if ( (cluster >= 0xfff8) && (cluster <= 0xffff) ) return cluster; */      if (cluster > 0xfff0) return -1; /* Invalid off-set */      offset2 += geom->cluster_size;   }/*    if (cluster == node->current_cluster) return 0; */   disk_offset = cluster * geom->cluster_size +                 geom->first_cluster_offset +                 offset % geom->cluster_size;   lseek(fd,disk_offset,SEEK_SET);   read(fd,node->cache,SECTORSIZE);   node->current_cluster = cluster;   node->cache_offset  = offset - offset % SECTORSIZE;   return 0;}/*------------------------------------------------------------------- * Not optimized fat read. It reads byte by byte and does not handle * errors */intfat_read (FAT_jnode_t *node, char *buffer, int count){   int byte_offset = node->offset & 0x1ff;   int offset = node->offset & 0xfffffe00;   int moved = 0;   int bytes, buffer_offset = 0;   int status;   if ( (node->type == FAT_FILE) && (count + node->offset > node->size) )

⌨️ 快捷键说明

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