/*
* Author: Pawel Jablonski
* E-mail: pj@xirx.net
* WWW: xirx.net
* GIT: git.xirx.net
*
* License: You can use this code however you like
* but leave information about the original author.
* Code is free for non-commercial and commercial use.
*/
#include "fs.h"
/**
* Constructor for the file system class
*
* @param parent Parent object
*/
FS::FS(QObject *parent) : QObject(parent)
{
this->path = "";
this->reset();
}
//! Reset the file system buffers and path
void FS::reset()
{
this->buffer.clear();
}
/**
* Set path to the emulated file system on the local disk
*
* @param path Path to emulated file system
*/
void FS::setPath(const QString &path)
{
this->path = path;
}
/**
* Open and load to buffer a file from the emulated file system
*
* @param dirName Name of the directory. "app" or "file".
* @param fileName Name of the file to open
* @param size Struct where size of the file will be written
*
* @return Status of the open operation
*/
bool FS::open(const QString &dirName, const FS::Name &fileName, FS::Size &size)
{
size.low = 0;
size.high = 0;
if(!dirName.contains(QRegularExpression("^([0-9a-zA-Z_-]{1,8})$")))
{
return(false);
}
QString name(reinterpret_cast<const char *>(fileName.data.constData()));
if(!name.contains(QRegularExpression("^([0-9a-zA-Z_-]{1,8})(([\\\\.])([0-9a-zA-Z_-]{1,3}))?$")))
{
return(false);
}
QString filePath = QString(this->path).append("/").append(dirName).append("/").append(name);
QFile file(filePath);
if(!file.open(QIODevice::ReadOnly))
{
return(false);
}
if(file.size() > FILE_MAX_SIZE)
{
file.close();
return(false);
}
this->buffer = file.readAll();
file.close();
size.low = static_cast<unsigned char>(this->buffer.size() % 256);
size.high = static_cast<unsigned char>((this->buffer.size() / 256) & 0xff);
return(true);
}
/**
* Create a list of files in the directory from the emulated file system
*
* @param dirName Name of the directory. "app" or "file".
* @param size Struct where size of the buffer with description of the files will be written
*
* @return Status of the list operation
*/
bool FS::list(const QString &dirName, FS::Size &size)
{
size.low = 0;
size.high = 0;
if(!dirName.contains(QRegularExpression("^([0-9a-zA-Z_-]{1,8})$")))
{
return(false);
}
QString dirPath = QString(this->path).append("/").append(dirName);
QDir dir;
dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
dir.setSorting(QDir::Name);
if(!dir.cd(dirPath))
{
return(false);
}
QFileInfoList fileInfoList = dir.entryInfoList();
this->buffer.clear();
for(const QFileInfo &fileInfo : fileInfoList)
{
QString fileName = fileInfo.fileName();
qint64 fileSize = fileInfo.size();
if(fileSize > FILE_MAX_SIZE)
{
continue;
}
if(!fileName.contains(QRegularExpression(R"(^([0-9a-zA-Z_-]{1,8})(([\\.])([0-9a-zA-Z_-]{1,3}))?$)")))
{
continue;
}
int j = 0;
for(; ((j < NAME_MAX_LENGTH) && (j < fileName.length())); j++)
{
this->buffer.append(fileName.at(j).toLatin1());
}
for(; j < (DIR_ENTRY_SIZE - DIR_SIZE_FIELD_SIZE); j++)
{
this->buffer.append(static_cast<char>(0));
}
QVector<unsigned char> size(2);
size[0] = static_cast<unsigned char>(fileSize % 256);
size[1] = static_cast<unsigned char>((fileSize / 256) & 0xff);
this->buffer.append(static_cast<char>(size[0]));
this->buffer.append(static_cast<char>(size[1]));
if(this->buffer.size() >= (DIR_MAX_QUANTITY * DIR_ENTRY_SIZE))
{
break;
}
}
size.low = static_cast<unsigned char>(this->buffer.size() % 256);
size.high = static_cast<unsigned char>((this->buffer.size() / 256) & 0xff);
return(true);
}
/**
* Read data from buffer to block based on offset
*
* @param block Struct where the data from the buffer will be written
* @param number Number of the selected virtual block selected to read
*/
void FS::readBlock(FS::Block &block, int number)
{
for(int i = 0; i < BLOCK_SIZE; i++)
{
int j = ((number * BLOCK_SIZE) + i);
if(j < this->buffer.size())
{
block.data[i] = static_cast<unsigned char>(this->buffer.at(j));
}
else
{
block.data[i] = 0;
}
}
}