From f75253148e66b25144457670bfb05a6dc603f5cd Mon Sep 17 00:00:00 2001 From: kervala Date: Sat, 23 Jan 2016 12:30:01 +0100 Subject: [PATCH] Changed: Use CBigFile to manage BNP and CCmdArgs for command-line in bnp_make --- code/nel/tools/misc/bnp_make/main.cpp | 537 +++++--------------------- 1 file changed, 95 insertions(+), 442 deletions(-) diff --git a/code/nel/tools/misc/bnp_make/main.cpp b/code/nel/tools/misc/bnp_make/main.cpp index a3f34a6a4..edab782b0 100644 --- a/code/nel/tools/misc/bnp_make/main.cpp +++ b/code/nel/tools/misc/bnp_make/main.cpp @@ -32,6 +32,8 @@ #include "nel/misc/path.h" #include "nel/misc/algo.h" #include "nel/misc/common.h" +#include "nel/misc/big_file.h" +#include "nel/misc/cmd_args.h" using namespace std; @@ -49,7 +51,7 @@ std::vector WildCards; // --------------------------------------------------------------------------- -bool keepFile (const char *fileName) +bool keepFile (const std::string &fileName) { uint i; bool ifPresent = false; @@ -60,13 +62,13 @@ bool keepFile (const char *fileName) if (WildCards[i].Not) { // One ifnot condition met and the file is not added - if (testWildCard(file.c_str(), WildCards[i].Expression.c_str())) + if (testWildCard(file, WildCards[i].Expression)) return false; } else { ifPresent = true; - ifTrue |= testWildCard(file.c_str(), WildCards[i].Expression.c_str()); + ifTrue |= testWildCard(file, WildCards[i].Expression); } } @@ -75,199 +77,7 @@ bool keepFile (const char *fileName) // --------------------------------------------------------------------------- -struct BNPFile -{ - string Name; - uint32 Size; - uint32 Pos; -}; - -struct BNPHeader -{ - vector 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(); - - // value to be serialized - uint32 nNbFile2 = nNbFile; - -#ifdef NL_BIG_ENDIAN - NLMISC_BSWAP32(nNbFile2); -#endif - - if (fwrite (&nNbFile2, sizeof(uint32), 1, f) != 1) - { - fclose(f); - return false; - } - - for (uint32 i = 0; i < nNbFile; ++i) - { - uint8 nStringSize = (uint8)Files[i].Name.size(); - if (fwrite (&nStringSize, 1, 1, f) != 1) - { - fclose(f); - return false; - } - - if (fwrite (Files[i].Name.c_str(), 1, nStringSize, f) != nStringSize) - { - fclose(f); - return false; - } - - uint32 nFileSize = Files[i].Size; - -#ifdef NL_BIG_ENDIAN - NLMISC_BSWAP32(nFileSize); -#endif - - if (fwrite (&nFileSize, sizeof(uint32), 1, f) != 1) - { - fclose(f); - return false; - } - - uint32 nFilePos = Files[i].Pos; - -#ifdef NL_BIG_ENDIAN - NLMISC_BSWAP32(nFilePos); -#endif - - if (fwrite (&nFilePos, sizeof(uint32), 1, f) != 1) - { - fclose(f); - return false; - } - } - - uint32 nOffsetFromBeginning = OffsetFromBeginning; - -#ifdef NL_BIG_ENDIAN - NLMISC_BSWAP32(nOffsetFromBeginning); -#endif - - if (fwrite (&nOffsetFromBeginning, sizeof(uint32), 1, f) != 1) - { - fclose(f); - return false; - } - - 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 nOffsetFromBeginning; - if (fread (&nOffsetFromBeginning, sizeof(uint32), 1, f) != 1) - { - fclose (f); - return false; - } - -#ifdef NL_BIG_ENDIAN - NLMISC_BSWAP32(nOffsetFromBeginning); -#endif - - if (nlfseek64 (f, nOffsetFromBeginning, SEEK_SET) != 0) - { - fclose (f); - return false; - } - - uint32 nNbFile; - if (fread (&nNbFile, sizeof(uint32), 1, f) != 1) - { - fclose (f); - return false; - } - -#ifdef NL_BIG_ENDIAN - NLMISC_BSWAP32(nNbFile); -#endif - - for (uint32 i = 0; i < nNbFile; ++i) - { - uint8 nStringSize; - char sName[256]; - if (fread (&nStringSize, 1, 1, f) != 1) - { - fclose (f); - return false; - } - if (fread (sName, 1, nStringSize, f) != nStringSize) - { - fclose (f); - return false; - } - sName[nStringSize] = 0; - BNPFile tmpBNPFile; - tmpBNPFile.Name = sName; - if (fread (&tmpBNPFile.Size, sizeof(uint32), 1, f) != 1) - { - fclose (f); - return false; - } - -#ifdef NL_BIG_ENDIAN - NLMISC_BSWAP32(tmpBNPFile.Size); -#endif - - if (fread (&tmpBNPFile.Pos, sizeof(uint32), 1, f) != 1) - { - fclose (f); - return false; - } - -#ifdef NL_BIG_ENDIAN - NLMISC_BSWAP32(tmpBNPFile.Pos); -#endif - - 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]; - if (fread (ptr, sizeToRead, 1, f2) != 1) - nlwarning("%s read error", filename2.c_str()); - if (fwrite (ptr, sizeToRead, 1, f1) != 1) - nlwarning("%s write error", filename1.c_str()); - delete [] ptr; - - fclose(f2); - fclose(f1); -} +NLMISC::CBigFile::BNP gBNPHeader; // --------------------------------------------------------------------------- bool i_comp(const string &s0, const string &s1) @@ -275,35 +85,24 @@ bool i_comp(const string &s0, const string &s1) return nlstricmp (CFile::getFilename(s0).c_str(), CFile::getFilename(s1).c_str()) < 0; } -void packSubRecurse () +void packSubRecurse(const std::string &srcDirectory) { vector pathContent; - string cp = CPath::getCurrentPath(); - printf ("Treating directory : %s\n", cp.c_str()); - CPath::getPathContent(cp, true, false, true, pathContent); + printf ("Treating directory: %s\n", srcDirectory.c_str()); + CPath::getPathContent(srcDirectory, true, false, true, pathContent); + + // TODO: remove duplicate files // 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 = toLower(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 = toLower(string(ppArgs[i+1])); - card.Not = true; - WildCards.push_back (card); - optionCount += 2; - } - } - return optionCount; -} - -// --------------------------------------------------------------------------- -int main (int nNbArg, char **ppArgs) +int main(int argc, char **argv) { NLMISC::CApplicationContext myApplicationContext; - if (nNbArg < 3) + NLMISC::CCmdArgs args; + + args.addArg("p", "pack", "", "Pack the directory to a BNP file"); + args.addArg("u", "unpack", "", "Unpack the BNP file to a directory"); + args.addArg("l", "list", "", "List the files contained in the BNP file"); + args.addArg("o", "output", "destination", "Output directory or file"); + args.addArg("i", "if", "wildcard", "Add the file if it matches the wilcard (at least one 'if' conditions must be met for a file to be adding)"); + args.addArg("n", "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)"); + args.addAdditionalArg("input", "Input directory or BNP file depending on command"); + + if (!args.parse(argc, argv)) return 1; + + if (args.haveArg("p")) { - usage(); - return -1; - } + std::vector filters; + + // If ? + filters = args.getLongArg("if"); - 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) + for (uint i = 0; i < filters.size(); ++i) { - // store current path - sCurDir = CPath::getCurrentPath(); + CWildCard card; + card.Expression = toLower(filters[i]); + card.Not = false; + WildCards.push_back(card); + } - // go to the dest path - string sDestDir; - if (CPath::setCurrentPath(ppArgs[3])) + // If not ? + filters = args.getLongArg("ifnot"); + + for (uint i = 0; i < filters.size(); ++i) + { + CWildCard card; + card.Expression = toLower(filters[i]); + card.Not = true; + WildCards.push_back(card); + } + + // Pack a directory + std::string srcDirectory = args.getAdditionalArg("input").front(); + + if (!CFile::isDirectory(srcDirectory) || !CFile::isExists(srcDirectory)) + { + nlwarning("Error: %s doesn't exist or is not a directory!", srcDirectory.c_str()); + } + + // Output directory or filename + if (args.haveArg("o")) + { + gBNPHeader.BigFileName = args.getArg("o").front(); + + if (CFile::isDirectory(gBNPHeader.BigFileName)) { - 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) : can't set current directory to %s", ppArgs[2]); - return -1; - } - } - else - { - nlwarning ("ERROR (bnp_make) : can't set current directory to %s", ppArgs[3]); - return -1; + gBNPHeader.BigFileName = CPath::standardizePath(gBNPHeader.BigFileName) + CFile::getFilename(srcDirectory); } } else { - if (chdir (ppArgs[2]) == -1) - { - nlwarning ("ERROR (bnp_make) : can't set current directory to %s", ppArgs[2]); - return -1; - } - //getcwd (sCurDir, MAX_PATH); - gDestBNPFile = CPath::getCurrentPath() + string(".bnp"); + gBNPHeader.BigFileName = CFile::getFilename(srcDirectory); } - - remove (gDestBNPFile.c_str()); - gBNPHeader.OffsetFromBeginning = 0; - packSubRecurse(); - gBNPHeader.append (gDestBNPFile); - return 0; + + if (CFile::getExtension(gBNPHeader.BigFileName) != "bnp") + gBNPHeader.BigFileName += ".bnp"; + + CFile::deleteFile(gBNPHeader.BigFileName); + + packSubRecurse(srcDirectory); + return gBNPHeader.appendHeader() ? 0:-1; } - if ((strcmp(ppArgs[1], "/u") == 0) || (strcmp(ppArgs[1], "/U") == 0) || - (strcmp(ppArgs[1], "-u") == 0) || (strcmp(ppArgs[1], "-U") == 0)) + if (args.haveArg("u")) { - 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) : 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; + gBNPHeader.BigFileName = args.getAdditionalArg("input").front(); - //mkdir (dirName.c_str()); - CFile::createDirectory(dirName); + std::string dirName; - unpack (dirName); - - return 0; - } - - 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)) + // Output directory or filename + if (args.haveArg("o")) { - 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) : can't set current directory to %s", path.c_str()); - return -1; - } + dirName = args.getArg("o").front(); } - if (stricmp (gDestBNPFile.c_str()+gDestBNPFile.size()-4, ".bnp") != 0) + else { - gDestBNPFile += ".bnp"; + dirName = CFile::getFilenameWithoutExtension(gBNPHeader.BigFileName); } - string dirName; - for (i = 0; i < gDestBNPFile.size()-4; ++i) - dirName += gDestBNPFile[i]; // Unpack a bnp file - if (!gBNPHeader.read (gDestBNPFile)) - return -1; + return gBNPHeader.unpack(dirName) ? 0:-1; + } - for (i = 0; i < gBNPHeader.Files.size(); ++i) - printf ("%s\n", gBNPHeader.Files[i].Name.c_str()); + if (args.haveArg("l")) + { + gBNPHeader.BigFileName = args.getAdditionalArg("input").front(); + + // Read header of BNP file + if (!gBNPHeader.readHeader()) return -1; + + for (uint i = 0; i < gBNPHeader.SFiles.size(); ++i) + { + printf("%s\n", gBNPHeader.SFiles[i].Name.c_str()); + } return 0; } - usage (); + args.displayHelp(); return -1; }