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

📄 fat.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -