[DEV] set Windows support zip data package

This commit is contained in:
Edouard DUPIN 2016-10-06 21:02:30 +02:00
parent f0fd073a24
commit bc4c8e2551
3 changed files with 160 additions and 77 deletions

View File

@ -50,9 +50,9 @@ etk::archive::Zip::Zip(const std::string& _fileName, uint64_t _offset) :
} }
etk::archive::Zip::~Zip() { etk::archive::Zip::~Zip() {
if (m_ctx!= NULL) { if (m_ctx!= nullptr) {
unzClose(m_ctx); unzClose(m_ctx);
m_ctx = NULL; m_ctx = nullptr;
}; };
} }
@ -66,7 +66,7 @@ void etk::archive::Zip::loadFile(const std::map<std::string, ArchiveContent>::it
char tmpFileName[FILENAME_MAX]; char tmpFileName[FILENAME_MAX];
unz_file_info tmpFileInfo; unz_file_info tmpFileInfo;
/* Get info about current file. */ /* Get info about current file. */
if(unzGetCurrentFileInfo(m_ctx, &tmpFileInfo, tmpFileName, FILENAME_MAX, NULL, 0, NULL, 0) != UNZ_OK) { if(unzGetCurrentFileInfo(m_ctx, &tmpFileInfo, tmpFileName, FILENAME_MAX, nullptr, 0, nullptr, 0) != UNZ_OK) {
TK_ERROR("Could not read file info from the zip file '" << m_fileName << "'"); TK_ERROR("Could not read file info from the zip file '" << m_fileName << "'");
return; return;
} }
@ -80,19 +80,19 @@ void etk::archive::Zip::loadFile(const std::map<std::string, ArchiveContent>::it
// request the resize of the data : // request the resize of the data :
it->second.getDataVector().resize(it->second.getTheoricSize(), 0); it->second.getDataVector().resize(it->second.getTheoricSize(), 0);
void* data = it->second.data(); void* data = it->second.data();
if(NULL == data) { if(data == nullptr) {
TK_ERROR("Allocation error..."); TK_ERROR("Allocation error...");
return; return;
} }
/* read the file */ /* read the file */
do { do {
error = unzReadCurrentFile(m_ctx, data, it->second.getTheoricSize()); error = unzReadCurrentFile(m_ctx, data, it->second.getTheoricSize());
if ( error < 0 ) { if (error < 0) {
TK_ERROR("Could not read file '" << tmpFileName << "' into the zip file '" << m_fileName << "': " << error); TK_ERROR("Could not read file '" << tmpFileName << "' into the zip file '" << m_fileName << "': " << error);
unzCloseCurrentFile(m_ctx); unzCloseCurrentFile(m_ctx);
return; return;
} }
} while ( error > 0 ); } while (error > 0);
//((char*)data)[m_content.GetValue(_id).GetTheoricSize()] = '\0'; //((char*)data)[m_content.GetValue(_id).GetTheoricSize()] = '\0';
// stop searching here // stop searching here
unzCloseCurrentFile(m_ctx); unzCloseCurrentFile(m_ctx);

View File

@ -122,6 +122,97 @@ std::string etk::simplifyPath(std::string _input) {
TK_DEBUG("Simplify(end) : '" << _input << "'"); TK_DEBUG("Simplify(end) : '" << _input << "'");
return _input; return _input;
} }
static int32_t FSNODE_LOCAL_mkdir(const char* _path, mode_t _mode) {
struct stat st;
int32_t status = 0;
if (stat(_path, &st) != 0) {
/* Directory does not exist. EEXIST for race condition */
#ifdef __TARGET_OS__Windows
if(0!=mkdir(_path)
#else
if(0!=mkdir(_path, _mode)
#endif
&& errno != EEXIST) {
status = -1;
}
} else if (!S_ISDIR(st.st_mode)) {
errno = ENOTDIR;
status = -1;
}
return(status);
}
static int32_t FSNODE_LOCAL_mkPath(const char* _path, mode_t _mode) {
char *pp;
char *sp;
int status;
char *copypath = strdup(_path);
if (nullptr==copypath) {
return -1;
}
status = 0;
pp = copypath;
while (status == 0 && (sp = strchr(pp, '/')) != 0) {
if (sp != pp) {
/* Neither root nor double slash in path */
*sp = '\0';
status = FSNODE_LOCAL_mkdir(copypath, _mode);
*sp = '/';
}
pp = sp + 1;
}
if (status == 0) {
status = FSNODE_LOCAL_mkdir(_path, _mode);
}
free(copypath);
return (status);
}
static bool FSNODE_LOCAL_exist(const std::string& _path) {
struct stat st;
int32_t status = 0;
if (stat(_path.c_str(), &st) != 0) {
return false;
}
return true;
}
static bool FSNODE_LOCAL_isDirectory(const std::string& _path) {
struct stat st;
int32_t status = 0;
if (stat(_path.c_str(), &st) != 0) {
return false;
} else if (!S_ISDIR(st.st_mode)) {
return false;
}
return true;
}
static bool FSNODE_LOCAL_isFile(const std::string& _path) {
struct stat st;
int32_t status = 0;
if (stat(_path.c_str(), &st) != 0) {
return false;
} else if (!S_ISREG(st.st_mode)) {
return false;
}
return true;
}
static std::string FSNODE_LOCAL_join(const std::string& _path1, const std::string& _path2) {
std::string out = etk::replace(_path1, '\\', '/');
if (out.size() == 0) {
out = etk::replace(_path2, '\\', '/');;
return out;
}
if (_path2.size() == 0) {
return out;
}
if (out[out.size()-1] != '/') {
out += "/";
}
out += etk::replace(_path2, '\\', '/');;
return out;
}
static std::mutex& getNodeMutex() { static std::mutex& getNodeMutex() {
static std::mutex g_nodeMutex; static std::mutex g_nodeMutex;
@ -156,18 +247,34 @@ std::string etk::FSNodeGetApplicationName() {
#ifdef HAVE_ZIP_DATA #ifdef HAVE_ZIP_DATA
static etk::Archive* s_APKArchive = nullptr; static etk::Archive* s_APKArchive = nullptr;
static void loadAPK(std::string& _apkPath) { static void loadAPK(const std::string& _apkPath) {
std::unique_lock<std::mutex> lock(getNodeMutex());
TK_INFO("Loading APK \"" << _apkPath << "\"");
#ifdef __TARGET_OS__Android #ifdef __TARGET_OS__Android
std::unique_lock<std::mutex> lock(getNodeMutex());
TK_INFO("Loading APK '" << _apkPath << "'");
s_APKArchive = etk::Archive::load(_apkPath); s_APKArchive = etk::Archive::load(_apkPath);
TK_ASSERT(s_APKArchive != nullptr, "Error loading APK ... '" << _apkPath << "'");
#else #else
s_APKArchive = etk::Archive::loadPackage(_apkPath); TK_INFO("Loading Intarnal data '" << _apkPath << "'");
//s_APKArchive = etk::Archive::loadPackage(_apkPath);
s_APKArchive = etk::Archive::load(_apkPath);
TK_ASSERT(s_APKArchive != nullptr, "Error loading PKG ... '" << _apkPath << "'");
#endif #endif
TK_ASSERT(s_APKArchive != nullptr, "Error loading APK ... \"" << _apkPath << "\""); #ifdef DEBUG
//Just for debug, print APK contents //Just for debug, print APK contents
s_APKArchive->display(); s_APKArchive->display();
#endif
} }
#ifdef __TARGET_OS__Windows
static void loadAPKBin(const std::string& _apkPath) {
TK_ERROR("Loading Intarnal data '" << _apkPath << "'");
s_APKArchive = etk::Archive::loadPackage(_apkPath);
TK_ASSERT(s_APKArchive != nullptr, "Error loading PKG ... '" << _apkPath << "'");
#ifdef DEBUG
//Just for debug, print APK contents
s_APKArchive->display();
#endif
}
#endif
#endif #endif
// for specific device contraint : // for specific device contraint :
@ -237,13 +344,10 @@ std::string getApplicationPath() {
memset(binaryCompleatePath, 0, FILENAME_MAX); memset(binaryCompleatePath, 0, FILENAME_MAX);
#ifdef __TARGET_OS__Windows #ifdef __TARGET_OS__Windows
GetModuleFileName(nullptr, binaryCompleatePath, FILENAME_MAX); GetModuleFileName(nullptr, binaryCompleatePath, FILENAME_MAX);
if (0==strlen(binaryCompleatePath)) { if (strlen(binaryCompleatePath) == 0) {
TK_CRITICAL("Can not get the binary position in the tree ==> this is really bad ..."); TK_CRITICAL("Can not get the binary position in the tree ==> this is really bad ...");
} else { } else {
binaryName = binaryCompleatePath; binaryName = binaryCompleatePath;
#ifdef HAVE_ZIP_DATA
loadAPK(binaryName);
#endif
} }
#else #else
// check it to prevent test mode in local folder ... // check it to prevent test mode in local folder ...
@ -344,15 +448,39 @@ void etk::initDefaultFolder(const char* _applName) {
TK_DBG_MODE("Find Basic running PATH : '" << baseRunPath << "'"); TK_DBG_MODE("Find Basic running PATH : '" << baseRunPath << "'");
#ifndef __TARGET_OS__Android #ifndef __TARGET_OS__Android
std::string binaryPath = getApplicationPath(); std::string binaryPath = getApplicationPath();
binaryPath = replace(binaryPath, '\\', '/'); binaryPath = etk::replace(binaryPath, '\\', '/');
size_t pos = binaryPath.rfind('/'); size_t pos = binaryPath.rfind('/');
std::string binaryName(binaryPath, pos); std::string binaryName(binaryPath, pos);
while( binaryName.size() >= 2
&& binaryName[1] == '/') {
binaryName = std::string(binaryName.begin()+1, binaryName.end());
}
binaryPath.erase(binaryPath.begin() + pos, binaryPath.end()); binaryPath.erase(binaryPath.begin() + pos, binaryPath.end());
TK_INFO("Bianry name : '" << binaryPath << "' && '" << binaryName << "'" ); TK_INFO("Bianry name : '" << binaryPath << "' && '" << binaryName << "'" );
#ifdef __TARGET_OS__Windows #ifdef __TARGET_OS__Windows
// check if we have a data path just near the .exe file
if ( FSNODE_LOCAL_exist(FSNODE_LOCAL_join(binaryPath,"data")) == true
&& FSNODE_LOCAL_isDirectory(FSNODE_LOCAL_join(binaryPath,"data")) == true) {
TK_INFO("Find data in external 'data' path");
baseFolderData = binaryPath; baseFolderData = binaryPath;
baseFolderData += "/data/"; baseFolderData += "/data/";
baseFolderData += std::string(binaryName.begin(), binaryName.end()-4); }
#ifdef HAVE_ZIP_DATA
// check if we have a data.zip just near the .exe file
else if ( FSNODE_LOCAL_exist(FSNODE_LOCAL_join(binaryPath,"data.zip")) == true
&& FSNODE_LOCAL_isFile(FSNODE_LOCAL_join(binaryPath,"data.zip")) == true) {
TK_INFO("Find data in external data.zip file");
loadAPK(FSNODE_LOCAL_join(binaryPath,"data.zip"));
baseFolderData = "";
}
// check if the application named .pkg.exe (this mean the data is inside the executable as a zip next the binary)
else if (etk::end_with(binaryName, ".pkg.exe") == true) {
TK_INFO("Find data in external internal exe package");
loadAPKBin(FSNODE_LOCAL_join(binaryPath,binaryName));
baseFolderData = "";
}
#endif
baseFolderData += std::string(binaryName.begin()+1, binaryName.end()-4);
baseFolderData += "/"; baseFolderData += "/";
baseFolderDataUser = binaryPath; baseFolderDataUser = binaryPath;
@ -472,54 +600,6 @@ bool etk::FSNode::loadDataZip() {
#endif #endif
static int32_t FSNODE_LOCAL_mkdir(const char* _path, mode_t _mode) {
struct stat st;
int32_t status = 0;
if (stat(_path, &st) != 0) {
/* Directory does not exist. EEXIST for race condition */
#ifdef __TARGET_OS__Windows
if(0!=mkdir(_path)
#else
if(0!=mkdir(_path, _mode)
#endif
&& errno != EEXIST) {
status = -1;
}
} else if (!S_ISDIR(st.st_mode)) {
errno = ENOTDIR;
status = -1;
}
return(status);
}
static int32_t FSNODE_LOCAL_mkPath(const char* _path, mode_t _mode) {
char *pp;
char *sp;
int status;
char *copypath = strdup(_path);
if (nullptr==copypath) {
return -1;
}
status = 0;
pp = copypath;
while (status == 0 && (sp = strchr(pp, '/')) != 0) {
if (sp != pp) {
/* Neither root nor double slash in path */
*sp = '\0';
status = FSNODE_LOCAL_mkdir(copypath, _mode);
*sp = '/';
}
pp = sp + 1;
}
if (status == 0) {
status = FSNODE_LOCAL_mkdir(_path, _mode);
}
free(copypath);
return (status);
}
etk::FSNode::FSNode(const std::string& _nodeName) : etk::FSNode::FSNode(const std::string& _nodeName) :
m_userFileName(""), m_userFileName(""),
m_type(etk::FSNType_unknow), m_type(etk::FSNType_unknow),
@ -593,7 +673,7 @@ void etk::FSNode::privateSetName(std::string _newName) {
|| nullptr != m_zipContent || nullptr != m_zipContent
#endif #endif
) { ) {
TK_ERROR("Missing to close the file : \"" << *this << "\""); TK_ERROR("Missing to close the file : '" << *this << "'");
fileClose(); fileClose();
} }
// set right at nullptr ... // set right at nullptr ...
@ -831,7 +911,7 @@ void etk::FSNode::generateFileSystemPath() {
break; break;
case etk::FSNType_data: case etk::FSNType_data:
{ {
TK_DBG_MODE("DATA lib : \"" << m_libSearch << "\" => \"" << m_userFileName << "\" forceLib = " << forceLibFolder); TK_DBG_MODE("DATA lib : '" << m_libSearch << "' => '" << m_userFileName << "' forceLib = " << forceLibFolder);
// search the correct folder: // search the correct folder:
if (forceLibFolder == false) { if (forceLibFolder == false) {
// check in the application folder. // check in the application folder.
@ -923,12 +1003,12 @@ void etk::FSNode::generateFileSystemPath() {
} }
// check in the user data : // check in the user data :
m_systemFileName = simplifyPath(baseFolderDataUser + "/../" + m_libSearch + "/theme/" + themeNameDefault + "/" + basicName); m_systemFileName = simplifyPath(baseFolderDataUser + "/../" + m_libSearch + "/theme/" + themeNameDefault + "/" + basicName);
if (true==directCheckFile(m_systemFileName)) { if (directCheckFile(m_systemFileName) == true) {
return; return;
} }
// check in the Appl data : In every case we return this one ... // check in the Appl data : In every case we return this one ...
m_systemFileName = simplifyPath(baseFolderData + "/../" + m_libSearch + "/theme/" + themeNameDefault + "/" + basicName); m_systemFileName = simplifyPath(baseFolderData + "/../" + m_libSearch + "/theme/" + themeNameDefault + "/" + basicName);
if (true==directCheckFile(m_systemFileName, true)) { if (directCheckFile(m_systemFileName, true) == true) {
m_type = etk::FSNType_themeData; m_type = etk::FSNType_themeData;
return; return;
} }
@ -966,7 +1046,7 @@ void etk::FSNode::updateFileSystemProperty() {
// = Check if it was a folder : = // = Check if it was a folder : =
// ---------------------------------------- // ----------------------------------------
std::string folderName = "/"; std::string folderName = "/";
if (true == end_with(m_systemFileName, folderName)) { if (etk::end_with(m_systemFileName, folderName) == true) {
folderName = m_systemFileName; folderName = m_systemFileName;
} else { } else {
folderName = m_systemFileName + "/"; folderName = m_systemFileName + "/";
@ -1473,12 +1553,15 @@ std::vector<etk::FSNode *> etk::FSNode::folderGetSubList(bool _showHidenFile, bo
for (int iii=0; iii<s_APKArchive->size(); iii++) { for (int iii=0; iii<s_APKArchive->size(); iii++) {
std::string filename = s_APKArchive->getName(iii); std::string filename = s_APKArchive->getName(iii);
if (start_with(filename, FolderName) == true) { if (start_with(filename, FolderName) == true) {
std::string tmpString(filename, FolderName.size()+1); //TK_INFO("pppppp '" << filename << "'");
//TK_INFO(" '" << FolderName << "'");
std::string tmpString(filename, FolderName.size());
size_t pos = tmpString.find('/'); size_t pos = tmpString.find('/');
if (pos != std::string::npos) { if (pos != std::string::npos) {
// a simple folder : // a simple folder :
tmpString = std::string(tmpString, 0, pos); tmpString = std::string(tmpString, 0, pos);
} }
//TK_INFO("plop '" << getName() << "' '" << tmpString << "'");
tmpString = getName() + tmpString; tmpString = getName() + tmpString;
bool findIt = false; bool findIt = false;
for (size_t jjj = 0; jjj < listAdded.size(); ++jjj) { for (size_t jjj = 0; jjj < listAdded.size(); ++jjj) {

View File

@ -20,11 +20,11 @@
#ifdef __TARGET_OS__Android #ifdef __TARGET_OS__Android
#define HAVE_ZIP_DATA #define HAVE_ZIP_DATA
#endif #endif
/*
#ifdef __TARGET_OS__Windows #ifdef __TARGET_OS__Windows
#define HAVE_ZIP_DATA #define HAVE_ZIP_DATA
#endif #endif
*/
#ifdef HAVE_ZIP_DATA #ifdef HAVE_ZIP_DATA
namespace etk { namespace etk {