RetroArch/wiiu/fs/fs_utils.c

207 lines
4.2 KiB
C

#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <wiiu/fs.h>
/* FS defines and types */
#define FS_MAX_LOCALPATH_SIZE 511
#define FS_MAX_MOUNTPATH_SIZE 128
#define FS_MAX_FULLPATH_SIZE (FS_MAX_LOCALPATH_SIZE + FS_MAX_MOUNTPATH_SIZE)
#define FS_MAX_ARGPATH_SIZE FS_MAX_FULLPATH_SIZE
#define FS_STATUS_OK 0
#define FS_RET_UNSUPPORTED_CMD 0x0400
#define FS_RET_NO_ERROR 0x0000
#define FS_RET_ALL_ERROR (unsigned int)(-1)
#define FS_STAT_FLAG_IS_DIRECTORY 0x80000000
/* max length of file/dir name */
#define FS_MAX_ENTNAME_SIZE 256
#define FS_SOURCETYPE_EXTERNAL 0
#define FS_SOURCETYPE_HFIO 1
#define FS_SOURCETYPE_HFIO 1
#define FS_MOUNT_SOURCE_SIZE 0x300
#define FS_CLIENT_SIZE 0x1700
#define FS_CMD_BLOCK_SIZE 0xA80
int MountFS(void *pClient, void *pCmd, char **mount_path)
{
char *mountPath = NULL;
int result = -1;
void *mountSrc = malloc(FS_MOUNT_SOURCE_SIZE);
if (!mountSrc)
return -3;
mountPath = (char*) malloc(FS_MAX_MOUNTPATH_SIZE);
if (!mountPath)
{
free(mountSrc);
return -4;
}
memset(mountSrc, 0, FS_MOUNT_SOURCE_SIZE);
memset(mountPath, 0, FS_MAX_MOUNTPATH_SIZE);
/* Mount sdcard */
if (FSGetMountSource(pClient, pCmd, FS_SOURCETYPE_EXTERNAL, mountSrc, -1) == 0)
{
result = FSMount(pClient, pCmd, mountSrc, mountPath, FS_MAX_MOUNTPATH_SIZE, -1);
if ((result == 0) && mount_path)
{
*mount_path = (char*)malloc(strlen(mountPath) + 1);
if (*mount_path)
strcpy(*mount_path, mountPath);
}
}
free(mountPath);
free(mountSrc);
return result;
}
int UmountFS(void *pClient, void *pCmd, const char *mountPath)
{
return FSUnmount(pClient, pCmd, mountPath, -1);
}
int LoadFileToMem(const char *filepath, u8 **inbuffer, u32 *size)
{
u8 *buffer;
u32 filesize;
int iFd;
u32 blocksize = 0x4000;
u32 done = 0;
int readBytes = 0;
/* always initialze input */
*inbuffer = NULL;
if (size)
*size = 0;
iFd = open(filepath, O_RDONLY);
if (iFd < 0)
return -1;
filesize = lseek(iFd, 0, SEEK_END);
lseek(iFd, 0, SEEK_SET);
buffer = (u8 *) malloc(filesize);
if (buffer == NULL)
{
close(iFd);
return -2;
}
while(done < filesize)
{
if (done + blocksize > filesize)
blocksize = filesize - done;
readBytes = read(iFd, buffer + done, blocksize);
if (readBytes <= 0)
break;
done += readBytes;
}
close(iFd);
if (done != filesize)
{
free(buffer);
return -3;
}
*inbuffer = buffer;
/* sign is optional input */
if (size)
*size = filesize;
return filesize;
}
int CheckFile(const char * filepath)
{
struct stat filestat;
char *notRoot = NULL;
if (!filepath)
return 0;
char dirnoslash[strlen(filepath)+2];
snprintf(dirnoslash, sizeof(dirnoslash), "%s", filepath);
while(dirnoslash[strlen(dirnoslash)-1] == '/')
dirnoslash[strlen(dirnoslash)-1] = '\0';
notRoot = strrchr(dirnoslash, '/');
if (!notRoot)
strcat(dirnoslash, "/");
if (stat(dirnoslash, &filestat) == 0)
return 1;
return 0;
}
int CreateSubfolder(const char * fullpath)
{
int pos;
int result = 0;
if (!fullpath)
return 0;
char dirnoslash[strlen(fullpath)+1];
strcpy(dirnoslash, fullpath);
pos = strlen(dirnoslash)-1;
while(dirnoslash[pos] == '/')
{
dirnoslash[pos] = '\0';
pos--;
}
if (CheckFile(dirnoslash))
return 1;
{
char parentpath[strlen(dirnoslash)+2];
strcpy(parentpath, dirnoslash);
char * ptr = strrchr(parentpath, '/');
if (!ptr)
{
/* Device root directory (must be with '/') */
strcat(parentpath, "/");
struct stat filestat;
if (stat(parentpath, &filestat) == 0)
return 1;
return 0;
}
ptr++;
ptr[0] = '\0';
result = CreateSubfolder(parentpath);
}
if (!result)
return 0;
if (mkdir(dirnoslash, 0777) == -1)
return 0;
return 1;
}