add locks for threaded systems.

fix eof conditions
https://sourceforge.net/tracker/?func=detail&atid=668553&aid=1970541&group_id=114505
This commit is contained in:
Dave Murphy 2008-05-23 19:37:46 +00:00
parent 8843a36ea2
commit 8b9d437f76
3 changed files with 107 additions and 3 deletions

View File

@ -62,6 +62,7 @@
#include "directory.h"
#include "bit_ops.h"
#include "filetime.h"
#include "lock.h"
int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) {
@ -70,9 +71,11 @@ int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) {
DIR_ENTRY dirEntry;
// Get the partition this file is on
_FAT_lock();
partition = _FAT_partition_getPartitionFromPath (path);
if (partition == NULL) {
_FAT_unlock();
r->_errno = ENODEV;
return -1;
}
@ -82,12 +85,14 @@ int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) {
path = strchr (path, ':') + 1;
}
if (strchr (path, ':') != NULL) {
_FAT_unlock();
r->_errno = EINVAL;
return -1;
}
// Search for the file on the disc
if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) {
_FAT_unlock();
r->_errno = ENOENT;
return -1;
}
@ -95,6 +100,7 @@ int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st) {
// Fill in the stat struct
_FAT_directory_entryStat (partition, &dirEntry, st);
_FAT_unlock();
return 0;
}
@ -112,15 +118,18 @@ int _FAT_unlink_r (struct _reent *r, const char *path) {
bool errorOccured = false;
// Get the partition this directory is on
_FAT_lock();
partition = _FAT_partition_getPartitionFromPath (path);
if (partition == NULL) {
_FAT_unlock();
r->_errno = ENODEV;
return -1;
}
// Make sure we aren't trying to write to a read-only disc
if (partition->readOnly) {
_FAT_unlock();
r->_errno = EROFS;
return -1;
}
@ -130,12 +139,14 @@ int _FAT_unlink_r (struct _reent *r, const char *path) {
path = strchr (path, ':') + 1;
}
if (strchr (path, ':') != NULL) {
_FAT_unlock();
r->_errno = EINVAL;
return -1;
}
// Search for the file on the disc
if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, NULL)) {
_FAT_unlock();
r->_errno = ENOENT;
return -1;
}
@ -150,6 +161,7 @@ int _FAT_unlink_r (struct _reent *r, const char *path) {
while (nextEntry) {
if (!_FAT_directory_isDot (&dirContents)) {
// The directory had something in it that isn't a reference to itself or it's parent
_FAT_unlock();
r->_errno = EPERM;
return -1;
}
@ -177,6 +189,7 @@ int _FAT_unlink_r (struct _reent *r, const char *path) {
errorOccured = true;
}
_FAT_unlock();
if (errorOccured) {
return -1;
} else {
@ -188,9 +201,11 @@ int _FAT_chdir_r (struct _reent *r, const char *path) {
PARTITION* partition = NULL;
// Get the partition this directory is on
_FAT_lock();
partition = _FAT_partition_getPartitionFromPath (path);
if (partition == NULL) {
_FAT_unlock();
r->_errno = ENODEV;
return -1;
}
@ -200,12 +215,14 @@ int _FAT_chdir_r (struct _reent *r, const char *path) {
path = strchr (path, ':') + 1;
}
if (strchr (path, ':') != NULL) {
_FAT_unlock();
r->_errno = EINVAL;
return -1;
}
// Set the default device to match this one
if (!_FAT_partition_setDefaultPartition (partition)) {
_FAT_unlock();
r->_errno = ENOENT;
return -1;
}
@ -213,9 +230,11 @@ int _FAT_chdir_r (struct _reent *r, const char *path) {
// Try changing directory
if (_FAT_directory_chdir (partition, path)) {
// Successful
_FAT_unlock();
return 0;
} else {
// Failed
_FAT_unlock();
r->_errno = ENOTDIR;
return -1;
}
@ -229,21 +248,25 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) {
u32 dirCluster;
// Get the partition this directory is on
_FAT_lock();
partition = _FAT_partition_getPartitionFromPath (oldName);
if (partition == NULL) {
_FAT_unlock();
r->_errno = ENODEV;
return -1;
}
// Make sure the same partition is used for the old and new names
if (partition != _FAT_partition_getPartitionFromPath (newName)) {
_FAT_unlock();
r->_errno = EXDEV;
return -1;
}
// Make sure we aren't trying to write to a read-only disc
if (partition->readOnly) {
_FAT_unlock();
r->_errno = EROFS;
return -1;
}
@ -253,6 +276,7 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) {
oldName = strchr (oldName, ':') + 1;
}
if (strchr (oldName, ':') != NULL) {
_FAT_unlock();
r->_errno = EINVAL;
return -1;
}
@ -260,18 +284,21 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) {
newName = strchr (newName, ':') + 1;
}
if (strchr (newName, ':') != NULL) {
_FAT_unlock();
r->_errno = EINVAL;
return -1;
}
// Search for the file on the disc
if (!_FAT_directory_entryFromPath (partition, &oldDirEntry, oldName, NULL)) {
_FAT_unlock();
r->_errno = ENOENT;
return -1;
}
// Make sure there is no existing file / directory with the new name
if (_FAT_directory_entryFromPath (partition, &newDirEntry, newName, NULL)) {
_FAT_unlock();
r->_errno = EEXIST;
return -1;
}
@ -288,6 +315,7 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) {
// Recycling newDirEntry, since it needs to be recreated anyway
if (!_FAT_directory_entryFromPath (partition, &newDirEntry, newName, pathEnd) ||
!_FAT_directory_isDirectory(&newDirEntry)) {
_FAT_unlock();
r->_errno = ENOTDIR;
return -1;
}
@ -304,22 +332,26 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) {
// Write the new entry
if (!_FAT_directory_addEntry (partition, &newDirEntry, dirCluster)) {
_FAT_unlock();
r->_errno = ENOSPC;
return -1;
}
// Remove the old entry
if (!_FAT_directory_removeEntry (partition, &oldDirEntry)) {
_FAT_unlock();
r->_errno = EIO;
return -1;
}
// Flush any sectors in the disc cache
if (!_FAT_cache_flush (partition->cache)) {
_FAT_unlock();
r->_errno = EIO;
return -1;
}
_FAT_unlock();
return 0;
}
@ -330,10 +362,12 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) {
const char* pathEnd;
u32 parentCluster, dirCluster;
u8 newEntryData[DIR_ENTRY_DATA_SIZE];
_FAT_lock();
partition = _FAT_partition_getPartitionFromPath (path);
if (partition == NULL) {
_FAT_unlock();
r->_errno = ENODEV;
return -1;
}
@ -343,6 +377,7 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) {
path = strchr (path, ':') + 1;
}
if (strchr (path, ':') != NULL) {
_FAT_unlock();
r->_errno = EINVAL;
return -1;
}
@ -352,12 +387,14 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) {
// Make sure it doesn't exist
if (fileExists) {
_FAT_unlock();
r->_errno = EEXIST;
return -1;
}
if (partition->readOnly) {
// We can't write to a read-only partition
_FAT_unlock();
r->_errno = EROFS;
return -1;
}
@ -373,6 +410,7 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) {
// Recycling dirEntry, since it needs to be recreated anyway
if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, pathEnd) ||
!_FAT_directory_isDirectory(&dirEntry)) {
_FAT_unlock();
r->_errno = ENOTDIR;
return -1;
}
@ -396,6 +434,7 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) {
dirCluster = _FAT_fat_linkFreeClusterCleared (partition, CLUSTER_FREE);
if (!_FAT_fat_isValidCluster(partition, dirCluster)) {
// No space left on disc for the cluster
_FAT_unlock();
r->_errno = ENOSPC;
return -1;
}
@ -404,6 +443,7 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) {
// Write the new directory's entry to it's parent
if (!_FAT_directory_addEntry (partition, &dirEntry, parentCluster)) {
_FAT_unlock();
r->_errno = ENOSPC;
return -1;
}
@ -432,10 +472,12 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) {
// Flush any sectors in the disc cache
if (!_FAT_cache_flush(partition->cache)) {
_FAT_unlock();
r->_errno = EIO;
return -1;
}
_FAT_unlock();
return 0;
}
@ -445,9 +487,11 @@ int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf)
u32 freeClusterCount;
// Get the partition of the requested path
_FAT_lock();
partition = _FAT_partition_getPartitionFromPath (path);
if (partition == NULL) {
_FAT_unlock();
r->_errno = ENODEV;
return -1;
}
@ -476,6 +520,7 @@ int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf)
// Maximum filename length.
buf->f_namemax = MAX_FILENAME_LENGTH;
_FAT_unlock();
return 0;
}
@ -484,9 +529,11 @@ DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path)
DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct);
bool fileExists;
_FAT_lock();
state->partition = _FAT_partition_getPartitionFromPath (path);
if (state->partition == NULL) {
_FAT_unlock();
r->_errno = ENODEV;
return NULL;
}
@ -496,6 +543,7 @@ DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path)
path = strchr (path, ':') + 1;
}
if (strchr (path, ':') != NULL) {
_FAT_unlock();
r->_errno = EINVAL;
return NULL;
}
@ -503,12 +551,14 @@ DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path)
fileExists = _FAT_directory_entryFromPath (state->partition, &dirEntry, path, NULL);
if (!fileExists) {
_FAT_unlock();
r->_errno = ENOENT;
return NULL;
}
// Make sure it is a directory
if (! _FAT_directory_isDirectory (&dirEntry)) {
_FAT_unlock();
r->_errno = ENOTDIR;
return NULL;
}
@ -522,6 +572,7 @@ DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path)
// We are now using this entry
state->inUse = true;
_FAT_unlock();
return (DIR_ITER*) state;
}
@ -529,7 +580,9 @@ int _FAT_dirreset_r (struct _reent *r, DIR_ITER *dirState) {
DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct);
// Make sure we are still using this entry
_FAT_lock();
if (!state->inUse) {
_FAT_unlock();
r->_errno = EBADF;
return -1;
}
@ -538,6 +591,7 @@ int _FAT_dirreset_r (struct _reent *r, DIR_ITER *dirState) {
state->validEntry =
_FAT_directory_getFirstEntry (state->partition, &(state->currentEntry), state->startCluster);
_FAT_unlock();
return 0;
}
@ -545,13 +599,16 @@ int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct
DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct);
// Make sure we are still using this entry
_FAT_lock();
if (!state->inUse) {
_FAT_unlock();
r->_errno = EBADF;
return -1;
}
// Make sure there is another file to report on
if (! state->validEntry) {
_FAT_unlock();
r->_errno = ENOENT;
return -1;
}
@ -567,6 +624,7 @@ int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct
state->validEntry =
_FAT_directory_getNextEntry (state->partition, &(state->currentEntry));
_FAT_unlock();
return 0;
}
@ -574,7 +632,9 @@ int _FAT_dirclose_r (struct _reent *r, DIR_ITER *dirState) {
DIR_STATE_STRUCT* state = (DIR_STATE_STRUCT*) (dirState->dirStruct);
// We are no longer using this entry
_FAT_lock();
state->inUse = false;
_FAT_unlock();
return 0;
}

