Update libfat to 1.1.1 + Ustealth support (Greywolf, Cyan)

This commit is contained in:
Cyan 2017-12-14 15:19:34 +01:00
parent 1fed6e83f2
commit 910f6f5f22
15 changed files with 168 additions and 118 deletions

View File

@ -5,8 +5,8 @@ endif
export TOPDIR := $(CURDIR) export TOPDIR := $(CURDIR)
export LIBFAT_MAJOR := 1 export LIBFAT_MAJOR := 1
export LIBFAT_MINOR := 0 export LIBFAT_MINOR := 1
export LIBFAT_PATCH := 13 export LIBFAT_PATCH := 1
export VERSTRING := $(LIBFAT_MAJOR).$(LIBFAT_MINOR).$(LIBFAT_PATCH) export VERSTRING := $(LIBFAT_MAJOR).$(LIBFAT_MINOR).$(LIBFAT_PATCH)

View File

@ -111,7 +111,7 @@ extern void fatGetVolumeLabel (const char* name, char *label);
Methods to modify DOS File Attributes Methods to modify DOS File Attributes
*/ */
int FAT_getAttr(const char *file); int FAT_getAttr(const char *file);
int FAT_setAttr(const char *file, int attr ); int FAT_setAttr(const char *file, uint8_t attr );
#define LIBFAT_FEOS_MULTICWD #define LIBFAT_FEOS_MULTICWD

View File

@ -2,9 +2,9 @@
#define __LIBFATVERSION_H__ #define __LIBFATVERSION_H__
#define _LIBFAT_MAJOR_ 1 #define _LIBFAT_MAJOR_ 1
#define _LIBFAT_MINOR_ 0 #define _LIBFAT_MINOR_ 1
#define _LIBFAT_PATCH_ 13 #define _LIBFAT_PATCH_ 1
#define _LIBFAT_STRING "libFAT Release 1.0.13" #define _LIBFAT_STRING "libFAT Release 1.1.1"
#endif // __LIBFATVERSION_H__ #endif // __LIBFATVERSION_H__

View File

