// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/> // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. #include "nel/misc/types_nl.h" #include <stdio.h> #include <stdlib.h> #ifdef NL_OS_WINDOWS # include <io.h> # include <direct.h> #endif #include <vector> #include <string> #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" #include "nel/misc/big_file.h" #include "nel/misc/cmd_args.h" using namespace std; using namespace NLMISC; // --------------------------------------------------------------------------- class CWildCard { public: string Expression; bool Not; }; std::vector<CWildCard> WildCards; // --------------------------------------------------------------------------- bool keepFile (const std::string &fileName) { uint i; bool ifPresent = false; bool ifTrue = false; string file = toLower(CFile::getFilename (fileName)); for (i=0; i<WildCards.size(); i++) { if (WildCards[i].Not) { // One ifnot condition met and the file is not added if (testWildCard(file, WildCards[i].Expression)) return false; } else { ifPresent = true; ifTrue |= testWildCard(file, WildCards[i].Expression); } } return !ifPresent || ifTrue; } // --------------------------------------------------------------------------- NLMISC::CBigFile::BNP gBNPHeader; // --------------------------------------------------------------------------- bool i_comp(const string &s0, const string &s1) { return nlstricmp (CFile::getFilename(s0).c_str(), CFile::getFilename(s1).c_str()) < 0; } void packSubRecurse(const std::string &srcDirectory) { vector<string> pathContent; printf ("Treating directory: %s\n", srcDirectory.c_str()); CPath::getPathContent(srcDirectory, true, false, true, pathContent); if (pathContent.empty()) return; // Sort filename sort (pathContent.begin(), pathContent.end(), i_comp); // check for files with same name for(uint i = 1, len = pathContent.size(); i < len; ++i) { if (toLower(CFile::getFilename(pathContent[i-1])) == toLower(CFile::getFilename(pathContent[i]))) { nlerror("File %s is not unique in BNP!", CFile::getFilename(pathContent[i]).c_str()); return; } } for (uint i=0; i<pathContent.size(); ++i) { if (keepFile(pathContent[i])) { if (gBNPHeader.appendFile(pathContent[i])) { printf("Adding %s\n", pathContent[i].c_str()); } else { printf("Error: cannot open %s\n", pathContent[i].c_str()); } } } } // --------------------------------------------------------------------------- int main(int argc, char **argv) { NLMISC::CApplicationContext myApplicationContext; 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)", false); 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)", false); args.addAdditionalArg("input", "Input directory or BNP file depending on command"); if (!args.parse(argc, argv)) return 1; if (args.haveArg("p")) { std::vector<std::string> filters; // If ? filters = args.getLongArg("if"); for (uint i = 0; i < filters.size(); ++i) { CWildCard card; card.Expression = toLower(filters[i]); card.Not = false; WildCards.push_back(card); } // 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)) { gBNPHeader.BigFileName = CPath::standardizePath(gBNPHeader.BigFileName) + CFile::getFilename(srcDirectory); } } else { gBNPHeader.BigFileName = CFile::getFilename(srcDirectory); } if (CFile::getExtension(gBNPHeader.BigFileName) != "bnp") gBNPHeader.BigFileName += ".bnp"; CFile::deleteFile(gBNPHeader.BigFileName); packSubRecurse(srcDirectory); return gBNPHeader.appendHeader() ? 0:-1; } if (args.haveArg("u")) { gBNPHeader.BigFileName = args.getAdditionalArg("input").front(); std::string dirName; // Output directory or filename if (args.haveArg("o")) { dirName = args.getArg("o").front(); } else { dirName = CFile::getFilenameWithoutExtension(gBNPHeader.BigFileName); } // Unpack a bnp file return gBNPHeader.unpack(dirName) ? 0:-1; } 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; } args.displayHelp(); return -1; }