usbloadergx/source/mload/fatffs_util.c

292 lines
5.7 KiB
C
Raw Normal View History

/*
From Custom IOS Module (FAT)
Copyright (C) 2009 Waninkoko.
Copyright (C) 2010 Hermes.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "fatffs_util.h"
#include <string.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <stdio.h>
#include <malloc.h>
extern u32 nand_mode;
s32 FAT_DeleteDir(const char *dirpath)
{
DIR_ITER *dir;
s32 ret;
/* Open directory */
dir = diropen(dirpath);
if (!dir)
return -1;
/* Read entries */
for (;;) {
char filename[256], newpath[256];
struct stat filestat;
/* Read entry */
if (dirnext(dir, filename, &filestat))
break;
/* Non valid entry */
if (filename[0]=='.')
continue;
/* Generate entry path */
strcpy(newpath, dirpath);
strcat(newpath, "/");
strcat(newpath, filename);
/* Delete directory contents */
if (filestat.st_mode & S_IFDIR)
FAT_DeleteDir(newpath);
/* Delete object */
ret = remove(newpath);
/* Error */
if (ret != 0)
break;
}
/* Close directory */
dirclose(dir);
return 0;
}
static int global_error=0;
static char temp_read_buffer[16384] ATTRIBUTE_ALIGN(32);
s32 _FFS_to_FAT_Copy(const char *ffsdirpath, const char *fatdirpath)
{
int n;
u32 blocks, ionodes;
int pos=0;
char *list;
s32 ret;
u32 ionodes_temp;
if(ISFS_GetUsage(ffsdirpath, &blocks, &ionodes)) {global_error=-1;return -1;}
list= memalign(32, ionodes*13);
if(!list) {global_error=-2;return -2;}
if(ISFS_ReadDir(ffsdirpath, list , &ionodes)) {free(list);global_error=-3;return -3;}
if(ionodes) mkdir(fatdirpath, S_IRWXO | S_IRWXG | S_IRWXU);
/* Read entries */
for (n=0;n<ionodes;n++) {
char * filename;
char newffspath[256], newfatpath[256];
/* Read entry */
filename=&list[pos];
pos+=strlen(&list[pos])+1;
/* Non valid entry */
if (filename[0]=='.')
continue;
/* Generate entry path */
strcpy(newffspath, ffsdirpath);
strcat(newffspath, "/");
strcat(newffspath, filename);
strcpy(newfatpath, fatdirpath);
strcat(newfatpath, "/");
strcat(newfatpath, filename);
ret=ISFS_ReadDir(newffspath, NULL, &ionodes_temp);
if(ret==0) // it is a directory
{
_FFS_to_FAT_Copy(newffspath, newfatpath);
if(global_error) {free(list);return global_error;}
}
else // copy the file
{
int fd;
FILE *fp;
fd=ISFS_Open(newffspath, ISFS_OPEN_READ);
if(fd<0)
{
global_error=-4;
free(list);return global_error;
}
else
{
int len;
fp=fopen(newfatpath,"w");
if(!fd) {ISFS_Close(fd);global_error=-5;free(list);return global_error;}
len= ISFS_Seek(fd, 0, 2);
//if(len<0) {ISFS_Close(fd);global_error=-6;free(list);return global_error;}
ISFS_Seek(fd, 0, 0);
while(len>0)
{
ret=len; if(len>16384) ret=16384;
if(ISFS_Read(fd, temp_read_buffer, ret)!=ret)
{
global_error=-7;
break;
}
if(fwrite(temp_read_buffer, 1, ret, fp)!=ret)
{
global_error=-8;
break;
}
len-=ret;
}
fclose(fp);
ISFS_Close(fd);
if(global_error) {free(list);return global_error;}
}
}
}
free(list);
return 0;
}
s32 FFS_to_FAT_Copy(const char *ffsdirpath, const char *fatdirpath)
{
u32 blocks, ionodes;
int ret;
char create_dir[256];
ISFS_Initialize();
ret=ISFS_GetUsage(ffsdirpath, &blocks, &ionodes);
if(ret==0)
{
int n=0;
// creating the path directory
strcpy(create_dir, fatdirpath);
while(create_dir[n]!=0 && create_dir[n]!='/') n++;
if(create_dir[n]=='/') n++;
while(create_dir[n]!=0)
{
if(create_dir[n]=='/')
{
create_dir[n]=0;
mkdir(create_dir, S_IRWXO | S_IRWXG | S_IRWXU);
create_dir[n]='/';
}
n++;
}
global_error=0;
// copy files
_FFS_to_FAT_Copy(ffsdirpath, fatdirpath);
ret=global_error=0;
}
else ret=-101;
ISFS_Deinitialize();
return ret;
}
static char temp_cad[512];
void create_FAT_FFS_Directory(struct discHdr *header)
{
char device[2][4]={
"sd:",
"ud:"
};
if(!header) return;
sprintf((char *) temp_cad,"%s/nand%c", &device[(nand_mode & 2)!=0][0], (nand_mode & 0xc) ? 49+((nand_mode>>2) & 3) : '\0');
sprintf((char *) temp_cad+32,"%2.2x%2.2x%2.2x%2.2x", header->id[0], header->id[1], header->id[2], header->id[3]);
sprintf((char *) temp_cad+64,"%s/title/00010000/%s", temp_cad, temp_cad+32);
sprintf((char *) temp_cad+128,"%s/title/00010004/%s", temp_cad, temp_cad+32);
sprintf((char *) temp_cad+256,"/title/00010000/%s", temp_cad+32);
sprintf((char *) temp_cad+384,"/title/00010004/%s", temp_cad+32);
}
int test_FAT_game(char * directory)
{
DIR_ITER * dir=NULL;
dir= diropen(directory);
if(dir) {dirclose(dir);return 1;}
return 0;
}
char *get_FAT_directory1(void)
{
return temp_cad+64;
}
char *get_FAT_directory2(void)
{
return temp_cad+128;
}
char *get_FFS_directory1(void)
{
return temp_cad+256;
}
char *get_FFS_directory2(void)
{
return temp_cad+384;
}