summaryrefslogtreecommitdiff
path: root/bin/bbackupquery
diff options
context:
space:
mode:
Diffstat (limited to 'bin/bbackupquery')
-rw-r--r--bin/bbackupquery/BackupQueries.cpp2410
-rw-r--r--bin/bbackupquery/BackupQueries.h440
-rw-r--r--bin/bbackupquery/BoxBackupCompareParams.h112
-rw-r--r--bin/bbackupquery/CommandCompletion.cpp604
-rw-r--r--bin/bbackupquery/Makefile.extra6
-rw-r--r--bin/bbackupquery/documentation.txt194
-rwxr-xr-xbin/bbackupquery/makedocumentation.pl.in75
7 files changed, 0 insertions, 3841 deletions
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 <unistd.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_DIRENT_H
- #include <dirent.h>
-#endif
-
-#include <algorithm>
-#include <cstring>
-#include <limits>
-#include <iostream>
-#include <ostream>
-#include <set>
-
-#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<std::string> 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<std::string> &, const bool *)
-// Purpose: List directories (optionally recursive)
-// Created: 2003/10/10
-//
-// --------------------------------------------------------------------------
-void BackupQueries::CommandList(const std::vector<std::string> &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<IOStream> 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<BackupStoreDirectory::Entry*> 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<BackupStoreDirectory::Entry*>::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 = "<decrypt failed>";
- }
-
-#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<std::pair<std::string, int64_t> > *pStack)
-{
- // Split up string into elements
- std::vector<std::string> dirElements;
- SplitString(rDirName, '/', dirElements);
-
- // Start from current stack, or root, whichever is required
- std::vector<std::pair<std::string, int64_t> > 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<BackupProtocolSuccess> 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<IOStream> 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<std::string, int64_t>(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<std::string> &)
-// Purpose: Change directory command
-// Created: 2003/10/10
-//
-// --------------------------------------------------------------------------
-void BackupQueries::CommandChangeDir(const std::vector<std::string> &args, const bool *opts)
-{
- if(args.size() != 1 || args[0].size() == 0)
- {
- BOX_ERROR("Incorrect usage. cd [-o] [-d] <directory>");
- 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<std::pair<std::string, int64_t> > 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<std::string> &)
-// Purpose: Change local directory command
-// Created: 2003/10/11
-//
-// --------------------------------------------------------------------------
-void BackupQueries::CommandChangeLocalDir(const std::vector<std::string> &args)
-{
- if(args.size() != 1 || args[0].size() == 0)
- {
- BOX_ERROR("Incorrect usage. lcd <local-directory>");
- 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<std::string> &, const bool *)
-// Purpose: Gets an object without any translation.
-// Created: 2003/10/11
-//
-// --------------------------------------------------------------------------
-void BackupQueries::CommandGetObject(const std::vector<std::string> &args, const bool *opts)
-{
- // Check args
- if(args.size() != 2)
- {
- BOX_ERROR("Incorrect usage. getobject <object-id> "
- "<local-filename>");
- return;
- }
-
- int64_t id = ::strtoll(args[0].c_str(), 0, 16);
- if(id == std::numeric_limits<long long>::min() || id == std::numeric_limits<long long>::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<BackupProtocolSuccess> getobj(mrConnection.QueryGetObject(id));
-
- // Stream that object out to the file
- std::auto_ptr<IOStream> 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<IOStream> 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<long long>::min() ||
- fileId == std::numeric_limits<long long>::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<std::string> &, const bool *)
-// Purpose: Command to get a file from the store
-// Created: 2003/10/12
-//
-// --------------------------------------------------------------------------
-void BackupQueries::CommandGet(std::vector<std::string> 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 <remote-filename> [<local-filename>] or\n"
- "get -i <object-id> <local-filename>");
- return;
- }
-
- // Find object ID somehow
- int64_t fileId, dirId;
- std::string localName;
-
-#ifdef WIN32
- for (std::vector<std::string>::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<IOStream> 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<std::string> &, const bool *)
-// Purpose: Command to compare data on the store with local data
-// Created: 2003/10/12
-//
-// --------------------------------------------------------------------------
-void BackupQueries::CommandCompare(const std::vector<std::string> &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<std::string> locNames =
- rLocations.GetSubConfigurationNames();
- for(std::vector<std::string>::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 <location-name>\n or compare <store-dir-name> <local-dir-name>");
- 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<IOStream> 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<IOStream> objectStream(mrConnection.ReceiveStream());
-
- // Decode it
- std::auto_ptr<BackupStoreFile::DecodedStream> 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<FileStream> 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<IOStream> 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<std::string> localFiles;
- std::set<std::string> 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<std::pair<std::string, BackupStoreDirectory::Entry *> > storeFiles;
- std::set<std::pair<std::string, BackupStoreDirectory::Entry *> > 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<std::string, BackupStoreDirectory::Entry *>(name.GetClearFilename(), storeDirEn));
- }
- else
- {
- // Dir
- storeDirs.insert(std::pair<std::string, BackupStoreDirectory::Entry *>(name.GetClearFilename(), storeDirEn));
- }
- }
-
-#ifdef _MSC_VER
- typedef std::set<std::string>::iterator string_set_iter_t;
-#else
- typedef std::set<std::string>::const_iterator string_set_iter_t;
-#endif
-
- // Now compare files.
- for(std::set<std::pair<std::string, BackupStoreDirectory::Entry *> >::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<std::pair<std::string, BackupStoreDirectory::Entry *> >::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<std::string>::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<std::string> &, const bool *)
-// Purpose: Restore a directory
-// Created: 23/11/03
-//
-// --------------------------------------------------------------------------
-void BackupQueries::CommandRestore(const std::vector<std::string> &args, const bool *opts)
-{
- // Check arguments
- if(args.size() < 1 || args.size() > 2)
- {
- BOX_ERROR("Incorrect usage. restore [-drif] <remote-name> "
- "[<local-name>]");
- 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<long long>::min() || dirID == std::numeric_limits<long long>::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<std::string> &args)
-// Purpose: Display help on commands
-// Created: 15/2/04
-//
-// --------------------------------------------------------------------------
-void BackupQueries::CommandHelp(const std::vector<std::string> &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 <command>\" 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<BackupProtocolAccountUsage> 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<std::string> &, const bool *)
-// Purpose: Undelete a directory
-// Created: 23/11/03
-//
-// --------------------------------------------------------------------------
-void BackupQueries::CommandUndelete(const std::vector<std::string> &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 <name> or undelete -i <object-id>");
- 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<std::string> &, const bool *)
-// Purpose: Deletes a file
-// Created: 23/11/03
-//
-// --------------------------------------------------------------------------
-void BackupQueries::CommandDelete(const std::vector<std::string> &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 <name>");
- 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 <iostream>
-#include <string>
-#include <vector>
-
-#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<std::string> 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<std::string> &args, const bool *opts);
-
- // Commands
- void CommandChangeDir(const std::vector<std::string> &args, const bool *opts);
- void CommandChangeLocalDir(const std::vector<std::string> &args);
- void CommandGetObject(const std::vector<std::string> &args, const bool *opts);
- void CommandGet(std::vector<std::string> args, const bool *opts);
- void CommandCompare(const std::vector<std::string> &args, const bool *opts);
- void CommandRestore(const std::vector<std::string> &args, const bool *opts);
- void CommandUndelete(const std::vector<std::string> &args, const bool *opts);
- void CommandDelete(const std::vector<std::string> &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<std::string> &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<std::pair<std::string, int64_t> > *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<std::pair<std::string, int64_t> > mDirStack;
- bool mRunningAsRoot;
- bool mWarnedAboutOwnerAttributes;
- int mReturnCode;
-};
-
-typedef std::vector<std::string> (*CompletionHandler)
- (BackupQueries::ParsedCommand& rCommand, const std::string& prefix,
- BackupProtocolCallable& rProtocol, const Configuration& rConfig,
- BackupQueries& rQueries);
-
-std::vector<std::string> CompleteCommand(BackupQueries::ParsedCommand& rCommand,
- const std::string& prefix, BackupProtocolCallable& rProtocol,
- const Configuration& rConfig, BackupQueries& rQueries);
-std::vector<std::string> 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 <memory>
-#include <string>
-
-#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<const ExcludeList> 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 <readline/readline.h>
- #elif defined(HAVE_EDITLINE_READLINE_H)
- #include <editline/readline.h>
- #elif defined(HAVE_READLINE_H)
- #include <readline.h>
- #endif
-#endif
-
-#ifdef HAVE_READLINE_HISTORY
- #ifdef HAVE_READLINE_HISTORY_H
- #include <readline/history.h>
- #elif defined(HAVE_HISTORY_H)
- #include <history.h>
- #endif
-#endif
-
-#include <cstring>
-
-#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<std::string> Complete ## name( \
- BackupQueries::ParsedCommand& rCommand, \
- const std::string& prefix, \
- BackupProtocolCallable& rProtocol, const Configuration& rConfig, \
- BackupQueries& rQueries) \
-{ \
- std::vector<std::string> 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<std::string>& 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<std::string> CompleteRemoteFileOrDirectory(
- BackupQueries::ParsedCommand& rCommand,
- const std::string& prefix, BackupProtocolCallable& rProtocol,
- BackupQueries& rQueries, int16_t includeFlags)
-{
- std::vector<std::string> 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<IOStream> 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<std::string> locNames =
- locations.GetSubConfigurationNames();
-
- for(std::vector<std::string>::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<IOStream> 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<std::string>::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] <directory-name>
-
- 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 <local-directory-name>
-
- Change local directory.
-
- Type "sh ls" to list the contents.
-<
-
-> sh <shell command>
-
- 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 <object-filename> [<local-filename>]
-get -i <object-id> <local-filename>
-
- 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 <location-name>
-compare <store-dir-name> <local-dir-name>
-
- 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] <directory-name> [<local-directory-name>]
-
- 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 <object-id> <local-filename>
-
- 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 <directory-name>
-undelete -i <object-id>
-
- 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 <file-name>
-
- 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(<DOC>)
-{
- if(m/\A>\s+(\w+)/)
- {
- $section = $1;
- m/\A>\s+(.+)\Z/;
- $help{$section} = $1."\n";
- push @in_order,$section;
- }
- elsif(m/\A</)
- {
- $section = '';
- }
- elsif($section ne '')
- {
- $help{$section} .= $_;
- }
-}
-
-close DOC;
-
-open OUT,">autogen_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;