homebrew_launcher/src/fs/CFile.cpp

198 lines
2.8 KiB
C++
Raw Normal View History

2016-02-29 22:28:18 +01:00
#include <stdarg.h>
#include <stdlib.h>
#include "CFile.hpp"
CFile::CFile()
{
iFd = -1;
mem_file = NULL;
filesize = 0;
pos = 0;
}
CFile::CFile(const std::string & filepath, eOpenTypes mode)
{
iFd = -1;
this->open(filepath, mode);
}
CFile::CFile(const u8 * mem, int size)
{
iFd = -1;
this->open(mem, size);
}
CFile::~CFile()
{
this->close();
}
int CFile::open(const std::string & filepath, eOpenTypes mode)
{
this->close();
s32 openMode = 0;
switch(mode)
{
default:
case ReadOnly:
openMode = O_RDONLY;
break;
case WriteOnly:
openMode = O_WRONLY;
break;
case ReadWrite:
openMode = O_RDWR;
break;
case Append:
openMode = O_APPEND | O_WRONLY;
break;
}
//! Using fopen works only on the first launch as expected
//! on the second launch it causes issues because we don't overwrite
//! the .data sections which is needed for a normal application to re-init
//! this will be added with launching as RPX
iFd = ::open(filepath.c_str(), openMode);
if(iFd < 0)
return iFd;
filesize = ::lseek(iFd, 0, SEEK_END);
::lseek(iFd, 0, SEEK_SET);
return 0;
}
int CFile::open(const u8 * mem, int size)
{
this->close();
mem_file = mem;
filesize = size;
return 0;
}
void CFile::close()
{
if(iFd >= 0)
::close(iFd);
iFd = -1;
mem_file = NULL;
filesize = 0;
pos = 0;
}
int CFile::read(u8 * ptr, size_t size)
{
if(iFd >= 0)
{
int ret = ::read(iFd, ptr,size);
if(ret > 0)
pos += ret;
return ret;
}
int readsize = size;
if(readsize > (s64) (filesize-pos))
readsize = filesize-pos;
if(readsize <= 0)
return readsize;
if(mem_file != NULL)
{
memcpy(ptr, mem_file+pos, readsize);
pos += readsize;
return readsize;
}
return -1;
}
int CFile::write(const u8 * ptr, size_t size)
{
if(iFd >= 0)
{
size_t done = 0;
while(done < size)
{
int ret = ::write(iFd, ptr, size - done);
if(ret <= 0)
return ret;
ptr += ret;
done += ret;
pos += ret;
}
return done;
}
return -1;
}
int CFile::seek(long int offset, int origin)
{
int ret = 0;
s64 newPos = pos;
if(origin == SEEK_SET)
{
newPos = offset;
}
else if(origin == SEEK_CUR)
{
newPos += offset;
}
else if(origin == SEEK_END)
{
newPos = filesize+offset;
}
if(newPos < 0)
{
pos = 0;
}
else {
pos = newPos;
}
if(iFd >= 0)
ret = ::lseek(iFd, pos, SEEK_SET);
if(mem_file != NULL)
{
if(pos > filesize)
{
pos = filesize;
}
}
return ret;
}
int CFile::fwrite(const char *format, ...)
{
int result = -1;
char * tmp = NULL;
va_list va;
va_start(va, format);
if((vasprintf(&tmp, format, va) >= 0) && tmp)
{
result = this->write((u8 *)tmp, strlen(tmp));
}
va_end(va);
if(tmp)
free(tmp);
return result;
}