#include "nel/misc/types_nl.h" #include #include #ifdef NL_OS_WINDOWS # include # include #endif #include #include #include "nel/misc/debug.h" #include "nel/misc/file.h" #include "nel/misc/path.h" #include "nel/misc/algo.h" #include "nel/misc/common.h" using namespace std; using namespace NLMISC; // --------------------------------------------------------------------------- class CWildCard { public: string Expression; bool Not; }; std::vector WildCards; // --------------------------------------------------------------------------- bool keepFile (const char *fileName) { uint i; bool ifPresent = false; bool ifTrue = false; string file = strlwr(CFile::getFilename (fileName)); for (i=0; i Files; uint32 OffsetFromBeginning; // Append the header to the big file bool append (const string &filename) { FILE *f = fopen (filename.c_str(), "ab"); if (f == NULL) return false; uint32 nNbFile = (uint32)Files.size(); fwrite (&nNbFile, sizeof(uint32), 1, f); for (uint32 i = 0; i < nNbFile; ++i) { uint8 nStringSize = (uint8)Files[i].Name.size(); fwrite (&nStringSize, 1, 1, f); fwrite (Files[i].Name.c_str(), 1, nStringSize, f); fwrite (&Files[i].Size, sizeof(uint32), 1, f); fwrite (&Files[i].Pos, sizeof(uint32), 1, f); } fwrite (&OffsetFromBeginning, sizeof(uint32), 1, f); fclose (f); return true; } // Read the header from a big file bool read (const string &filename) { FILE *f = fopen (filename.c_str(), "rb"); if (f == NULL) return false; nlfseek64 (f, 0, SEEK_END); uint32 nFileSize=CFile::getFileSize (filename); nlfseek64 (f, nFileSize-sizeof(uint32), SEEK_SET); uint32 nOffsetFromBegining; fread (&nOffsetFromBegining, sizeof(uint32), 1, f); if (nlfseek64 (f, nOffsetFromBegining, SEEK_SET) != 0) return false; uint32 nNbFile; if (fread (&nNbFile, sizeof(uint32), 1, f) != 1) return false; for (uint32 i = 0; i < nNbFile; ++i) { uint8 nStringSize; char sName[256]; if (fread (&nStringSize, 1, 1, f) != 1) return false; if (fread (sName, 1, nStringSize, f) != nStringSize) return false; sName[nStringSize] = 0; BNPFile tmpBNPFile; tmpBNPFile.Name = sName; if (fread (&tmpBNPFile.Size, sizeof(uint32), 1, f) != 1) return false; if (fread (&tmpBNPFile.Pos, sizeof(uint32), 1, f) != 1) return false; Files.push_back (tmpBNPFile); } fclose (f); return true; } }; string gDestBNPFile; BNPHeader gBNPHeader; // --------------------------------------------------------------------------- void append(const string &filename1, const string &filename2, uint32 sizeToRead) { FILE *f1 = fopen(filename1.c_str(), "ab"); FILE *f2 = fopen(filename2.c_str(), "rb"); if (f1 == NULL) return; if (f2 == NULL) { fclose(f1); return; } uint8 *ptr = new uint8[sizeToRead]; fread (ptr, sizeToRead, 1, f2); fwrite (ptr, sizeToRead, 1, f1); delete ptr; fclose(f2); fclose(f1); } // --------------------------------------------------------------------------- bool i_comp(const string &s0, const string &s1) { return nlstricmp (CFile::getFilename(s0).c_str(), CFile::getFilename(s1).c_str()) < 0; } void packSubRecurse () { vector pathContent; string cp = CPath::getCurrentPath(); printf ("Treating directory : %s\n", cp.c_str()); CPath::getPathContent(cp, true, false, true, pathContent); // Sort filename sort (pathContent.begin(), pathContent.end(), i_comp); uint i; for (i=0; i [] [] [option] ... [option]\n"); printf (" option : \n"); printf (" -if wildcard : add the file if it matches the wilcard (at least one 'if' conditions must be met for a file to be adding)\n"); printf (" -ifnot wildcard : add the file if it doesn't match the wilcard (all the 'ifnot' conditions must be met for a file to be adding)\n"); printf (" Pack the directory to a bnp file\n"); printf (" bnp_make /u \n"); printf (" Unpack the bnp file to a directory\n"); printf (" bnp_make /l \n"); printf (" List the files contained in the bnp file\n"); } // --------------------------------------------------------------------------- uint readOptions (int nNbArg, char **ppArgs) { uint i; uint optionCount = 0; for (i=0; i<(uint)nNbArg; i++) { // If ? if ((strcmp (ppArgs[i], "-if") == 0) && ((i+1)<(uint)nNbArg)) { CWildCard card; card.Expression = strlwr(string(ppArgs[i+1])); card.Not = false; WildCards.push_back (card); optionCount += 2; } // If not ? if ((strcmp (ppArgs[i], "-ifnot") == 0) && ((i+1)<(uint)nNbArg)) { CWildCard card; card.Expression = strlwr(string(ppArgs[i+1])); card.Not = true; WildCards.push_back (card); optionCount += 2; } } return optionCount; } // --------------------------------------------------------------------------- int main (int nNbArg, char **ppArgs) { NLMISC::CApplicationContext myApplicationContext; if (nNbArg < 3) { usage(); return -1; } if ((strcmp(ppArgs[1], "/p") == 0) || (strcmp(ppArgs[1], "/P") == 0) || (strcmp(ppArgs[1], "-p") == 0) || (strcmp(ppArgs[1], "-P") == 0)) { // Pack a directory uint count = readOptions (nNbArg, ppArgs); nNbArg -= count; // Read options string sCurDir; if (nNbArg >= 4) { // store current path sCurDir = CPath::getCurrentPath(); // go to the dest path string sDestDir; if (CPath::setCurrentPath(ppArgs[3])) { sDestDir = CPath::getCurrentPath(); bool tmp = CPath::setCurrentPath(sCurDir.c_str()); // restore current path, should not failed nlassert (tmp); // removed in release // go to the source dir if (CPath::setCurrentPath(ppArgs[2])) { sCurDir = CPath::getCurrentPath(); gDestBNPFile = CPath::standardizePath(sDestDir); if(nNbArg == 5) { gDestBNPFile += ppArgs[4]; // add ext if necessary if (string(ppArgs[4]).find(".") == string::npos) gDestBNPFile += string(".bnp"); } else { const char *pos = strrchr (sCurDir.c_str(), '/'); if (pos != NULL) { gDestBNPFile += string(pos+1); } // get the dest file name gDestBNPFile += string(".bnp"); } } else { nlwarning ("ERROR (bnp_make.exe) : can't set current directory to %s", ppArgs[2]); return -1; } } else { nlwarning ("ERROR (bnp_make.exe) : can't set current directory to %s", ppArgs[3]); return -1; } } else { if (chdir (ppArgs[2]) == -1) { nlwarning ("ERROR (bnp_make.exe) : can't set current directory to %s", ppArgs[2]); return -1; } //getcwd (sCurDir, MAX_PATH); gDestBNPFile = CPath::getCurrentPath() + string(".bnp"); } remove (gDestBNPFile.c_str()); gBNPHeader.OffsetFromBeginning = 0; packSubRecurse(); gBNPHeader.append (gDestBNPFile); return 1; } if ((strcmp(ppArgs[1], "/u") == 0) || (strcmp(ppArgs[1], "/U") == 0) || (strcmp(ppArgs[1], "-u") == 0) || (strcmp(ppArgs[1], "-U") == 0)) { string::size_type i; string path; gDestBNPFile = ppArgs[2]; if ((gDestBNPFile.rfind('/') != string::npos) || (gDestBNPFile.rfind('/') != string::npos)) { string::size_type pos = gDestBNPFile.rfind('/'); if (pos == string::npos) pos = gDestBNPFile.rfind('/'); for (i = 0; i <= pos; ++i) path += gDestBNPFile[i]; string wholeName = gDestBNPFile; gDestBNPFile = ""; for (; i < wholeName.size(); ++i) gDestBNPFile += wholeName[i]; if (CPath::setCurrentPath(path.c_str())) { path = CPath::getCurrentPath(); } else { nlwarning ("ERROR (bnp_make.exe) : can't set current directory to %s", path.c_str()); return -1; } } if (stricmp (gDestBNPFile.c_str()+gDestBNPFile.size()-4, ".bnp") != 0) { gDestBNPFile += ".bnp"; } string dirName; for (i = 0; i < gDestBNPFile.size()-4; ++i) dirName += gDestBNPFile[i]; // Unpack a bnp file if (!gBNPHeader.read (gDestBNPFile)) return -1; //mkdir (dirName.c_str()); CFile::createDirectory(dirName); unpack (dirName); return 1; } if ((strcmp(ppArgs[1], "/l") == 0) || (strcmp(ppArgs[1], "/L") == 0) || (strcmp(ppArgs[1], "-l") == 0) || (strcmp(ppArgs[1], "-L") == 0)) { string::size_type i; string path; gDestBNPFile = ppArgs[2]; if ((gDestBNPFile.rfind('/') != string::npos) || (gDestBNPFile.rfind('/') != string::npos)) { string::size_type pos = gDestBNPFile.rfind('/'); if (pos == string::npos) pos = gDestBNPFile.rfind('/'); for (i = 0; i <= pos; ++i) path += gDestBNPFile[i]; string wholeName = gDestBNPFile; gDestBNPFile = ""; for (; i < wholeName.size(); ++i) gDestBNPFile += wholeName[i]; if (CPath::setCurrentPath(path.c_str())) { path = CPath::getCurrentPath(); } else { nlwarning ("ERROR (bnp_make.exe) : can't set current directory to %s", path.c_str()); return -1; } } if (stricmp (gDestBNPFile.c_str()+gDestBNPFile.size()-4, ".bnp") != 0) { gDestBNPFile += ".bnp"; } string dirName; for (i = 0; i < gDestBNPFile.size()-4; ++i) dirName += gDestBNPFile[i]; // Unpack a bnp file if (!gBNPHeader.read (gDestBNPFile)) return -1; for (i = 0; i < gBNPHeader.Files.size(); ++i) printf ("%s\n", gBNPHeader.Files[i].Name.c_str()); return 1; } usage (); return -1; }