123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716 |
- //
- // Utility.cc
- //
- // Utility functions for BuildDistribution.
- //
- // (C) Copyright 2010 ARM Research Labs, LLC See
- // www.armresearch.com for the copyright terms.
- //
- // $Id$
- //
-
- #include <windows.h>
- #include <tchar.h>
-
- #include <string>
- #include <iostream>
- #include <stdexcept>
- #include <algorithm>
- #include <sstream>
- #include <iterator>
-
- #include "Utility.h"
-
- static DWORD LastError = 0; // Last value from GetLastError(). Needed because
- // GetLastError() doesn't return the correct value
- // after an exception is thrown.
-
- void
- OutputUsage(std::string DefaultTempPath) {
- std::cout <<
- "\n"
- "Usage:\n"
- "\n"
- " BuildDistribution -d DistPath -t TempPath\n"
- "\n"
- " where DistPath is the path of the distribution\n"
- " (e.g. SNFMultiSDK_Windows_3.1, and TempPath is the name of the\n"
- " directory to use for temporary storage. TempPath must exist.\n"
- " The default value of TempPath is '" << DefaultTempPath << "'.\n"
- ;
- }
-
- void
- OutputHelp() {
- std::cout <<
- "\n"
- "The program does the following:\n"
- "\n"
- " 1) For each directory DIR that appears in DistPath and also in\n"
- " DistPath\\..:\n"
- "\n"
- " a) Delete the contents of DistPath/DIR, except for .svn.\n"
- "\n"
- " b) Copy the contents of DistPath\\..\\DIR to DistPath\\DIR, except\n"
- " for .svn.\n"
- "\n"
- " 2) Create a temporary directory TempPath/DistName, where DistName is\n"
- " the directory name of DistPath (e.g. if DistName is\n"
- " c:\\dir1\\dir2\\SNFMultiSDK_Windows_3.1, then DistName is\n"
- " SNFMultiSDK_Windows_3.1).\n"
- "\n"
- " 3) For each directory DIR that appears in DistPath and also in\n"
- " DistPath\\..:\n"
- "\n"
- " a) Copy all files from DistPath/DIR to TempPath/DistName, except\n"
- " for .svn.\n\n"
- ;
-
- }
-
- void
- OutputErrorMessage(std::string Message) {
- LPVOID lpMsgBuf;
-
- if (LastError != 0) {
-
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- LastError,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf,
- 0,
- NULL);
- std::cerr << Message << ": " << (LPCSTR) lpMsgBuf;
-
- } else {
-
- std::cerr << Message << "\n";
-
- }
-
- }
-
- /// Case-insensitive search for a specified string in a container of strings.
- //
- // \param[in] Needle is the string to search for.
- //
- // \param[in] Haystack is the container of strings to search.
- //
- // \returns true if Needle is in Haystack (case-insensitive
- // comparison), false otherwise.
- //
- bool IsInContainer(std::string Needle, StringContainer Haystack);
-
- /// Get a list of directories in a specified path.
- //
- // This function returns a list of directories in the specified path,
- // excluding a specified list of names.
- //
- // \param[in] DistPath is the path to search.
- //
- // \param[in] ExcludeName contains the names to exclude.
- //
- // \returns a list of directory names in the specified path, excluding
- // names in ExcludeNames.
- //
- StringContainer GetDirectoryList(std::string DistPath,
- StringContainer ExcludeName);
-
- /// Get a list of files in a specified path.
- //
- // This function returns a list of files in the specified path,
- // excluding a specified list of names.
- //
- // \param[in] DistPath is the path to search.
- //
- // \param[in] ExcludeName contains the names to exclude.
- //
- // \returns a list of file names in the specified path,
- // excluding names in ExcludeNames.
- //
- StringContainer GetFileList(std::string DistPath,
- StringContainer ExcludeName);
-
- /// Update the files in one directory.
- //
- // \param[in] SourceDir is the name of the directory that contains the
- // files to copy from.
- //
- // \param[in] DestDir is the name of the directory to clear and copy
- // files to.
- //
- // \param[in] ExcludeName contains the names of the files to not
- // delete or copy.
- //
- // This function:
- //
- // 1) Deletes the files in DestDir, except for ExcludeName and directories.
- //
- // 2) If a directory in exists in both SourceDir and DestDir, then
- // update that directory by invoking UpdateCommonDirectories().
- //
- // 3) If a directory exists in DestDir but not in SourceDir, delete
- // that directory and all it's contents.
- //
- // 4) Copy the non-directory files SourceDir to DestDir, except for
- // ExcludeName.
- //
- void UpdateOneDirectory(std::string SourceDir,
- std::string DestDir,
- StringContainer ExcludeName);
-
- /// Delete a directory and all it's contents.
- //
- // This function recursively deletes the contents of a directory, and
- // then deletes the directory.
- //
- // \param[in] Path is the path to delete.
- //
- void DeletePath(std::string Path);
-
- void
- GetDirectoryNames(std::string &InputDistPath,
- std::string &DistSourcePath,
- std::string &DistParentPath,
- std::string &DistName) {
-
- DWORD RetVal = 0;
- TCHAR PathPart[MAX_PATH];
- LPTSTR FilePart = NULL;
-
- RetVal = GetFullPathName(InputDistPath.c_str(), // Get the path name for the source.
- MAX_PATH,
- PathPart,
- &FilePart);
- LastError = GetLastError();
- if (0 == RetVal) {
-
- throw(std::invalid_argument("Error determining directory names"));
-
- }
- DistSourcePath = PathPart;
-
- if ( (NULL != FilePart) && (0 != *FilePart) ) { // Extract the distribution name
- // (last component of the source path.
-
-
- DistName = FilePart;
-
- } else {
-
- throw(std::invalid_argument("Unable to determine distribution name"));
-
- }
-
- std::string::size_type DistNameIndex; // Get the parent directory of the
- // source directory.
-
-
- DistNameIndex = DistSourcePath.rfind("\\");
- if (std::string::npos == DistNameIndex) {
-
- throw(std::invalid_argument("Unable to determine the name of the "
- "distribution parent directory"));
-
- }
-
- DistParentPath = DistSourcePath.substr(0, DistNameIndex);
-
- }
-
- bool
- IsInContainer(std::string Needle, StringContainer Haystack) {
-
- std::transform(Needle.begin(), Needle.end(), Needle.begin(), ::toupper);
-
- StringContainer::iterator iFile;
-
- for (iFile = Haystack.begin(); iFile != Haystack.end(); iFile++) { // Check each file in the container.
-
- std::transform(iFile->begin(), iFile->end(), iFile->begin(), ::toupper);
- if (*iFile == Needle) {
-
- return true;
-
- }
- }
-
- return false;
-
- }
-
-
- StringContainer
- GetDirectoryList(std::string DistPath, StringContainer ExcludeName) {
-
- DistPath += "\\*.*"; // Create filter string.
-
- WIN32_FIND_DATA FileData;
- HANDLE ListHandle;
- std::string FileName;
-
- ListHandle = FindFirstFile(DistPath.c_str(),
- &FileData);
-
- StringContainer DirName; // Container to hold directory
- // names of the distribution.
-
- if ( (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && // Is this a directory...
-
- (! IsInContainer(FileData.cFileName, ExcludeName)) ) { // ...and not an excluded file?
-
- DirName.push_back(FileData.cFileName); // Yes. Save the name.
-
- }
-
- while (true) {
-
- if (FindNextFile(ListHandle, &FileData)) {
-
- if ( (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && // Is this a directory...
-
- (! IsInContainer(FileData.cFileName, ExcludeName)) ) { // ...and not an excluded file?
-
- DirName.push_back(FileData.cFileName); // Yes. Save the name.
-
- }
-
- } else {
-
- LastError = GetLastError();
- if (ERROR_NO_MORE_FILES == LastError) {
-
- break;
-
- } else {
- std::ostringstream temp;
-
- temp << "Error determining directory list of '"
- << DistPath << "'";
- throw(std::runtime_error(temp.str()));
-
- }
- }
- }
-
- if (FindClose(ListHandle) == 0) {
- std::ostringstream Temp;
-
- LastError = GetLastError();
- Temp << "***Error closing handle for " << DistPath;
- throw(std::runtime_error(Temp.str()));
-
- }
-
- return DirName;
- }
-
- StringContainer
- GetFileList(std::string DirPath, StringContainer ExcludeName) {
-
- std::string DirPathFilter;
-
- DirPathFilter = DirPath + "\\*.*"; // Create filter string.
-
- WIN32_FIND_DATA FileData;
- HANDLE ListHandle;
-
- ListHandle = FindFirstFile(DirPathFilter.c_str(),
- &FileData);
-
- StringContainer FileNameList; // Container to hold file names.
- std::string FileName;
-
- if ( !(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && // Is this not a directory...
-
- (! IsInContainer(FileData.cFileName, ExcludeName)) ) { // ...and not an excluded file?
-
- FileNameList.push_back(FileData.cFileName); // Yes. Save the name.
-
- }
-
- while (true) {
-
- if (FindNextFile(ListHandle, &FileData)) {
-
- if ( !(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && // Is this not a directory...
-
- (! IsInContainer(FileData.cFileName, ExcludeName)) ) { // ...and not an excluded file?
-
- FileNameList.push_back(FileData.cFileName); // Yes. Save the name.
-
- }
-
- } else {
-
- LastError = GetLastError();
- if (ERROR_NO_MORE_FILES == LastError) {
-
- break;
-
- } else {
- std::ostringstream temp;
-
- temp << "Error determining directory list of '"
- << DirPath << "'";
- throw(std::runtime_error(temp.str()));
-
- }
- }
- }
-
- if (FindClose(ListHandle) == 0) {
- std::ostringstream Temp;
-
- LastError = GetLastError();
- Temp << "***Error closing handle for " << DirPath;
- throw(std::runtime_error(Temp.str()));
-
- }
-
- return FileNameList;
- }
-
- void
- UpdateOneDirectory(std::string SourceDir,
- std::string DestDir,
- StringContainer ExcludeName) {
-
- StringContainer DestDirFileList; // Files in DestDir.
-
-
- DestDirFileList = GetFileList(DestDir, ExcludeName);
-
- StringContainer::iterator iFile;
- std::string FileToDelete;
-
- for (iFile = DestDirFileList.begin(); // Remove the files.
- iFile != DestDirFileList.end();
- iFile++) {
-
- if (! IsInContainer(*iFile, ExcludeName)) { // Check if this file is in ExcludeName.
-
- FileToDelete = DestDir + "\\"; // It is not. Delete it.
- FileToDelete += *iFile;
- if (DeleteFile(FileToDelete.c_str()) == 0) {
- std::ostringstream Temp;
-
- LastError = GetLastError();
- Temp << "***Error deleting " << FileToDelete;
- throw(std::runtime_error(Temp.str()));
-
- }
- }
- }
-
- StringContainer SourceDirFileList; // Files in SourceDir.
- std::string SourceFile, DestFile;
-
- SourceDirFileList = GetFileList(SourceDir, ExcludeName);
- for (iFile = SourceDirFileList.begin(); // Copy the files from SourceDir.
- iFile != SourceDirFileList.end();
- iFile++) {
-
- if (! IsInContainer(*iFile, ExcludeName)) { // Check if this file is in ExcludeName.
-
- SourceFile = SourceDir + "\\"; // It is not. Copy it.
- SourceFile += *iFile;
- DestFile = DestDir + "\\";
- DestFile += *iFile;
- if (CopyFile(SourceFile.c_str(), DestFile.c_str(), true) == 0) {
- std::ostringstream Temp;
-
- LastError = GetLastError();
- Temp << "Error copying " << SourceFile << " to " << DestFile;
- throw(std::runtime_error(Temp.str()));
-
- }
- }
- }
-
- StringContainer SourceDirDirList, DestDirDirList;
- std::string SourceUpdateDir, DestUpdateDir;
- StringContainer SourceDirExtraDirList, DestDirExtraDirList;
-
- SourceDirDirList = GetDirectoryList(SourceDir, ExcludeName);
- DestDirDirList = GetDirectoryList(DestDir, ExcludeName);
-
- for (iFile = DestDirDirList.begin(); // Check that all directories in
- iFile != DestDirDirList.end(); // the destination directory are
- iFile++) { // also in the source directory.
-
- if (! IsInContainer(*iFile, SourceDirDirList)) { // Not in source directory?
-
- DestDirExtraDirList.push_back(*iFile); // It is not. This is an error.
-
- }
-
- }
-
- for (iFile = SourceDirDirList.begin(); // Check that all directories in
- iFile != SourceDirDirList.end(); // the source directory are also
- iFile++) { // in the destination directory.
-
- if (! IsInContainer(*iFile, DestDirDirList)) { // Not in source directory?
-
- SourceDirExtraDirList.push_back(*iFile); // It is not. This is an error.
-
- }
-
- }
-
-
- if (!SourceDirExtraDirList.empty() || !DestDirExtraDirList.empty()) { // Check for error.
- std::ostringstream Temp;
-
- if (!SourceDirExtraDirList.empty()) { // Extra directories in source.
-
- Temp << "***Error--There were directories in " << SourceDir
- << " that are not in " << DestDir << ":\n\t";
-
- std::copy(SourceDirExtraDirList.begin(),
- SourceDirExtraDirList.end(),
- std::ostream_iterator<std::string>(Temp, "\n\t"));
-
- }
-
- if (!DestDirExtraDirList.empty()) { // Extra directories in destination.
-
- Temp << "***Error--There were directories in " << DestDir
- << " that are not in " << SourceDir << ":\n\t";
- std::copy(DestDirExtraDirList.begin(),
- DestDirExtraDirList.end(),
- std::ostream_iterator<std::string>(Temp, "\n\t"));
-
- }
-
- throw(std::runtime_error(Temp.str()));
- }
-
- for (iFile = DestDirDirList.begin(); // Update each directory.
- iFile != DestDirDirList.end();
- iFile++) {
-
- SourceUpdateDir = SourceDir + "\\";
- SourceUpdateDir += *iFile;
- DestUpdateDir = DestDir + "\\";
- DestUpdateDir += *iFile;
- UpdateOneDirectory(SourceUpdateDir, DestUpdateDir, ExcludeName);
-
- }
-
- }
-
-
- void
- UpdateCommonDirectories(std::string DistPath, std::string DistParentPath,
- StringContainer ExcludeName) {
-
- StringContainer DistDirList, DistParentDirList;
-
- DistDirList = GetDirectoryList(DistPath, ExcludeName); // Distribution directory names.
- DistParentDirList = GetDirectoryList(DistParentPath, ExcludeName); // Parent of distribution directory names.
-
- #if 0
- // DEBUG.
- std::cout << "Directory list of distribution--\n";
- std::copy(DistDirList.begin(),
- DistDirList.end(),
- std::ostream_iterator<std::string>(std::cout, "\n"));
-
- std::cout << "\nDirectory list of distribution parent--\n";
- std::copy(DistParentDirList.begin(),
- DistParentDirList.end(),
- std::ostream_iterator<std::string>(std::cout, "\n"));
- // END OF DEBUG.
- #endif
-
- StringContainer::iterator iDistDir; // Update direcotries with the same name.
-
- for (iDistDir = DistDirList.begin();
- iDistDir != DistDirList.end();
- iDistDir++) {
- std::string SourceDir, DestDir;
-
- if (IsInContainer(*iDistDir, DistParentDirList)) { // Check if this is a common directory.
-
- SourceDir = DistParentPath + "\\"; // This is a common directory.
- SourceDir += *iDistDir;
- DestDir = DistPath + "\\";
- DestDir += *iDistDir;
- UpdateOneDirectory(SourceDir, DestDir, ExcludeName);
- }
-
- }
-
- return;
-
- }
-
- void
- PrepareTempDir(std::string TempPath) {
-
- WIN32_FIND_DATA FileData;
- DWORD LastError;
- HANDLE DirHandle;
- std::ostringstream Temp;
-
- DirHandle = FindFirstFile(TempPath.c_str(), &FileData); // Check whether the directory exists.
- if (INVALID_HANDLE_VALUE == DirHandle) { // Directory doesn't exist.
-
- if (!CreateDirectory(TempPath.c_str(), NULL)) {
-
- LastError = GetLastError();
- Temp << "***Error creating the temporary directory " << TempPath;
- throw(std::runtime_error(Temp.str()));
-
- }
-
- return;
-
- }
-
- // If the path is a file, delete it and create a new directory.
- if ( !(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
-
- if (CloseHandle(DirHandle) != 0) {
-
- LastError = GetLastError();
- Temp << "***Error closing handle for " << TempPath;
- throw(std::runtime_error(Temp.str()));
-
- }
-
- if (DeleteFile(TempPath.c_str()) != 0) {
-
- LastError = GetLastError();
- Temp << "***Error deleting " << TempPath;
- throw(std::runtime_error(Temp.str()));
-
- }
-
- PrepareTempDir(TempPath);
- return;
-
- }
-
- if (CloseHandle(DirHandle) != 0) {
-
- LastError = GetLastError();
- Temp << "***Error closing handle for " << TempPath;
- throw(std::runtime_error(Temp.str()));
-
- }
-
- DeletePath(TempPath); // TempPath is a directory. Delete it.
- PrepareTempDir(TempPath); // Create an empty directory.
-
- }
-
- void
- DeletePath(std::string Path) {
-
- StringContainer DirList, FileList, ExcludeName;
- StringContainer::iterator iName;
- std::string NameToDelete;
-
- ExcludeName.push_back(".");
- ExcludeName.push_back("..");
-
- DirList = GetDirectoryList(Path, ExcludeName);
- FileList = GetFileList(Path, ExcludeName);
-
- for (iName = FileList.begin(); // Delete each file.
- iName != FileList.end();
- iName++) {
-
- NameToDelete = Path + "\\";
- NameToDelete += *iName;
- if (DeleteFile(NameToDelete.c_str()) == 0) {
- std::ostringstream Temp;
-
- LastError = GetLastError();
- Temp << "***Error deleting " << NameToDelete << " in " << Path;
- throw(std::runtime_error(Temp.str()));
-
- }
-
- }
-
- for (iName = DirList.begin(); // Delete each directory.
- iName != DirList.end();
- iName++) {
-
- NameToDelete = Path + "\\";
- NameToDelete += *iName;
- DeletePath(NameToDelete);
-
- }
-
- if (RemoveDirectory(Path.c_str()) == 0) {
- std::ostringstream Temp;
-
- LastError = GetLastError();
- Temp << "***Error removing directory " << Path;
- throw(std::runtime_error(Temp.str()));
-
- }
-
- }
-
- void
- CopyDirectory(std::string SourcePath, std::string DestPath, StringContainer ExcludeName) {
-
- StringContainer DirList, FileList;
- StringContainer::iterator iName;
- std::string SourceName, DestName;
- BOOL FailIfExists = true;
-
- DirList = GetDirectoryList(SourcePath, ExcludeName);
- FileList = GetFileList(SourcePath, ExcludeName);
-
- for (iName = FileList.begin(); // Copy each file.
- iName != FileList.end();
- iName++) {
-
- SourceName = SourcePath + "\\";
- SourceName += *iName;
- DestName = DestPath + "\\";
- DestName += *iName;
- if (!CopyFile(SourceName.c_str(), DestName.c_str(), FailIfExists)) {
- std::ostringstream Temp;
-
- LastError = GetLastError();
- Temp << "Error copying " << *iName << " to " << DestPath;
- throw(std::runtime_error(Temp.str()));
-
- }
-
- }
-
- for (iName = DirList.begin(); // Copy each directory.
- iName != DirList.end();
- iName++) {
-
- SourceName = SourcePath + "\\";
- SourceName += *iName;
- DestName = DestPath + "\\";
- DestName += *iName;
-
- if (!CreateDirectory(DestName.c_str(), NULL)) { // Create the directory.
- std::ostringstream Temp;
-
- LastError = GetLastError();
- Temp << "***Error creating the temporary directory " << DestName;
- throw(std::runtime_error(Temp.str()));
-
- }
-
- CopyDirectory(SourceName, DestName, ExcludeName);
-
- }
-
- }
|