@ -2,7 +2,9 @@
fat.h fat.h
Simple functionality for startup, mounting and unmounting of FAT-based devices. Simple functionality for startup, mounting and unmounting of FAT-based devices.
Copyright (c) 2006 Michael "Chishm" Chisholm Copyright (c) 2006 - 2012
Michael "Chishm" Chisholm
Dave "WinterMute" Murphy
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: are permitted provided that the following conditions are met:
@ -34,8 +36,26 @@
extern "C" { extern "C" {
#endif #endif
#include "libfatversion.h"
// When compiling for NDS, make sure NDS is defined
#ifndef NDS
#if defined ARM9 || defined ARM7
#define NDS
#endif
#endif
#include <stdint.h> #include <stdint.h>
#include <ogc/disc_io.h>
#if defined(__gamecube__) || defined (__wii__)
# include <ogc/disc_io.h>
#else
# ifdef NDS
# include <nds/disc_io.h>
# else
# include <disc_io.h>
# endif
#endif
/* /*
Initialise any inserted block-devices. Initialise any inserted block-devices.
@ -79,6 +99,22 @@ Get Volume Label
*/ */
extern void fatGetVolumeLabel (const char* name, char *label); extern void fatGetVolumeLabel (const char* name, char *label);
// File attributes
#define ATTR_ARCHIVE 0x20 // Archive
#define ATTR_DIRECTORY 0x10 // Directory
#define ATTR_VOLUME 0x08 // Volume
#define ATTR_SYSTEM 0x04 // System
#define ATTR_HIDDEN 0x02 // Hidden
#define ATTR_READONLY 0x01 // Read only
/*
Methods to modify DOS File Attributes
*/
int FAT_getAttr(const char *file);
int FAT_setAttr(const char *file, uint8_t attr );
#define LIBFAT_FEOS_MULTICWD
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -45,9 +45,6 @@
#define DIR_ENTRY_LAST 0x00 #define DIR_ENTRY_LAST 0x00
#define DIR_ENTRY_FREE 0xE5 #define DIR_ENTRY_FREE 0xE5
#define LAST_LFN_POS (19*13)
#define LAST_LFN_POS_CORRECTION (MAX_LFN_LENGTH-15)
typedef unsigned short ucs2_t; typedef unsigned short ucs2_t;
// Long file name directory entry // Long file name directory entry
@ -90,9 +87,9 @@ static int _FAT_directory_lfnLength (const char* name) {
int ucsLength; int ucsLength;
const char* tempName = name; const char* tempName = name;
nameLength = strnlen(name, MAX_FILENAME_LENGTH); nameLength = strnlen(name, NAME_MAX);
// Make sure the name is short enough to be valid // Make sure the name is short enough to be valid
if ( nameLength >= MAX_FILENAME_LENGTH) { if ( nameLength >= NAME_MAX) {
return -1; return -1;
} }
// Make sure it doesn't contain any invalid characters // Make sure it doesn't contain any invalid characters
@ -101,7 +98,8 @@ static int _FAT_directory_lfnLength (const char* name) {
} }
// Make sure the name doesn't contain any control codes or codes not representable in UCS-2 // Make sure the name doesn't contain any control codes or codes not representable in UCS-2
for (i = 0; i < nameLength; i++) { for (i = 0; i < nameLength; i++) {
if (name[i] < 0x20 || name[i] >= ABOVE_UCS_RANGE) { unsigned char ch = (unsigned char) name[i];
if (ch < 0x20 || ch >= ABOVE_UCS_RANGE) {
return -1; return -1;
} }
} }
@ -315,6 +313,7 @@ bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry) {
while (!found && !notFound) { while (!found && !notFound) {
if (_FAT_directory_incrementDirEntryPosition (partition, &entryEnd, false) == false) { if (_FAT_directory_incrementDirEntryPosition (partition, &entryEnd, false) == false) {
notFound = true; notFound = true;
break;
} }
_FAT_cache_readPartialSector (partition->cache, entryData, _FAT_cache_readPartialSector (partition->cache, entryData,
@ -341,14 +340,12 @@ bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry) {
} }
if (lfnExists) { if (lfnExists) {
lfnPos = ((entryData[LFN_offset_ordinal] & ~LFN_END) - 1) * 13; lfnPos = ((entryData[LFN_offset_ordinal] & ~LFN_END) - 1) * 13;
if (lfnPos > LAST_LFN_POS) {
// Force it within the buffer. Will corrupt the filename but prevent buffer overflows
lfnPos = LAST_LFN_POS;
}
for (i = 0; i < 13; i++) { for (i = 0; i < 13; i++) {
if (lfnPos + i < MAX_LFN_LENGTH - 1) {
lfn[lfnPos + i] = entryData[LFN_offset_table[i]] | (entryData[LFN_offset_table[i]+1] << 8); lfn[lfnPos + i] = entryData[LFN_offset_table[i]] | (entryData[LFN_offset_table[i]+1] << 8);
} }
} }
}
} else if (entryData[DIR_ENTRY_attributes] & ATTRIB_VOL) { } else if (entryData[DIR_ENTRY_attributes] & ATTRIB_VOL) {
// This is a volume name, don't bother with it // This is a volume name, don't bother with it
} else if (entryData[0] == DIR_ENTRY_LAST) { } else if (entryData[0] == DIR_ENTRY_LAST) {
@ -368,7 +365,7 @@ bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry) {
} }
if (lfnExists) { if (lfnExists) {
if (_FAT_directory_ucs2tombs (entry->filename, lfn, MAX_FILENAME_LENGTH) == (size_t)-1) { if (_FAT_directory_ucs2tombs (entry->filename, lfn, NAME_MAX) == (size_t)-1) {
// Failed to convert the file name to UTF-8. Maybe the wrong locale is set? // Failed to convert the file name to UTF-8. Maybe the wrong locale is set?
return false; return false;
} }
@ -409,7 +406,7 @@ bool _FAT_directory_getRootEntry (PARTITION* partition, DIR_ENTRY* entry) {
entry->dataEnd = entry->dataStart; entry->dataEnd = entry->dataStart;
memset (entry->filename, '\0', MAX_FILENAME_LENGTH); memset (entry->filename, '\0', NAME_MAX);
entry->filename[0] = '.'; entry->filename[0] = '.';
memset (entry->entryData, 0, DIR_ENTRY_DATA_SIZE); memset (entry->entryData, 0, DIR_ENTRY_DATA_SIZE);
@ -478,7 +475,7 @@ bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry) {
int lfnPos; int lfnPos;
uint8_t entryData[DIR_ENTRY_DATA_SIZE]; uint8_t entryData[DIR_ENTRY_DATA_SIZE];
memset (entry->filename, '\0', MAX_FILENAME_LENGTH); memset (entry->filename, '\0', NAME_MAX);
// Create an empty directory entry to overwrite the old ones with // Create an empty directory entry to overwrite the old ones with
for ( entryStillValid = true, finished = false; for ( entryStillValid = true, finished = false;
@ -498,19 +495,19 @@ bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry) {
} else { } else {
// Copy the long file name data // Copy the long file name data
lfnPos = ((entryData[LFN_offset_ordinal] & ~LFN_END) - 1) * 13; lfnPos = ((entryData[LFN_offset_ordinal] & ~LFN_END) - 1) * 13;
if (lfnPos > LAST_LFN_POS) {
lfnPos = LAST_LFN_POS_CORRECTION;
}
for (i = 0; i < 13; i++) { for (i = 0; i < 13; i++) {
if (lfnPos + i < MAX_LFN_LENGTH - 1) {
lfn[lfnPos + i] = entryData[LFN_offset_table[i]] | (entryData[LFN_offset_table[i]+1] << 8); lfn[lfnPos + i] = entryData[LFN_offset_table[i]] | (entryData[LFN_offset_table[i]+1] << 8);
} }
} }
} }
}
if (!entryStillValid) { if (!entryStillValid) {
return false; return false;
} }
entryStart = entry->dataStart;
if ((entryStart.cluster == entryEnd.cluster) if ((entryStart.cluster == entryEnd.cluster)
&& (entryStart.sector == entryEnd.sector) && (entryStart.sector == entryEnd.sector)
&& (entryStart.offset == entryEnd.offset)) { && (entryStart.offset == entryEnd.offset)) {
@ -520,7 +517,7 @@ bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry) {
} }
} else { } else {
// Encode the long file name into a multibyte string // Encode the long file name into a multibyte string
if (_FAT_directory_ucs2tombs (entry->filename, lfn, MAX_FILENAME_LENGTH) == (size_t)-1) { if (_FAT_directory_ucs2tombs (entry->filename, lfn, NAME_MAX) == (size_t)-1) {
return false; return false;
} }
} }
@ -575,7 +572,7 @@ bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const
dirnameLength = strlen(pathPosition); dirnameLength = strlen(pathPosition);
} }
if (dirnameLength > MAX_FILENAME_LENGTH) { if (dirnameLength > NAME_MAX) {
// The path is too long to bother with // The path is too long to bother with
return false; return false;
} }
@ -593,7 +590,7 @@ bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const
while (foundFile && !found && !notFound) { // It hasn't already found the file while (foundFile && !found && !notFound) { // It hasn't already found the file
// Check if the filename matches // Check if the filename matches
if ((dirnameLength == strnlen(entry->filename, MAX_FILENAME_LENGTH)) if ((dirnameLength == strnlen(entry->filename, NAME_MAX))
&& (_FAT_directory_mbsncasecmp(pathPosition, entry->filename, dirnameLength) == 0)) { && (_FAT_directory_mbsncasecmp(pathPosition, entry->filename, dirnameLength) == 0)) {
found = true; found = true;
} }
@ -705,7 +702,9 @@ static bool _FAT_directory_findEntryGap (PARTITION* partition, DIR_ENTRY* entry,
_FAT_fat_clusterToSector(partition, gapEnd.cluster) + gapEnd.sector, _FAT_fat_clusterToSector(partition, gapEnd.cluster) + gapEnd.sector,
gapEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE); gapEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE);
if (entryData[0] == DIR_ENTRY_LAST) { if (entryData[0] == DIR_ENTRY_LAST) {
if (dirEntryRemain == size) {
gapStart = gapEnd; gapStart = gapEnd;
}
-- dirEntryRemain; -- dirEntryRemain;
endOfDirectory = true; endOfDirectory = true;
} else if (entryData[0] == DIR_ENTRY_FREE) { } else if (entryData[0] == DIR_ENTRY_FREE) {
@ -760,9 +759,9 @@ static bool _FAT_directory_entryExists (PARTITION* partition, const char* name,
char alias[MAX_ALIAS_LENGTH]; char alias[MAX_ALIAS_LENGTH];
size_t dirnameLength; size_t dirnameLength;
dirnameLength = strnlen(name, MAX_FILENAME_LENGTH); dirnameLength = strnlen(name, NAME_MAX);
if (dirnameLength >= MAX_FILENAME_LENGTH) { if (dirnameLength >= NAME_MAX) {
return false; return false;
} }
@ -771,7 +770,7 @@ static bool _FAT_directory_entryExists (PARTITION* partition, const char* name,
while (foundFile) { // It hasn't already found the file while (foundFile) { // It hasn't already found the file
// Check if the filename matches // Check if the filename matches
if ((dirnameLength == strnlen(tempEntry.filename, MAX_FILENAME_LENGTH)) if ((dirnameLength == strnlen(tempEntry.filename, NAME_MAX))
&& (_FAT_directory_mbsncasecmp(name, tempEntry.filename, dirnameLength) == 0)) { && (_FAT_directory_mbsncasecmp(name, tempEntry.filename, dirnameLength) == 0)) {
return true; return true;
} }
@ -810,7 +809,7 @@ static int _FAT_directory_createAlias (char* alias, const char* lfn) {
// Primary portion of alias // Primary portion of alias
while (aliasPos < 8 && lfn[lfnPos] != '.' && lfn[lfnPos] != '\0') { while (aliasPos < 8 && lfn[lfnPos] != '.' && lfn[lfnPos] != '\0') {
bytesUsed = mbrtowc(&lfnChar, lfn + lfnPos, MAX_FILENAME_LENGTH - lfnPos, &ps); bytesUsed = mbrtowc(&lfnChar, lfn + lfnPos, NAME_MAX - lfnPos, &ps);
if (bytesUsed < 0) { if (bytesUsed < 0) {
return -1; return -1;
} }
@ -857,7 +856,7 @@ static int _FAT_directory_createAlias (char* alias, const char* lfn) {
aliasPos++; aliasPos++;
memset (&ps, 0, sizeof(ps)); memset (&ps, 0, sizeof(ps));
for (aliasExtLen = 0; aliasExtLen < MAX_ALIAS_EXT_LENGTH && *lfnExt != '\0'; aliasExtLen++) { for (aliasExtLen = 0; aliasExtLen < MAX_ALIAS_EXT_LENGTH && *lfnExt != '\0'; aliasExtLen++) {
bytesUsed = mbrtowc(&lfnChar, lfnExt, MAX_FILENAME_LENGTH - lfnPos, &ps); bytesUsed = mbrtowc(&lfnChar, lfnExt, NAME_MAX - lfnPos, &ps);
if (bytesUsed < 0) { if (bytesUsed < 0) {
return -1; return -1;
} }
@ -912,8 +911,20 @@ bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t d
int aliasLen; int aliasLen;
int lfnLen; int lfnLen;
// Remove trailing spaces
for (i = strlen (entry->filename) - 1; (i >= 0) && (entry->filename[i] == ' '); --i) {
entry->filename[i] = '\0';
}
#if 0
// Remove leading spaces
for (i = 0; entry->filename[i] == ' '; ++i) ;
if (i > 0) {
memmove (entry->filename, entry->filename + i, strlen (entry->filename + i));
}
#endif
// Make sure the filename is not 0 length // Make sure the filename is not 0 length
if (strnlen (entry->filename, MAX_FILENAME_LENGTH) < 1) { if (strnlen (entry->filename, NAME_MAX) < 1) {
return false; return false;
} }
@ -923,19 +934,9 @@ bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t d
return false; return false;
} }
// Remove trailing spaces
for (i = strlen (entry->filename) - 1; (i > 0) && (entry->filename[i] == ' '); --i) {
entry->filename[i] = '\0';
}
// Remove leading spaces
for (i = 0; (i < (int)strlen (entry->filename)) && (entry->filename[i] == ' '); ++i) ;
if (i > 0) {
memmove (entry->filename, entry->filename + i, strlen (entry->filename + i));
}
// Remove junk in filename // Remove junk in filename
i = strlen (entry->filename); i = strlen (entry->filename);
memset (entry->filename + i, '\0', MAX_FILENAME_LENGTH - i); memset (entry->filename + i, '\0', NAME_MAX - i);
// Make sure the entry doesn't already exist // Make sure the entry doesn't already exist
if (_FAT_directory_entryExists (partition, entry->filename, dirCluster)) { if (_FAT_directory_entryExists (partition, entry->filename, dirCluster)) {
@ -945,11 +946,11 @@ bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t d
// Clear out alias, so we can generate a new one // Clear out alias, so we can generate a new one
memset (entry->entryData, ' ', 11); memset (entry->entryData, ' ', 11);
if ( strncmp(entry->filename, ".", MAX_FILENAME_LENGTH) == 0) { if ( strncmp(entry->filename, ".", NAME_MAX) == 0) {
// "." entry // "." entry
entry->entryData[0] = '.'; entry->entryData[0] = '.';
entrySize = 1; entrySize = 1;
} else if ( strncmp(entry->filename, "..", MAX_FILENAME_LENGTH) == 0) { } else if ( strncmp(entry->filename, "..", NAME_MAX) == 0) {
// ".." entry // ".." entry
entry->entryData[0] = '.'; entry->entryData[0] = '.';
entry->entryData[1] = '.'; entry->entryData[1] = '.';
@ -972,17 +973,15 @@ bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t d
_FAT_directory_entryExists (partition, alias, dirCluster)) _FAT_directory_entryExists (partition, alias, dirCluster))
{ {
// expand primary part to 8 characters long by padding the end with underscores // expand primary part to 8 characters long by padding the end with underscores
i = MAX_ALIAS_PRI_LENGTH - 1; i = 0;
j = MAX_ALIAS_PRI_LENGTH;
// Move extension to last 3 characters // Move extension to last 3 characters
while (alias[i] != '.' && i > 0) i--; while (alias[i] != '.' && alias[i] != '\0') i++;
if (i > 0) { if (i < j) {
j = MAX_ALIAS_LENGTH - MAX_ALIAS_EXT_LENGTH - 2; // 1 char for '.', one for NUL, 3 for extension memmove (alias + j, alias + i, aliasLen - i + 1);
memmove (alias + j, alias + i, strlen(alias) - i);
// Pad primary component // Pad primary component
memset (alias + i, '_', j - i); memset (alias + i, '_', j - i);
alias[MAX_ALIAS_LENGTH-1]=0;
} }
// Generate numeric tail // Generate numeric tail
for (i = 1; i <= MAX_NUMERIC_TAIL; i++) { for (i = 1; i <= MAX_NUMERIC_TAIL; i++) {
j = i; j = i;

View File

@ -31,13 +31,13 @@
#define _DIRECTORY_H #define _DIRECTORY_H
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/syslimits.h>
#include "common.h" #include "common.h"
#include "partition.h" #include "partition.h"
#define DIR_ENTRY_DATA_SIZE 0x20 #define DIR_ENTRY_DATA_SIZE 0x20
#define MAX_LFN_LENGTH 256 #define MAX_LFN_LENGTH 256
#define MAX_FILENAME_LENGTH 768 // 256 UCS-2 characters encoded into UTF-8 can use up to 768 UTF-8 chars
#define MAX_ALIAS_LENGTH 13 #define MAX_ALIAS_LENGTH 13
#define LFN_ENTRY_LENGTH 13 #define LFN_ENTRY_LENGTH 13
#define ALIAS_ENTRY_LENGTH 11 #define ALIAS_ENTRY_LENGTH 11
@ -72,7 +72,7 @@ typedef struct {
uint8_t entryData[DIR_ENTRY_DATA_SIZE]; uint8_t entryData[DIR_ENTRY_DATA_SIZE];
DIR_ENTRY_POSITION dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN DIR_ENTRY_POSITION dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN
DIR_ENTRY_POSITION dataEnd; // Always points to the file/directory's alias entry DIR_ENTRY_POSITION dataEnd; // Always points to the file/directory's alias entry
char filename[MAX_FILENAME_LENGTH]; char filename[NAME_MAX];
} DIR_ENTRY; } DIR_ENTRY;
// Directory entry offsets // Directory entry offsets

View File

@ -86,10 +86,11 @@ const INTERFACE_ID _FAT_disc_interfaces[] = {
/* ====================== NDS ====================== */ /* ====================== NDS ====================== */
#elif defined (NDS) #elif defined (NDS)
#include <nds/system.h>
#include <nds/arm9/dldi.h> #include <nds/arm9/dldi.h>
static const DISC_INTERFACE* get_io_dsisd (void) { static const DISC_INTERFACE* get_io_dsisd (void) {
return &__io_dsisd; return isDSiMode() ? &__io_dsisd : NULL;
} }
const INTERFACE_ID _FAT_disc_interfaces[] = { const INTERFACE_ID _FAT_disc_interfaces[] = {

View File

@ -136,7 +136,7 @@ int _FAT_unlink_r (struct _reent *r, const char *path) {
if (!_FAT_directory_isDot (&dirContents)) { if (!_FAT_directory_isDot (&dirContents)) {
// The directory had something in it that isn't a reference to itself or it's parent // The directory had something in it that isn't a reference to itself or it's parent
_FAT_unlock(&partition->lock); _FAT_unlock(&partition->lock);
r->_errno = EPERM; r->_errno = ENOTEMPTY;
return -1; return -1;
} }
nextEntry = _FAT_directory_getNextEntry (partition, &dirContents); nextEntry = _FAT_directory_getNextEntry (partition, &dirContents);
@ -292,7 +292,7 @@ int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName) {
memcpy (&newDirEntry, &oldDirEntry, sizeof(DIR_ENTRY)); memcpy (&newDirEntry, &oldDirEntry, sizeof(DIR_ENTRY));
// Set the new name // Set the new name
strncpy (newDirEntry.filename, pathEnd, MAX_FILENAME_LENGTH - 1); strncpy (newDirEntry.filename, pathEnd, NAME_MAX - 1);
// Write the new entry // Write the new entry
if (!_FAT_directory_addEntry (partition, &newDirEntry, dirCluster)) { if (!_FAT_directory_addEntry (partition, &newDirEntry, dirCluster)) {
@ -381,7 +381,7 @@ int _FAT_mkdir_r (struct _reent *r, const char *path, int mode) {
pathEnd += 1; pathEnd += 1;
} }
// Create the entry data // Create the entry data
strncpy (dirEntry.filename, pathEnd, MAX_FILENAME_LENGTH - 1); strncpy (dirEntry.filename, pathEnd, NAME_MAX - 1);
memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE); memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE);
// Set the creation time and date // Set the creation time and date
@ -465,16 +465,13 @@ int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf)
_FAT_lock(&partition->lock); _FAT_lock(&partition->lock);
if(memcmp(&buf->f_flag, "SCAN", 4) == 0) if(partition->filesysType == FS_FAT32) {
{ // Sync FSinfo block
//Special command was given to sync the numberFreeCluster _FAT_partition_readFSinfo(partition);
_FAT_partition_createFSinfo(partition);
}
if(partition->filesysType == FS_FAT32)
freeClusterCount = partition->fat.numberFreeCluster; freeClusterCount = partition->fat.numberFreeCluster;
else } else {
freeClusterCount = _FAT_fat_freeClusterCount (partition); freeClusterCount = _FAT_fat_freeClusterCount (partition);
}
// FAT clusters = POSIX blocks // FAT clusters = POSIX blocks
buf->f_bsize = partition->bytesPerCluster; // File system block size. buf->f_bsize = partition->bytesPerCluster; // File system block size.
@ -496,7 +493,7 @@ int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf)
buf->f_flag = ST_NOSUID /* No support for ST_ISUID and ST_ISGID file mode bits */ buf->f_flag = ST_NOSUID /* No support for ST_ISUID and ST_ISGID file mode bits */
| (partition->readOnly ? ST_RDONLY /* Read only file system */ : 0 ) ; | (partition->readOnly ? ST_RDONLY /* Read only file system */ : 0 ) ;
// Maximum filename length. // Maximum filename length.
buf->f_namemax = MAX_FILENAME_LENGTH; buf->f_namemax = NAME_MAX;
_FAT_unlock(&partition->lock); _FAT_unlock(&partition->lock);
return 0; return 0;
@ -588,12 +585,11 @@ int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct
// Make sure there is another file to report on // Make sure there is another file to report on
if (! state->validEntry) { if (! state->validEntry) {
_FAT_unlock(&state->partition->lock); _FAT_unlock(&state->partition->lock);
r->_errno = ENOENT;
return -1; return -1;
} }
// Get the filename // Get the filename
strncpy (filename, state->currentEntry.filename, MAX_FILENAME_LENGTH); strncpy (filename, state->currentEntry.filename, NAME_MAX);
// Get the stats, if requested // Get the stats, if requested
if (filestat != NULL) { if (filestat != NULL) {
_FAT_directory_entryStat (state->partition, &(state->currentEntry), filestat); _FAT_directory_entryStat (state->partition, &(state->currentEntry), filestat);

View File

@ -48,6 +48,10 @@
bool _FAT_findEntry(const char *path, DIR_ENTRY *dirEntry) { bool _FAT_findEntry(const char *path, DIR_ENTRY *dirEntry) {
PARTITION *partition = _FAT_partition_getPartitionFromPath(path); PARTITION *partition = _FAT_partition_getPartitionFromPath(path);
// Check Partition
if( !partition )
return false;
// Move the path pointer to the start of the actual path // Move the path pointer to the start of the actual path
if (strchr (path, ':') != NULL) { if (strchr (path, ':') != NULL) {
path = strchr (path, ':') + 1; path = strchr (path, ':') + 1;
@ -68,12 +72,12 @@ int FAT_getAttr(const char *file) {
return dirEntry.entryData[DIR_ENTRY_attributes]; return dirEntry.entryData[DIR_ENTRY_attributes];
} }
int FAT_setAttr(const char *file, int attr) { int FAT_setAttr(const char *file, uint8_t attr) {
// Defines... // Defines...
DIR_ENTRY_POSITION entryEnd; DIR_ENTRY_POSITION entryEnd;
PARTITION *partition = NULL; PARTITION *partition = NULL;
DIR_ENTRY* dirEntry = NULL; DIR_ENTRY dirEntry;
// Get Partition // Get Partition
partition = _FAT_partition_getPartitionFromPath( file ); partition = _FAT_partition_getPartitionFromPath( file );
@ -89,11 +93,11 @@ int FAT_setAttr(const char *file, int attr) {
return -1; return -1;
// Get DIR_ENTRY // Get DIR_ENTRY
if( !_FAT_directory_entryFromPath (partition, dirEntry, file, NULL) ) if( !_FAT_directory_entryFromPath (partition, &dirEntry, file, NULL) )
return -1; return -1;
// Get Entry-End // Get Entry-End
entryEnd = dirEntry->dataEnd; entryEnd = dirEntry.dataEnd;
// Lock Partition // Lock Partition
_FAT_lock(&partition->lock); _FAT_lock(&partition->lock);
@ -222,7 +226,7 @@ int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags
pathEnd += 1; pathEnd += 1;
} }
// Create the entry data // Create the entry data
strncpy (dirEntry.filename, pathEnd, MAX_FILENAME_LENGTH - 1); strncpy (dirEntry.filename, pathEnd, NAME_MAX - 1);
memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE); memset (dirEntry.entryData, 0, DIR_ENTRY_DATA_SIZE);
// Set the creation time and date // Set the creation time and date
@ -378,7 +382,7 @@ int _FAT_syncToDisc (FILE_STRUCT* file) {
} }
int _FAT_close_r (struct _reent *r, int fd) { int _FAT_close_r (struct _reent *r, void *fd) {
FILE_STRUCT* file = (FILE_STRUCT*) fd; FILE_STRUCT* file = (FILE_STRUCT*) fd;
int ret = 0; int ret = 0;
@ -415,7 +419,7 @@ int _FAT_close_r (struct _reent *r, int fd) {
return ret; return ret;
} }
ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len) { ssize_t _FAT_read_r (struct _reent *r, void *fd, char *ptr, size_t len) {
FILE_STRUCT* file = (FILE_STRUCT*) fd; FILE_STRUCT* file = (FILE_STRUCT*) fd;
PARTITION* partition; PARTITION* partition;
CACHE* cache; CACHE* cache;
@ -598,7 +602,7 @@ static bool _FAT_check_position_for_next_cluster(struct _reent *r,
// do nothing if no more data to write // do nothing if no more data to write
if (remain == 0) return true; if (remain == 0) return true;
if (flagNoError && *flagNoError == false) return false; if (flagNoError && *flagNoError == false) return false;
if ((remain < 0) || (position->sector > partition->sectorsPerCluster)) { if (position->sector > partition->sectorsPerCluster) {
// invalid arguments - internal error // invalid arguments - internal error
r->_errno = EINVAL; r->_errno = EINVAL;
goto err; goto err;
@ -709,7 +713,7 @@ static bool _FAT_file_extend_r (struct _reent *r, FILE_STRUCT* file) {
return true; return true;
} }
ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) { ssize_t _FAT_write_r (struct _reent *r, void *fd, const char *ptr, size_t len) {
FILE_STRUCT* file = (FILE_STRUCT*) fd; FILE_STRUCT* file = (FILE_STRUCT*) fd;
PARTITION* partition; PARTITION* partition;
CACHE* cache; CACHE* cache;
@ -937,7 +941,7 @@ ssize_t _FAT_write_r (struct _reent *r, int fd, const char *ptr, size_t len) {
} }
off_t _FAT_seek_r (struct _reent *r, int fd, off_t pos, int dir) { off_t _FAT_seek_r (struct _reent *r, void *fd, off_t pos, int dir) {
FILE_STRUCT* file = (FILE_STRUCT*) fd; FILE_STRUCT* file = (FILE_STRUCT*) fd;
PARTITION* partition; PARTITION* partition;
uint32_t cluster, nextCluster; uint32_t cluster, nextCluster;
@ -1039,7 +1043,7 @@ off_t _FAT_seek_r (struct _reent *r, int fd, off_t pos, int dir) {
int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st) { int _FAT_fstat_r (struct _reent *r, void *fd, struct stat *st) {
FILE_STRUCT* file = (FILE_STRUCT*) fd; FILE_STRUCT* file = (FILE_STRUCT*) fd;
PARTITION* partition; PARTITION* partition;
DIR_ENTRY fileEntry; DIR_ENTRY fileEntry;
@ -1074,7 +1078,7 @@ int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st) {
return 0; return 0;
} }
int _FAT_ftruncate_r (struct _reent *r, int fd, off_t len) { int _FAT_ftruncate_r (struct _reent *r, void *fd, off_t len) {
FILE_STRUCT* file = (FILE_STRUCT*) fd; FILE_STRUCT* file = (FILE_STRUCT*) fd;
PARTITION* partition; PARTITION* partition;
int ret=0; int ret=0;
@ -1186,7 +1190,7 @@ int _FAT_ftruncate_r (struct _reent *r, int fd, off_t len) {
return ret; return ret;
} }
int _FAT_fsync_r (struct _reent *r, int fd) { int _FAT_fsync_r (struct _reent *r, void *fd) {
FILE_STRUCT* file = (FILE_STRUCT*) fd; FILE_STRUCT* file = (FILE_STRUCT*) fd;
int ret = 0; int ret = 0;

View File

@ -71,15 +71,15 @@ typedef struct _FILE_STRUCT FILE_STRUCT;
int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode); int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode);
int _FAT_close_r (struct _reent *r, int fd); int _FAT_close_r (struct _reent *r, void *fd);
ssize_t _FAT_write_r (struct _reent *r,int fd, const char *ptr, size_t len); ssize_t _FAT_write_r (struct _reent *r,void *fd, const char *ptr, size_t len);
ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len); ssize_t _FAT_read_r (struct _reent *r, void *fd, char *ptr, size_t len);
off_t _FAT_seek_r (struct _reent *r, int fd, off_t pos, int dir); off_t _FAT_seek_r (struct _reent *r, void *fd, off_t pos, int dir);
int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st); int _FAT_fstat_r (struct _reent *r, void *fd, struct stat *st);
int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st); int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st);
@ -91,9 +91,9 @@ int _FAT_chdir_r (struct _reent *r, const char *name);
int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName); int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName);
int _FAT_ftruncate_r (struct _reent *r, int fd, off_t len); int _FAT_ftruncate_r (struct _reent *r, void *fd, off_t len);
int _FAT_fsync_r (struct _reent *r, int fd); int _FAT_fsync_r (struct _reent *r, void *fd);
/* /*
Synchronizes the file data to disc. Synchronizes the file data to disc.

View File

@ -58,6 +58,6 @@ int _FAT_get_fragments (const char *path, _fat_frag_append_t append_fragment, vo
out: out:
_FAT_unlock(&partition->lock); _FAT_unlock(&partition->lock);
_FAT_close_r(&r, fd); _FAT_close_r(&r, (void *)fd);
return ret; return ret;
} }

View File

@ -30,7 +30,7 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <sys/param.h> #include <limits.h>
#include "common.h" #include "common.h"
#include "partition.h" #include "partition.h"
@ -64,8 +64,9 @@ static const devoptab_t dotab_fat = {
_FAT_ftruncate_r, _FAT_ftruncate_r,
_FAT_fsync_r, _FAT_fsync_r,
NULL, /* Device data */ NULL, /* Device data */
NULL, NULL, // chmod_r
NULL NULL, // fchmod_r
NULL // rmdir_r
}; };
bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage) { bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage) {
@ -153,6 +154,9 @@ bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice) {
i++) i++)
{ {
disc = _FAT_disc_interfaces[i].getInterface(); disc = _FAT_disc_interfaces[i].getInterface();
if (!disc) {
continue;
}
if (fatMount (_FAT_disc_interfaces[i].name, disc, 0, cacheSize, DEFAULT_SECTORS_PAGE)) { if (fatMount (_FAT_disc_interfaces[i].name, disc, 0, cacheSize, DEFAULT_SECTORS_PAGE)) {
// The first device to successfully mount is set as the default // The first device to successfully mount is set as the default
if (defaultDevice < 0) { if (defaultDevice < 0) {
@ -167,7 +171,7 @@ bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice) {
} }
if (setAsDefaultDevice) { if (setAsDefaultDevice) {
char filePath[MAXPATHLEN * 2]; char filePath[PATH_MAX];
strcpy (filePath, _FAT_disc_interfaces[defaultDevice].name); strcpy (filePath, _FAT_disc_interfaces[defaultDevice].name);
strcat (filePath, ":/"); strcat (filePath, ":/");
#ifdef ARGV_MAGIC #ifdef ARGV_MAGIC

View File

@ -35,16 +35,19 @@
#include "mem2.h" #include "mem2.h"
static inline void* _FAT_mem_allocate (size_t size) { static inline void* _FAT_mem_allocate (size_t size) {
return MEM2_alloc(size); return MEM2_alloc (size);
} }
static inline void* _FAT_mem_align (size_t size) { static inline void* _FAT_mem_align (size_t size) {
return MEM2_alloc(size); #ifdef __wii__
return memalign (32, size);
#else
return MEM2_alloc (size);
#endif
} }
static inline void _FAT_mem_free (void* mem) { static inline void _FAT_mem_free (void* mem) {
//using normal free, it will decide which free to use (just to be on the safe side) free (mem);
free(mem);
} }
#endif // _MEM_ALLOCATE_H #endif // _MEM_ALLOCATE_H

View File

@ -180,7 +180,7 @@ PARTITION* _FAT_partition_constructor_buf (const DISC_INTERFACE* disc, uint32_t
} }
// Make sure it is a valid MBR or boot sector // Make sure it is a valid MBR or boot sector
if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) { if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA && sectorBuffer[BPB_bootSig_AA] != 0xAB)) {
return NULL; return NULL;
} }
@ -348,6 +348,13 @@ PARTITION* _FAT_partition_getPartitionFromPath (const char* path) {
return (PARTITION*)devops->deviceData; return (PARTITION*)devops->deviceData;
} }
static void _FAT_updateFS_INFO(PARTITION * partition, uint8_t *sectorBuffer) {
partition->fat.numberFreeCluster = _FAT_fat_freeClusterCount(partition);
u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster);
u32_to_u8array(sectorBuffer, FSIB_numberLastAllocCluster, partition->fat.numberLastAllocCluster);
_FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer);
}
void _FAT_partition_createFSinfo(PARTITION * partition) void _FAT_partition_createFSinfo(PARTITION * partition)
{ {
if(partition->readOnly || partition->filesysType != FS_FAT32) if(partition->readOnly || partition->filesysType != FS_FAT32)
@ -364,14 +371,10 @@ void _FAT_partition_createFSinfo(PARTITION * partition)
sectorBuffer[FSIB_SIG2+i] = FS_INFO_SIG2[i]; sectorBuffer[FSIB_SIG2+i] = FS_INFO_SIG2[i];
} }
partition->fat.numberFreeCluster = _FAT_fat_freeClusterCount(partition);
u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster);
u32_to_u8array(sectorBuffer, FSIB_numberLastAllocCluster, partition->fat.numberLastAllocCluster);
sectorBuffer[FSIB_bootSig_55] = 0x55; sectorBuffer[FSIB_bootSig_55] = 0x55;
sectorBuffer[FSIB_bootSig_AA] = 0xAA; sectorBuffer[FSIB_bootSig_AA] = 0xAA;
_FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer); _FAT_updateFS_INFO(partition,sectorBuffer);
_FAT_mem_free(sectorBuffer); _FAT_mem_free(sectorBuffer);
} }
@ -398,6 +401,10 @@ void _FAT_partition_readFSinfo(PARTITION * partition)
_FAT_partition_createFSinfo(partition); _FAT_partition_createFSinfo(partition);
} else { } else {
partition->fat.numberFreeCluster = u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster); partition->fat.numberFreeCluster = u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster);
if(partition->fat.numberFreeCluster == 0xffffffff) {
_FAT_updateFS_INFO(partition,sectorBuffer);
partition->fat.numberFreeCluster = u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster);
}
partition->fat.numberLastAllocCluster = u8array_to_u32(sectorBuffer, FSIB_numberLastAllocCluster); partition->fat.numberLastAllocCluster = u8array_to_u32(sectorBuffer, FSIB_numberLastAllocCluster);
} }
_FAT_mem_free(sectorBuffer); _FAT_mem_free(sectorBuffer);