diff options
Diffstat (limited to '')
-rw-r--r-- | c/src/exec/libfs/src/dosfs/fat_file.c | 978 |
1 files changed, 0 insertions, 978 deletions
diff --git a/c/src/exec/libfs/src/dosfs/fat_file.c b/c/src/exec/libfs/src/dosfs/fat_file.c deleted file mode 100644 index 8046f47720..0000000000 --- a/c/src/exec/libfs/src/dosfs/fat_file.c +++ /dev/null @@ -1,978 +0,0 @@ -/* - * 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$ - * - */ - -#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, - void **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) - */ -int -fat_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, (void **)&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, (void **)&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 - */ -int -fat_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) - */ -int -fat_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); - } - } - 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_t -fat_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_t -fat_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) - */ -int -fat_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)) && - (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) - */ -int -fat_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 - */ -int -fat_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, int); - ret = va_arg(ap, int *); - - /* 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 - */ -void -fat_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 - */ -int -fat_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) - */ -int -fat_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, - void **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; -} |