summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/arm/nds/libfat/source/fatfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/arm/nds/libfat/source/fatfile.c')
-rw-r--r--c/src/lib/libbsp/arm/nds/libfat/source/fatfile.c815
1 files changed, 0 insertions, 815 deletions
diff --git a/c/src/lib/libbsp/arm/nds/libfat/source/fatfile.c b/c/src/lib/libbsp/arm/nds/libfat/source/fatfile.c
deleted file mode 100644
index 17151ab6fa..0000000000
--- a/c/src/lib/libbsp/arm/nds/libfat/source/fatfile.c
+++ /dev/null
@@ -1,815 +0,0 @@
-/*
- fatfile.c
-
- Functions used by the newlib disc stubs to interface with
- this library
-
- Copyright (c) 2006 Michael "Chishm" Chisholm
-
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation and/or
- other materials provided with the distribution.
- 3. The name of the author may not be used to endorse or promote products derived
- from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- 2006-07-11 - Chishm
- * Original release
-
- 2006-07-17 - Chishm
- * Made all path inputs const char*
- * Added _FAT_rename_r
-
- 2006-08-02 - Chishm
- * Fixed _FAT_seek_r
-
- 2006-08-13 - Chishm
- * Moved all externally visible directory related functions to fatdir
-*/
-
-
-#include "fatfile.h"
-
-#include <fcntl.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <unistd.h>
-
-#include "cache.h"
-#include "file_allocation_table.h"
-#include "bit_ops.h"
-#include "filetime.h"
-
-int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) {
- PARTITION* partition = NULL;
- bool fileExists;
- DIR_ENTRY dirEntry;
- const char* pathEnd;
- u32 dirCluster;
- FILE_STRUCT* file = (FILE_STRUCT*) fileStruct;
- partition = _FAT_partition_getPartitionFromPath (path);
-
- if (partition == NULL) {
- r->_errno = ENODEV;
- return -1;
- }
-
- // Move the path pointer to the start of the actual path
- if (strchr (path, ':') != NULL) {
- path = strchr (path, ':') + 1;
- }
- if (strchr (path, ':') != NULL) {
- r->_errno = EINVAL;
- return -1;
- }
-
- // Determine which mode the file is openned for
- if ((flags & 0x03) == O_RDONLY) {
- // Open the file for read-only access
- file->read = true;
- file->write = false;
- file->append = false;
- } else if ((flags & 0x03) == O_WRONLY) {
- // Open file for write only access
- file->read = false;
- file->write = true;
- file->append = false;
- } else if ((flags & 0x03) == O_RDWR) {
- // Open file for read/write access
- file->read = true;
- file->write = true;
- file->append = false;
- } else {
- r->_errno = EACCES;
- return -1;
- }
-
- // Make sure we aren't trying to write to a read-only disc
- if (file->write && partition->readOnly) {
- r->_errno = EROFS;
- return -1;
- }
-
- // Search for the file on the disc
- fileExists = _FAT_directory_entryFromPath (partition, &dirEntry, path, NULL);
-
- // The file shouldn't exist if we are trying to create it
- if ((flags & O_CREAT) && (flags & O_EXCL) && fileExists) {
- r->_errno = EEXIST;
- return -1;
- }
-
- // It should not be a directory if we're openning a file,
- if (fileExists && _FAT_directory_isDirectory(&dirEntry)) {
- r->_errno = EISDIR;
- return -1;
- }
-
- // If the file doesn't exist, create it if we're allowed to
- if (!fileExists) {
- if (flags & O_CREAT) {
- if (partition->readOnly) {
- // We can't write to a read-only partition
- r->_errno = EROFS;
- return -1;
- }
- // Create the file
- // Get the directory it has to go in
- pathEnd = strrchr (path, DIR_SEPARATOR);
- if (pathEnd == NULL) {
- // No path was specified
- dirCluster = partition->cwdCluster;
- pathEnd = path;
- } else {
- // Path was specified -- get the right dirCluster
- // Recycling dirEntry, since it needs to be recreated anyway
- if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, pathEnd) ||
- !_FAT_directory_isDirectory(&dirEntry)) {
- r->_errno = ENOTDIR;
- return -1;
- }
- dirCluster = _FAT_directory_entryGetCluster (dirEntry.entryData);
- // Move the pathEnd past the last DIR_SEPARATOR
- pathEnd += 1;
- }
- // Create the entry data
- strncpy (dirEntry.filename, pathEnd, MAX_FILENAME_LENGTH - 1);
- memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE);
-
- // Set the creation time and date
- dirEntry.entryData[DIR_ENTRY_cTime_ms] = 0;
- u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cTime, _FAT_filetime_getTimeFromRTC());
- u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cDate, _FAT_filetime_getDateFromRTC());
-
- if (!_FAT_directory_addEntry (partition, &dirEntry, dirCluster)) {
- r->_errno = ENOSPC;
- return -1;
- }
- } else {
- // file doesn't exist, and we aren't creating it
- r->_errno = ENOENT;
- return -1;
- }
- }
-
- file->filesize = u8array_to_u32 (dirEntry.entryData, DIR_ENTRY_fileSize);
-
- /* Allow LARGEFILEs with undefined results
- // Make sure that the file size can fit in the available space
- if (!(flags & O_LARGEFILE) && (file->filesize >= (1<<31))) {
- r->_errno = EFBIG;
- return -1;
- }
- */
-
- // Make sure we aren't trying to write to a read-only file
- if (file->write && !_FAT_directory_isWritable(&dirEntry)) {
- r->_errno = EROFS;
- return -1;
- }
-
- // Associate this file with a particular partition
- file->partition = partition;
-
- file->startCluster = _FAT_directory_entryGetCluster (dirEntry.entryData);
-
- // Truncate the file if requested
- if ((flags & O_TRUNC) && file->write && (file->startCluster != 0)) {
- _FAT_fat_clearLinks (partition, file->startCluster);
- file->startCluster = 0;
- file->filesize = 0;
- }
-
- // Get a new cluster for the file if required
- if (file->startCluster == 0) {
- file->startCluster = _FAT_fat_linkFreeCluster (partition, CLUSTER_FREE);
- }
-
- // Remember the position of this file's directory entry
- file->dirEntryStart = dirEntry.dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN
- file->dirEntryEnd = dirEntry.dataEnd;
-
- file->currentPosition = 0;
-
- file->rwPosition.cluster = file->startCluster;
- file->rwPosition.sector = 0;
- file->rwPosition.byte = 0;
-
- file->appendPosition.cluster = _FAT_fat_lastCluster (partition, file->startCluster);
- file->appendPosition.sector = (file->filesize % partition->bytesPerCluster) / BYTES_PER_READ;
- file->appendPosition.byte = file->filesize % BYTES_PER_READ;
-
- // Check if the end of the file is on the end of a cluster
- if ( (file->filesize > 0) && ((file->filesize % partition->bytesPerCluster)==0) ){
- // Set flag to allocate a new cluster
- file->appendPosition.sector = partition->sectorsPerCluster;
- file->appendPosition.byte = 0;
- }
-
- if (flags & O_APPEND) {
- file->append = true;
- }
-
- file->inUse = true;
-
- partition->openFileCount += 1;
-
- return (int) file;
-}
-
-int _FAT_close_r (struct _reent *r, int fd) {
- FILE_STRUCT* file = (FILE_STRUCT*) fd;
- u8 dirEntryData[DIR_ENTRY_DATA_SIZE];
-
- if (!file->inUse) {
- r->_errno = EBADF;
- return -1;
- }
- if (file->write) {
- // Load the old entry
- _FAT_cache_readPartialSector (file->partition->cache, dirEntryData,
- _FAT_fat_clusterToSector(file->partition, file->dirEntryEnd.cluster) + file->dirEntryEnd.sector,
- file->dirEntryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE);
-
- // Write new data to the directory entry
- // File size
- u32_to_u8array (dirEntryData, DIR_ENTRY_fileSize, file->filesize);
-
- // Start cluster
- u16_to_u8array (dirEntryData, DIR_ENTRY_cluster, file->startCluster);
- u16_to_u8array (dirEntryData, DIR_ENTRY_clusterHigh, file->startCluster >> 16);
-
- // Modification time and date
- u16_to_u8array (dirEntryData, DIR_ENTRY_mTime, _FAT_filetime_getTimeFromRTC());
- u16_to_u8array (dirEntryData, DIR_ENTRY_mDate, _FAT_filetime_getDateFromRTC());
-
- // Access date
- u16_to_u8array (dirEntryData, DIR_ENTRY_aDate, _FAT_filetime_getDateFromRTC());
-
- // Write the new entry
- _FAT_cache_writePartialSector (file->partition->cache, dirEntryData,
- _FAT_fat_clusterToSector(file->partition, file->dirEntryEnd.cluster) + file->dirEntryEnd.sector,
- file->dirEntryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE);
-
- // Flush any sectors in the disc cache
- if (!_FAT_cache_flush(file->partition->cache)) {
- r->_errno = EIO;
- return -1;
- }
- }
-
- file->inUse = false;
- file->partition->openFileCount -= 1;
-
- return 0;
-}
-
-int _FAT_read_r (struct _reent *r, int fd, char *ptr, int len) {
- FILE_STRUCT* file = (FILE_STRUCT*) fd;
-
- PARTITION* partition;
- CACHE* cache;
-
- FILE_POSITION position;
- u32 tempNextCluster;
-
- int tempVar;
-
- u32 remain;
-
- bool flagNoError = true;
-
- // Make sure we can actually read from the file
- if ((file == NULL) || !file->inUse || !file->read) {
- r->_errno = EBADF;
- return 0;
- }
-
- // Don't try to read if the read pointer is past the end of file
- if (file->currentPosition >= file->filesize) {
- return 0;
- }
-
- // Don't read past end of file
- if (len + file->currentPosition > file->filesize) {
- r->_errno = EOVERFLOW;
- len = file->filesize - file->currentPosition;
- }
-
- remain = len;
-
- position = file->rwPosition;
-
- partition = file->partition;
- cache = file->partition->cache;
-
- // Align to sector
- tempVar = BYTES_PER_READ - position.byte;
- if (tempVar > remain) {
- tempVar = remain;
- }
-
- if ((tempVar < BYTES_PER_READ) && flagNoError)
- {
- _FAT_cache_readPartialSector ( cache, ptr, _FAT_fat_clusterToSector (partition, position.cluster) + position.sector,
- position.byte, tempVar);
-
- remain -= tempVar;
- ptr += tempVar;
-
- position.byte += tempVar;
- if (position.byte >= BYTES_PER_READ) {
- position.byte = 0;
- position.sector++;
- }
- }
-
- // align to cluster
- // tempVar is number of sectors to read
- if (remain > (partition->sectorsPerCluster - position.sector) * BYTES_PER_READ) {
- tempVar = partition->sectorsPerCluster - position.sector;
- } else {
- tempVar = remain / BYTES_PER_READ;
- }
-
- if ((tempVar > 0) && flagNoError) {
- _FAT_disc_readSectors (partition->disc, _FAT_fat_clusterToSector (partition, position.cluster) + position.sector,
- tempVar, ptr);
- ptr += tempVar * BYTES_PER_READ;
- remain -= tempVar * BYTES_PER_READ;
- position.sector += tempVar;
- }
-
- // Move onto next cluster
- // It should get to here without reading anything if a cluster is due to be allocated
- if (position.sector >= partition->sectorsPerCluster) {
- tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster);
- if ((remain == 0) && (tempNextCluster == CLUSTER_EOF)) {
- position.sector = partition->sectorsPerCluster;
- } else if (tempNextCluster == CLUSTER_FREE) {
- r->_errno = EIO;
- flagNoError = false;
- } else {
- position.sector = 0;
- position.cluster = tempNextCluster;
- }
- }
-
- // Read in whole clusters
- while ((remain >= partition->bytesPerCluster) && flagNoError) {
- _FAT_disc_readSectors (partition->disc, _FAT_fat_clusterToSector (partition, position.cluster), partition->sectorsPerCluster, ptr);
- ptr += partition->bytesPerCluster;
- remain -= partition->bytesPerCluster;
-
- // Advance to next cluster
- tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster);
- if ((remain == 0) && (tempNextCluster == CLUSTER_EOF)) {
- position.sector = partition->sectorsPerCluster;
- } else if (tempNextCluster == CLUSTER_FREE) {
- r->_errno = EIO;
- flagNoError = false;
- } else {
- position.sector = 0;
- position.cluster = tempNextCluster;
- }
- }
-
- // Read remaining sectors
- tempVar = remain / BYTES_PER_READ; // Number of sectors left
- if ((tempVar > 0) && flagNoError) {
- _FAT_disc_readSectors (partition->disc, _FAT_fat_clusterToSector (partition, position.cluster),
- tempVar, ptr);
- ptr += tempVar * BYTES_PER_READ;
- remain -= tempVar * BYTES_PER_READ;
- position.sector += tempVar;
- }
-
- // Last remaining sector
- // Check if anything is left
- if ((remain > 0) && flagNoError) {
- _FAT_cache_readPartialSector ( cache, ptr,
- _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain);
- position.byte += remain;
- remain = 0;
- }
-
- // Length read is the wanted length minus the stuff not read
- len = len - remain;
-
- // Update file information
- file->rwPosition = position;
- file->currentPosition += len;
- return len;
-}
-
-/*
-Extend a file so that the size is the same as the rwPosition
-*/
-static bool file_extend_r (struct _reent *r, FILE_STRUCT* file) {
- PARTITION* partition = file->partition;
- CACHE* cache = file->partition->cache;
-
- FILE_POSITION position;
-
- u32 remain;
-
- u8 zeroBuffer [BYTES_PER_READ] = {0};
-
- u32 tempNextCluster;
-
- position.byte = file->filesize % BYTES_PER_READ;
- position.sector = (file->filesize % partition->bytesPerCluster) / BYTES_PER_READ;
- position.cluster = _FAT_fat_lastCluster (partition, file->startCluster);
-
- remain = file->currentPosition - file->filesize;
-
-
- // Only need to clear to the end of the sector
- if (remain + position.byte < BYTES_PER_READ) {
- _FAT_cache_writePartialSector (cache, zeroBuffer,
- _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, remain);
- position.byte += remain;
- } else {
- if (position.byte > 0) {
- _FAT_cache_writePartialSector (cache, zeroBuffer,
- _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte,
- BYTES_PER_READ - position.byte);
- remain -= (BYTES_PER_READ - position.byte);
- position.byte = 0;
- position.sector ++;
- }
-
- while (remain >= BYTES_PER_READ) {
- if (position.sector >= partition->sectorsPerCluster) {
- position.sector = 0;
- tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster);
- if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) {
- // Ran out of clusters so get a new one
- tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster);
- }
- if (tempNextCluster == CLUSTER_FREE) {
- // Couldn't get a cluster, so abort
- r->_errno = ENOSPC;
- return false;
- } else {
- position.cluster = tempNextCluster;
- }
- }
-
- _FAT_disc_writeSectors (partition->disc,
- _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 1, zeroBuffer);
-
- remain -= BYTES_PER_READ;
- position.sector ++;
- }
-
- if (position.sector >= partition->sectorsPerCluster) {
- position.sector = 0;
- tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster);
- if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) {
- // Ran out of clusters so get a new one
- tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster);
- }
- if (tempNextCluster == CLUSTER_FREE) {
- // Couldn't get a cluster, so abort
- r->_errno = ENOSPC;
- return false;
- } else {
- position.cluster = tempNextCluster;
- }
- }
-
- if (remain > 0) {
- _FAT_cache_writePartialSector (cache, zeroBuffer,
- _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain);
- position.byte = remain;
- }
- }
-
- file->rwPosition = position;
- file->filesize = file->currentPosition;
- return true;
-}
-
-
-int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len) {
- FILE_STRUCT* file = (FILE_STRUCT*) fd;
-
- PARTITION* partition;
- CACHE* cache;
-
- FILE_POSITION position;
- u32 tempNextCluster;
-
- int tempVar;
-
- u32 remain;
-
- bool flagNoError = true;
- bool flagAppending = false;
-
- // Make sure we can actually write to the file
- if ((file == NULL) || !file->inUse || !file->write) {
- r->_errno = EBADF;
- return -1;
- }
-
- partition = file->partition;
- cache = file->partition->cache;
- remain = len;
-
- if (file->append) {
- position = file->appendPosition;
- flagAppending = true;
- } else {
- // If the write pointer is past the end of the file, extend the file to that size
- if (file->currentPosition > file->filesize) {
- if (!file_extend_r (r, file)) {
- return 0;
- }
- }
-
- // Write at current read pointer
- position = file->rwPosition;
-
- // If it is writing past the current end of file, set appending flag
- if (len + file->currentPosition > file->filesize) {
- flagAppending = true;
- }
- }
-
- // Move onto next cluster if needed
- if (position.sector >= partition->sectorsPerCluster) {
- position.sector = 0;
- tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster);
- if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) {
- // Ran out of clusters so get a new one
- tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster);
- }
- if (tempNextCluster == CLUSTER_FREE) {
- // Couldn't get a cluster, so abort
- r->_errno = ENOSPC;
- flagNoError = false;
- } else {
- position.cluster = tempNextCluster;
- }
- }
-
- // Align to sector
- tempVar = BYTES_PER_READ - position.byte;
- if (tempVar > remain) {
- tempVar = remain;
- }
-
- if ((tempVar < BYTES_PER_READ) && flagNoError) {
- // Write partial sector to disk
- _FAT_cache_writePartialSector (cache, ptr,
- _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, position.byte, tempVar);
-
- remain -= tempVar;
- ptr += tempVar;
- position.byte += tempVar;
-
-
- // Move onto next sector
- if (position.byte >= BYTES_PER_READ) {
- position.byte = 0;
- position.sector ++;
- }
- }
-
- // Align to cluster
- // tempVar is number of sectors to write
- if (remain > (partition->sectorsPerCluster - position.sector) * BYTES_PER_READ) {
- tempVar = partition->sectorsPerCluster - position.sector;
- } else {
- tempVar = remain / BYTES_PER_READ;
- }
-
- if ((tempVar > 0) && flagNoError) {
- _FAT_disc_writeSectors (partition->disc,
- _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, tempVar, ptr);
- ptr += tempVar * BYTES_PER_READ;
- remain -= tempVar * BYTES_PER_READ;
- position.sector += tempVar;
- }
-
- if ((position.sector >= partition->sectorsPerCluster) && flagNoError && (remain > 0)) {
- position.sector = 0;
- tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster);
- if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) {
- // Ran out of clusters so get a new one
- tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster);
- }
- if (tempNextCluster == CLUSTER_FREE) {
- // Couldn't get a cluster, so abort
- r->_errno = ENOSPC;
- flagNoError = false;
- } else {
- position.cluster = tempNextCluster;
- }
- }
-
- // Write whole clusters
- while ((remain >= partition->bytesPerCluster) && flagNoError) {
- _FAT_disc_writeSectors (partition->disc, _FAT_fat_clusterToSector(partition, position.cluster),
- partition->sectorsPerCluster, ptr);
- ptr += partition->bytesPerCluster;
- remain -= partition->bytesPerCluster;
- if (remain > 0) {
- tempNextCluster = _FAT_fat_nextCluster(partition, position.cluster);
- if ((tempNextCluster == CLUSTER_EOF) || (tempNextCluster == CLUSTER_FREE)) {
- // Ran out of clusters so get a new one
- tempNextCluster = _FAT_fat_linkFreeCluster(partition, position.cluster);
- }
- if (tempNextCluster == CLUSTER_FREE) {
- // Couldn't get a cluster, so abort
- r->_errno = ENOSPC;
- flagNoError = false;
- } else {
- position.cluster = tempNextCluster;
- }
- } else {
- // Allocate a new cluster when next writing the file
- position.sector = partition->sectorsPerCluster;
- }
- }
-
- // Write remaining sectors
- tempVar = remain / BYTES_PER_READ; // Number of sectors left
- if ((tempVar > 0) && flagNoError) {
- _FAT_disc_writeSectors (partition->disc, _FAT_fat_clusterToSector (partition, position.cluster),
- tempVar, ptr);
- ptr += tempVar * BYTES_PER_READ;
- remain -= tempVar * BYTES_PER_READ;
- position.sector += tempVar;
- }
-
- // Last remaining sector
- if ((remain > 0) && flagNoError) {
- if (flagAppending) {
- _FAT_cache_eraseWritePartialSector ( cache, ptr,
- _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain);
- } else {
- _FAT_cache_writePartialSector ( cache, ptr,
- _FAT_fat_clusterToSector (partition, position.cluster) + position.sector, 0, remain);
- }
- position.byte += remain;
- remain = 0;
- }
-
-
- // Amount read is the originally requested amount minus stuff remaining
- len = len - remain;
-
- // Update file information
- if (file->append) {
- // Appending doesn't affect the read pointer
- file->appendPosition = position;
- file->filesize += len;
- } else {
- // Writing also shifts the read pointer
- file->rwPosition = position;
- file->currentPosition += len;
- if (file->filesize < file->currentPosition) {
- file->filesize = file->currentPosition;
- }
- }
-
- return len;
-}
-
-
-int _FAT_seek_r (struct _reent *r, int fd, int pos, int dir) {
- FILE_STRUCT* file = (FILE_STRUCT*) fd;
-
- PARTITION* partition;
-
- u32 cluster, nextCluster;
- int clusCount;
- int position;
-
- if ((file == NULL) || (file->inUse == false)) {
- // invalid file
- r->_errno = EBADF;
- return -1;
- }
-
- partition = file->partition;
-
- switch (dir) {
- case SEEK_SET:
- position = pos;
- break;
- case SEEK_CUR:
- position = file->currentPosition + pos;
- break;
- case SEEK_END:
- position = file->filesize + pos;
- break;
- default:
- r->_errno = EINVAL;
- return -1;
- }
-
- if ((pos > 0) && (position < 0)) {
- r->_errno = EOVERFLOW;
- return -1;
- }
-
- if (position < 0) {
- r->_errno = EINVAL;
- return -1;
- }
-
- // Only change the read/write position if it is within the bounds of the current filesize
- if (file->filesize > position) {
-
- // Calculate the sector and byte of the current position,
- // and store them
- file->rwPosition.sector = (position % partition->bytesPerCluster) / BYTES_PER_READ;
- file->rwPosition.byte = position % BYTES_PER_READ;
-
- // Calculate where the correct cluster is
- if (position >= file->currentPosition) {
- clusCount = (position / partition->bytesPerCluster) - (file->currentPosition / partition->bytesPerCluster);
- cluster = file->rwPosition.cluster;
- } else {
- clusCount = position / partition->bytesPerCluster;
- cluster = file->startCluster;
- }
-
- nextCluster = _FAT_fat_nextCluster (partition, cluster);
- while ((clusCount > 0) && (nextCluster != CLUSTER_FREE) && (nextCluster != CLUSTER_EOF)) {
- clusCount--;
- cluster = nextCluster;
- nextCluster = _FAT_fat_nextCluster (partition, cluster);
- }
-
- // Check if ran out of clusters, and the file is being written to
- if ((clusCount > 0) && (file->write || file->append)) {
- // Set flag to allocate a new cluster
- file->rwPosition.sector = partition->sectorsPerCluster;
- file->rwPosition.byte = 0;
- }
-
- file->rwPosition.cluster = cluster;
- }
-
- // Save position
- file->currentPosition = position;
-
- return position;
-}
-
-
-
-int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st) {
- FILE_STRUCT* file = (FILE_STRUCT*) fd;
-
- PARTITION* partition;
-
- DIR_ENTRY fileEntry;
-
- if ((file == NULL) || (file->inUse == false)) {
- // invalid file
- r->_errno = EBADF;
- return -1;
- }
-
- partition = file->partition;
-
- // Get the file's entry data
- fileEntry.dataStart = file->dirEntryStart;
- fileEntry.dataEnd = file->dirEntryEnd;
-
- if (!_FAT_directory_entryFromPosition (partition, &fileEntry)) {
- r->_errno = EIO;
- return -1;
- }
-
- // Fill in the stat struct
- _FAT_directory_entryStat (partition, &fileEntry, st);
-
- // Fix stats that have changed since the file was openned
- st->st_ino = (ino_t)(file->startCluster); // The file serial number is the start cluster
- st->st_size = file->filesize; // File size
-
- return 0;
-}
-