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

📄 fat_file.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
        (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))          set_errno_and_return_minus_one( ENOSPC );    bytes_remain = (fs_info->vol.bpc -                    (fat_fd->fat_file_size & (fs_info->vol.bpc - 1))) &                    (fs_info->vol.bpc - 1);    bytes2add = new_length - fat_fd->fat_file_size;        if (bytes2add > bytes_remain)        bytes2add -= bytes_remain;    else        bytes2add = 0;        /*      * if in last cluster allocated for the file there is enough room to     * handle extention (hence we don't need to add even one cluster to the      * file ) - return     */    if (bytes2add == 0)        return RC_OK;      cls2add = ((bytes2add - 1) >> fs_info->vol.bpc_log2) + 1;        rc = fat_scan_fat_for_free_clusters(mt_entry, &chain, cls2add,                                         &cls_added, &last_cl);        /* this means that low level I/O error occured */    if (rc != RC_OK)        return rc;    /* this means that no space left on device */    if ((cls_added == 0) && (bytes_remain == 0))        set_errno_and_return_minus_one(ENOSPC);        /*  check wether we satisfied request for 'cls2add' clusters */    if (cls2add != cls_added)        *a_length = new_length -                     ((cls2add - cls_added - 1) << fs_info->vol.bpc_log2) -                     (bytes2add & (fs_info->vol.bpc - 1));    /* add new chain to the end of existed */    if ( fat_fd->fat_file_size == 0 )    {        fat_fd->map.disk_cln = fat_fd->cln = chain;        fat_fd->map.file_cln = 0;    }    else    {        if (fat_fd->map.last_cln != FAT_UNDEFINED_VALUE)        {            old_last_cl = fat_fd->map.last_cln;        }        else        {            rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,                                (fat_fd->fat_file_size - 1), &old_last_cl);            if ( rc != RC_OK )            {                fat_free_fat_clusters_chain(mt_entry, chain);                return rc;            }        }            rc = fat_set_fat_cluster(mt_entry, old_last_cl, chain);        if ( rc != RC_OK )        {            fat_free_fat_clusters_chain(mt_entry, chain);            return rc;          }        fat_buf_release(fs_info);    }        /* update number of the last cluster of the file if it changed */    if (cls_added != 0)    {        fat_fd->map.last_cln = last_cl;        if (fat_fd->fat_file_type == FAT_DIRECTORY)        {            rc = fat_init_clusters_chain(mt_entry, chain);            if ( rc != RC_OK )            {                fat_free_fat_clusters_chain(mt_entry, chain);                return rc;              }        }    }         return RC_OK;}/* fat_file_truncate -- *     Truncate fat-file. If new length greater than current fat-file size -  *     do nothing. Otherwise find first cluster to free and free all clusters *     in the chain starting from this cluster. *      * PARAMETERS: *     mt_entry   - mount table entry *     fat_fd     - fat-file descriptor *     new_length - new length   * * RETURNS: *     RC_OK on success, or -1 if error occured (errno set appropriately) */intfat_file_truncate(    rtems_filesystem_mount_table_entry_t *mt_entry,    fat_file_fd_t                        *fat_fd,         unsigned32                            new_length    ){    int            rc = RC_OK;    fat_fs_info_t *fs_info = mt_entry->fs_info;    unsigned32     cur_cln = 0;    unsigned32     cl_start = 0;    unsigned32     new_last_cln = FAT_UNDEFINED_VALUE;          if ( new_length >= fat_fd->fat_file_size )        return rc;    assert(fat_fd->fat_file_size);        cl_start = (new_length + fs_info->vol.bpc - 1) >> fs_info->vol.bpc_log2;        if ((cl_start << fs_info->vol.bpc_log2) >= fat_fd->fat_file_size)        return RC_OK;            if (cl_start != 0)    {        rc = fat_file_lseek(mt_entry, fat_fd, cl_start - 1, &new_last_cln);        if (rc != RC_OK)            return rc;    }            rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);    if (rc != RC_OK)        return rc;    rc = fat_free_fat_clusters_chain(mt_entry, cur_cln);    if (rc != RC_OK)        return rc;    if (cl_start != 0)    {        rc = fat_set_fat_cluster(mt_entry, new_last_cln, FAT_GENFAT_EOC);        if ( rc != RC_OK )            return rc;          fat_fd->map.file_cln = cl_start - 1;        fat_fd->map.disk_cln = new_last_cln;        fat_fd->map.last_cln = new_last_cln;    }         return RC_OK;}                  /* fat_file_ioctl -- *     F_CLU_NUM: *         make mapping between serial number of the cluster in fat-file and  *         its real number on the volume      *           * PARAMETERS: *     fat_fd     - fat-file descriptor *     mt_entry   - mount table entry *     cmd        - command *     ...  * * RETURNS: *     RC_OK on success, or -1 if error occured and errno set appropriately */intfat_file_ioctl(    rtems_filesystem_mount_table_entry_t *mt_entry,    fat_file_fd_t                        *fat_fd,     int                                   cmd,     ...){    int            rc = RC_OK;    fat_fs_info_t *fs_info = mt_entry->fs_info;    unsigned32     cur_cln = 0;    unsigned32     cl_start = 0;    unsigned32     pos = 0;    unsigned32    *ret;    va_list        ap;       va_start(ap, cmd);    switch (cmd)    {        case F_CLU_NUM:            pos = va_arg(ap, unsigned32);            ret = va_arg(ap, unsigned32 *);            /* sanity check */            if ( pos >= fat_fd->fat_file_size )                set_errno_and_return_minus_one( EIO );            if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&                 (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))            {                /* cluster 0 (zero) reserved for root dir */                *ret  = 0;                return RC_OK;            }                     cl_start = pos >> fs_info->vol.bpc_log2;                            rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);            if ( rc != RC_OK )                return rc;              *ret = cur_cln;            break;        default:            errno = EINVAL;            rc = -1;            break;      }    return rc;}/* fat_file_mark_removed -- *     Remove the fat-file descriptor from "valid" hash table, insert it  *     into "removed-but-still-open" hash table and set up "removed" bit.  *   * PARAMETERS: *     fat_fd     - fat-file descriptor *     mt_entry   - mount table entry * * RETURNS: *     None */voidfat_file_mark_removed(    rtems_filesystem_mount_table_entry_t *mt_entry,    fat_file_fd_t                        *fat_fd    ){    fat_fs_info_t *fs_info = mt_entry->fs_info;    unsigned32     key = 0;      key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);      _hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);    _hash_insert(fs_info->rhash, key, fat_fd->ino, fat_fd);    fat_fd->flags |= FAT_FILE_REMOVED;  } /* fat_file_datasync -- *     Synchronize fat-file -  flush all buffered data to the media. *   * PARAMETERS: *     mt_entry - mount table entry *     fat_fd   - fat-file descriptor * * RETURNS: *     RC_OK on success, or -1 if error occured and errno set appropriately */intfat_file_datasync(    rtems_filesystem_mount_table_entry_t *mt_entry,    fat_file_fd_t                        *fat_fd    ){    int                rc = RC_OK;    rtems_status_code  sc = RTEMS_SUCCESSFUL;    fat_fs_info_t     *fs_info = mt_entry->fs_info;    unsigned32         cur_cln = fat_fd->cln;     bdbuf_buffer      *block = NULL;    unsigned32         sec = 0;    unsigned32         i = 0;      if (fat_fd->fat_file_size == 0)        return RC_OK;            /*      * we can use only one bdbuf :( and we also know that cache is useless      * for sync operation, so don't use it     */    rc = fat_buf_release(fs_info);    if (rc != RC_OK)        return rc;            /* for each cluster of the file ... */    while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)    {        sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);        /* for each sector in cluster ... */        for ( i = 0; i < fs_info->vol.spc; i++ )        {            /* ... sync it */            sc = rtems_bdbuf_read(fs_info->vol.dev, (sec + i), &block);                  if (sc != RTEMS_SUCCESSFUL)                set_errno_and_return_minus_one( EIO );            sc = rtems_bdbuf_sync(block);                  if ( sc != RTEMS_SUCCESSFUL )                set_errno_and_return_minus_one( EIO );        }        rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);        if ( rc != RC_OK )            return rc;    }    return rc;}   /* fat_file_size -- *     Calculate fat-file size - fat-file is nothing that clusters chain, so *     go through all clusters in the chain and count it. Only *     special case is root directory for FAT12/16 volumes. *     This function is used only for directories which are fat-files with *     non-zero length, hence 'fat_fd->cln' always contains valid data. *     Calculated size is stored in 'fat_file_size' field of fat-file  *     descriptor. *   * PARAMETERS: *     mt_entry - mount table entry *     fat_fd   - fat-file descriptor * * RETURNS: *     RC_OK on success, or -1 if error occured (errno set appropriately) */intfat_file_size(     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     cur_cln = fat_fd->cln;     unsigned32     save_cln = 0;      /* Have we requested root dir size for FAT12/16? */    if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&         (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))      {        fat_fd->fat_file_size = fs_info->vol.rdir_size;        return rc;    }      fat_fd->fat_file_size = 0;      while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)    {        save_cln = cur_cln;        rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);        if ( rc != RC_OK )            return rc;        fat_fd->fat_file_size += fs_info->vol.bpc;    }    fat_fd->map.last_cln = save_cln;    return rc;}  /* hash support routines *//* _hash_insert -- *     Insert elemnt into hash based on key 'key1' * * PARAMETERS: *     hash - hash element will be inserted into *     key1 - key on which insertion is based on *     key2 - not used during insertion *     el   - element to insert * * RETURNS: *     None */static inline void_hash_insert(Chain_Control *hash, unsigned32 key1, unsigned32 key2,              fat_file_fd_t *el){    _Chain_Append((hash) + ((key1) % FAT_HASH_MODULE), &(el)->link);}/* _hash_delete -- *     Remove element from hash * * PARAMETERS: *     hash - hash element will be removed from *     key1 - not used *     key2 - not used  *     el   - element to delete * * RETURNS: *     None */static inline void_hash_delete(Chain_Control *hash, unsigned32 key1, unsigned32 key2,              fat_file_fd_t *el){    _Chain_Extract(&(el)->link);}   /* _hash_search -- *     Search element in hash. If both keys match pointer to found element *     is returned * * PARAMETERS: *     mt_entry - mount table entry  *     hash     - hash element will be removed from *     key1     - search key *     key2     - search key *     ret      - placeholder for result * * RETURNS: *     0 and pointer to found element on success, -1 otherwise */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    ){                              unsigned32 mod = (key1) % FAT_HASH_MODULE;    Chain_Node *the_node = ((Chain_Control *)((hash) + mod))->first;    for ( ; !_Chain_Is_tail((hash) + mod, the_node) ; )     {        fat_file_fd_t *ffd = (fat_file_fd_t *)the_node;        unsigned32 ck =                 fat_construct_key(mt_entry, ffd->info_cln, ffd->info_ofs);        if ( (key1) == ck)        {            if ( ((key2) == 0) || ((key2) == ffd->ino) )            {                *ret = (void *)the_node;                return 0;            }        }        the_node = the_node->next;     }    return -1; }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    ){    int rc = RC_OK;/*        assert(fat_fd->fat_file_size); */       if (file_cln == fat_fd->map.file_cln)        *disk_cln = fat_fd->map.disk_cln;    else    {        unsigned32 cur_cln;        unsigned32 count;        unsigned32 i;                if (file_cln > fat_fd->map.file_cln)        {            cur_cln = fat_fd->map.disk_cln;            count = file_cln - fat_fd->map.file_cln;        }         else        {            cur_cln = fat_fd->cln;            count = file_cln;        }         /* skip over the clusters */        for (i = 0; i < count; i++)        {            rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);            if ( rc != RC_OK )                return rc;          }                                      /* update cache */        fat_fd->map.file_cln = file_cln;        fat_fd->map.disk_cln = cur_cln;                *disk_cln = cur_cln;    }    return RC_OK;    }

⌨️ 快捷键说明

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