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

📄 fat_dir.c

📁 A FAT filesystem library in C. Very easy to add to any embedded system.
💻 C
字号:
/* *  FAT dir ops Initialization * *  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 <dirent.h>#include <stdlib.h>#include <string.h>#include <stdio.h>#include <errno.h>#include "fat.h"#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))extern void add_cluster(unsigned last_cluster, unsigned new_cluster, fat_geom_t *geom);extern unsigned search_free_cluster(fat_geom_t *geom);extern void save_fat( fat_geom_t *geom);/*------------------------------------------------------------------- * Open directory */intFAT_dir_open(iop, pathname, flag, mode)   rtems_libio_t  *iop;   const char *pathname;   unsigned flag;   unsigned mode;{   FAT_jnode_t *node = iop->file_info;   node->reference++;   iop->offset = 0;   return 0;}/*------------------------------------------------------------------- * Close directory */intFAT_dir_close(iop)   rtems_libio_t  *iop;{   FAT_jnode_t *node = iop->file_info;   node->reference--;   if (node->reference <= 0)      del_node(node);   return 0;}intadd_cluster_to_dir(FAT_jnode_t *node){   int moved;   int cluster;   unsigned char *buffer;   if (!node->parent) return -1; /* Root directory can not grow */   buffer = calloc(node->geometry->cluster_size, sizeof(char));   if (!buffer) return -1;   /*   rtems_semaphore_obtain( node->geometry->mutex_id,   RTEMS_WAIT,RTEMS_NO_TIMEOUT );   */   cluster = search_free_cluster(node->geometry);   if (cluster < 2) { /* No room in disk */      return -1;   }   add_cluster(node->current_cluster, cluster, node->geometry);   /*    rtems_semaphore_release( node->geometry->mutex_id );    */   save_fat(node->geometry);   moved = fat_write(node, buffer, node->geometry->cluster_size);   if (moved < node->geometry->cluster_size) {      /* ???? */   }   return 0;}/*------------------------------------------------------------------- * Find a free directory entry */intfind_free_entry(FAT_jnode_t *node){   unsigned char loc_buffer[32];   int offset;   if (node->type != FAT_DIRECTORY) return -1;   node->offset = 0;   while (1) {      if (fat_read(node,loc_buffer,32) <= 0) {         offset = node->offset;         return add_cluster_to_dir(node) ? -1:offset;      }      if (FAT_FREE_ENTRY(loc_buffer))         return (node->offset-32);   }   return -1;}/*------------------------------------------------------------------- * Read directory */intfat_dir_read(FAT_jnode_t *node, char *buffer, int count, FAT_jnode_t *new_node){   int offset,i,j;   int result = -1;   int bytes_moved = 0;   unsigned char loc_buffer[64];   struct dirent tmp_dirent;   if (node->type != FAT_DIRECTORY) return -1;   offset = node->offset;   while (count) {      result = -1;      while (result) {         if (fat_read(node,loc_buffer,32) <= 0) return -1;         if (!FAT_DIRENTRY_VALID(loc_buffer))            continue;         tmp_dirent.d_ino = FAT_DIRENTRY_FIRST_CLUSTER(loc_buffer);         tmp_dirent.d_off = offset;         tmp_dirent.d_reclen = sizeof(struct dirent);         for (i=0, j=0; i< 11 ; i++ ) {            if ( i == 8 && loc_buffer[i] != ' ' ) {               tmp_dirent.d_name[j++] = '.';            }            if (loc_buffer[i] != ' ') {               tmp_dirent.d_name[j++] = lowchar(loc_buffer[i]);            }         } /* end for */         tmp_dirent.d_name[j] = '\0';         tmp_dirent.d_namlen = j;         memcpy(                (void *)(buffer + bytes_moved),                (void *)&tmp_dirent,                sizeof( struct dirent )               );         bytes_moved += sizeof(struct dirent);         result = 0;      }      count -= sizeof(struct dirent);   }   if (new_node) {      strcpy(new_node->name,tmp_dirent.d_name);      new_node->parent = node;      new_node->reference = 0;      new_node->size = FAT_DIRENTRY_FILELENGTH(loc_buffer);      new_node->st_ino = FAT_DIRENTRY_FIRST_CLUSTER(loc_buffer);      new_node->attrib = FAT_DIRENTRY_ATTRIB(loc_buffer);      new_node->dir_offset = node->offset - 32;      new_node->geometry   = node->geometry;      if (new_node->attrib & 0x10) {         new_node->type = FAT_DIRECTORY;      } else {         new_node->type = FAT_FILE;      }   } /* end if */   return bytes_moved;}intFAT_dir_read(iop, buffer, count)   rtems_libio_t  *iop;   void *buffer;   int count;{   int bytes_moved = 0;   FAT_jnode_t *node = iop->file_info;   if (iop->offset != node->offset) {      node->offset = iop->offset;   }   count = (count / sizeof(struct dirent)) * sizeof(struct dirent);   bytes_moved = fat_dir_read(node, (char *)buffer, count, NULL);   iop->offset = node->offset;   return bytes_moved;}/* ----------------------------------------------------------------------- * This routine will behave in one of three ways based on the state of  * argument whence. Based on the state of its value the offset argument will * be interpreted using one of the following methods: * * 	SEEK_SET - offset is the absolute byte offset from the start of the *                 logical start of the dirent sequence that represents the *                 directory * 	SEEK_CUR - offset is used as the relative byte offset from the current *                 directory position index held in the iop structure *	SEEK_END - N/A --> This will cause an assert. */int FAT_dir_lseek(  rtems_libio_t  *iop,  off_t           offset,  int             whence){   off_t normal_offset;   normal_offset = (offset/32) * 32;   switch( whence )   {   case SEEK_SET:	/* absolute move from the start of the file */      iop->offset = normal_offset;      break;   case SEEK_CUR:	/* relative move */      iop->offset = iop->offset + normal_offset;      break;   case SEEK_END:	/* Movement past the end of the directory via lseek */      /* is not a permitted operation                     */   default:      set_errno_and_return_minus_one( EINVAL );      break;   }   return 0;}/* ----------------------------------------------------------------------- * This routine will obtain the following information concerning the current  * directory: * 	st_dev		0ll *	st_ino		1 *  	st_mode		mode extracted from the jnode *	st_nlink	number of links to this node * 	st_uid		uid extracted from the jnode *	st_gid		gid extracted from the jnode * 	st_rdev		0ll *	st_size		the number of bytes in the directory  *			This is calculated by taking the number of entries *			in the directory and multiplying by the size of a  *			dirent structure *	st_blksize	0 *   	st_blocks	0 *	stat_atime	time of last access *	stat_mtime	time of last modification *	stat_ctime	time of the last change * * This information will be returned to the calling function in a -stat- struct *	 */intFAT_dir_fstat( rtems_filesystem_location_info_t *loc, struct stat  *buf ){   FAT_jnode_t       *node;   node = (FAT_jnode_t *) loc->node_access;   buf->st_dev   = node->geometry->fd;   buf->st_ino   = node->st_ino;   buf->st_mode  = S_IRWXU | S_IRWXG | S_IRWXO | S_IWRITE | S_IREAD | S_IEXEC;   if (node->type == FAT_DIRECTORY)      buf->st_mode |= S_IFDIR;   buf->st_nlink = 1;   buf->st_uid   = 0;   buf->st_gid   = 0;   buf->st_rdev  = node->geometry->fd;   buf->st_blksize = 0;   buf->st_blocks  = 0;   buf->st_atime = node->stat_atime;   buf->st_mtime = node->stat_mtime;   buf->st_ctime = node->stat_ctime;   buf->st_size = 0;   return 0;}

⌨️ 快捷键说明

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