📄 fat_dir.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 + -