[Box Backup-dev] COMMIT r516 - box/chris/general/lib/backupclient
boxbackup-dev@fluffy.co.uk
boxbackup-dev@fluffy.co.uk
Sun, 26 Feb 2006 00:28:24 +0000 (GMT)
Author: chris
Date: 2006-02-26 00:28:22 +0000 (Sun, 26 Feb 2006)
New Revision: 516
Modified:
box/chris/general/lib/backupclient/BackupClientRestore.cpp
Log:
* BackupClientRestore.cpp
- Detect when the user tries to restore to a directory whose parent does not
exist, and return an appropriate error
Modified: box/chris/general/lib/backupclient/BackupClientRestore.cpp
===================================================================
--- box/chris/general/lib/backupclient/BackupClientRestore.cpp 2006-02-26 00:27:45 UTC (rev 515)
+++ box/chris/general/lib/backupclient/BackupClientRestore.cpp 2006-02-26 00:28:22 UTC (rev 516)
@@ -206,7 +206,7 @@
// Created: 23/11/03
//
// --------------------------------------------------------------------------
-static void BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t DirectoryID, std::string &rLocalDirectoryName,
+static int BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t DirectoryID, std::string &rLocalDirectoryName,
RestoreParams &Params, RestoreResumeInfo &rLevel)
{
// If we're resuming... check that we haven't got a next level to look at
@@ -222,12 +222,11 @@
// Remove the level for the recursed directory
rLevel.RemoveLevel();
}
-
- // Save the resumption information
- Params.mResumeInfo.Save(Params.mRestoreResumeInfoFilename);
// Create the local directory (if not already done) -- path and owner set later, just use restrictive owner mode
- switch(ObjectExists(rLocalDirectoryName.c_str()))
+ int exists = ObjectExists(rLocalDirectoryName.c_str());
+
+ switch(exists)
{
case ObjectExists_Dir:
// Do nothing
@@ -244,16 +243,64 @@
}
// follow through to... (no break)
case ObjectExists_NoObject:
- if(::mkdir(rLocalDirectoryName.c_str(), S_IRWXU) != 0)
- {
- THROW_EXCEPTION(CommonException, OSFileError);
- }
break;
default:
ASSERT(false);
break;
}
+
+ std::string parentDirectoryName(rLocalDirectoryName);
+ if(parentDirectoryName[parentDirectoryName.size() - 1] == '/')
+ {
+ parentDirectoryName.resize(parentDirectoryName.size() - 1);
+ }
+
+ int lastSlash = parentDirectoryName.rfind(DIRECTORY_SEPARATOR_ASCHAR);
+ if(lastSlash != std::string::npos)
+ {
+ // the target directory is a deep path, remove the last
+ // directory name and check that the resulting parent
+ // exists, otherwise the restore should fail.
+ parentDirectoryName.resize(lastSlash);
+ switch(ObjectExists(parentDirectoryName.c_str()))
+ {
+ case ObjectExists_Dir:
+ // this is fine, do nothing
+ break;
+
+ case ObjectExists_File:
+ fprintf(stderr, "Failed to restore: '%s' "
+ "is a file, but should be a "
+ "directory.\n",
+ parentDirectoryName.c_str());
+ return Restore_TargetPathNotFound;
+
+ case ObjectExists_NoObject:
+ fprintf(stderr, "Failed to restore: "
+ "parent '%s' of target directory "
+ "does not exist.\n",
+ parentDirectoryName.c_str());
+ return Restore_TargetPathNotFound;
+
+ default:
+ fprintf(stderr, "Failed to restore: "
+ "unknown result from "
+ "ObjectExists('%s').\n",
+ parentDirectoryName.c_str());
+ return Restore_UnknownError;
+ }
+ }
+
+ if((exists == ObjectExists_NoObject ||
+ exists == ObjectExists_File) &&
+ ::mkdir(rLocalDirectoryName.c_str(), S_IRWXU) != 0)
+ {
+ THROW_EXCEPTION(CommonException, OSFileError);
+ }
+ // Save the resumption information
+ Params.mResumeInfo.Save(Params.mRestoreResumeInfoFilename);
+
// Fetch the directory listing from the server -- getting a list of files which is approparite to the restore type
rConnection.QueryListDirectory(
DirectoryID,
@@ -347,7 +394,7 @@
}
- // Recuse to directories
+ // Recurse to directories
{
BackupStoreDirectory::Iterator i(dir);
BackupStoreDirectory::Entry *en = 0;
@@ -364,7 +411,14 @@
RestoreResumeInfo &rnextLevel(rLevel.AddLevel(en->GetObjectID(), nm.GetClearFilename()));
// Recurse
- BackupClientRestoreDir(rConnection, en->GetObjectID(), localDirname, Params, rnextLevel);
+ int result = BackupClientRestoreDir(
+ rConnection, en->GetObjectID(),
+ localDirname, Params, rnextLevel);
+
+ if (result != Restore_Complete)
+ {
+ return result;
+ }
// Remove the level for the above call
rLevel.RemoveLevel();
@@ -373,7 +427,9 @@
rLevel.mRestoredObjects.insert(en->GetObjectID());
}
}
- }
+ }
+
+ return Restore_Complete;
}
@@ -444,7 +500,12 @@
// Restore the directory
std::string localName(LocalDirectoryName);
- BackupClientRestoreDir(rConnection, DirectoryID, localName, params, params.mResumeInfo);
+ int result = BackupClientRestoreDir(rConnection, DirectoryID,
+ localName, params, params.mResumeInfo);
+ if (result != Restore_Complete)
+ {
+ return result;
+ }
// Undelete the directory on the server?
if(RestoreDeleted && UndeleteAfterRestoreDeleted)