2009-11-15 22:30:44 +01:00
|
|
|
/*
|
2010-09-24 02:48:03 +02:00
|
|
|
libfat.c
|
|
|
|
Simple functionality for startup, mounting and unmounting of FAT-based devices.
|
2009-11-15 22:30:44 +01:00
|
|
|
|
|
|
|
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:
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
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.
|
2009-11-15 22:30:44 +01:00
|
|
|
|
|
|
|
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.
|
2010-09-24 02:48:03 +02:00
|
|
|
*/
|
2009-11-15 22:30:44 +01:00
|
|
|
|
|
|
|
#include <sys/iosupport.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
#include "partition.h"
|
|
|
|
#include "fatfile.h"
|
|
|
|
#include "fatdir.h"
|
|
|
|
#include "lock.h"
|
|
|
|
#include "mem_allocate.h"
|
2010-09-18 01:28:01 +02:00
|
|
|
#include "disc_fat.h"
|
2009-11-15 22:30:44 +01:00
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
static const devoptab_t dotab_fat = { "fat", sizeof(FILE_STRUCT), _FAT_open_r, _FAT_close_r, _FAT_write_r, _FAT_read_r,
|
|
|
|
_FAT_seek_r, _FAT_fstat_r, _FAT_stat_r, _FAT_link_r, _FAT_unlink_r, _FAT_chdir_r, _FAT_rename_r, _FAT_mkdir_r,
|
|
|
|
sizeof(DIR_STATE_STRUCT), _FAT_diropen_r, _FAT_dirreset_r, _FAT_dirnext_r, _FAT_dirclose_r, _FAT_statvfs_r,
|
|
|
|
_FAT_ftruncate_r, _FAT_fsync_r, NULL /* Device data */
|
2009-11-15 22:30:44 +01:00
|
|
|
};
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
bool fatMount(const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize,
|
|
|
|
uint32_t SectorsPerPage)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
PARTITION* partition;
|
|
|
|
devoptab_t* devops;
|
|
|
|
char* nameCopy;
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
if (!interface->startup()) return false;
|
2010-09-19 01:16:05 +02:00
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
if (!interface->isInserted())
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
interface->shutdown();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
devops = _FAT_mem_allocate(sizeof(devoptab_t) + strlen(name) + 1);
|
|
|
|
if (!devops)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
interface->shutdown();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// Use the space allocated at the end of the devoptab struct for storing the name
|
2010-09-24 02:48:03 +02:00
|
|
|
nameCopy = (char*) (devops + 1);
|
2010-09-19 01:16:05 +02:00
|
|
|
|
|
|
|
// Initialize the file system
|
2010-09-24 02:48:03 +02:00
|
|
|
partition = _FAT_partition_constructor(interface, cacheSize, SectorsPerPage, startSector);
|
|
|
|
if (!partition)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2010-09-24 02:48:03 +02:00
|
|
|
_FAT_mem_free(devops);
|
2010-09-19 01:16:05 +02:00
|
|
|
interface->shutdown();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add an entry for this device to the devoptab table
|
2010-09-24 02:48:03 +02:00
|
|
|
memcpy(devops, &dotab_fat, sizeof(dotab_fat));
|
|
|
|
strcpy(nameCopy, name);
|
2010-09-19 01:16:05 +02:00
|
|
|
devops->name = nameCopy;
|
|
|
|
devops->deviceData = partition;
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
AddDevice(devops);
|
2010-09-19 01:16:05 +02:00
|
|
|
|
|
|
|
return true;
|
2009-11-15 22:30:44 +01:00
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
bool fatMountSimple(const char* name, const DISC_INTERFACE* interface)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2010-09-24 02:48:03 +02:00
|
|
|
return fatMount(name, interface, 0, DEFAULT_CACHE_PAGES, DEFAULT_SECTORS_PAGE);
|
2009-11-15 22:30:44 +01:00
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
void fatUnmount(const char* name)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
devoptab_t *devops;
|
|
|
|
PARTITION* partition;
|
|
|
|
const DISC_INTERFACE *disc;
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
devops = (devoptab_t*) GetDeviceOpTab(name);
|
|
|
|
if (!devops)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Perform a quick check to make sure we're dealing with a libfat controlled device
|
2010-09-24 02:48:03 +02:00
|
|
|
if (devops->open_r != dotab_fat.open_r)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
if (RemoveDevice(name) == -1)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
partition = (PARTITION*) devops->deviceData;
|
2010-09-19 01:16:05 +02:00
|
|
|
disc = partition->disc;
|
2010-09-24 02:48:03 +02:00
|
|
|
_FAT_partition_destructor(partition);
|
|
|
|
_FAT_mem_free(devops);
|
2010-09-19 01:16:05 +02:00
|
|
|
disc->shutdown();
|
2009-11-15 22:30:44 +01:00
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
bool fatInit(uint32_t cacheSize, bool setAsDefaultDevice)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int defaultDevice = -1;
|
|
|
|
const DISC_INTERFACE *disc;
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
for (i = 0; _FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL; i++)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
disc = _FAT_disc_interfaces[i].getInterface();
|
2010-09-24 02:48:03 +02:00
|
|
|
if (fatMount(_FAT_disc_interfaces[i].name, disc, 0, cacheSize, DEFAULT_SECTORS_PAGE))
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
// The first device to successfully mount is set as the default
|
2010-09-24 02:48:03 +02:00
|
|
|
if (defaultDevice < 0)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
defaultDevice = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
if (defaultDevice < 0)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
// None of our devices mounted
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
if (setAsDefaultDevice)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
char filePath[MAXPATHLEN * 2];
|
2010-09-24 02:48:03 +02:00
|
|
|
strcpy(filePath, _FAT_disc_interfaces[defaultDevice].name);
|
|
|
|
strcat(filePath, ":/");
|
2009-11-15 22:30:44 +01:00
|
|
|
#ifdef ARGV_MAGIC
|
2010-09-24 02:48:03 +02:00
|
|
|
if (__system_argv->argvMagic == ARGV_MAGIC && __system_argv->argc >= 1 && strrchr(__system_argv->argv[0], '/')
|
|
|
|
!= NULL)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
// Check the app's path against each of our mounted devices, to see
|
|
|
|
// if we can support it. If so, change to that path.
|
2010-09-24 02:48:03 +02:00
|
|
|
for (i = 0; _FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL; i++)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2010-09-24 02:48:03 +02:00
|
|
|
if (!strncasecmp(__system_argv->argv[0], _FAT_disc_interfaces[i].name, strlen(
|
|
|
|
_FAT_disc_interfaces[i].name)))
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
|
|
|
char *lastSlash;
|
2010-09-24 02:48:03 +02:00
|
|
|
strcpy(filePath, __system_argv->argv[0]);
|
|
|
|
lastSlash = strrchr(filePath, '/');
|
2010-09-19 01:16:05 +02:00
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
if (NULL != lastSlash)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2010-09-24 02:48:03 +02:00
|
|
|
if (*(lastSlash - 1) == ':') lastSlash++;
|
2010-09-19 01:16:05 +02:00
|
|
|
*lastSlash = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-11-15 22:30:44 +01:00
|
|
|
#endif
|
2010-09-24 02:48:03 +02:00
|
|
|
chdir(filePath);
|
2010-09-19 01:16:05 +02:00
|
|
|
}
|
2009-11-15 22:30:44 +01:00
|
|
|
|
2010-09-19 01:16:05 +02:00
|
|
|
return true;
|
2009-11-15 22:30:44 +01:00
|
|
|
}
|
|
|
|
|
2010-09-24 02:48:03 +02:00
|
|
|
bool fatInitDefault(void)
|
2010-09-19 01:16:05 +02:00
|
|
|
{
|
2010-09-24 02:48:03 +02:00
|
|
|
return fatInit(DEFAULT_CACHE_PAGES, true);
|
2009-11-15 22:30:44 +01:00
|
|
|
}
|
|
|
|
|