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

📄 fat_sup.c

📁 A FAT filesystem library in C. Very easy to add to any embedded system.
💻 C
📖 第 1 页 / 共 3 页
字号:
      count = node->size - node->offset;   while ( count > 0 ) {      if ( (node->type == FAT_FILE) && (node->offset >= node->size) ) {         return moved;      }      /* Read requested sector if needed */      if ( (node->offset >= node->cache_offset + SECTORSIZE) ||           (node->offset < node->cache_offset) ||           (node->cache_offset < 0)) {         status = node->parent ?             read_block(node, node->geometry, offset):            read_root_block(node, node->geometry, offset);         if (status) {            return -1;         }         offset += SECTORSIZE;      }      /* How many bytes are going to be read from the current sector */      bytes = (count < (SECTORSIZE - byte_offset)) ? count: (SECTORSIZE - byte_offset);      /* Transfer them to cache */      memcpy (buffer+buffer_offset, node->cache + byte_offset, bytes);      buffer_offset += bytes;      byte_offset   += bytes;      byte_offset   &= 0x1ff;      count         -= bytes;      node->offset  += bytes;      moved         += bytes;   } /* end while */   return moved;}/* Writes a block from disk */intwrite_root_block(FAT_jnode_t *node, fat_geom_t *geom){   int disk_offset;   int offset;   int fd = geom->fd;   /* check block alignment */   if (node->cache_offset < 0) node->cache_offset = 0;   offset = node->cache_offset - node->cache_offset % SECTORSIZE;   disk_offset = geom->root_dir_offset + offset;   if (disk_offset >= geom->data_offset) return -1;   lseek(fd,disk_offset,SEEK_SET);   write(fd,node->cache,SECTORSIZE);   return 0;}/*------------------------------------------------------------------- * Writes block to disk */intwrite_block(FAT_jnode_t *node, fat_geom_t *geom){   int cluster = node->current_cluster;   int disk_offset;   int fd = geom->fd;   int offset;   /* check block alignment */   if (node->cache_offset < 0) node->cache_offset = 0;   offset = node->cache_offset - node->cache_offset % SECTORSIZE;   disk_offset = cluster * geom->cluster_size +                 geom->first_cluster_offset +                 offset % geom->cluster_size;   lseek(fd,disk_offset,SEEK_SET);   write(fd,node->cache,SECTORSIZE);   return 0;}/*------------------------------------------------------------------- * Not optimized fat write. It reads byte by byte and does not handle * errors */intfat_write (FAT_jnode_t *node, const char *buffer, int count){   int moved = 0;   int status, read_sector, cluster = 0;   int byte_offset, sector_offset, bytes;   while (count > 0) {      byte_offset = node->offset & 0x1ff;      sector_offset = node->offset & 0xfffffe00;      read_sector = 1;      bytes = count > SECTORSIZE ? SECTORSIZE : count; /* Write less than one sector */      bytes = (bytes + byte_offset) > SECTORSIZE ? SECTORSIZE - byte_offset: bytes;      if ( (node->offset + bytes > node->size) && (node->type == FAT_FILE) ) {         if (node->size == 0) {            /* New file */            /* printf("Archivo nuevo\n"); */            node->cache_offset = 0;            node->current_cluster = node->st_ino;            read_sector = 0;         } else if ( (node->size % SECTORSIZE) !=0 ) {            /* Room in the sector */            /* Do nothing */            /* printf("Hay espacio en el sector\n"); */         } else if ( (node->size % node->geometry->cluster_size) != 0 ) {            /* Room in the cluster */            /* printf("Hay espacio en el cluster\n"); */            if (node->cache_offset != sector_offset) {               find_cluster(node,sector_offset,&node->current_cluster);            }            node->cache_offset = sector_offset;            byte_offset = 0;            /* No need to read the sector because it is empty */            read_sector = 0;         } else {            /* File must grow */            /* printf("El archivo debe crecer\n"); */            if (find_cluster(node,sector_offset,&node->current_cluster) < 0) {               rtems_semaphore_obtain( node->geometry->mutex_id,                                       RTEMS_WAIT,RTEMS_NO_TIMEOUT );               cluster = search_free_cluster(node->geometry);               /* printf("cluster actual: %d\n",node->current_cluster);               printf("nuevo cluster: %d\n",cluster); */               if (cluster < 2) { /* No room in disk */                  rtems_semaphore_release( node->geometry->mutex_id );                  return moved;               }               add_cluster(node->current_cluster, cluster, node->geometry);               rtems_semaphore_release( node->geometry->mutex_id );            }            read_sector = 0; /* New cluster is empty */            node->cache_offset = sector_offset;            node->current_cluster = cluster;            byte_offset = 0;         }         node->size += bytes;      } else {      }      if (read_sector) {         status = node->parent ?            read_block(node, node->geometry, sector_offset):            read_root_block(node, node->geometry, sector_offset);      }      memcpy(node->cache+byte_offset,buffer+moved,bytes);      status = node->parent ?         write_block(node, node->geometry):         write_root_block(node, node->geometry);      count        -= bytes;      moved        += bytes;      node->offset += bytes;   } /* end while */   return moved;}/*------------------------------------------------------------------- * After any change (write or truncate) in a FAT file, directory * entry must be updated. */intupdate_dir_entry(FAT_jnode_t *node){   FAT_jnode_t *parent = node->parent;   unsigned char buffer[32];   int j, k;   rtems_time_of_day tod;   unsigned short date;   unsigned short time;   if (node->type != FAT_FILE)      return 0;   if (parent) {      memset(buffer,0,32);      memset(buffer,0x20,11);      rtems_clock_get(RTEMS_CLOCK_GET_TOD, &tod);      for (j=0, k=0; node->name[j] != 0; j++) {         if (node->name[j] == '.') {            k = 8;            continue;         }                            buffer[k++] = upchar(node->name[j]);      };      buffer[11]  = 0x20; /* Normal file */      time = (tod.hour << 11) + (tod.minute << 5) + (tod.second / 2);      date = ((tod.year - 1980) << 9) + (tod.month << 5) + tod.day;      *(unsigned short *)(buffer+22) = time;      *(unsigned short *)(buffer+24) = date;      *(unsigned short *)(buffer+26) = node->st_ino;      *(unsigned       *)(buffer+28) = node->size;      parent->offset = node->dir_offset;      fat_write(parent, buffer, 32);   } else {   }   return 0;}/*------------------------------------------------------------------- * */FAT_jnode_t *FAT_find_match_in_dir(const char *token, FAT_jnode_t *parent){   FAT_jnode_t *index;   unsigned char buffer[sizeof(struct dirent)];   index = fat_root_dir;   while (index) {      if (index->parent == parent) {	 if (!strcmp(token,index->name)) {	    return index;	 }      }      index = index->next;   }   if (!index) {      /* If the node does not exist, find it       * and create a new one       */      parent->offset = 0;      index = (FAT_jnode_t *)calloc(1, sizeof(FAT_jnode_t));      if (!index)         return NULL;      while (fat_dir_read( parent, buffer,sizeof(struct dirent), index ) > 0) {         if (strcmp(token, index->name) == 0) {            /* printf("%s %s\n",token,index->name); */            index->cache_offset = -1;            index->offset = 0;            index->current_cluster = index->st_ino;            add_node(index);            return index;         }      };      free(index);      return NULL;   }   return index;}inline intFAT_Set_handlers( rtems_filesystem_location_info_t *loc ){  FAT_jnode_t    *node = loc->node_access;  switch( node->type ) {    case FAT_DIRECTORY:      loc->handlers = &FAT_directory_handlers;      break;    case FAT_FILE:      loc->handlers = &FAT_file_handlers;      break;  default:     loc->handlers = NULL;     return -1;     break;  }  return 0;}FAT_token_typesFAT_get_token( const char *path, char *token, int *token_len ){  register int i = 0;  FAT_token_types  type = FAT_NAME;  register char c;  /*    *  Copy a name into token.  (Remember NULL is a token.)   */  c = path[i];  while ( (c != '/') && (c != '\0') && (i <= FAT_NAME_MAX+1) ) {     token[i] = c;     if ( i > (FAT_NAME_MAX+1) )	return FAT_INVALID_TOKEN;     if ( fat_is_not_valid_char(c) )	type = FAT_INVALID_TOKEN;     c = path [++i];  }  /*   *  Copy a seperator into token.   */  if ( i == 0 ) {     token[i] = c;     if ( token[i] != '\0' ) {	i++;	type = FAT_CURRENT_DIR;     } else {	type = FAT_NO_MORE_PATH;     }  } else if (token[ i-1 ] != '\0') {     token[i] = '\0';  }  /*   *  Set token_len to the number of characters copied.   */  *token_len = i;  /*   *  If we copied something that was not a seperator see if   *  it was a special name.   */  if ( type == FAT_NAME ) {     if ( strcmp( token, "..") == 0 )	type = FAT_UP_DIR;     else if ( strcmp( token, "." ) == 0 )	type = FAT_CURRENT_DIR;  }  return type;}/* *  FAT_evaluate_for_make * *  The following routine evaluate path for a new node to be created. *  pathloc is returned with a pointer to the parent of the new node. *  name is returned with a pointer to the first character in the  *  new node name.  The parent node is verified to be a directory. */intFAT_evaluate_for_make(path, pathloc, name)   const char                         *path;       /* IN     */   rtems_filesystem_location_info_t   *pathloc;    /* IN/OUT */   const char                        **name;        /* OUT    */{  int                                 i = 0;  int                                 len;  FAT_token_types                     type;  char                                token[ 14 ];  rtems_filesystem_location_info_t    newloc;  FAT_jnode_t                        *node;  int                                 done = 0;  int                                 result;     /*   * This was filled in by the caller and is valid in the    * mount table.   */  node = pathloc->node_access;  /*   *  Evaluate all tokens until we are done or an error occurs.   */  while( !done ) {    type = FAT_get_token( &path[i], token, &len );    i +=  len;        if ( !pathloc->node_access )      set_errno_and_return_minus_one( ENOENT );    node = pathloc->node_access;    switch( type ) {      case FAT_UP_DIR:	/*	 * Am I at the root of this mounted filesystem?	 */        if (pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access) {           newloc = pathloc->mt_entry->mt_point_node;           *pathloc = newloc;           return (*pathloc->ops->evalformake)( &path[i-len], pathloc, name );	} else {          if ( !node->parent )            set_errno_and_return_minus_one( ENOENT );          node = node->parent;

⌨️ 快捷键说明

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