summaryrefslogtreecommitdiff
path: root/lib/backupclient/BackupClientRestore.cpp
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2007-02-09 22:34:21 +0000
committerChris Wilson <chris+github@qwirx.com>2007-02-09 22:34:21 +0000
commit57a36f04af1ae81cec83ab706cdfd76ff445c664 (patch)
tree96f3cfbc64a3e6be2c4d15a4e0486de660653c5f /lib/backupclient/BackupClientRestore.cpp
parent6779d3cb4ffcc9fa7d860a6f4abaa5bed009098c (diff)
Check whether the restore target parent directory exists before trying
to create the target directory or save restore info in the parent (refs #3)
Diffstat (limited to 'lib/backupclient/BackupClientRestore.cpp')
-rw-r--r--lib/backupclient/BackupClientRestore.cpp101
1 files changed, 93 insertions, 8 deletions
diff --git a/lib/backupclient/BackupClientRestore.cpp b/lib/backupclient/BackupClientRestore.cpp
index 65ee377c..9c1a5346 100644
--- a/lib/backupclient/BackupClientRestore.cpp
+++ b/lib/backupclient/BackupClientRestore.cpp
@@ -224,9 +224,6 @@ static void BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Di
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.
@@ -270,17 +267,105 @@ static void BackupClientRestoreDir(BackupProtocolClient &rConnection, int64_t Di
}
TRACE1("In restore, directory name collision with file %s", rLocalDirectoryName.c_str());
}
- // follow through to... (no break)
+ break;
case ObjectExists_NoObject:
- if(::mkdir(rLocalDirectoryName.c_str(), S_IRWXU) != 0)
- {
- THROW_EXCEPTION(CommonException, OSFileError);
- }
+ // we'll create it in a second, after checking
+ // whether the parent directory exists
break;
default:
ASSERT(false);
break;
}
+
+ std::string parentDirectoryName(rLocalDirectoryName);
+ if(parentDirectoryName[parentDirectoryName.size() - 1] ==
+ DIRECTORY_SEPARATOR_ASCHAR)
+ {
+ parentDirectoryName.resize(parentDirectoryName.size() - 1);
+ }
+
+ int lastSlash = parentDirectoryName.rfind(DIRECTORY_SEPARATOR_ASCHAR);
+
+ if(lastSlash == std::string::npos)
+ {
+ // might be a forward slash separator,
+ // especially in the unit tests!
+ lastSlash = parentDirectoryName.rfind('/');
+ }
+
+ 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);
+
+ int parentExists;
+
+ try
+ {
+ parentExists = ObjectExists(parentDirectoryName.c_str());
+ }
+ catch (BoxException &e)
+ {
+ ::syslog(LOG_ERR, "Failed to check existence for %s: "
+ "%s", parentDirectoryName.c_str(), e.what());
+ return Restore_UnknownError;
+ }
+ catch(std::exception &e)
+ {
+ ::syslog(LOG_ERR, "Failed to check existence for %s: "
+ "%s", parentDirectoryName.c_str(), e.what());
+ return Restore_UnknownError;
+ }
+ catch(...)
+ {
+ ::syslog(LOG_ERR, "Failed to check existence for %s: "
+ "unknown error", parentDirectoryName.c_str());
+ return Restore_UnknownError;
+ }
+
+ switch(parentExists)
+ {
+ 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)
+ {
+ ::syslog(LOG_ERR, "Failed to create directory %s: %s",
+ rLocalDirectoryName.c_str(),
+ strerror(errno));
+ return Restore_UnknownError;
+ }
+
+ // Save the resumption information
+ Params.mResumeInfo.Save(Params.mRestoreResumeInfoFilename);
// Fetch the directory listing from the server -- getting a list
// of files which is appropriate to the restore type