📄 fat.c
字号:
/* * fat.c * * Low-level operations on a volume with FAT filesystem * * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru> * * @(#) $Id: fat.c,v 1.2.2.4 2003/10/22 16:35:02 joel Exp $ */#if HAVE_CONFIG_H#include "config.h"#endif#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <stdlib.h>#include <assert.h>#include <rtems/libio_.h>#include "fat.h"#include "fat_fat_operations.h"/* _fat_block_read -- * This function reads 'count' bytes from device filesystem is mounted on, * starts at 'start+offset' position where 'start' computed in sectors * and 'offset' is offset inside sector (reading may cross sectors * boundary; in this case assumed we want to read sequential sector(s)) * * PARAMETERS: * mt_entry - mount table entry * start - sector num to start read from * offset - offset inside sector 'start' * count - count of bytes to read * buff - buffer provided by user * * RETURNS: * bytes read on success, or -1 if error occured * and errno set appropriately */ssize_t_fat_block_read( rtems_filesystem_mount_table_entry_t *mt_entry, unsigned32 start, unsigned32 offset, unsigned32 count, void *buff ){ int rc = RC_OK; register fat_fs_info_t *fs_info = mt_entry->fs_info; ssize_t cmpltd = 0; unsigned32 blk = start; unsigned32 ofs = offset; bdbuf_buffer *block = NULL; unsigned32 c = 0; while (count > 0) { rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block); if (rc != RC_OK) return -1; c = MIN(count, (fs_info->vol.bps - ofs)); memcpy((buff + cmpltd), (block->buffer + ofs), c); count -= c; cmpltd += c; blk++; ofs = 0; } return cmpltd;}/* _fat_block_write -- * This function write 'count' bytes to device filesystem is mounted on, * starts at 'start+offset' position where 'start' computed in sectors * and 'offset' is offset inside sector (writing may cross sectors * boundary; in this case assumed we want to write sequential sector(s)) * * PARAMETERS: * mt_entry - mount table entry * start - sector num to start read from * offset - offset inside sector 'start' * count - count of bytes to write * buff - buffer provided by user * * RETURNS: * bytes written on success, or -1 if error occured * and errno set appropriately */ssize_t_fat_block_write( rtems_filesystem_mount_table_entry_t *mt_entry, unsigned32 start, unsigned32 offset, unsigned32 count, const void *buff){ int rc = RC_OK; fat_fs_info_t *fs_info = mt_entry->fs_info; ssize_t cmpltd = 0; unsigned32 blk = start; unsigned32 ofs = offset; bdbuf_buffer *block = NULL; unsigned32 c = 0; while(count > 0) { c = MIN(count, (fs_info->vol.bps - ofs)); if (c == fs_info->vol.bps) rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_GET, &block); else rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block); if (rc != RC_OK) return -1; memcpy((block->buffer + ofs), (buff + cmpltd), c); fat_buf_mark_modified(fs_info); count -= c; cmpltd +=c; blk++; ofs = 0; } return cmpltd;}/* fat_cluster_read -- * wrapper for reading a whole cluster at once * * PARAMETERS: * mt_entry - mount table entry * cln - number of cluster to read * buff - buffer provided by user * * RETURNS: * bytes read on success, or -1 if error occured * and errno set appropriately */ssize_t fat_cluster_read( rtems_filesystem_mount_table_entry_t *mt_entry, unsigned32 cln, void *buff ){ fat_fs_info_t *fs_info = mt_entry->fs_info; unsigned32 fsec = 0; fsec = fat_cluster_num_to_sector_num(mt_entry, cln); return _fat_block_read(mt_entry, fsec, 0, fs_info->vol.spc << fs_info->vol.sec_log2, buff); } /* fat_cluster_write -- * wrapper for writting a whole cluster at once * * PARAMETERS: * mt_entry - mount table entry * cln - number of cluster to write * buff - buffer provided by user * * RETURNS: * bytes written on success, or -1 if error occured * and errno set appropriately */ssize_t fat_cluster_write( rtems_filesystem_mount_table_entry_t *mt_entry, unsigned32 cln, const void *buff ){ fat_fs_info_t *fs_info = mt_entry->fs_info; unsigned32 fsec = 0; fsec = fat_cluster_num_to_sector_num(mt_entry, cln); return _fat_block_write(mt_entry, fsec, 0, fs_info->vol.spc << fs_info->vol.sec_log2, buff); } /* fat_init_volume_info -- * Get inforamtion about volume on which filesystem is mounted on * * PARAMETERS: * mt_entry - mount table entry * * RETURNS: * RC_OK on success, or -1 if error occured * and errno set appropriately */intfat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry){ int rc = RC_OK; fat_fs_info_t *fs_info = mt_entry->fs_info; register fat_vol_t *vol = &fs_info->vol; unsigned32 data_secs = 0; char boot_rec[FAT_MAX_BPB_SIZE]; char fs_info_sector[FAT_USEFUL_INFO_SIZE]; ssize_t ret = 0; int fd; struct stat stat_buf; int i = 0; rc = stat(mt_entry->dev, &stat_buf); if (rc == -1) return rc; /* rtmes feature: no block devices, all are character devices */ if (!S_ISCHR(stat_buf.st_mode)) set_errno_and_return_minus_one(ENOTBLK); /* check that device is registred as block device and lock it */ vol->dd = rtems_disk_lookup(stat_buf.st_dev); if (vol->dd == NULL) set_errno_and_return_minus_one(ENOTBLK); vol->dev = stat_buf.st_dev; fd = open(mt_entry->dev, O_RDONLY); if (fd == -1) { rtems_disk_release(vol->dd); return -1; } ret = read(fd, (void *)boot_rec, FAT_MAX_BPB_SIZE); if ( ret != FAT_MAX_BPB_SIZE ) { close(fd); rtems_disk_release(vol->dd); set_errno_and_return_minus_one( EIO ); } close(fd); vol->bps = FAT_BR_BYTES_PER_SECTOR(boot_rec); if ( (vol->bps != 512) && (vol->bps != 1024) && (vol->bps != 2048) && (vol->bps != 4096)) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one( EINVAL ); } for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0; i >>= 1, vol->sec_mul++); for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0; i >>= 1, vol->sec_log2++); vol->spc = FAT_BR_SECTORS_PER_CLUSTER(boot_rec); /* * "sectors per cluster" of zero is invalid * (and would hang the following loop) */ if (vol->spc == 0) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one(EINVAL); } for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0; i >>= 1, vol->spc_log2++); /* * "bytes per cluster" value greater than 32K is invalid */ if ((vol->bpc = vol->bps << vol->spc_log2) > MS_BYTES_PER_CLUSTER_LIMIT) { rtems_disk_release(vol->dd); set_errno_and_return_minus_one(EINVAL); } for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0; i >>= 1, vol->bpc_log2++); vol->fats = FAT_BR_FAT_NUM(boot_rec); vol->fat_loc = FAT_BR_RESERVED_SECTORS_NUM(boot_rec); vol->rdir_entrs = FAT_BR_FILES_PER_ROOT_DIR(boot_rec); /* calculate the count of sectors occupied by the root directory */ vol->rdir_secs = ((vol->rdir_entrs * FAT_DIRENTRY_SIZE) + (vol->bps - 1)) / vol->bps; vol->rdir_size = vol->rdir_secs << vol->sec_log2; if ( (FAT_BR_SECTORS_PER_FAT(boot_rec)) != 0) vol->fat_length = FAT_BR_SECTORS_PER_FAT(boot_rec); else vol->fat_length = FAT_BR_SECTORS_PER_FAT32(boot_rec); vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length + vol->rdir_secs; /* for FAT12/16 root dir starts at(sector) */ vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length; if ( (FAT_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0) vol->tot_secs = FAT_BR_TOTAL_SECTORS_NUM16(boot_rec); else vol->tot_secs = FAT_BR_TOTAL_SECTORS_NUM32(boot_rec); data_secs = vol->tot_secs - vol->data_fsec; vol->data_cls = data_secs / vol->spc; /* determine FAT type at least */ if ( vol->data_cls < FAT_FAT12_MAX_CLN) { vol->type = FAT_FAT12; vol->mask = FAT_FAT12_MASK; vol->eoc_val = FAT_FAT12_EOC; } else { if ( vol->data_cls < FAT_FAT16_MAX_CLN) { vol->type = FAT_FAT16; vol->mask = FAT_FAT16_MASK; vol->eoc_val = FAT_FAT16_EOC; } else { vol->type = FAT_FAT32; vol->mask = FAT_FAT32_MASK; vol->eoc_val = FAT_FAT32_EOC; } } if (vol->type == FAT_FAT32) { vol->rdir_cl = FAT_BR_FAT32_ROOT_CLUSTER(boot_rec); vol->mirror = FAT_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR; if (vol->mirror) vol->afat = FAT_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM; else vol->afat = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -