summaryrefslogtreecommitdiffstats
path: root/c/src/exec/libfs/src/dosfs/fat_file.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--c/src/exec/libfs/src/dosfs/fat_file.c978
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;
-}