From 403e7e2051ee3bd3e16a616cfca63b036481282b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 13 Dec 2015 23:39:18 +0000 Subject: Move reusable code out of bin directories. Allows tests to depend on lib/bbackupd instead of bin/bbackupd, which was always a hack, and really doesn't work with CMake. --- bin/bbackupquery/BackupQueries.cpp | 2410 ----------------------------- bin/bbackupquery/BackupQueries.h | 440 ------ bin/bbackupquery/BoxBackupCompareParams.h | 112 -- bin/bbackupquery/CommandCompletion.cpp | 604 -------- bin/bbackupquery/Makefile.extra | 6 - bin/bbackupquery/documentation.txt | 194 --- bin/bbackupquery/makedocumentation.pl.in | 75 - 7 files changed, 3841 deletions(-) delete mode 100644 bin/bbackupquery/BackupQueries.cpp delete mode 100644 bin/bbackupquery/BackupQueries.h delete mode 100644 bin/bbackupquery/BoxBackupCompareParams.h delete mode 100644 bin/bbackupquery/CommandCompletion.cpp delete mode 100644 bin/bbackupquery/Makefile.extra delete mode 100644 bin/bbackupquery/documentation.txt delete mode 100755 bin/bbackupquery/makedocumentation.pl.in (limited to 'bin/bbackupquery') diff --git a/bin/bbackupquery/BackupQueries.cpp b/bin/bbackupquery/BackupQueries.cpp deleted file mode 100644 index bcb1827e..00000000 --- a/bin/bbackupquery/BackupQueries.cpp +++ /dev/null @@ -1,2410 +0,0 @@ -// -------------------------------------------------------------------------- -// -// File -// Name: BackupQueries.cpp -// Purpose: Perform various queries on the backup store server. -// Created: 2003/10/10 -// -// -------------------------------------------------------------------------- - -#include "Box.h" - -#ifdef HAVE_UNISTD_H - #include -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_DIRENT_H - #include -#endif - -#include -#include -#include -#include -#include -#include - -#include "BackupClientFileAttributes.h" -#include "BackupClientMakeExcludeList.h" -#include "BackupClientRestore.h" -#include "BackupQueries.h" -#include "BackupStoreDirectory.h" -#include "BackupStoreException.h" -#include "BackupStoreFile.h" -#include "BackupStoreFilenameClear.h" -#include "BoxTimeToText.h" -#include "CommonException.h" -#include "Configuration.h" -#include "ExcludeList.h" -#include "FileModificationTime.h" -#include "FileStream.h" -#include "IOStream.h" -#include "Logging.h" -#include "PathUtils.h" -#include "SelfFlushingStream.h" -#include "Utils.h" -#include "autogen_BackupProtocol.h" -#include "autogen_CipherException.h" - -#include "MemLeakFindOn.h" - -// min() and max() macros from stdlib.h break numeric_limits<>::min(), etc. -#undef min -#undef max - -#define COMPARE_RETURN_SAME 1 -#define COMPARE_RETURN_DIFFERENT 2 -#define COMPARE_RETURN_ERROR 3 -#define COMMAND_RETURN_ERROR 4 - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::BackupQueries() -// Purpose: Constructor -// Created: 2003/10/10 -// -// -------------------------------------------------------------------------- -BackupQueries::BackupQueries(BackupProtocolCallable &rConnection, - const Configuration &rConfiguration, bool readWrite) - : mReadWrite(readWrite), - mrConnection(rConnection), - mrConfiguration(rConfiguration), - mQuitNow(false), - mRunningAsRoot(false), - mWarnedAboutOwnerAttributes(false), - mReturnCode(0) // default return code -{ - #ifdef WIN32 - mRunningAsRoot = TRUE; - #else - mRunningAsRoot = (::geteuid() == 0); - #endif -} - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::~BackupQueries() -// Purpose: Destructor -// Created: 2003/10/10 -// -// -------------------------------------------------------------------------- -BackupQueries::~BackupQueries() -{ -} - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::DoCommand(const char *, bool) -// Purpose: Perform a command -// Created: 2003/10/10 -// -// -------------------------------------------------------------------------- -void BackupQueries::DoCommand(ParsedCommand& rCommand) -{ - // Check... - - if(rCommand.mFailed) - { - BOX_ERROR("Parse failed: unknown command '" << - rCommand.mCmdElements[0] << "' or failed to convert " - "encoding of arguments"); - return; - } - - if(rCommand.mCmdElements.size() < 1) - { - // blank command - return; - } - - if(rCommand.pSpec->type == Command_sh && - rCommand.mCmdElements.size() == 2) - { - // Yes, run shell command - int result = ::system(rCommand.mCmdElements[1].c_str()); - if(result != 0) - { - BOX_WARNING("System command returned error code " << - result); - SetReturnCode(ReturnCode::Command_Error); - } - return; - } - - if(rCommand.pSpec->type == Command_Unknown) - { - // No such command - BOX_ERROR("Unrecognised command: " << rCommand.mCmdElements[0]); - return; - } - - // Arguments - std::vector args(rCommand.mCmdElements.begin() + 1, - rCommand.mCmdElements.end()); - - // Set up options - bool opts[256]; - for(int o = 0; o < 256; ++o) opts[o] = false; - // BLOCK - { - // options - const char *c = rCommand.mOptions.c_str(); - while(*c != 0) - { - // Valid option? - if(::strchr(rCommand.pSpec->opts, *c) == NULL) - { - BOX_ERROR("Invalid option '" << *c << "' for " - "command " << rCommand.pSpec->name); - return; - } - opts[(int)*c] = true; - ++c; - } - } - - if(rCommand.pSpec->type != Command_Quit) - { - // If not a quit command, set the return code to zero - SetReturnCode(ReturnCode::Command_OK); - } - - // Handle command - switch(rCommand.pSpec->type) - { - case Command_Quit: - mQuitNow = true; - break; - - case Command_List: - CommandList(args, opts); - break; - - case Command_pwd: - { - // Simple implementation, so do it here - BOX_NOTICE(GetCurrentDirectoryName() << " (" << - BOX_FORMAT_OBJECTID(GetCurrentDirectoryID()) << - ")"); - } - break; - - case Command_cd: - CommandChangeDir(args, opts); - break; - - case Command_lcd: - CommandChangeLocalDir(args); - break; - - case Command_sh: - BOX_ERROR("The command to run must be specified as an argument."); - break; - - case Command_GetObject: - CommandGetObject(args, opts); - break; - - case Command_Get: - CommandGet(args, opts); - break; - - case Command_Compare: - CommandCompare(args, opts); - break; - - case Command_Restore: - CommandRestore(args, opts); - break; - - case Command_Usage: - CommandUsage(opts); - break; - - case Command_Help: - CommandHelp(args); - break; - - case Command_Undelete: - CommandUndelete(args, opts); - break; - - case Command_Delete: - CommandDelete(args, opts); - break; - - default: - BOX_ERROR("Unknown command: " << rCommand.mCmdElements[0]); - break; - } -} - -#define LIST_OPTION_TIMES_ATTRIBS 'a' -#define LIST_OPTION_SORT_NO_DIRS_FIRST 'D' -#define LIST_OPTION_NOFLAGS 'F' -#define LIST_OPTION_DISPLAY_HASH 'h' -#define LIST_OPTION_SORT_ID 'i' -#define LIST_OPTION_NOOBJECTID 'I' -#define LIST_OPTION_SORT_REVERSE 'r' -#define LIST_OPTION_RECURSIVE 'R' -#define LIST_OPTION_SIZEINBLOCKS 's' -#define LIST_OPTION_SORT_SIZE 'S' -#define LIST_OPTION_TIMES_LOCAL 't' -#define LIST_OPTION_TIMES_UTC 'T' -#define LIST_OPTION_SORT_NONE 'U' - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CommandList(const std::vector &, const bool *) -// Purpose: List directories (optionally recursive) -// Created: 2003/10/10 -// -// -------------------------------------------------------------------------- -void BackupQueries::CommandList(const std::vector &args, const bool *opts) -{ - // default to using the current directory - int64_t rootDir = GetCurrentDirectoryID(); - - // name of base directory - std::string listRoot; // blank - - // Got a directory in the arguments? - if(args.size() > 0) - { -#ifdef WIN32 - std::string storeDirEncoded; - if(!ConvertConsoleToUtf8(args[0].c_str(), storeDirEncoded)) - return; -#else - const std::string& storeDirEncoded(args[0]); -#endif - - // Attempt to find the directory - rootDir = FindDirectoryObjectID(storeDirEncoded, - opts[LIST_OPTION_ALLOWOLD], - opts[LIST_OPTION_ALLOWDELETED]); - - if(rootDir == 0) - { - BOX_ERROR("Directory '" << args[0] << "' not found " - "on store."); - SetReturnCode(ReturnCode::Command_Error); - return; - } - } - - // List it - List(rootDir, listRoot, opts, true /* first level to list */); -} - -static std::string GetTimeString(BackupStoreDirectory::Entry& en, - bool useLocalTime, bool showAttrModificationTimes) -{ - std::ostringstream out; - box_time_t originalTime, newAttributesTime; - - // there is no attribute modification time in the directory - // entry, unfortunately, so we can't display it. - originalTime = en.GetModificationTime(); - out << BoxTimeToISO8601String(originalTime, useLocalTime); - - if(en.HasAttributes()) - { - const StreamableMemBlock &storeAttr(en.GetAttributes()); - BackupClientFileAttributes attr(storeAttr); - - box_time_t NewModificationTime, NewAttrModificationTime; - attr.GetModificationTimes(&NewModificationTime, - &NewAttrModificationTime); - - if (showAttrModificationTimes) - { - newAttributesTime = NewAttrModificationTime; - } - else - { - newAttributesTime = NewModificationTime; - } - - if (newAttributesTime == originalTime) - { - out << "*"; - } - else - { - out << "~" << BoxTimeToISO8601String(newAttributesTime, - useLocalTime); - } - } - else - { - out << " "; - } - - return out.str(); -} - -/* We need a way to pass options to sort functions for sorting. The algorithm - * doesn't seem to provide a way to do this, so I'm using a global variable. - * Which is not thread safe, but we don't currently use threads so that should - * be OK. Do not use threads without checking! - */ -const bool *gThreadUnsafeOptions; - -int DirsFirst(BackupStoreDirectory::Entry* a, - BackupStoreDirectory::Entry* b) -{ - if (a->IsDir() && !b->IsDir()) - { - return -1; // a < b - } - else if (!a->IsDir() && b->IsDir()) - { - return 1; // b > a - } - else - { - return 0; // continue comparison - } -} - -#define MAYBE_DIRS_FIRST(a, b) \ - if (!gThreadUnsafeOptions[LIST_OPTION_SORT_NO_DIRS_FIRST]) \ - { \ - int result = DirsFirst(a, b); \ - if (result < 0) return true; /* a < b */ \ - else if (result > 0) return false; /* a > b */ \ - /* else: fall through */ \ - } - -#define MAYBE_REVERSE(result) \ - (result != gThreadUnsafeOptions[LIST_OPTION_SORT_REVERSE]) -// result is false, opts[reverse] is false => return false -// result is false, opts[reverse] is true => return true -// result is true, opts[reverse] is false => return true -// result is true, opts[reverse] is true => return false -// this is logical XOR, for which the boolean operator is !=. - -bool SortById(BackupStoreDirectory::Entry* a, - BackupStoreDirectory::Entry* b) -{ - MAYBE_DIRS_FIRST(a, b); - bool result = (a->GetObjectID() < b->GetObjectID()); - return MAYBE_REVERSE(result); -} - -bool SortBySize(BackupStoreDirectory::Entry* a, - BackupStoreDirectory::Entry* b) -{ - MAYBE_DIRS_FIRST(a, b); - bool result = (a->GetSizeInBlocks() < b->GetSizeInBlocks()); - return MAYBE_REVERSE(result); -} - -bool SortByName(BackupStoreDirectory::Entry* a, - BackupStoreDirectory::Entry* b) -{ - MAYBE_DIRS_FIRST(a, b); - BackupStoreFilenameClear afc(a->GetName()); - BackupStoreFilenameClear bfc(b->GetName()); - std::string an = afc.GetClearFilename(); - std::string bn = bfc.GetClearFilename(); - bool result = (an < bn); - return MAYBE_REVERSE(result); -} - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::List(int64_t, const std::string &, const bool *, bool) -// Purpose: Do the actual listing of directories and files -// Created: 2003/10/10 -// -// -------------------------------------------------------------------------- -void BackupQueries::List(int64_t DirID, const std::string &rListRoot, - const bool *opts, bool FirstLevel, std::ostream* pOut) -{ -#ifdef WIN32 - DWORD n_chars; - HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); -#endif - - // Generate exclude flags - int16_t excludeFlags = BackupProtocolListDirectory::Flags_EXCLUDE_NOTHING; - if(!opts[LIST_OPTION_ALLOWOLD]) excludeFlags |= BackupProtocolListDirectory::Flags_OldVersion; - if(!opts[LIST_OPTION_ALLOWDELETED]) excludeFlags |= BackupProtocolListDirectory::Flags_Deleted; - - // Do communication - try - { - mrConnection.QueryListDirectory( - DirID, - BackupProtocolListDirectory::Flags_INCLUDE_EVERYTHING, - // both files and directories - excludeFlags, - true /* want attributes */); - } - catch (std::exception &e) - { - BOX_ERROR("Failed to list directory: " << e.what()); - SetReturnCode(ReturnCode::Command_Error); - return; - } - catch (...) - { - BOX_ERROR("Failed to list directory: unknown error"); - SetReturnCode(ReturnCode::Command_Error); - return; - } - - // Retrieve the directory from the stream following - BackupStoreDirectory dir; - std::auto_ptr dirstream(mrConnection.ReceiveStream()); - dir.ReadFromStream(*dirstream, mrConnection.GetTimeout()); - - // Store entry pointers in a std::vector for sorting - BackupStoreDirectory::Iterator i(dir); - BackupStoreDirectory::Entry *en = 0; - std::vector sorted_entries; - while((en = i.Next()) != 0) - { - sorted_entries.push_back(en); - } - - // Typedef to avoid mind-bending while dealing with pointers to functions. - typedef bool (EntryComparator_t)(BackupStoreDirectory::Entry* a, - BackupStoreDirectory::Entry* b); - // Default is no comparator, i.e. no sorting. - EntryComparator_t* pComparator = NULL; - - if (opts[LIST_OPTION_SORT_ID]) - { - pComparator = &SortById; - } - else if (opts[LIST_OPTION_SORT_SIZE]) - { - pComparator = &SortBySize; - } - else if (opts[LIST_OPTION_SORT_NONE]) - { - // do nothing - } - else // sort by name - { - pComparator = &SortByName; - } - - if (pComparator != NULL) - { - gThreadUnsafeOptions = opts; - sort(sorted_entries.begin(), sorted_entries.end(), - pComparator); - gThreadUnsafeOptions = NULL; - } - - for (std::vector::const_iterator - i = sorted_entries.begin(); - i != sorted_entries.end(); i++) - { - en = *i; - std::ostringstream buf; - - // Display this entry - BackupStoreFilenameClear clear(en->GetName()); - - // Object ID? - if(!opts[LIST_OPTION_NOOBJECTID]) - { - // add object ID to line - buf << std::hex << std::internal << std::setw(8) << - std::setfill('0') << en->GetObjectID() << - std::dec << " "; - } - - // Flags? - if(!opts[LIST_OPTION_NOFLAGS]) - { - static const char *flags = BACKUPSTOREDIRECTORY_ENTRY_FLAGS_DISPLAY_NAMES; - char displayflags[16]; - // make sure f is big enough - ASSERT(sizeof(displayflags) >= sizeof(BACKUPSTOREDIRECTORY_ENTRY_FLAGS_DISPLAY_NAMES) + 3); - // Insert flags - char *f = displayflags; - const char *t = flags; - int16_t en_flags = en->GetFlags(); - while(*t != 0) - { - *f = ((en_flags&1) == 0)?'-':*t; - en_flags >>= 1; - f++; - t++; - } - // attributes flags - *(f++) = (en->HasAttributes())?'a':'-'; - - // terminate - *(f++) = ' '; - *(f++) = '\0'; - buf << displayflags; - - if(en_flags != 0) - { - buf << "[ERROR: Entry has additional flags set] "; - } - } - - if(opts[LIST_OPTION_TIMES_UTC]) - { - // Show UTC times... - buf << GetTimeString(*en, false, - opts[LIST_OPTION_TIMES_ATTRIBS]) << " "; - } - - if(opts[LIST_OPTION_TIMES_LOCAL]) - { - // Show local times... - buf << GetTimeString(*en, true, - opts[LIST_OPTION_TIMES_ATTRIBS]) << " "; - } - - if(opts[LIST_OPTION_DISPLAY_HASH]) - { - buf << std::hex << std::internal << std::setw(16) << - std::setfill('0') << en->GetAttributesHash() << - std::dec; - } - - if(opts[LIST_OPTION_SIZEINBLOCKS]) - { - buf << std::internal << std::setw(5) << - std::setfill('0') << en->GetSizeInBlocks() << - " "; - } - - // add name - if(!FirstLevel) - { -#ifdef WIN32 - std::string listRootDecoded; - if(!ConvertUtf8ToConsole(rListRoot.c_str(), - listRootDecoded)) return; - listRootDecoded += "/"; - buf << listRootDecoded; - WriteConsole(hOut, listRootDecoded.c_str(), - strlen(listRootDecoded.c_str()), &n_chars, NULL); -#else - buf << rListRoot << "/"; -#endif - } - - std::string fileName; - try - { - fileName = clear.GetClearFilename(); - } - catch(CipherException &e) - { - fileName = ""; - } - -#ifdef WIN32 - std::string fileNameUtf8 = fileName; - if(!ConvertUtf8ToConsole(fileNameUtf8, fileName)) - { - fileName = fileNameUtf8 + " [convert encoding failed]"; - } -#endif - - buf << fileName; - - if(!en->GetName().IsEncrypted()) - { - buf << " [FILENAME NOT ENCRYPTED]"; - } - - buf << std::endl; - - if(pOut) - { - (*pOut) << buf.str(); - } - else - { -#ifdef WIN32 - std::string line = buf.str(); - if (!WriteConsole(hOut, line.c_str(), line.size(), - &n_chars, NULL)) - { - // WriteConsole failed, try standard method - std::cout << buf.str(); - } -#else - std::cout << buf.str(); -#endif - } - - // Directory? - if((en->GetFlags() & BackupStoreDirectory::Entry::Flags_Dir) != 0) - { - // Recurse? - if(opts[LIST_OPTION_RECURSIVE]) - { - std::string subroot(rListRoot); - if(!FirstLevel) subroot += '/'; - subroot += clear.GetClearFilename(); - List(en->GetObjectID(), subroot, opts, - false /* not the first level to list */, - pOut); - } - } - } -} - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::FindDirectoryObjectID(const -// std::string &) -// Purpose: Find the object ID of a directory on the store, -// or return 0 for not found. If pStack != 0, the -// object is set to the stack of directories. -// Will start from the current directory stack. -// Created: 2003/10/10 -// -// -------------------------------------------------------------------------- -int64_t BackupQueries::FindDirectoryObjectID(const std::string &rDirName, - bool AllowOldVersion, bool AllowDeletedDirs, - std::vector > *pStack) -{ - // Split up string into elements - std::vector dirElements; - SplitString(rDirName, '/', dirElements); - - // Start from current stack, or root, whichever is required - std::vector > stack; - int64_t dirID = BackupProtocolListDirectory::RootDirectory; - if(rDirName.size() > 0 && rDirName[0] == '/') - { - // Root, do nothing - } - else - { - // Copy existing stack - stack = mDirStack; - if(stack.size() > 0) - { - dirID = stack[stack.size() - 1].second; - } - } - - // Generate exclude flags - int16_t excludeFlags = BackupProtocolListDirectory::Flags_EXCLUDE_NOTHING; - if(!AllowOldVersion) excludeFlags |= BackupProtocolListDirectory::Flags_OldVersion; - if(!AllowDeletedDirs) excludeFlags |= BackupProtocolListDirectory::Flags_Deleted; - - // Read directories - for(unsigned int e = 0; e < dirElements.size(); ++e) - { - if(dirElements[e].size() > 0) - { - if(dirElements[e] == ".") - { - // Ignore. - } - else if(dirElements[e] == "..") - { - // Up one! - if(stack.size() > 0) - { - // Remove top element - stack.pop_back(); - - // New dir ID - dirID = (stack.size() > 0)?(stack[stack.size() - 1].second):BackupProtocolListDirectory::RootDirectory; - } - else - { - // At root anyway - dirID = BackupProtocolListDirectory::RootDirectory; - } - } - else - { - // Not blank element. Read current directory. - std::auto_ptr dirreply(mrConnection.QueryListDirectory( - dirID, - BackupProtocolListDirectory::Flags_Dir, // just directories - excludeFlags, - true /* want attributes */)); - - // Retrieve the directory from the stream following - BackupStoreDirectory dir; - std::auto_ptr dirstream(mrConnection.ReceiveStream()); - dir.ReadFromStream(*dirstream, mrConnection.GetTimeout()); - - // Then... find the directory within it - BackupStoreDirectory::Iterator i(dir); - BackupStoreFilenameClear dirname(dirElements[e]); - BackupStoreDirectory::Entry *en = i.FindMatchingClearName(dirname); - if(en == 0) - { - // Not found - return 0; - } - - // Object ID for next round of searching - dirID = en->GetObjectID(); - - // Push onto stack - stack.push_back(std::pair(dirElements[e], dirID)); - } - } - } - - // If required, copy the new stack to the caller - if(pStack) - { - *pStack = stack; - } - - return dirID; -} - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::GetCurrentDirectoryID() -// Purpose: Returns the ID of the current directory -// Created: 2003/10/10 -// -// -------------------------------------------------------------------------- -int64_t BackupQueries::GetCurrentDirectoryID() -{ - // Special case for root - if(mDirStack.size() == 0) - { - return BackupProtocolListDirectory::RootDirectory; - } - - // Otherwise, get from the last entry on the stack - return mDirStack[mDirStack.size() - 1].second; -} - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::GetCurrentDirectoryName() -// Purpose: Gets the name of the current directory -// Created: 2003/10/10 -// -// -------------------------------------------------------------------------- -std::string BackupQueries::GetCurrentDirectoryName() -{ - // Special case for root - if(mDirStack.size() == 0) - { - return std::string("/"); - } - - // Build path - std::string r; - for(unsigned int l = 0; l < mDirStack.size(); ++l) - { - r += "/"; -#ifdef WIN32 - std::string dirName; - if(!ConvertUtf8ToConsole(mDirStack[l].first.c_str(), dirName)) - return "error"; - r += dirName; -#else - r += mDirStack[l].first; -#endif - } - - return r; -} - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CommandChangeDir(const std::vector &) -// Purpose: Change directory command -// Created: 2003/10/10 -// -// -------------------------------------------------------------------------- -void BackupQueries::CommandChangeDir(const std::vector &args, const bool *opts) -{ - if(args.size() != 1 || args[0].size() == 0) - { - BOX_ERROR("Incorrect usage. cd [-o] [-d] "); - SetReturnCode(ReturnCode::Command_Error); - return; - } - -#ifdef WIN32 - std::string dirName; - if(!ConvertConsoleToUtf8(args[0].c_str(), dirName)) return; -#else - const std::string& dirName(args[0]); -#endif - - std::vector > newStack; - int64_t id = FindDirectoryObjectID(dirName, opts['o'], opts['d'], - &newStack); - - if(id == 0) - { - BOX_ERROR("Directory '" << args[0] << "' not found."); - SetReturnCode(ReturnCode::Command_Error); - return; - } - - // Store new stack - mDirStack = newStack; -} - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CommandChangeLocalDir(const std::vector &) -// Purpose: Change local directory command -// Created: 2003/10/11 -// -// -------------------------------------------------------------------------- -void BackupQueries::CommandChangeLocalDir(const std::vector &args) -{ - if(args.size() != 1 || args[0].size() == 0) - { - BOX_ERROR("Incorrect usage. lcd "); - SetReturnCode(ReturnCode::Command_Error); - return; - } - - // Try changing directory -#ifdef WIN32 - std::string dirName; - if(!ConvertConsoleToUtf8(args[0].c_str(), dirName)) - { - BOX_ERROR("Failed to convert path from console encoding."); - SetReturnCode(ReturnCode::Command_Error); - return; - } - int result = ::chdir(dirName.c_str()); -#else - int result = ::chdir(args[0].c_str()); -#endif - if(result != 0) - { - if(errno == ENOENT || errno == ENOTDIR) - { - BOX_ERROR("Directory '" << args[0] << "' does not exist."); - } - else - { - BOX_LOG_SYS_ERROR("Failed to change to directory " - "'" << args[0] << "'"); - } - - SetReturnCode(ReturnCode::Command_Error); - return; - } - - // Report current dir - char wd[PATH_MAX]; - if(::getcwd(wd, PATH_MAX) == 0) - { - BOX_LOG_SYS_ERROR("Error getting current directory"); - SetReturnCode(ReturnCode::Command_Error); - return; - } - -#ifdef WIN32 - if(!ConvertUtf8ToConsole(wd, dirName)) - { - BOX_ERROR("Failed to convert new path from console encoding."); - SetReturnCode(ReturnCode::Command_Error); - return; - } - BOX_INFO("Local current directory is now '" << dirName << "'."); -#else - BOX_INFO("Local current directory is now '" << wd << "'."); -#endif -} - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CommandGetObject(const std::vector &, const bool *) -// Purpose: Gets an object without any translation. -// Created: 2003/10/11 -// -// -------------------------------------------------------------------------- -void BackupQueries::CommandGetObject(const std::vector &args, const bool *opts) -{ - // Check args - if(args.size() != 2) - { - BOX_ERROR("Incorrect usage. getobject " - ""); - return; - } - - int64_t id = ::strtoll(args[0].c_str(), 0, 16); - if(id == std::numeric_limits::min() || id == std::numeric_limits::max() || id == 0) - { - BOX_ERROR("Not a valid object ID (specified in hex): " << - args[0]); - return; - } - - // Does file exist? - EMU_STRUCT_STAT st; - if(EMU_STAT(args[1].c_str(), &st) == 0 || errno != ENOENT) - { - BOX_ERROR("The local file '" << args[1] << " already exists."); - return; - } - - // Open file - FileStream out(args[1].c_str(), O_WRONLY | O_CREAT | O_EXCL); - - // Request that object - try - { - // Request object - std::auto_ptr getobj(mrConnection.QueryGetObject(id)); - - // Stream that object out to the file - std::auto_ptr objectStream(mrConnection.ReceiveStream()); - objectStream->CopyStreamTo(out); - - BOX_INFO("Object ID " << BOX_FORMAT_OBJECTID(id) << - " fetched successfully."); - } - catch(ConnectionException &e) - { - if(mrConnection.GetLastErrorType() == BackupProtocolError::Err_DoesNotExist) - { - BOX_ERROR("Object ID " << BOX_FORMAT_OBJECTID(id) << - " does not exist on store."); - ::unlink(args[1].c_str()); - } - else - { - BOX_ERROR("Error occured fetching object."); - ::unlink(args[1].c_str()); - } - } - catch(...) - { - ::unlink(args[1].c_str()); - BOX_ERROR("Error occured fetching object."); - } -} - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::FindFileID(const std::string& -// rNameOrIdString, const bool *options, -// int64_t *pDirIdOut, std::string* pFileNameOut) -// Purpose: Locate a file on the store (either by name or by -// object ID, depending on opts['i'], where name can -// include a path) and return the file ID, placing the -// directory ID in *pDirIdOut and the filename part -// of the path in *pFileNameOut (if not NULL). -// Created: 2008-09-12 -// -// -------------------------------------------------------------------------- -int64_t BackupQueries::FindFileID(const std::string& rNameOrIdString, - const bool *opts, int64_t *pDirIdOut, std::string* pFileNameOut, - int16_t flagsInclude, int16_t flagsExclude, int16_t* pFlagsOut) -{ - // Find object ID somehow - int64_t fileId; - int64_t dirId = GetCurrentDirectoryID(); - std::string fileName = rNameOrIdString; - - if(!opts['i']) - { - // does this remote filename include a path? - std::string::size_type index = fileName.rfind('/'); - if(index != std::string::npos) - { - std::string dirName(fileName.substr(0, index)); - fileName = fileName.substr(index + 1); - - dirId = FindDirectoryObjectID(dirName); - if(dirId == 0) - { - BOX_ERROR("Directory '" << dirName << - "' not found."); - return 0; - } - } - } - - BackupStoreFilenameClear fn(fileName); - - // Need to look it up in the current directory - mrConnection.QueryListDirectory( - dirId, flagsInclude, flagsExclude, - true /* do want attributes */); - - // Retrieve the directory from the stream following - BackupStoreDirectory dir; - std::auto_ptr dirstream(mrConnection.ReceiveStream()); - dir.ReadFromStream(*dirstream, mrConnection.GetTimeout()); - BackupStoreDirectory::Entry *en; - - if(opts['i']) - { - // Specified as ID. - fileId = ::strtoll(rNameOrIdString.c_str(), 0, 16); - if(fileId == std::numeric_limits::min() || - fileId == std::numeric_limits::max() || - fileId == 0) - { - BOX_ERROR("Not a valid object ID (specified in hex): " - << rNameOrIdString); - return 0; - } - - // Check that the item is actually in the directory - en = dir.FindEntryByID(fileId); - if(en == 0) - { - BOX_ERROR("File ID " << - BOX_FORMAT_OBJECTID(fileId) << - " not found in current directory on store.\n" - "(You can only access files by ID from the " - "current directory.)"); - return 0; - } - } - else - { - // Specified by name, find the object in the directory to get the ID - BackupStoreDirectory::Iterator i(dir); - en = i.FindMatchingClearName(fn); - if(en == 0) - { - BOX_ERROR("Filename '" << rNameOrIdString << "' " - "not found in current directory on store.\n" - "(Subdirectories in path not searched.)"); - return 0; - } - - fileId = en->GetObjectID(); - } - - *pDirIdOut = dirId; - - if(pFlagsOut) - { - *pFlagsOut = en->GetFlags(); - } - - if(pFileNameOut) - { - BackupStoreFilenameClear entryName(en->GetName()); - *pFileNameOut = entryName.GetClearFilename(); - } - - return fileId; -} - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CommandGet(const std::vector &, const bool *) -// Purpose: Command to get a file from the store -// Created: 2003/10/12 -// -// -------------------------------------------------------------------------- -void BackupQueries::CommandGet(std::vector args, const bool *opts) -{ - // At least one argument? - // Check args - if(args.size() < 1 || (opts['i'] && args.size() != 2) || args.size() > 2) - { - BOX_ERROR("Incorrect usage.\n" - "get [] or\n" - "get -i "); - return; - } - - // Find object ID somehow - int64_t fileId, dirId; - std::string localName; - -#ifdef WIN32 - for (std::vector::iterator - i = args.begin(); i != args.end(); i++) - { - std::string out; - if(!ConvertConsoleToUtf8(i->c_str(), out)) - { - BOX_ERROR("Failed to convert encoding."); - return; - } - *i = out; - } -#endif - - int16_t flagsExclude; - - if(opts['i']) - { - // can retrieve anything by ID - flagsExclude = BackupProtocolListDirectory::Flags_EXCLUDE_NOTHING; - } - else - { - // only current versions by name - flagsExclude = - BackupProtocolListDirectory::Flags_OldVersion | - BackupProtocolListDirectory::Flags_Deleted; - } - - - fileId = FindFileID(args[0], opts, &dirId, &localName, - BackupProtocolListDirectory::Flags_File, // just files - flagsExclude, NULL /* don't care about flags found */); - - if (fileId == 0) - { - // error already reported - return; - } - - if(opts['i']) - { - // Specified as ID. Must have a local name in the arguments - // (check at beginning of function ensures this) - localName = args[1]; - } - else - { - // Specified by name. Local name already set by FindFileID, - // but may be overridden by user supplying a second argument. - if(args.size() == 2) - { - localName = args[1]; - } - } - - // Does local file already exist? (don't want to overwrite) - EMU_STRUCT_STAT st; - if(EMU_STAT(localName.c_str(), &st) == 0 || errno != ENOENT) - { - BOX_ERROR("The local file " << localName << " already exists, " - "will not overwrite it."); - SetReturnCode(ReturnCode::Command_Error); - return; - } - - // Request it from the store - try - { - // Request object - mrConnection.QueryGetFile(dirId, fileId); - - // Stream containing encoded file - std::auto_ptr objectStream(mrConnection.ReceiveStream()); - - // Decode it - BackupStoreFile::DecodeFile(*objectStream, localName.c_str(), mrConnection.GetTimeout()); - - // Done. - BOX_INFO("Object ID " << BOX_FORMAT_OBJECTID(fileId) << - " fetched successfully."); - } - catch (BoxException &e) - { - BOX_ERROR("Failed to fetch file: " << - e.what()); - ::unlink(localName.c_str()); - } - catch(std::exception &e) - { - BOX_ERROR("Failed to fetch file: " << - e.what()); - ::unlink(localName.c_str()); - } - catch(...) - { - BOX_ERROR("Failed to fetch file: unknown error"); - ::unlink(localName.c_str()); - } -} - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CompareParams::CompareParams() -// Purpose: Constructor -// Created: 29/1/04 -// -// -------------------------------------------------------------------------- -BackupQueries::CompareParams::CompareParams(bool QuickCompare, - bool IgnoreExcludes, bool IgnoreAttributes, - box_time_t LatestFileUploadTime) -: BoxBackupCompareParams(QuickCompare, IgnoreExcludes, IgnoreAttributes, - LatestFileUploadTime), - mDifferences(0), - mDifferencesExplainedByModTime(0), - mUncheckedFiles(0), - mExcludedDirs(0), - mExcludedFiles(0) -{ } - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CommandCompare(const std::vector &, const bool *) -// Purpose: Command to compare data on the store with local data -// Created: 2003/10/12 -// -// -------------------------------------------------------------------------- -void BackupQueries::CommandCompare(const std::vector &args, const bool *opts) -{ - box_time_t LatestFileUploadTime = GetCurrentBoxTime(); - - // Try and work out the time before which all files should be on the server - { - std::string syncTimeFilename(mrConfiguration.GetKeyValue("DataDirectory") + DIRECTORY_SEPARATOR_ASCHAR); - syncTimeFilename += "last_sync_start"; - // Stat it to get file time - EMU_STRUCT_STAT st; - if(EMU_STAT(syncTimeFilename.c_str(), &st) == 0) - { - // Files modified after this time shouldn't be on the server, so report errors slightly differently - LatestFileUploadTime = FileModificationTime(st) - - SecondsToBoxTime(mrConfiguration.GetKeyValueInt("MinimumFileAge")); - } - else - { - BOX_WARNING("Failed to determine the time of the last " - "synchronisation -- checks not performed."); - } - } - - // Parameters, including count of differences - BackupQueries::CompareParams params(opts['q'], // quick compare? - opts['E'], // ignore excludes - opts['A'], // ignore attributes - LatestFileUploadTime); - - params.mQuietCompare = opts['Q']; - - // Quick compare? - if(params.QuickCompare()) - { - BOX_WARNING("Quick compare used -- file attributes are not " - "checked."); - } - - if(!opts['l'] && opts['a'] && args.size() == 0) - { - // Compare all locations - const Configuration &rLocations( - mrConfiguration.GetSubConfiguration("BackupLocations")); - std::vector locNames = - rLocations.GetSubConfigurationNames(); - for(std::vector::iterator - pLocName = locNames.begin(); - pLocName != locNames.end(); - pLocName++) - { - CompareLocation(*pLocName, params); - } - } - else if(opts['l'] && !opts['a'] && args.size() == 1) - { - // Compare one location - CompareLocation(args[0], params); - } - else if(!opts['l'] && !opts['a'] && args.size() == 2) - { - // Compare directory to directory - - // Can't be bothered to do all the hard work to work out which location it's on, and hence which exclude list - if(!params.IgnoreExcludes()) - { - BOX_ERROR("Cannot use excludes on directory to directory comparison -- use -E flag to specify ignored excludes."); - return; - } - else - { - // Do compare - Compare(args[0], args[1], params); - } - } - else - { - BOX_ERROR("Incorrect usage.\ncompare -a\n or compare -l \n or compare "); - return; - } - - if (!params.mQuietCompare) - { - BOX_INFO("[ " << - params.mDifferencesExplainedByModTime << " (of " << - params.mDifferences << ") differences probably " - "due to file modifications after the last upload ]"); - } - - BOX_INFO("Differences: " << params.mDifferences << " (" << - params.mExcludedDirs << " dirs excluded, " << - params.mExcludedFiles << " files excluded, " << - params.mUncheckedFiles << " files not checked)"); - - // Set return code? - if(opts['c']) - { - if (params.mUncheckedFiles != 0) - { - SetReturnCode(ReturnCode::Compare_Error); - } - else if (params.mDifferences != 0) - { - SetReturnCode(ReturnCode::Compare_Different); - } - else - { - SetReturnCode(ReturnCode::Compare_Same); - } - } -} - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CompareLocation(const std::string &, BackupQueries::CompareParams &) -// Purpose: Compare a location -// Created: 2003/10/13 -// -// -------------------------------------------------------------------------- -void BackupQueries::CompareLocation(const std::string &rLocation, - BoxBackupCompareParams &rParams) -{ - // Find the location's sub configuration - const Configuration &locations(mrConfiguration.GetSubConfiguration("BackupLocations")); - if(!locations.SubConfigurationExists(rLocation.c_str())) - { - BOX_ERROR("Location " << rLocation << " does not exist."); - return; - } - const Configuration &loc(locations.GetSubConfiguration(rLocation.c_str())); - - #ifdef WIN32 - { - std::string path = loc.GetKeyValue("Path"); - if (path.size() > 0 && path[path.size()-1] == - DIRECTORY_SEPARATOR_ASCHAR) - { - BOX_WARNING("Location '" << rLocation << "' path ends " - "with '" DIRECTORY_SEPARATOR "', " - "compare may fail!"); - } - } - #endif - - // Generate the exclude lists - if(!rParams.IgnoreExcludes()) - { - rParams.LoadExcludeLists(loc); - } - - // Then get it compared - Compare(std::string("/") + rLocation, loc.GetKeyValue("Path"), rParams); -} - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::Compare(const std::string &, -// const std::string &, BackupQueries::CompareParams &) -// Purpose: Compare a store directory against a local directory -// Created: 2003/10/13 -// -// -------------------------------------------------------------------------- -void BackupQueries::Compare(const std::string &rStoreDir, - const std::string &rLocalDir, BoxBackupCompareParams &rParams) -{ -#ifdef WIN32 - std::string localDirEncoded; - std::string storeDirEncoded; - if(!ConvertConsoleToUtf8(rLocalDir.c_str(), localDirEncoded)) return; - if(!ConvertConsoleToUtf8(rStoreDir.c_str(), storeDirEncoded)) return; -#else - const std::string& localDirEncoded(rLocalDir); - const std::string& storeDirEncoded(rStoreDir); -#endif - - // Get the directory ID of the directory -- only use current data - int64_t dirID = FindDirectoryObjectID(storeDirEncoded); - - // Found? - if(dirID == 0) - { - bool modifiedAfterLastSync = false; - - EMU_STRUCT_STAT st; - if(EMU_STAT(rLocalDir.c_str(), &st) == 0) - { - if(FileAttrModificationTime(st) > - rParams.LatestFileUploadTime()) - { - modifiedAfterLastSync = true; - } - } - - rParams.NotifyRemoteFileMissing(localDirEncoded, - storeDirEncoded, modifiedAfterLastSync); - return; - } - - // Go! - Compare(dirID, storeDirEncoded, localDirEncoded, rParams); -} - -void BackupQueries::CompareOneFile(int64_t DirID, - BackupStoreDirectory::Entry *pEntry, - const std::string& rLocalPath, - const std::string& rStorePath, - BoxBackupCompareParams &rParams) -{ - int64_t fileId = pEntry->GetObjectID(); - int64_t fileSize = 0; - - EMU_STRUCT_STAT st; - if(EMU_STAT(rLocalPath.c_str(), &st) == 0) - { - fileSize = st.st_size; - } - - try - { - // Files the same flag? - bool equal = true; - - // File modified after last sync flag - bool modifiedAfterLastSync = false; - - bool hasDifferentAttribs = false; - - bool alreadyReported = false; - - if(rParams.QuickCompare()) - { - // Compare file -- fetch it - mrConnection.QueryGetBlockIndexByID(fileId); - - // Stream containing block index - std::auto_ptr blockIndexStream(mrConnection.ReceiveStream()); - - // Compare - equal = BackupStoreFile::CompareFileContentsAgainstBlockIndex( - rLocalPath.c_str(), *blockIndexStream, - mrConnection.GetTimeout()); - } - else - { - // Compare file -- fetch it - mrConnection.QueryGetFile(DirID, pEntry->GetObjectID()); - - // Stream containing encoded file - std::auto_ptr objectStream(mrConnection.ReceiveStream()); - - // Decode it - std::auto_ptr fileOnServerStream; - - // Got additional attributes? - if(pEntry->HasAttributes()) - { - // Use these attributes - const StreamableMemBlock &storeAttr(pEntry->GetAttributes()); - BackupClientFileAttributes attr(storeAttr); - fileOnServerStream.reset( - BackupStoreFile::DecodeFileStream( - *objectStream, - mrConnection.GetTimeout(), - &attr).release()); - } - else - { - // Use attributes stored in file - fileOnServerStream.reset(BackupStoreFile::DecodeFileStream(*objectStream, mrConnection.GetTimeout()).release()); - } - - // Should always be something in the auto_ptr, it's how the interface is defined. But be paranoid. - if(!fileOnServerStream.get()) - { - THROW_EXCEPTION(BackupStoreException, Internal) - } - - // Compare attributes - BackupClientFileAttributes localAttr; - box_time_t fileModTime = 0; - localAttr.ReadAttributes(rLocalPath.c_str(), false /* don't zero mod times */, &fileModTime); - modifiedAfterLastSync = (fileModTime > rParams.LatestFileUploadTime()); - bool ignoreAttrModTime = true; - - #ifdef WIN32 - // attr mod time is really - // creation time, so check it - ignoreAttrModTime = false; - #endif - - if(!rParams.IgnoreAttributes() && - #ifdef PLATFORM_DISABLE_SYMLINK_ATTRIB_COMPARE - !fileOnServerStream->IsSymLink() && - #endif - !localAttr.Compare(fileOnServerStream->GetAttributes(), - ignoreAttrModTime, - fileOnServerStream->IsSymLink() /* ignore modification time if it's a symlink */)) - { - hasDifferentAttribs = true; - } - - // Compare contents, if it's a regular file not a link - // Remember, we MUST read the entire stream from the server. - SelfFlushingStream flushObject(*objectStream); - - if(!fileOnServerStream->IsSymLink()) - { - SelfFlushingStream flushFile(*fileOnServerStream); - // Open the local file - std::auto_ptr apLocalFile; - - try - { - apLocalFile.reset(new FileStream(rLocalPath.c_str())); - } - catch(std::exception &e) - { - rParams.NotifyLocalFileReadFailed(rLocalPath, - rStorePath, fileSize, e); - alreadyReported = true; - } - catch(...) - { - rParams.NotifyLocalFileReadFailed(rLocalPath, - rStorePath, fileSize); - alreadyReported = true; - } - - if(apLocalFile.get()) - { - equal = apLocalFile->CompareWith(*fileOnServerStream, - mrConnection.GetTimeout()); - } - } - } - - rParams.NotifyFileCompared(rLocalPath, rStorePath, fileSize, - hasDifferentAttribs, !equal, modifiedAfterLastSync, - pEntry->HasAttributes()); - } - catch(BoxException &e) - { - rParams.NotifyDownloadFailed(rLocalPath, rStorePath, fileSize, - e); - } - catch(std::exception &e) - { - rParams.NotifyDownloadFailed(rLocalPath, rStorePath, fileSize, - e); - } - catch(...) - { - rParams.NotifyDownloadFailed(rLocalPath, rStorePath, fileSize); - } -} - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::Compare(int64_t, const std::string &, -// const std::string &, BackupQueries::CompareParams &) -// Purpose: Compare a store directory against a local directory -// Created: 2003/10/13 -// -// -------------------------------------------------------------------------- -void BackupQueries::Compare(int64_t DirID, const std::string &rStoreDir, - const std::string &rLocalDir, BoxBackupCompareParams &rParams) -{ - rParams.NotifyDirComparing(rLocalDir, rStoreDir); - - // Get info on the local directory - EMU_STRUCT_STAT st; - if(EMU_LSTAT(rLocalDir.c_str(), &st) != 0) - { - // What kind of error? - if(errno == ENOTDIR || errno == ENOENT) - { - rParams.NotifyLocalDirMissing(rLocalDir, rStoreDir); - } - else - { - rParams.NotifyLocalDirAccessFailed(rLocalDir, rStoreDir); - } - return; - } - - // Get the directory listing from the store - mrConnection.QueryListDirectory( - DirID, - BackupProtocolListDirectory::Flags_INCLUDE_EVERYTHING, - // get everything - BackupProtocolListDirectory::Flags_OldVersion | - BackupProtocolListDirectory::Flags_Deleted, - // except for old versions and deleted files - true /* want attributes */); - - // Retrieve the directory from the stream following - BackupStoreDirectory dir; - std::auto_ptr dirstream(mrConnection.ReceiveStream()); - dir.ReadFromStream(*dirstream, mrConnection.GetTimeout()); - - // Test out the attributes - if(!dir.HasAttributes()) - { - rParams.NotifyStoreDirMissingAttributes(rLocalDir, rStoreDir); - } - else - { - // Fetch the attributes - const StreamableMemBlock &storeAttr(dir.GetAttributes()); - BackupClientFileAttributes attr(storeAttr); - - // Get attributes of local directory - BackupClientFileAttributes localAttr; - localAttr.ReadAttributes(rLocalDir.c_str(), - true /* directories have zero mod times */); - - if(attr.Compare(localAttr, true, true /* ignore modification times */)) - { - rParams.NotifyDirCompared(rLocalDir, rStoreDir, - false, false /* actually we didn't check :) */); - } - else - { - bool modifiedAfterLastSync = false; - - EMU_STRUCT_STAT st; - if(EMU_STAT(rLocalDir.c_str(), &st) == 0) - { - if(FileAttrModificationTime(st) > - rParams.LatestFileUploadTime()) - { - modifiedAfterLastSync = true; - } - } - - rParams.NotifyDirCompared(rLocalDir, rStoreDir, - true, modifiedAfterLastSync); - } - } - - // Open the local directory - DIR *dirhandle = ::opendir(rLocalDir.c_str()); - if(dirhandle == 0) - { - rParams.NotifyLocalDirAccessFailed(rLocalDir, rStoreDir); - return; - } - - try - { - // Read the files and directories into sets - std::set localFiles; - std::set localDirs; - struct dirent *localDirEn = 0; - while((localDirEn = readdir(dirhandle)) != 0) - { - // Not . and ..! - if(localDirEn->d_name[0] == '.' && - (localDirEn->d_name[1] == '\0' || (localDirEn->d_name[1] == '.' && localDirEn->d_name[2] == '\0'))) - { - // ignore, it's . or .. - -#ifdef HAVE_VALID_DIRENT_D_TYPE - if (localDirEn->d_type != DT_DIR) - { - BOX_ERROR("d_type does not really " - "work on your platform. " - "Reconfigure Box!"); - return; - } -#endif - - continue; - } - - std::string localDirPath(MakeFullPath(rLocalDir, - localDirEn->d_name)); - std::string storeDirPath(rStoreDir + "/" + - localDirEn->d_name); - -#ifndef HAVE_VALID_DIRENT_D_TYPE - EMU_STRUCT_STAT st; - if(EMU_LSTAT(localDirPath.c_str(), &st) != 0) - { - // Check whether dir is excluded before trying - // to stat it, to fix problems with .gvfs - // directories that are not readable by root - // causing compare to crash: - // http://lists.boxbackup.org/pipermail/boxbackup/2010-January/000013.html - if(rParams.IsExcludedDir(localDirPath)) - { - rParams.NotifyExcludedDir(localDirPath, - storeDirPath); - continue; - } - else - { - THROW_EXCEPTION_MESSAGE(CommonException, - OSFileError, localDirPath); - } - } - - // Entry -- file or dir? - if(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) - { - // File or symbolic link - localFiles.insert(std::string(localDirEn->d_name)); - } - else if(S_ISDIR(st.st_mode)) - { - // Directory - localDirs.insert(std::string(localDirEn->d_name)); - } -#else - // Entry -- file or dir? - if(localDirEn->d_type == DT_REG || localDirEn->d_type == DT_LNK) - { - // File or symbolic link - localFiles.insert(std::string(localDirEn->d_name)); - } - else if(localDirEn->d_type == DT_DIR) - { - // Directory - localDirs.insert(std::string(localDirEn->d_name)); - } -#endif - } - // Close directory - if(::closedir(dirhandle) != 0) - { - BOX_LOG_SYS_ERROR("Failed to close local directory " - "'" << rLocalDir << "'"); - } - dirhandle = 0; - - // Do the same for the store directories - std::set > storeFiles; - std::set > storeDirs; - - BackupStoreDirectory::Iterator i(dir); - BackupStoreDirectory::Entry *storeDirEn = 0; - while((storeDirEn = i.Next()) != 0) - { - // Decrypt filename - BackupStoreFilenameClear name(storeDirEn->GetName()); - - // What is it? - if((storeDirEn->GetFlags() & BackupStoreDirectory::Entry::Flags_File) == BackupStoreDirectory::Entry::Flags_File) - { - // File - storeFiles.insert(std::pair(name.GetClearFilename(), storeDirEn)); - } - else - { - // Dir - storeDirs.insert(std::pair(name.GetClearFilename(), storeDirEn)); - } - } - -#ifdef _MSC_VER - typedef std::set::iterator string_set_iter_t; -#else - typedef std::set::const_iterator string_set_iter_t; -#endif - - // Now compare files. - for(std::set >::const_iterator i = storeFiles.begin(); i != storeFiles.end(); ++i) - { - const std::string& fileName(i->first); - - std::string localPath(MakeFullPath(rLocalDir, fileName)); - std::string storePath(rStoreDir + "/" + fileName); - - rParams.NotifyFileComparing(localPath, storePath); - - // Does the file exist locally? - string_set_iter_t local(localFiles.find(fileName)); - if(local == localFiles.end()) - { - // Not found -- report - rParams.NotifyLocalFileMissing(localPath, - storePath); - } - else - { - CompareOneFile(DirID, i->second, localPath, - storePath, rParams); - - // Remove from set so that we know it's been compared - localFiles.erase(local); - } - } - - // Report any files which exist locally, but not on the store - for(string_set_iter_t i = localFiles.begin(); i != localFiles.end(); ++i) - { - std::string localPath(MakeFullPath(rLocalDir, *i)); - std::string storePath(rStoreDir + "/" + *i); - - // Should this be ignored (ie is excluded)? - if(!rParams.IsExcludedFile(localPath)) - { - bool modifiedAfterLastSync = false; - - EMU_STRUCT_STAT st; - if(EMU_STAT(localPath.c_str(), &st) == 0) - { - if(FileModificationTime(st) > - rParams.LatestFileUploadTime()) - { - modifiedAfterLastSync = true; - } - } - - rParams.NotifyRemoteFileMissing(localPath, - storePath, modifiedAfterLastSync); - } - else - { - rParams.NotifyExcludedFile(localPath, - storePath); - } - } - - // Finished with the files, clear the sets to reduce memory usage slightly - localFiles.clear(); - storeFiles.clear(); - - // Now do the directories, recursively to check subdirectories - for(std::set >::const_iterator i = storeDirs.begin(); i != storeDirs.end(); ++i) - { - std::string localPath(MakeFullPath(rLocalDir, i->first)); - std::string storePath(rStoreDir + "/" + i->first); - - // Does the directory exist locally? - string_set_iter_t local(localDirs.find(i->first)); - if(local == localDirs.end() && - rParams.IsExcludedDir(localPath)) - { - rParams.NotifyExcludedFileNotDeleted(localPath, - storePath); - } - else if(local == localDirs.end()) - { - // Not found -- report - rParams.NotifyLocalFileMissing(localPath, - storePath); - } - else if(rParams.IsExcludedDir(localPath)) - { - // don't recurse into excluded directories - } - else - { - // Compare directory - Compare(i->second->GetObjectID(), - storePath, localPath, rParams); - - // Remove from set so that we know it's been compared - localDirs.erase(local); - } - } - - // Report any directories which exist locally, but not on the store - for(std::set::const_iterator - i = localDirs.begin(); - i != localDirs.end(); ++i) - { - std::string localPath(MakeFullPath(rLocalDir, *i)); - std::string storePath(rStoreDir + "/" + *i); - - // Should this be ignored (ie is excluded)? - if(!rParams.IsExcludedDir(localPath)) - { - bool modifiedAfterLastSync = false; - - // Check the dir modification time - EMU_STRUCT_STAT st; - if(EMU_STAT(localPath.c_str(), &st) == 0 && - FileModificationTime(st) > - rParams.LatestFileUploadTime()) - { - modifiedAfterLastSync = true; - } - - rParams.NotifyRemoteFileMissing(localPath, - storePath, modifiedAfterLastSync); - } - else - { - rParams.NotifyExcludedDir(localPath, storePath); - } - } - } - catch(...) - { - if(dirhandle != 0) - { - ::closedir(dirhandle); - } - throw; - } -} - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CommandRestore(const std::vector &, const bool *) -// Purpose: Restore a directory -// Created: 23/11/03 -// -// -------------------------------------------------------------------------- -void BackupQueries::CommandRestore(const std::vector &args, const bool *opts) -{ - // Check arguments - if(args.size() < 1 || args.size() > 2) - { - BOX_ERROR("Incorrect usage. restore [-drif] " - "[]"); - return; - } - - // Restoring deleted things? - bool restoreDeleted = opts['d']; - - std::string storeDirEncoded; - - // Get directory ID - int64_t dirID = 0; - if(opts['i']) - { - // Specified as ID. - dirID = ::strtoll(args[0].c_str(), 0, 16); - if(dirID == std::numeric_limits::min() || dirID == std::numeric_limits::max() || dirID == 0) - { - BOX_ERROR("Not a valid object ID (specified in hex): " - << args[0]); - return; - } - std::ostringstream oss; - oss << BOX_FORMAT_OBJECTID(args[0]); - storeDirEncoded = oss.str(); - } - else - { -#ifdef WIN32 - if(!ConvertConsoleToUtf8(args[0].c_str(), storeDirEncoded)) - return; -#else - storeDirEncoded = args[0]; -#endif - - // Look up directory ID - dirID = FindDirectoryObjectID(storeDirEncoded, - false /* no old versions */, - restoreDeleted /* find deleted dirs */); - } - - // Allowable? - if(dirID == 0) - { - BOX_ERROR("Directory '" << args[0] << "' not found on server"); - return; - } - - if(dirID == BackupProtocolListDirectory::RootDirectory) - { - BOX_ERROR("Cannot restore the root directory -- restore locations individually."); - return; - } - - std::string localName; - - if(args.size() == 2) - { - #ifdef WIN32 - if(!ConvertConsoleToUtf8(args[1].c_str(), localName)) - { - return; - } - #else - localName = args[1]; - #endif - } - else - { - localName = args[0]; - } - - // Go and restore... - int result; - - try - { - // At TRACE level, we print a line for each file and - // directory, so we don't need dots. - - result = BackupClientRestore(mrConnection, dirID, - storeDirEncoded.c_str(), localName.c_str(), - true /* print progress dots */, restoreDeleted, - false /* don't undelete after restore! */, - opts['r'] /* resume? */, - opts['f'] /* force continue after errors */); - } - catch(std::exception &e) - { - BOX_ERROR("Failed to restore: " << e.what()); - SetReturnCode(ReturnCode::Command_Error); - return; - } - catch(...) - { - BOX_ERROR("Failed to restore: unknown exception"); - SetReturnCode(ReturnCode::Command_Error); - return; - } - - switch(result) - { - case Restore_Complete: - BOX_INFO("Restore complete."); - break; - - case Restore_CompleteWithErrors: - BOX_WARNING("Restore complete, but some files could not be " - "restored."); - break; - - case Restore_ResumePossible: - BOX_ERROR("Resume possible -- repeat command with -r flag " - "to resume."); - SetReturnCode(ReturnCode::Command_Error); - break; - - case Restore_TargetExists: - BOX_ERROR("The target directory exists. You cannot restore " - "over an existing directory."); - SetReturnCode(ReturnCode::Command_Error); - break; - - case Restore_TargetPathNotFound: - BOX_ERROR("The target directory path does not exist.\n" - "To restore to a directory whose parent " - "does not exist, create the parent first."); - SetReturnCode(ReturnCode::Command_Error); - break; - - case Restore_UnknownError: - BOX_ERROR("Unknown error during restore."); - SetReturnCode(ReturnCode::Command_Error); - break; - - default: - BOX_ERROR("Unknown restore result " << result << "."); - SetReturnCode(ReturnCode::Command_Error); - break; - } -} - - - -// These are autogenerated by a script. -extern const char *help_commands[]; -extern const char *help_text[]; - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CommandHelp(const std::vector &args) -// Purpose: Display help on commands -// Created: 15/2/04 -// -// -------------------------------------------------------------------------- -void BackupQueries::CommandHelp(const std::vector &args) -{ - if(args.size() == 0) - { - // Display a list of all commands - printf("Available commands are:\n"); - for(int c = 0; help_commands[c] != 0; ++c) - { - printf(" %s\n", help_commands[c]); - } - printf("Type \"help \" for more information on a command.\n\n"); - } - else - { - // Display help on a particular command - int c; - for(c = 0; help_commands[c] != 0; ++c) - { - if(::strcmp(help_commands[c], args[0].c_str()) == 0) - { - // Found the command, print help - printf("\n%s\n", help_text[c]); - break; - } - } - if(help_commands[c] == 0) - { - printf("No help found for command '%s'\n", args[0].c_str()); - } - } -} - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CommandUsage() -// Purpose: Display storage space used on server -// Created: 19/4/04 -// -// -------------------------------------------------------------------------- -void BackupQueries::CommandUsage(const bool *opts) -{ - bool MachineReadable = opts['m']; - - // Request full details from the server - std::auto_ptr usage(mrConnection.QueryGetAccountUsage()); - - // Display each entry in turn - int64_t hardLimit = usage->GetBlocksHardLimit(); - int32_t blockSize = usage->GetBlockSize(); - CommandUsageDisplayEntry("Used", usage->GetBlocksUsed(), hardLimit, - blockSize, MachineReadable); - CommandUsageDisplayEntry("Old files", usage->GetBlocksInOldFiles(), - hardLimit, blockSize, MachineReadable); - CommandUsageDisplayEntry("Deleted files", usage->GetBlocksInDeletedFiles(), - hardLimit, blockSize, MachineReadable); - CommandUsageDisplayEntry("Directories", usage->GetBlocksInDirectories(), - hardLimit, blockSize, MachineReadable); - CommandUsageDisplayEntry("Soft limit", usage->GetBlocksSoftLimit(), - hardLimit, blockSize, MachineReadable); - CommandUsageDisplayEntry("Hard limit", hardLimit, hardLimit, blockSize, - MachineReadable); -} - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CommandUsageDisplayEntry(const char *, -// int64_t, int64_t, int32_t, bool) -// Purpose: Display an entry in the usage table -// Created: 19/4/04 -// -// -------------------------------------------------------------------------- -void BackupQueries::CommandUsageDisplayEntry(const char *Name, int64_t Size, -int64_t HardLimit, int32_t BlockSize, bool MachineReadable) -{ - std::cout << FormatUsageLineStart(Name, MachineReadable) << - FormatUsageBar(Size, Size * BlockSize, HardLimit * BlockSize, - MachineReadable) << std::endl; -} - - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CommandUndelete(const std::vector &, const bool *) -// Purpose: Undelete a directory -// Created: 23/11/03 -// -// -------------------------------------------------------------------------- -void BackupQueries::CommandUndelete(const std::vector &args, const bool *opts) -{ - if (!mReadWrite) - { - BOX_ERROR("This command requires a read-write connection. " - "Please reconnect with the -w option."); - return; - } - - // Check arguments - if(args.size() != 1) - { - BOX_ERROR("Incorrect usage. undelete or undelete -i "); - return; - } - -#ifdef WIN32 - std::string storeDirEncoded; - if(!ConvertConsoleToUtf8(args[0].c_str(), storeDirEncoded)) return; -#else - const std::string& storeDirEncoded(args[0]); -#endif - - // Find object ID somehow - int64_t fileId, parentId; - std::string fileName; - int16_t flagsOut; - - fileId = FindFileID(storeDirEncoded, opts, &parentId, &fileName, - /* include files and directories */ - BackupProtocolListDirectory::Flags_EXCLUDE_NOTHING, - /* include old and deleted files */ - BackupProtocolListDirectory::Flags_EXCLUDE_NOTHING, - &flagsOut); - - if (fileId == 0) - { - // error already reported - return; - } - - // Undelete it on the store - try - { - // Undelete object - if(flagsOut & BackupProtocolListDirectory::Flags_File) - { - mrConnection.QueryUndeleteFile(parentId, fileId); - } - else - { - mrConnection.QueryUndeleteDirectory(fileId); - } - } - catch (BoxException &e) - { - BOX_ERROR("Failed to undelete object: " << - e.what()); - } - catch(std::exception &e) - { - BOX_ERROR("Failed to undelete object: " << - e.what()); - } - catch(...) - { - BOX_ERROR("Failed to undelete object: unknown error"); - } -} - -// -------------------------------------------------------------------------- -// -// Function -// Name: BackupQueries::CommandDelete(const -// std::vector &, const bool *) -// Purpose: Deletes a file -// Created: 23/11/03 -// -// -------------------------------------------------------------------------- -void BackupQueries::CommandDelete(const std::vector &args, - const bool *opts) -{ - if (!mReadWrite) - { - BOX_ERROR("This command requires a read-write connection. " - "Please reconnect with the -w option."); - return; - } - - // Check arguments - if(args.size() != 1) - { - BOX_ERROR("Incorrect usage. delete "); - return; - } - -#ifdef WIN32 - std::string storeDirEncoded; - if(!ConvertConsoleToUtf8(args[0].c_str(), storeDirEncoded)) return; -#else - const std::string& storeDirEncoded(args[0]); -#endif - - // Find object ID somehow - int64_t fileId, parentId; - std::string fileName; - int16_t flagsOut; - - fileId = FindFileID(storeDirEncoded, opts, &parentId, &fileName, - /* include files and directories */ - BackupProtocolListDirectory::Flags_EXCLUDE_NOTHING, - /* exclude old and deleted files */ - BackupProtocolListDirectory::Flags_OldVersion | - BackupProtocolListDirectory::Flags_Deleted, - &flagsOut); - - if (fileId == 0) - { - // error already reported - return; - } - - BackupStoreFilenameClear fn(fileName); - - // Delete it on the store - try - { - // Delete object - if(flagsOut & BackupProtocolListDirectory::Flags_File) - { - mrConnection.QueryDeleteFile(parentId, fn); - } - else - { - mrConnection.QueryDeleteDirectory(fileId); - } - } - catch (BoxException &e) - { - BOX_ERROR("Failed to delete object: " << - e.what()); - } - catch(std::exception &e) - { - BOX_ERROR("Failed to delete object: " << - e.what()); - } - catch(...) - { - BOX_ERROR("Failed to delete object: unknown error"); - } -} diff --git a/bin/bbackupquery/BackupQueries.h b/bin/bbackupquery/BackupQueries.h deleted file mode 100644 index 96df34f5..00000000 --- a/bin/bbackupquery/BackupQueries.h +++ /dev/null @@ -1,440 +0,0 @@ -// -------------------------------------------------------------------------- -// -// File -// Name: BackupQueries.h -// Purpose: Perform various queries on the backup store server. -// Created: 2003/10/10 -// -// -------------------------------------------------------------------------- - -#ifndef BACKUPQUERIES__H -#define BACKUPQUERIES__H - -#include -#include -#include - -#include "BoxTime.h" -#include "BoxBackupCompareParams.h" -#include "BackupStoreDirectory.h" - -class BackupProtocolCallable; -class Configuration; -class ExcludeList; - -typedef enum -{ - Command_Unknown = 0, - Command_Quit, - Command_List, - Command_pwd, - Command_cd, - Command_lcd, - Command_sh, - Command_GetObject, - Command_Get, - Command_Compare, - Command_Restore, - Command_Help, - Command_Usage, - Command_Undelete, - Command_Delete, -} -CommandType; - -struct QueryCommandSpecification; - -// -------------------------------------------------------------------------- -// -// Class -// Name: BackupQueries -// Purpose: Perform various queries on the backup store server. -// Created: 2003/10/10 -// -// -------------------------------------------------------------------------- -class BackupQueries -{ -public: - BackupQueries(BackupProtocolCallable &rConnection, - const Configuration &rConfiguration, - bool readWrite); - ~BackupQueries(); -private: - BackupQueries(const BackupQueries &); -public: - struct ParsedCommand - { - std::vector mCmdElements; - std::string mOptions; - std::string mCompleteCommand; - bool mInOptions, mFailed; - QueryCommandSpecification* pSpec; - // mArgCount is the same as mCmdElements.size() for a complete - // command, but if the command line ends in a space, - // e.g. during readline parsing, it can be one greater, - // to indicate that we should complete the next item instead. - size_t mCompleteArgCount; - ParsedCommand(const std::string& Command, - bool isFromCommandLine); - bool IsEmpty() { return mCmdElements.empty(); } - bool IsFailed() { return mFailed; } - }; - - void DoCommand(ParsedCommand& rCommand); - - // Ready to stop? - bool Stop() {return mQuitNow;} - - // Return code? - int GetReturnCode() {return mReturnCode;} - - void List(int64_t DirID, const std::string &rListRoot, const bool *opts, - bool FirstLevel, std::ostream* pOut = NULL); - void CommandList(const std::vector &args, const bool *opts); - - // Commands - void CommandChangeDir(const std::vector &args, const bool *opts); - void CommandChangeLocalDir(const std::vector &args); - void CommandGetObject(const std::vector &args, const bool *opts); - void CommandGet(std::vector args, const bool *opts); - void CommandCompare(const std::vector &args, const bool *opts); - void CommandRestore(const std::vector &args, const bool *opts); - void CommandUndelete(const std::vector &args, const bool *opts); - void CommandDelete(const std::vector &args, - const bool *opts); - void CommandUsage(const bool *opts); - void CommandUsageDisplayEntry(const char *Name, int64_t Size, - int64_t HardLimit, int32_t BlockSize, bool MachineReadable); - void CommandHelp(const std::vector &args); - - class CompareParams : public BoxBackupCompareParams - { - public: - CompareParams(bool QuickCompare, bool IgnoreExcludes, - bool IgnoreAttributes, box_time_t LatestFileUploadTime); - - bool mQuietCompare; - int mDifferences; - int mDifferencesExplainedByModTime; - int mUncheckedFiles; - int mExcludedDirs; - int mExcludedFiles; - - std::string ConvertForConsole(const std::string& rUtf8String) - { - #ifdef WIN32 - std::string output; - - if(!ConvertUtf8ToConsole(rUtf8String.c_str(), output)) - { - BOX_WARNING("Character set conversion failed " - "on string: " << rUtf8String); - return rUtf8String; - } - - return output; - #else - return rUtf8String; - #endif - } - - virtual void NotifyLocalDirMissing(const std::string& rLocalPath, - const std::string& rRemotePath) - { - BOX_WARNING("Local directory '" << - ConvertForConsole(rLocalPath) << "' " - "does not exist, but remote directory does."); - mDifferences ++; - } - - virtual void NotifyLocalDirAccessFailed( - const std::string& rLocalPath, - const std::string& rRemotePath) - { - BOX_LOG_SYS_WARNING("Failed to access local directory " - "'" << ConvertForConsole(rLocalPath) << "'"); - mUncheckedFiles ++; - } - - virtual void NotifyStoreDirMissingAttributes( - const std::string& rLocalPath, - const std::string& rRemotePath) - { - BOX_WARNING("Store directory '" << - ConvertForConsole(rRemotePath) << "' " - "doesn't have attributes."); - } - - virtual void NotifyRemoteFileMissing( - const std::string& rLocalPath, - const std::string& rRemotePath, - bool modifiedAfterLastSync) - { - BOX_WARNING("Local file '" << - ConvertForConsole(rLocalPath) << "' " - "exists, but remote file '" << - ConvertForConsole(rRemotePath) << "' " - "does not."); - mDifferences ++; - - if(modifiedAfterLastSync) - { - mDifferencesExplainedByModTime ++; - BOX_INFO("(the file above was modified after " - "the last sync time -- might be " - "reason for difference)"); - } - } - - virtual void NotifyLocalFileMissing( - const std::string& rLocalPath, - const std::string& rRemotePath) - { - BOX_WARNING("Remote file '" << - ConvertForConsole(rRemotePath) << "' " - "exists, but local file '" << - ConvertForConsole(rLocalPath) << "' does not."); - mDifferences ++; - } - - virtual void NotifyExcludedFileNotDeleted( - const std::string& rLocalPath, - const std::string& rRemotePath) - { - BOX_WARNING("Local file '" << - ConvertForConsole(rLocalPath) << "' " - "is excluded, but remote file '" << - ConvertForConsole(rRemotePath) << "' " - "still exists."); - mDifferences ++; - } - - virtual void NotifyDownloadFailed(const std::string& rLocalPath, - const std::string& rRemotePath, int64_t NumBytes, - BoxException& rException) - { - BOX_ERROR("Failed to download remote file '" << - ConvertForConsole(rRemotePath) << "': " << - rException.what() << " (" << - rException.GetType() << "/" << - rException.GetSubType() << ")"); - mUncheckedFiles ++; - } - - virtual void NotifyDownloadFailed(const std::string& rLocalPath, - const std::string& rRemotePath, int64_t NumBytes, - std::exception& rException) - { - BOX_ERROR("Failed to download remote file '" << - ConvertForConsole(rRemotePath) << "': " << - rException.what()); - mUncheckedFiles ++; - } - - virtual void NotifyDownloadFailed(const std::string& rLocalPath, - const std::string& rRemotePath, int64_t NumBytes) - { - BOX_ERROR("Failed to download remote file '" << - ConvertForConsole(rRemotePath)); - mUncheckedFiles ++; - } - - virtual void NotifyLocalFileReadFailed(const std::string& rLocalPath, - const std::string& rRemotePath, int64_t NumBytes, - std::exception& rException) - { - BOX_ERROR("Failed to read local file '" << - ConvertForConsole(rLocalPath) << "': " << - rException.what()); - mUncheckedFiles ++; - } - - virtual void NotifyLocalFileReadFailed(const std::string& rLocalPath, - const std::string& rRemotePath, int64_t NumBytes) - { - BOX_ERROR("Failed to read local file '" << - ConvertForConsole(rLocalPath)); - mUncheckedFiles ++; - } - - virtual void NotifyExcludedFile(const std::string& rLocalPath, - const std::string& rRemotePath) - { - mExcludedFiles ++; - } - - virtual void NotifyExcludedDir(const std::string& rLocalPath, - const std::string& rRemotePath) - { - mExcludedDirs ++; - } - - virtual void NotifyDirComparing(const std::string& rLocalPath, - const std::string& rRemotePath) - { - BOX_INFO("Comparing directory: " << rLocalPath); - } - - virtual void NotifyDirCompared( - const std::string& rLocalPath, - const std::string& rRemotePath, - bool HasDifferentAttributes, - bool modifiedAfterLastSync) - { - if(HasDifferentAttributes) - { - BOX_WARNING("Local directory '" << - ConvertForConsole(rLocalPath) << "' " - "has different attributes to " - "store directory '" << - ConvertForConsole(rRemotePath) << "'."); - mDifferences ++; - - if(modifiedAfterLastSync) - { - mDifferencesExplainedByModTime ++; - BOX_INFO("(the directory above was " - "modified after the last sync " - "time -- might be reason for " - "difference)"); - } - } - } - - virtual void NotifyFileComparing(const std::string& rLocalPath, - const std::string& rRemotePath) - { - BOX_TRACE("Comparing file: " << rLocalPath); - } - - virtual void NotifyFileCompared(const std::string& rLocalPath, - const std::string& rRemotePath, int64_t NumBytes, - bool HasDifferentAttributes, bool HasDifferentContents, - bool ModifiedAfterLastSync, bool NewAttributesApplied) - { - int NewDifferences = 0; - - if(HasDifferentAttributes) - { - BOX_WARNING("Local file '" << - ConvertForConsole(rLocalPath) << "' " - "has different attributes to " - "store file '" << - ConvertForConsole(rRemotePath) << "'."); - NewDifferences ++; - } - - if(HasDifferentContents) - { - BOX_WARNING("Local file '" << - ConvertForConsole(rLocalPath) << "' " - "has different contents to " - "store file '" << - ConvertForConsole(rRemotePath) << "'."); - NewDifferences ++; - } - - if(HasDifferentAttributes || HasDifferentContents) - { - if(ModifiedAfterLastSync) - { - mDifferencesExplainedByModTime += - NewDifferences; - BOX_INFO("(the file above was modified " - "after the last sync time -- " - "might be reason for difference)"); - } - else if(NewAttributesApplied) - { - BOX_INFO("(the file above has had new " - "attributes applied)\n"); - } - } - - mDifferences += NewDifferences; - } - }; - void CompareLocation(const std::string &rLocation, - BoxBackupCompareParams &rParams); - void Compare(const std::string &rStoreDir, - const std::string &rLocalDir, BoxBackupCompareParams &rParams); - void Compare(int64_t DirID, const std::string &rStoreDir, - const std::string &rLocalDir, BoxBackupCompareParams &rParams); - void CompareOneFile(int64_t DirID, BackupStoreDirectory::Entry *pEntry, - const std::string& rLocalPath, const std::string& rStorePath, - BoxBackupCompareParams &rParams); - -public: - - class ReturnCode - { - public: - typedef enum { - Command_OK = 0, - Compare_Same = 1, - Compare_Different, - Compare_Error, - Command_Error, - } Type; - }; - - // Were private, but needed by completion functions: - int64_t GetCurrentDirectoryID(); - int64_t FindDirectoryObjectID(const std::string &rDirName, - bool AllowOldVersion = false, bool AllowDeletedDirs = false, - std::vector > *pStack = 0); - -private: - - // Utility functions - int64_t FindFileID(const std::string& rNameOrIdString, - const bool *opts, int64_t *pDirIdOut, - std::string* pFileNameOut, int16_t flagsInclude, - int16_t flagsExclude, int16_t* pFlagsOut); - std::string GetCurrentDirectoryName(); - void SetReturnCode(int code) {mReturnCode = code;} - -private: - bool mReadWrite; - BackupProtocolCallable &mrConnection; - const Configuration &mrConfiguration; - bool mQuitNow; - std::vector > mDirStack; - bool mRunningAsRoot; - bool mWarnedAboutOwnerAttributes; - int mReturnCode; -}; - -typedef std::vector (*CompletionHandler) - (BackupQueries::ParsedCommand& rCommand, const std::string& prefix, - BackupProtocolCallable& rProtocol, const Configuration& rConfig, - BackupQueries& rQueries); - -std::vector CompleteCommand(BackupQueries::ParsedCommand& rCommand, - const std::string& prefix, BackupProtocolCallable& rProtocol, - const Configuration& rConfig, BackupQueries& rQueries); -std::vector CompleteOptions(BackupQueries::ParsedCommand& rCommand, - const std::string& prefix, BackupProtocolCallable& rProtocol, - const Configuration& rConfig, BackupQueries& rQueries); - -#define MAX_COMPLETION_HANDLERS 4 - -struct QueryCommandSpecification -{ - const char* name; - const char* opts; - CommandType type; - CompletionHandler complete[MAX_COMPLETION_HANDLERS]; -}; - -// Data about commands -extern QueryCommandSpecification commands[]; - -extern const char *alias[]; -extern const int aliasIs[]; - -#define LIST_OPTION_ALLOWOLD 'o' -#define LIST_OPTION_ALLOWDELETED 'd' - -#endif // BACKUPQUERIES__H - diff --git a/bin/bbackupquery/BoxBackupCompareParams.h b/bin/bbackupquery/BoxBackupCompareParams.h deleted file mode 100644 index 655df947..00000000 --- a/bin/bbackupquery/BoxBackupCompareParams.h +++ /dev/null @@ -1,112 +0,0 @@ -// -------------------------------------------------------------------------- -// -// File -// Name: BoxBackupCompareParams.h -// Purpose: Parameters and notifiers for a compare operation -// Created: 2008/12/30 -// -// -------------------------------------------------------------------------- - -#ifndef BOXBACKUPCOMPAREPARAMS__H -#define BOXBACKUPCOMPAREPARAMS__H - -#include -#include - -#include "BoxTime.h" -#include "ExcludeList.h" -#include "BackupClientMakeExcludeList.h" - -// -------------------------------------------------------------------------- -// -// Class -// Name: BoxBackupCompareParams -// Purpose: Parameters and notifiers for a compare operation -// Created: 2003/10/10 -// -// -------------------------------------------------------------------------- -class BoxBackupCompareParams -{ -private: - std::auto_ptr mapExcludeFiles, mapExcludeDirs; - bool mQuickCompare; - bool mIgnoreExcludes; - bool mIgnoreAttributes; - box_time_t mLatestFileUploadTime; - -public: - BoxBackupCompareParams(bool QuickCompare, bool IgnoreExcludes, - bool IgnoreAttributes, box_time_t LatestFileUploadTime) - : mQuickCompare(QuickCompare), - mIgnoreExcludes(IgnoreExcludes), - mIgnoreAttributes(IgnoreAttributes), - mLatestFileUploadTime(LatestFileUploadTime) - { } - - virtual ~BoxBackupCompareParams() { } - - bool QuickCompare() { return mQuickCompare; } - bool IgnoreExcludes() { return mIgnoreExcludes; } - bool IgnoreAttributes() { return mIgnoreAttributes; } - box_time_t LatestFileUploadTime() { return mLatestFileUploadTime; } - - void LoadExcludeLists(const Configuration& rLoc) - { - mapExcludeFiles.reset(BackupClientMakeExcludeList_Files(rLoc)); - mapExcludeDirs.reset(BackupClientMakeExcludeList_Dirs(rLoc)); - } - bool IsExcludedFile(const std::string& rLocalPath) - { - if (!mapExcludeFiles.get()) return false; - return mapExcludeFiles->IsExcluded(rLocalPath); - } - bool IsExcludedDir(const std::string& rLocalPath) - { - if (!mapExcludeDirs.get()) return false; - return mapExcludeDirs->IsExcluded(rLocalPath); - } - - virtual void NotifyLocalDirMissing(const std::string& rLocalPath, - const std::string& rRemotePath) = 0; - virtual void NotifyLocalDirAccessFailed(const std::string& rLocalPath, - const std::string& rRemotePath) = 0; - virtual void NotifyStoreDirMissingAttributes(const std::string& rLocalPath, - const std::string& rRemotePath) = 0; - virtual void NotifyRemoteFileMissing(const std::string& rLocalPath, - const std::string& rRemotePath, - bool modifiedAfterLastSync) = 0; - virtual void NotifyLocalFileMissing(const std::string& rLocalPath, - const std::string& rRemotePath) = 0; - virtual void NotifyExcludedFileNotDeleted(const std::string& rLocalPath, - const std::string& rRemotePath) = 0; - virtual void NotifyDownloadFailed(const std::string& rLocalPath, - const std::string& rRemotePath, int64_t NumBytes, - BoxException& rException) = 0; - virtual void NotifyLocalFileReadFailed(const std::string& rLocalPath, - const std::string& rRemotePath, int64_t NumBytes, - std::exception& rException) = 0; - virtual void NotifyLocalFileReadFailed(const std::string& rLocalPath, - const std::string& rRemotePath, int64_t NumBytes) = 0; - virtual void NotifyDownloadFailed(const std::string& rLocalPath, - const std::string& rRemotePath, int64_t NumBytes, - std::exception& rException) = 0; - virtual void NotifyDownloadFailed(const std::string& rLocalPath, - const std::string& rRemotePath, int64_t NumBytes) = 0; - virtual void NotifyExcludedFile(const std::string& rLocalPath, - const std::string& rRemotePath) = 0; - virtual void NotifyExcludedDir(const std::string& rLocalPath, - const std::string& rRemotePath) = 0; - virtual void NotifyDirComparing(const std::string& rLocalPath, - const std::string& rRemotePath) = 0; - virtual void NotifyDirCompared(const std::string& rLocalPath, - const std::string& rRemotePath, bool HasDifferentAttributes, - bool modifiedAfterLastSync) = 0; - virtual void NotifyFileComparing(const std::string& rLocalPath, - const std::string& rRemotePath) = 0; - virtual void NotifyFileCompared(const std::string& rLocalPath, - const std::string& rRemotePath, int64_t NumBytes, - bool HasDifferentAttributes, bool HasDifferentContents, - bool modifiedAfterLastSync, bool newAttributesApplied) = 0; -}; - -#endif // BOXBACKUPCOMPAREPARAMS__H diff --git a/bin/bbackupquery/CommandCompletion.cpp b/bin/bbackupquery/CommandCompletion.cpp deleted file mode 100644 index 761fc97e..00000000 --- a/bin/bbackupquery/CommandCompletion.cpp +++ /dev/null @@ -1,604 +0,0 @@ -// -------------------------------------------------------------------------- -// -// File -// Name: CommandCompletion.cpp -// Purpose: Parts of BackupQueries that depend on readline -// Created: 2011/01/21 -// -// -------------------------------------------------------------------------- - -#include "Box.h" - -#ifdef HAVE_LIBREADLINE - #ifdef HAVE_READLINE_READLINE_H - #include - #elif defined(HAVE_EDITLINE_READLINE_H) - #include - #elif defined(HAVE_READLINE_H) - #include - #endif -#endif - -#ifdef HAVE_READLINE_HISTORY - #ifdef HAVE_READLINE_HISTORY_H - #include - #elif defined(HAVE_HISTORY_H) - #include - #endif -#endif - -#include - -#include "BackupQueries.h" -#include "Configuration.h" - -#include "autogen_BackupProtocol.h" - -#include "MemLeakFindOn.h" - -#define COMPARE_RETURN_SAME 1 -#define COMPARE_RETURN_DIFFERENT 2 -#define COMPARE_RETURN_ERROR 3 -#define COMMAND_RETURN_ERROR 4 - -#define COMPLETION_FUNCTION(name, code) \ -std::vector Complete ## name( \ - BackupQueries::ParsedCommand& rCommand, \ - const std::string& prefix, \ - BackupProtocolCallable& rProtocol, const Configuration& rConfig, \ - BackupQueries& rQueries) \ -{ \ - std::vector completions; \ - \ - try \ - { \ - code \ - } \ - catch(std::exception &e) \ - { \ - BOX_TRACE("Failed to complete " << prefix << ": " << e.what()); \ - } \ - catch(...) \ - { \ - BOX_TRACE("Failed to complete " << prefix << ": " \ - "unknown error"); \ - } \ - \ - return completions; \ -} - -#define DELEGATE_COMPLETION(name) \ - completions = Complete ## name(rCommand, prefix, rProtocol, rConfig, \ - rQueries); - -COMPLETION_FUNCTION(None,) - -#ifdef HAVE_RL_FILENAME_COMPLETION_FUNCTION - #define RL_FILENAME_COMPLETION_FUNCTION rl_filename_completion_function - #define HAVE_A_FILENAME_COMPLETION_FUNCTION 1 -#elif defined HAVE_FILENAME_COMPLETION_FUNCTION - #define RL_FILENAME_COMPLETION_FUNCTION filename_completion_function - #define HAVE_A_FILENAME_COMPLETION_FUNCTION 1 -#endif - -#ifdef HAVE_A_FILENAME_COMPLETION_FUNCTION -COMPLETION_FUNCTION(Default, - int i = 0; - - while (const char *match = RL_FILENAME_COMPLETION_FUNCTION(prefix.c_str(), i)) - { - completions.push_back(match); - ++i; - } -) -#else // !HAVE_A_FILENAME_COMPLETION_FUNCTION -COMPLETION_FUNCTION(Default,) -#endif // HAVE_A_FILENAME_COMPLETION_FUNCTION - -COMPLETION_FUNCTION(Command, - int len = prefix.length(); - - for(int i = 0; commands[i].name != NULL; i++) - { - if(::strncmp(commands[i].name, prefix.c_str(), len) == 0) - { - completions.push_back(commands[i].name); - } - } -) - -void CompleteOptionsInternal(const std::string& prefix, - BackupQueries::ParsedCommand& rCommand, - std::vector& completions) -{ - std::string availableOptions = rCommand.pSpec->opts; - - for(std::string::iterator - opt = availableOptions.begin(); - opt != availableOptions.end(); opt++) - { - if(rCommand.mOptions.find(*opt) == std::string::npos) - { - if(prefix == "") - { - // complete with possible option strings - completions.push_back(std::string("-") + *opt); - } - else - { - // complete with possible additional options - completions.push_back(prefix + *opt); - } - } - } -} - -COMPLETION_FUNCTION(Options, - CompleteOptionsInternal(prefix, rCommand, completions); -) - -std::string EncodeFileName(const std::string &rUnEncodedName) -{ -#ifdef WIN32 - std::string encodedName; - if(!ConvertConsoleToUtf8(rUnEncodedName, encodedName)) - { - return std::string(); - } - return encodedName; -#else - return rUnEncodedName; -#endif -} - -int16_t GetExcludeFlags(BackupQueries::ParsedCommand& rCommand) -{ - int16_t excludeFlags = 0; - - if (rCommand.mOptions.find(LIST_OPTION_ALLOWOLD) == std::string::npos) - { - excludeFlags |= BackupProtocolListDirectory::Flags_OldVersion; - } - - if (rCommand.mOptions.find(LIST_OPTION_ALLOWDELETED) == std::string::npos) - { - excludeFlags |= BackupProtocolListDirectory::Flags_Deleted; - } - - return excludeFlags; -} - -std::vector CompleteRemoteFileOrDirectory( - BackupQueries::ParsedCommand& rCommand, - const std::string& prefix, BackupProtocolCallable& rProtocol, - BackupQueries& rQueries, int16_t includeFlags) -{ - std::vector completions; - - // default to using the current directory - int64_t listDirId = rQueries.GetCurrentDirectoryID(); - std::string searchPrefix; - std::string listDir = prefix; - - if(rCommand.mCompleteArgCount == rCommand.mCmdElements.size()) - { - // completing an empty name, from the current directory - // nothing to change - } - else - { - // completing a partially-completed subdirectory name - searchPrefix = prefix; - listDir = ""; - - // do we need to list a subdirectory to complete? - size_t lastSlash = searchPrefix.rfind('/'); - if(lastSlash == std::string::npos) - { - // no slashes, so the whole name is the prefix - // nothing to change - } - else - { - // listing a partially-completed subdirectory name - listDir = searchPrefix.substr(0, lastSlash); - - listDirId = rQueries.FindDirectoryObjectID(listDir, - rCommand.mOptions.find(LIST_OPTION_ALLOWOLD) - != std::string::npos, - rCommand.mOptions.find(LIST_OPTION_ALLOWDELETED) - != std::string::npos); - - if(listDirId == 0) - { - // no matches for subdir to list, - // return empty-handed. - return completions; - } - - // matched, and updated listDir and listDirId already - searchPrefix = searchPrefix.substr(lastSlash + 1); - } - } - - // Always include directories, because they contain files. - // We will append a slash later for each directory if we're - // actually looking for files. - // - // If we're looking for directories, then only list directories. - - bool completeFiles = includeFlags & - BackupProtocolListDirectory::Flags_File; - bool completeDirs = includeFlags & - BackupProtocolListDirectory::Flags_Dir; - int16_t listFlags = 0; - - if(completeFiles) - { - listFlags = BackupProtocolListDirectory::Flags_INCLUDE_EVERYTHING; - } - else if(completeDirs) - { - listFlags = BackupProtocolListDirectory::Flags_Dir; - } - - rProtocol.QueryListDirectory(listDirId, - listFlags, GetExcludeFlags(rCommand), - false /* no attributes */); - - // Retrieve the directory from the stream following - BackupStoreDirectory dir; - std::auto_ptr dirstream(rProtocol.ReceiveStream()); - dir.ReadFromStream(*dirstream, rProtocol.GetTimeout()); - - // Then... display everything - BackupStoreDirectory::Iterator i(dir); - BackupStoreDirectory::Entry *en = 0; - while((en = i.Next()) != 0) - { - BackupStoreFilenameClear clear(en->GetName()); - std::string name = clear.GetClearFilename().c_str(); - if(name.compare(0, searchPrefix.length(), searchPrefix) == 0) - { - bool dir_added = false; - - if(en->IsDir() && - (includeFlags & BackupProtocolListDirectory::Flags_Dir) == 0) - { - // Was looking for a file, but this is a - // directory, so append a slash to the name - name += "/"; - } - - #ifdef HAVE_LIBREADLINE - if(strchr(name.c_str(), ' ')) - { - int n_quote = 0; - - for(int k = strlen(rl_line_buffer); k >= 0; k--) - { - if (rl_line_buffer[k] == '\"') { - ++n_quote; - } - } - - dir_added = false; - - if (!(n_quote % 2)) - { - name = "\"" + (listDir == "" ? name : listDir + "/" + name); - dir_added = true; - } - - name = name + "\""; - } - #endif - - if(listDir == "" || dir_added) - { - completions.push_back(name); - } - else - { - completions.push_back(listDir + "/" + name); - } - } - } - - return completions; -} - -COMPLETION_FUNCTION(RemoteDir, - completions = CompleteRemoteFileOrDirectory(rCommand, prefix, - rProtocol, rQueries, - BackupProtocolListDirectory::Flags_Dir); -) - -COMPLETION_FUNCTION(RemoteFile, - completions = CompleteRemoteFileOrDirectory(rCommand, prefix, - rProtocol, rQueries, - BackupProtocolListDirectory::Flags_File); -) - -COMPLETION_FUNCTION(LocalDir, - DELEGATE_COMPLETION(Default); -) - -COMPLETION_FUNCTION(LocalFile, - DELEGATE_COMPLETION(Default); -) - -COMPLETION_FUNCTION(LocationName, - const Configuration &locations(rConfig.GetSubConfiguration( - "BackupLocations")); - - std::vector locNames = - locations.GetSubConfigurationNames(); - - for(std::vector::iterator - pLocName = locNames.begin(); - pLocName != locNames.end(); - pLocName++) - { - if(pLocName->compare(0, pLocName->length(), prefix) == 0) - { - completions.push_back(*pLocName); - } - } -) - -COMPLETION_FUNCTION(RemoteFileIdInCurrentDir, - int64_t listDirId = rQueries.GetCurrentDirectoryID(); - int16_t excludeFlags = GetExcludeFlags(rCommand); - - rProtocol.QueryListDirectory( - listDirId, - BackupProtocolListDirectory::Flags_File, - excludeFlags, false /* no attributes */); - - // Retrieve the directory from the stream following - BackupStoreDirectory dir; - std::auto_ptr dirstream(rProtocol.ReceiveStream()); - dir.ReadFromStream(*dirstream, rProtocol.GetTimeout()); - - // Then... compare each item - BackupStoreDirectory::Iterator i(dir); - BackupStoreDirectory::Entry *en = 0; - while((en = i.Next()) != 0) - { - std::ostringstream hexId; - hexId << std::hex << en->GetObjectID(); - if(hexId.str().compare(0, prefix.length(), prefix) == 0) - { - completions.push_back(hexId.str()); - } - } -) - -// TODO implement completion of hex IDs up to the maximum according to Usage -COMPLETION_FUNCTION(RemoteId,) - -COMPLETION_FUNCTION(GetFileOrId, - if(rCommand.mOptions.find('i') != std::string::npos) - { - DELEGATE_COMPLETION(RemoteFileIdInCurrentDir); - } - else - { - DELEGATE_COMPLETION(RemoteFile); - } -) - -COMPLETION_FUNCTION(CompareLocationOrRemoteDir, - if(rCommand.mOptions.find('l') != std::string::npos) - { - DELEGATE_COMPLETION(LocationName); - } - else - { - DELEGATE_COMPLETION(RemoteDir); - } -) - -COMPLETION_FUNCTION(CompareNoneOrLocalDir, - if(rCommand.mOptions.find('l') != std::string::npos) - { - // no completions - DELEGATE_COMPLETION(None); - } - else - { - DELEGATE_COMPLETION(LocalDir); - } -) - -COMPLETION_FUNCTION(RestoreRemoteDirOrId, - if(rCommand.mOptions.find('i') != std::string::npos) - { - DELEGATE_COMPLETION(RemoteId); - } - else - { - DELEGATE_COMPLETION(RemoteDir); - } -) - -// Data about commands -QueryCommandSpecification commands[] = -{ - { "quit", "", Command_Quit, {} }, - { "exit", "", Command_Quit, {} }, - { "list", "adDFhiIorRsStTU", Command_List, {CompleteRemoteDir} }, - { "pwd", "", Command_pwd, {} }, - { "cd", "od", Command_cd, {CompleteRemoteDir} }, - { "lcd", "", Command_lcd, {CompleteLocalDir} }, - { "sh", "", Command_sh, {CompleteDefault} }, - { "getobject", "", Command_GetObject, - {CompleteRemoteId, CompleteLocalDir} }, - { "get", "i", Command_Get, - {CompleteGetFileOrId, CompleteLocalDir} }, - { "compare", "alcqAEQ", Command_Compare, - {CompleteCompareLocationOrRemoteDir, CompleteCompareNoneOrLocalDir} }, - { "restore", "drif", Command_Restore, - {CompleteRestoreRemoteDirOrId, CompleteLocalDir} }, - { "help", "", Command_Help, {} }, - { "usage", "m", Command_Usage, {} }, - { "undelete", "i", Command_Undelete, - {CompleteGetFileOrId} }, - { "delete", "i", Command_Delete, {CompleteGetFileOrId} }, - { NULL, NULL, Command_Unknown, {} } -}; - -const char *alias[] = {"ls", 0}; -const int aliasIs[] = {Command_List, 0}; - -BackupQueries::ParsedCommand::ParsedCommand(const std::string& Command, - bool isFromCommandLine) -: mInOptions(false), - mFailed(false), - pSpec(NULL), - mCompleteArgCount(0) -{ - mCompleteCommand = Command; - - // is the command a shell command? - if(Command[0] == 's' && Command[1] == 'h' && Command[2] == ' ' && Command[3] != '\0') - { - // Yes, run shell command - for(int i = 0; commands[i].type != Command_Unknown; i++) - { - if(commands[i].type == Command_sh) - { - pSpec = &(commands[i]); - break; - } - } - - mCmdElements[0] = "sh"; - mCmdElements[1] = Command.c_str() + 3; - return; - } - - // split command into components - bool inQuoted = false; - mInOptions = false; - - std::string currentArg; - for (std::string::const_iterator c = Command.begin(); - c != Command.end(); c++) - { - // Terminating char? - if(*c == ((inQuoted)?'"':' ')) - { - if(!currentArg.empty()) - { - mCmdElements.push_back(currentArg); - - // Because we just found a space, and the last - // word was not options (otherwise currentArg - // would be empty), we've received a complete - // command or non-option argument. - mCompleteArgCount++; - } - - currentArg.resize(0); - inQuoted = false; - mInOptions = false; - } - // Start of quoted parameter? - else if(currentArg.empty() && *c == '"') - { - inQuoted = true; - } - // Start of options? You can't have options if there's no - // command before them, so treat the options as a command (which - // doesn't exist, so it will fail to parse) in that case. - else if(currentArg.empty() && *c == '-' && !mCmdElements.empty()) - { - mInOptions = true; - } - else if(mInOptions) - { - // Option char - mOptions += *c; - } - else - { - // Normal string char, part of current arg - currentArg += *c; - } - } - - if(!currentArg.empty()) - { - mCmdElements.push_back(currentArg); - } - - // If there are no commands then there's nothing to do except return - if(mCmdElements.empty()) - { - return; - } - - // Work out which command it is... - int cmd = 0; - while(commands[cmd].name != 0 && - mCmdElements[0] != commands[cmd].name) - { - cmd++; - } - - if(commands[cmd].name == 0) - { - // Check for aliases - int a; - for(a = 0; alias[a] != 0; ++a) - { - if(mCmdElements[0] == alias[a]) - { - // Found an alias - cmd = aliasIs[a]; - break; - } - } - } - - if(commands[cmd].name == 0) - { - mFailed = true; - return; - } - - pSpec = &(commands[cmd]); - - #ifdef WIN32 - if(isFromCommandLine) - { - std::string converted; - - if(!ConvertEncoding(mCompleteCommand, CP_ACP, converted, - GetConsoleCP())) - { - BOX_ERROR("Failed to convert encoding"); - mFailed = true; - } - - mCompleteCommand = converted; - - for(std::vector::iterator - i = mCmdElements.begin(); - i != mCmdElements.end(); i++) - { - if(!ConvertEncoding(*i, CP_ACP, converted, - GetConsoleCP())) - { - BOX_ERROR("Failed to convert encoding"); - mFailed = true; - } - - *i = converted; - } - } - #endif -} - diff --git a/bin/bbackupquery/Makefile.extra b/bin/bbackupquery/Makefile.extra deleted file mode 100644 index e1049b6d..00000000 --- a/bin/bbackupquery/Makefile.extra +++ /dev/null @@ -1,6 +0,0 @@ - -# AUTOGEN SEEDING -autogen_Documentation.cpp: makedocumentation.pl documentation.txt - $(_PERL) makedocumentation.pl - - diff --git a/bin/bbackupquery/documentation.txt b/bin/bbackupquery/documentation.txt deleted file mode 100644 index b16a6f7c..00000000 --- a/bin/bbackupquery/documentation.txt +++ /dev/null @@ -1,194 +0,0 @@ - -bbackupquery utility -- examine store, compare files, restore, etc. - -This file has markers for automatic help generation script -- '>' marks a start of a command/help topic, -and '<' marks the end of a section. - -Command line: -============= - -> bbackupquery [-q] [-c configfile] [commands ...] - - -q -- quiet, no information prompts - -c -- specify another bbackupd configuation file - -The commands following the options are executed, then (if there was no quit -command) an interactive mode is entered. - -If a command contains a space, enclose it in quotes. Example - - bbackupquery "list testdir1" quit - -to list the contents of testdir1, and then exit without interactive mode. -< - -Commands: -========= - -All directory names relative to a "current" directory, or from root if they -start with '/'. The initial directory is always the root directory. - - -> ls [options] [directory-name] - - List contents of current directory, or specified directory. - - -R -- recursively list all files - -d -- list deleted files/directories - -o -- list old versions of files/directories - -I -- don't display object ID - -F -- don't display flags - -t -- show file modification time in local time - (and attr mod time if has the object has attributes, ~ separated) - -T -- show file modification time in GMT - -a -- show updated attribute instead of file modification time - -s -- show file size in blocks used on server - (only very approximate indication of size locally) - -h -- show file attributes hash - -D -- sort directories together with files (not dirs first) - -i -- sort by object ID (the old default) - -S -- sort by object size in blocks - -U -- don't sort the results (new default is to sort by name) - -list can be used as an alias. -< - -> list - - Alias for 'ls'. Type 'help ls' for options. -< - -> cd [options] - - Change directory - - -d -- consider deleted directories for traversal - -o -- consider old versions of directories for traversal - (this option should never be useful in a correctly formed store) -< - -> pwd - - Print current directory, always root relative. -< - -> lcd - - Change local directory. - - Type "sh ls" to list the contents. -< - -> sh - - All of the parameters after the "sh" are run as a shell command. - - For example, to list the contents of the location directory, type "sh ls" -< - -> get [] -get -i - - Gets a file from the store. Object is specified as the filename within - the current directory, and local filename is optional. Ignores old and - deleted files when searching the directory for the file to retrieve. - - To get an old or deleted file, use the -i option and select the object - as a hex object ID (first column in listing). The local filename must - be specified. -< - -> compare -a -compare -l -compare - - Compares the (current) data on the store with the data on the disc. - All the data will be downloaded -- this is potentially a very long - operation. - - -a -- compare all locations - -l -- compare one backup location as specified in the configuration file. - -c -- set return code - -q -- quick compare. Only checks file contents against checksums, - doesn't do a full download - -A -- ignore attribute differences - -E -- ignore exclusion settings - - Comparing with the root directory is an error, use -a option instead. - - If -c is set, then the return code (if quit is the next command) will be - 1 Comparison was exact - 2 Differences were found - 3 An error occured - This can be used for automated tests. -< - -> restore [-drif] [] - - Restores a directory to the local disc. The local directory specified - must not exist (unless a previous restore is being restarted). If the - local directory is omitted, the default is to restore to the same - directory name and path, relative to the current local directory, - as set with the "lcd" command. - - The root cannot be restored -- restore locations individually. - - -d -- restore a deleted directory or deleted files inside - -r -- resume an interrupted restoration - -i -- directory name is actually an ID - -f -- force restore to continue if errors are encountered - - If a restore operation is interrupted for any reason, it can be restarted - using the -r switch. Restore progress information is saved in a file at - regular intervals during the restore operation to allow restarts. -< - -> getobject - - Gets the object specified by the object id (in hex) and stores the raw - contents in the local file specified. - - This is only useful for debugging as it does not decode files from the - stored format, which is encrypted and compressed. -< - -> usage [-m] - - Show space used on the server for this account. - - -m -- display the output in machine-readable form - - Used: Total amount of space used on the server. - Old files: Space used by old files - Deleted files: Space used by deleted files - Directories: Space used by the directory structure. - - When Used exceeds the soft limit, the server will start to remove old and - deleted files until the usage drops below the soft limit. - - After a while, you would expect to see the usage stay at just below the - soft limit. You only need more space if the space used by old and deleted - files is near zero. -< - -> undelete -undelete -i - - Removes the deleted flag from the specified directory name (in the - current directory) or hex object ID. Be careful not to use this - command where a directory already exists with the same name which is - not marked as deleted. -< - -> delete - - Sets the deleted flag on the specified file name (in the current - directory, or with a relative path). -< - -> quit - - End session and exit. -< - - diff --git a/bin/bbackupquery/makedocumentation.pl.in b/bin/bbackupquery/makedocumentation.pl.in deleted file mode 100755 index 530c4ff6..00000000 --- a/bin/bbackupquery/makedocumentation.pl.in +++ /dev/null @@ -1,75 +0,0 @@ -#!@PERL@ -use strict; - -print "Creating built-in documentation for bbackupquery...\n"; - -open DOC,"documentation.txt" or die "Can't open documentation.txt file"; -my $section; -my %help; -my @in_order; - -while() -{ - if(m/\A>\s+(\w+)/) - { - $section = $1; - m/\A>\s+(.+)\Z/; - $help{$section} = $1."\n"; - push @in_order,$section; - } - elsif(m/\Aautogen_Documentation.cpp" or die "Can't open output file for writing"; - -print OUT <<__E; -// -// Automatically generated file, do not edit. -// - -#include "Box.h" - -#include "MemLeakFindOn.h" - -const char *help_commands[] = -{ -__E - -for(@in_order) -{ - print OUT qq:\t"$_",\n:; -} - -print OUT <<__E; - 0 -}; - -const char *help_text[] = -{ -__E - -for(@in_order) -{ - my $t = $help{$_}; - $t =~ s/\t/ /g; - $t =~ s/\n/\\n/g; - $t =~ s/"/\\"/g; - print OUT qq:\t"$t",\n:; -} - -print OUT <<__E; - 0 -}; - -__E - -close OUT; -- cgit v1.2.3