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

📄 fat_file.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  fat_file.c * *  General operations on "fat-file" * * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru> * * @(#) $Id: fat_file.c,v 1.2.2.5 2003/09/26 17:21:16 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 <stdarg.h>#include <errno.h>#include <stdlib.h>#include <assert.h>#include <time.h>#include <rtems/libio_.h>#include "fat.h"#include "fat_fat_operations.h"#include "fat_file.h"static inline void_hash_insert(Chain_Control *hash, unsigned32 key1, unsigned32 key2,              fat_file_fd_t *el);static inline void_hash_delete(Chain_Control *hash, unsigned32 key1, unsigned32 key2,              fat_file_fd_t *el);static inline int _hash_search(    rtems_filesystem_mount_table_entry_t  *mt_entry,    Chain_Control                         *hash,     unsigned32                             key1,     unsigned32                             key2,     fat_file_fd_t			   **ret);static int fat_file_lseek(    rtems_filesystem_mount_table_entry_t  *mt_entry,    fat_file_fd_t                         *fat_fd,    unsigned32                             file_cln,    unsigned32                            *disk_cln);/* fat_file_open -- *     Open fat-file. Two hash tables are accessed by key  *     constructed from cluster num and offset of the node (i.e.  *     files/directories are distinguished by location on the disk). *     First, hash table("vhash") consists of fat-file descriptors corresponded  *     to "valid" files is accessed. Search is made by 2 fields equal to key  *     constructed. If descriptor is found in the "vhash" - return it.  *     Otherwise search is made in hash table("rhash") consits of fat-file  *     descriptors corresponded to "removed-but-still-open" files with the  *     same keys. *     If search failed, new fat-file descriptor is added to "vhash" *     with both key fields equal to constructed key. Otherwise new fat-file  *     descriptor is added to "vhash" with first key field equal to key *     constructed and the second equal to an unique (unique among all values *     of second key fields) value.   * * PARAMETERS: *     mt_entry - mount table entry *     cln      - cluster num of the node *     ofs      - offset of the node *     fat_fd   - placeholder for returned fat-file descriptor * * RETURNS: *     RC_OK and pointer to opened descriptor on success, or -1 if error  *     occured (errno set appropriately) */intfat_file_open(    rtems_filesystem_mount_table_entry_t  *mt_entry,    unsigned32                             cln,    unsigned32                             ofs,      fat_file_fd_t                        **fat_fd    ){    int            rc = RC_OK;     fat_fs_info_t *fs_info = mt_entry->fs_info;    fat_file_fd_t *lfat_fd = NULL;    unsigned32     key = 0;      /* construct key */    key = fat_construct_key(mt_entry, cln, ofs);      /* access "valid" hash table */    rc = _hash_search(mt_entry, fs_info->vhash, key, 0, &lfat_fd);    if ( rc == RC_OK )      {        /* return pointer to fat_file_descriptor allocated before */        (*fat_fd) = lfat_fd;        lfat_fd->links_num++;        return rc;                }    /* access "removed-but-still-open" hash table */    rc = _hash_search(mt_entry, fs_info->rhash, key, key, &lfat_fd);    lfat_fd = (*fat_fd) = (fat_file_fd_t*)malloc(sizeof(fat_file_fd_t));    if ( lfat_fd == NULL )        set_errno_and_return_minus_one( ENOMEM );      lfat_fd->links_num = 1;    lfat_fd->flags &= ~FAT_FILE_REMOVED;    lfat_fd->map.last_cln = FAT_UNDEFINED_VALUE;        if ( rc != RC_OK )        lfat_fd->ino = key;    else    {        lfat_fd->ino = fat_get_unique_ino(mt_entry);            if ( lfat_fd->ino == 0 )        {            free((*fat_fd));            /*              * XXX: kernel resource is unsufficient, but not the memory,              * but there is no suitable errno :(             */            set_errno_and_return_minus_one( ENOMEM );          }    }    _hash_insert(fs_info->vhash, key, lfat_fd->ino, lfat_fd);        /*      * other fields of fat-file descriptor will be initialized on upper      * level      */    return RC_OK;}/* fat_file_reopen -- *     Increment by 1 number of links     * * PARAMETERS: *     fat_fd - fat-file descriptor * * RETURNS: *     RC_OK   */intfat_file_reopen(fat_file_fd_t *fat_fd){    fat_fd->links_num++;    return RC_OK;}/* fat_file_close -- *     Close fat-file. If count of links to fat-file  *     descriptor is greater than 1 (i.e. somebody esle holds pointer *     to this descriptor) just decrement it. Otherwise  *     do the following. If this descriptor corresponded to removed fat-file *     then free clusters contained fat-file data, delete descriptor from  *     "rhash" table and free memory allocated by descriptor. If descriptor  *     correspondes to non-removed fat-file and 'ino' field has value from  *     unique inode numbers pool then set count of links to descriptor to zero  *     and leave it in hash, otherwise delete descriptor from "vhash" and free  *     memory allocated by the descriptor * * PARAMETERS: *     mt_entry - mount table entry *     fat_fd   - fat-file descriptor * * RETURNS: *     RC_OK, or -1 if error occured (errno set appropriately) */intfat_file_close(    rtems_filesystem_mount_table_entry_t *mt_entry,    fat_file_fd_t                        *fat_fd    ){    int            rc = RC_OK;    fat_fs_info_t *fs_info = mt_entry->fs_info;    unsigned32     key = 0;    /*     * if links_num field of fat-file descriptor is greater than 1       * decrement the count of links and return     */    if (fat_fd->links_num > 1)    {        fat_fd->links_num--;        return rc;    }    key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);    if (fat_fd->flags & FAT_FILE_REMOVED)    {        rc = fat_file_truncate(mt_entry, fat_fd, 0);        if ( rc != RC_OK )            return rc;        _hash_delete(fs_info->rhash, key, fat_fd->ino, fat_fd);        if ( fat_ino_is_unique(mt_entry, fat_fd->ino) )            fat_free_unique_ino(mt_entry, fat_fd->ino);        free(fat_fd);    }    else    {        if (fat_ino_is_unique(mt_entry, fat_fd->ino))        {            fat_fd->links_num = 0;        }        else        {            _hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);            free(fat_fd);        }      }      /*     * flush any modified "cached" buffer back to disk     */    rc = fat_buf_release(fs_info);    return rc;}/* fat_file_read -- *     Read 'count' bytes from 'start' position from fat-file. This  *     interface hides the architecture of fat-file, represents it as *     linear file * * PARAMETERS: *     mt_entry - mount table entry *     fat_fd   - fat-file descriptor *     start    - offset in fat-file (in bytes) to read from *     count    - count of bytes to read *     buf      - buffer provided by user   * * RETURNS: *     the number of bytes read on success, or -1 if error occured (errno  *     set appropriately) */ssize_tfat_file_read(    rtems_filesystem_mount_table_entry_t *mt_entry,    fat_file_fd_t                        *fat_fd,    unsigned32                            start,    unsigned32                            count,    char                                 *buf    ){    int            rc = RC_OK;    ssize_t        ret = 0;    fat_fs_info_t *fs_info = mt_entry->fs_info;    unsigned32     cmpltd = 0;    unsigned32     cur_cln = 0;    unsigned32     cl_start = 0;    unsigned32     save_cln = 0;    unsigned32     ofs = 0;    unsigned32     save_ofs;    unsigned32     sec = 0;    unsigned32     byte = 0;    unsigned32     c = 0;    /* it couldn't be removed - otherwise cache update will be broken */    if (count == 0)        return cmpltd;    /*      * >= because start is offset and computed from 0 and file_size      * computed from 1     */    if ( start >= fat_fd->fat_file_size )        return FAT_EOF;      if ((count > fat_fd->fat_file_size) ||         (start > fat_fd->fat_file_size - count))         count = fat_fd->fat_file_size - start;      if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&         (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))      {        sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->cln);        sec += (start >> fs_info->vol.sec_log2);        byte = start & (fs_info->vol.bps - 1);        ret = _fat_block_read(mt_entry, sec, byte, count, buf);         if ( ret < 0 )            return -1;          return ret;    }             cl_start = start >> fs_info->vol.bpc_log2;     save_ofs = ofs = start & (fs_info->vol.bpc - 1);    rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);    if (rc != RC_OK)        return rc;            while (count > 0)    {        c = MIN(count, (fs_info->vol.bpc - ofs));        sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);        sec += (ofs >> fs_info->vol.sec_log2);        byte = ofs & (fs_info->vol.bps - 1);        ret = _fat_block_read(mt_entry, sec, byte, c, buf + cmpltd);        if ( ret < 0 )            return -1;          count -= c;        cmpltd += c;        save_cln = cur_cln;        rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);        if ( rc != RC_OK )            return rc;          ofs = 0;    }    /* update cache */    /* XXX: check this - I'm not sure :( */    fat_fd->map.file_cln = cl_start +                            ((save_ofs + cmpltd - 1) >> fs_info->vol.bpc_log2);    fat_fd->map.disk_cln = save_cln;    return cmpltd;}/* fat_file_write -- *     Write 'count' bytes of data from user supplied buffer to fat-file  *     starting at offset 'start'. This interface hides the architecture  *     of fat-file, represents it as linear file * * PARAMETERS: *     mt_entry - mount table entry *     fat_fd   - fat-file descriptor *     start    - offset(in bytes) to write from *     count    - count *     buf      - buffer provided by user   * * RETURNS: *     number of bytes actually written to the file on success, or -1 if  *     error occured (errno set appropriately) */ssize_tfat_file_write(    rtems_filesystem_mount_table_entry_t *mt_entry,    fat_file_fd_t                        *fat_fd,    unsigned32                            start,    unsigned32                            count,    const char                            *buf    ){    int            rc = 0;    ssize_t        ret = 0;    fat_fs_info_t *fs_info = mt_entry->fs_info;    unsigned32     cmpltd = 0;    unsigned32     cur_cln = 0;    unsigned32     save_cln = 0; /* FIXME: This might be incorrect, cf. below */    unsigned32     cl_start = 0;    unsigned32     ofs = 0;      unsigned32     save_ofs;    unsigned32     sec = 0;    unsigned32     byte = 0;    unsigned32     c = 0;      if ( count == 0 )        return cmpltd;    if ( start > fat_fd->fat_file_size )        set_errno_and_return_minus_one( EIO );    if ((count > fat_fd->size_limit) ||         (start > fat_fd->size_limit - count))         set_errno_and_return_minus_one( EIO );               rc = fat_file_extend(mt_entry, fat_fd, start + count, &c);    if (rc != RC_OK)        return rc;    /*      * check whether there was enough room on device to locate      * file of 'start + count' bytes     */    if (c != (start + count))        count = c - start;          if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&         (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))      {        sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->cln);        sec += (start >> fs_info->vol.sec_log2);        byte = start & (fs_info->vol.bps - 1);        ret = _fat_block_write(mt_entry, sec, byte, count, buf);         if ( ret < 0 )            return -1;          return ret;    }             cl_start = start >> fs_info->vol.bpc_log2;     save_ofs = ofs = start & (fs_info->vol.bpc - 1);    rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);    if (rc != RC_OK)        return rc;    while (count > 0)    {        c = MIN(count, (fs_info->vol.bpc - ofs));        sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);        sec += (ofs >> fs_info->vol.sec_log2);        byte = ofs & (fs_info->vol.bps - 1);        ret = _fat_block_write(mt_entry, sec, byte, c, buf + cmpltd);        if ( ret < 0 )            return -1;          count -= c;        cmpltd += c;        save_cln = cur_cln;        rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);        if ( rc != RC_OK )            return rc;          ofs = 0;    }    /* update cache */    /* XXX: check this - I'm not sure :( */    fat_fd->map.file_cln = cl_start +                            ((save_ofs + cmpltd - 1) >> fs_info->vol.bpc_log2);    fat_fd->map.disk_cln = save_cln;    return cmpltd;}/* fat_file_extend -- *     Extend fat-file. If new length less than current fat-file size -  *     do nothing. Otherwise calculate necessary count of clusters to add,  *     allocate it and add new clusters chain to the end of  *     existing clusters chain. * * PARAMETERS: *     mt_entry   - mount table entry *     fat_fd     - fat-file descriptor *     new_length - new length   *     a_length   - placeholder for result - actual new length of file * * RETURNS: *     RC_OK and new length of file on success, or -1 if error occured (errno  *     set appropriately) */intfat_file_extend(    rtems_filesystem_mount_table_entry_t *mt_entry,    fat_file_fd_t                        *fat_fd,     unsigned32                            new_length,    unsigned32                           *a_length    ){    int            rc = RC_OK;    fat_fs_info_t *fs_info = mt_entry->fs_info;    unsigned32     chain = 0;     unsigned32     bytes2add = 0;    unsigned32     cls2add = 0;    unsigned32     old_last_cl;    unsigned32     last_cl = 0;    unsigned32     bytes_remain = 0;    unsigned32     cls_added;      *a_length = new_length;    if (new_length <= fat_fd->fat_file_size)        return RC_OK;    if ((FAT_FD_OF_ROOT_DIR(fat_fd)) && 

⌨️ 快捷键说明

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