View File

@ -75,6 +75,7 @@
#include "file_allocation_table.h"
#include "bit_ops.h"
#include "filetime.h"
#include "lock.h"
int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) {
PARTITION* partition = NULL;
@ -127,16 +128,19 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags
}
// Search for the file on the disc
_FAT_lock();
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) {
_FAT_unlock();
r->_errno = EEXIST;
return -1;
}
// It should not be a directory if we're openning a file,
if (fileExists && _FAT_directory_isDirectory(&dirEntry)) {
_FAT_unlock();
r->_errno = EISDIR;
return -1;
}
@ -146,6 +150,7 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags
if (flags & O_CREAT) {
if (partition->readOnly) {
// We can't write to a read-only partition
_FAT_unlock();
r->_errno = EROFS;
return -1;
}
@ -161,6 +166,7 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags
// Recycling dirEntry, since it needs to be recreated anyway
if (!_FAT_directory_entryFromPath (partition, &dirEntry, path, pathEnd) ||
!_FAT_directory_isDirectory(&dirEntry)) {
_FAT_unlock();
r->_errno = ENOTDIR;
return -1;
}
@ -178,11 +184,13 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags
u16_to_u8array (dirEntry.entryData, DIR_ENTRY_cDate, _FAT_filetime_getDateFromRTC());
if (!_FAT_directory_addEntry (partition, &dirEntry, dirCluster)) {
_FAT_unlock();
r->_errno = ENOSPC;
return -1;
}
} else {
// file doesn't exist, and we aren't creating it
_FAT_unlock();
r->_errno = ENOENT;
return -1;
}
@ -200,6 +208,7 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags
// Make sure we aren't trying to write to a read-only file
if (file->write && !_FAT_directory_isWritable(&dirEntry)) {
_FAT_unlock();
r->_errno = EROFS;
return -1;
}
@ -243,6 +252,7 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags
file->inUse = true;
partition->openFileCount += 1;
_FAT_unlock();
return (int) file;
}
@ -251,7 +261,9 @@ int _FAT_close_r (struct _reent *r, int fd) {
FILE_STRUCT* file = (FILE_STRUCT*) fd;
u8 dirEntryData[DIR_ENTRY_DATA_SIZE];
_FAT_lock();
if (!file->inUse) {
_FAT_unlock();
r->_errno = EBADF;
return -1;
}
@ -283,13 +295,16 @@ int _FAT_close_r (struct _reent *r, int fd) {
// Flush any sectors in the disc cache
if (!_FAT_cache_flush(file->partition->cache)) {
_FAT_unlock();
r->_errno = EIO;
return -1;
}
}
file->inUse = false;
file->partition->openFileCount -= 1;
_FAT_unlock();
return 0;
}
@ -310,14 +325,18 @@ int _FAT_read_r (struct _reent *r, int fd, char *ptr, int len) {
bool flagNoError = true;
// Make sure we can actually read from the file
_FAT_lock();
if ((file == NULL) || !file->inUse || !file->read) {
_FAT_unlock();
r->_errno = EBADF;
return -1;
}
// Don't try to read if the read pointer is past the end of file
if (file->currentPosition >= file->filesize || file->startCluster == CLUSTER_FREE) {
return -1;
r->_errno = EOVERFLOW;
_FAT_unlock();
return 0;
}
// Don't read past end of file
@ -328,6 +347,7 @@ int _FAT_read_r (struct _reent *r, int fd, char *ptr, int len) {
// Short circuit cases where len is 0 (or less)
if (len <= 0) {
_FAT_unlock();
return 0;
}
@ -451,6 +471,8 @@ int _FAT_read_r (struct _reent *r, int fd, char *ptr, int len) {
// Update file information
file->rwPosition = position;
file->currentPosition += len;
_FAT_unlock();
return len;
}
@ -468,7 +490,7 @@ static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) {
u8 zeroBuffer [BYTES_PER_READ] = {0};
u32 tempNextCluster;
position.byte = file->filesize % BYTES_PER_READ;
position.sector = (file->filesize % partition->bytesPerCluster) / BYTES_PER_READ;
// It is assumed that there is always a startCluster
@ -571,13 +593,16 @@ int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len) {
bool flagAppending = false;
// Make sure we can actually write to the file
_FAT_lock();
if ((file == NULL) || !file->inUse || !file->write) {
_FAT_unlock();
r->_errno = EBADF;
return -1;
}
// Short circuit cases where len is 0 (or less)
if (len <= 0) {
_FAT_unlock();
return 0;
}
@ -590,6 +615,7 @@ int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len) {
tempNextCluster = _FAT_fat_linkFreeCluster (partition, CLUSTER_FREE);
if (!_FAT_fat_isValidCluster(partition, tempNextCluster)) {
// Couldn't get a cluster, so abort immediately
_FAT_unlock();
r->_errno = ENOSPC;
return -1;
}
@ -612,6 +638,7 @@ int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len) {
// If the write pointer is past the end of the file, extend the file to that size
if (file->currentPosition > file->filesize) {
if (!_FAT_file_extend_r (r, file)) {
_FAT_unlock();
return -1;
}
}
@ -777,6 +804,8 @@ int _FAT_write_r (struct _reent *r,int fd, const char *ptr, int len) {
file->filesize = file->currentPosition;
}
}
_FAT_unlock();
return len;
}
@ -791,8 +820,10 @@ int _FAT_seek_r (struct _reent *r, int fd, int pos, int dir) {
int clusCount;
int position;
_FAT_lock();
if ((file == NULL) || (file->inUse == false)) {
// invalid file
_FAT_unlock();
r->_errno = EBADF;
return -1;
}
@ -810,16 +841,19 @@ int _FAT_seek_r (struct _reent *r, int fd, int pos, int dir) {
position = file->filesize + pos;
break;
default:
_FAT_unlock();
r->_errno = EINVAL;
return -1;
}
if ((pos > 0) && (position < 0)) {
r->_errno = EOVERFLOW;
_FAT_unlock();
return -1;
}
if (position < 0) {
_FAT_unlock();
r->_errno = EINVAL;
return -1;
}
@ -855,6 +889,7 @@ int _FAT_seek_r (struct _reent *r, int fd, int pos, int dir) {
file->rwPosition.sector = partition->sectorsPerCluster;
file->rwPosition.byte = 0;
} else {
_FAT_unlock();
r->_errno = EINVAL;
return -1;
}
@ -866,6 +901,7 @@ int _FAT_seek_r (struct _reent *r, int fd, int pos, int dir) {
// Save position
file->currentPosition = position;
_FAT_unlock();
return position;
}
@ -878,8 +914,10 @@ int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st) {
DIR_ENTRY fileEntry;
_FAT_lock();
if ((file == NULL) || (file->inUse == false)) {
// invalid file
_FAT_unlock();
r->_errno = EBADF;
return -1;
}
@ -891,6 +929,7 @@ int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st) {
fileEntry.dataEnd = file->dirEntryEnd;
if (!_FAT_directory_entryFromPosition (partition, &fileEntry)) {
_FAT_unlock();
r->_errno = EIO;
return -1;
}
@ -902,6 +941,7 @@ int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st) {
st->st_ino = (ino_t)(file->startCluster); // The file serial number is the start cluster
st->st_size = file->filesize; // File size
_FAT_unlock();
return 0;
}

View File

@ -52,6 +52,7 @@
#include "partition.h"
#include "fatfile.h"
#include "fatdir.h"
#include "lock.h"
#ifdef GBA
#define DEFAULT_CACHE_PAGES 2
@ -127,6 +128,9 @@ bool fatInit (u32 cacheSize, bool setAsDefaultDevice) {
#endif
chdir (filePath);
}
_FAT_lock_init();
return true;
}