* Fixed problems when installing onto non-empty target volumes. The
'system' folder will be a clean copy of the source volume. Other folders will be merged (as before), but in case a folder is in the way of a link or file from the source volume, it will now be purged. * Clarified the alert for non-empty target volumes, so it is very clear what happens. (Maybe there ought to the be option to only copy the system folder, though.) * Fixed a problem with copying attributes in certain cases. * Fixed the main GUI not resetting state properly after encountering an error during the copy process. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31042 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
f664c6474b
commit
f76e944e24
@ -263,8 +263,11 @@ CopyEngine::_CopyFolder(const char* _source, const char* _destination,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = create_directory(_destination, 0777);
|
ret = create_directory(_destination, 0777);
|
||||||
if (ret < B_OK && ret != B_FILE_EXISTS)
|
if (ret < B_OK && ret != B_FILE_EXISTS) {
|
||||||
|
fprintf(stderr, "Could not create '%s': %s\n", _destination,
|
||||||
|
strerror(ret));
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
BDirectory destination(_destination);
|
BDirectory destination(_destination);
|
||||||
ret = destination.InitCheck();
|
ret = destination.InitCheck();
|
||||||
@ -301,10 +304,24 @@ CopyEngine::_CopyFolder(const char* _source, const char* _destination,
|
|||||||
// handle recursive directory copy
|
// handle recursive directory copy
|
||||||
|
|
||||||
if (copy.Exists()) {
|
if (copy.Exists()) {
|
||||||
// Do not overwrite attributes on folders that exist.
|
ret = B_OK;
|
||||||
// This should work better when the install target already
|
if (copy.IsDirectory()) {
|
||||||
// contains a Haiku installation.
|
if (_ShouldClobberFolder(name, statInfo, level))
|
||||||
copyAttributes = false;
|
ret = _RemoveFolder(copy);
|
||||||
|
else {
|
||||||
|
// Do not overwrite attributes on folders that exist.
|
||||||
|
// This should work better when the install target
|
||||||
|
// already contains a Haiku installation.
|
||||||
|
copyAttributes = false;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
ret = copy.Remove();
|
||||||
|
|
||||||
|
if (ret != B_OK) {
|
||||||
|
fprintf(stderr, "Failed to make room for folder '%s': "
|
||||||
|
"%s\n", name, strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BPath srcFolder;
|
BPath srcFolder;
|
||||||
@ -329,35 +346,52 @@ CopyEngine::_CopyFolder(const char* _source, const char* _destination,
|
|||||||
// We are supposed to quit
|
// We are supposed to quit
|
||||||
return B_CANCELED;
|
return B_CANCELED;
|
||||||
}
|
}
|
||||||
} else if (S_ISLNK(statInfo.st_mode)) {
|
|
||||||
// copy symbolic links
|
|
||||||
BSymLink srcLink(&entry);
|
|
||||||
if (ret < B_OK)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
char linkPath[B_PATH_NAME_LENGTH];
|
|
||||||
ssize_t read = srcLink.ReadLink(linkPath, B_PATH_NAME_LENGTH - 1);
|
|
||||||
if (read < 0)
|
|
||||||
return (status_t)read;
|
|
||||||
|
|
||||||
// just in case it already exists...
|
|
||||||
copy.Remove();
|
|
||||||
|
|
||||||
BSymLink dstLink;
|
|
||||||
ret = destination.CreateSymLink(name, linkPath, &dstLink);
|
|
||||||
if (ret < B_OK)
|
|
||||||
return ret;
|
|
||||||
} else {
|
} else {
|
||||||
// copy file data
|
if (copy.Exists()) {
|
||||||
// NOTE: Do not pass the locker, we simply keep holding the lock!
|
if (copy.IsDirectory())
|
||||||
ret = CopyFile(entry, copy);
|
ret = _RemoveFolder(copy);
|
||||||
if (ret < B_OK)
|
else
|
||||||
return ret;
|
ret = copy.Remove();
|
||||||
|
if (ret != B_OK) {
|
||||||
|
fprintf(stderr, "Failed to make room for entry '%s': "
|
||||||
|
"%s\n", name, strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (S_ISLNK(statInfo.st_mode)) {
|
||||||
|
// copy symbolic links
|
||||||
|
BSymLink srcLink(&entry);
|
||||||
|
if (ret < B_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
char linkPath[B_PATH_NAME_LENGTH];
|
||||||
|
ssize_t read = srcLink.ReadLink(linkPath, B_PATH_NAME_LENGTH - 1);
|
||||||
|
if (read < 0)
|
||||||
|
return (status_t)read;
|
||||||
|
|
||||||
|
// just in case it already exists...
|
||||||
|
copy.Remove();
|
||||||
|
|
||||||
|
BSymLink dstLink;
|
||||||
|
ret = destination.CreateSymLink(name, linkPath, &dstLink);
|
||||||
|
if (ret < B_OK)
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
// copy file data
|
||||||
|
// NOTE: Do not pass the locker, we simply keep holding the lock!
|
||||||
|
ret = CopyFile(entry, copy);
|
||||||
|
if (ret < B_OK)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!copyAttributes)
|
if (!copyAttributes)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
ret = copy.SetTo(&destination, name);
|
||||||
|
if (ret != B_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
// copy attributes
|
// copy attributes
|
||||||
BNode sourceNode(&entry);
|
BNode sourceNode(&entry);
|
||||||
BNode targetNode(©);
|
BNode targetNode(©);
|
||||||
@ -396,6 +430,30 @@ CopyEngine::_CopyFolder(const char* _source, const char* _destination,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
CopyEngine::_RemoveFolder(BEntry& entry)
|
||||||
|
{
|
||||||
|
BDirectory directory(&entry);
|
||||||
|
status_t ret = directory.InitCheck();
|
||||||
|
if (ret != B_OK)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
BEntry subEntry;
|
||||||
|
while (directory.GetNextEntry(&subEntry) == B_OK) {
|
||||||
|
if (subEntry.IsDirectory()) {
|
||||||
|
ret = _RemoveFolder(subEntry);
|
||||||
|
if (ret != B_OK)
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
ret = subEntry.Remove();
|
||||||
|
if (ret != B_OK)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entry.Remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CopyEngine::_UpdateProgress()
|
CopyEngine::_UpdateProgress()
|
||||||
{
|
{
|
||||||
@ -430,6 +488,24 @@ CopyEngine::_ShouldCopyEntry(const char* name, const struct stat& statInfo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
CopyEngine::_ShouldClobberFolder(const char* name, const struct stat& statInfo,
|
||||||
|
int32 level) const
|
||||||
|
{
|
||||||
|
if (level == 1 && S_ISDIR(statInfo.st_mode)) {
|
||||||
|
if (strcmp("system", name) == 0) {
|
||||||
|
printf("clobbering '%s'.\n", name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// if (strcmp("develop", name) == 0) {
|
||||||
|
// printf("clobbering '%s'.\n", name);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
CopyEngine::_WriteThreadEntry(void* cookie)
|
CopyEngine::_WriteThreadEntry(void* cookie)
|
||||||
{
|
{
|
||||||
|
@ -48,6 +48,12 @@ private:
|
|||||||
const struct stat& statInfo,
|
const struct stat& statInfo,
|
||||||
int32 level) const;
|
int32 level) const;
|
||||||
|
|
||||||
|
bool _ShouldClobberFolder(const char* name,
|
||||||
|
const struct stat& statInfo,
|
||||||
|
int32 level) const;
|
||||||
|
|
||||||
|
status_t _RemoveFolder(BEntry& entry);
|
||||||
|
|
||||||
void _UpdateProgress();
|
void _UpdateProgress();
|
||||||
|
|
||||||
static int32 _WriteThreadEntry(void* cookie);
|
static int32 _WriteThreadEntry(void* cookie);
|
||||||
|
@ -373,15 +373,12 @@ InstallerWindow::MessageReceived(BMessage *msg)
|
|||||||
(new BAlert("error", errorMessage, "Ok"))->Go();
|
(new BAlert("error", errorMessage, "Ok"))->Go();
|
||||||
}
|
}
|
||||||
|
|
||||||
fInstallStatus = kReadyForInstall;
|
|
||||||
fBeginButton->SetEnabled(true);
|
|
||||||
_DisableInterface(false);
|
_DisableInterface(false);
|
||||||
|
|
||||||
fProgressLayoutItem->SetVisible(false);
|
fProgressLayoutItem->SetVisible(false);
|
||||||
fPkgSwitchLayoutItem->SetVisible(true);
|
fPkgSwitchLayoutItem->SetVisible(true);
|
||||||
_ShowOptionalPackages();
|
_ShowOptionalPackages();
|
||||||
|
_UpdateControls();
|
||||||
fBeginButton->SetLabel("Begin");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case START_SCAN:
|
case START_SCAN:
|
||||||
|
@ -234,14 +234,14 @@ WorkerThread::_LaunchFinishScript(BPath &path)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WorkerThread::_PerformInstall(BMenu *srcMenu, BMenu *targetMenu)
|
WorkerThread::_PerformInstall(BMenu* srcMenu, BMenu* targetMenu)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
BPath targetDirectory, srcDirectory;
|
BPath targetDirectory, srcDirectory;
|
||||||
BDirectory targetDir;
|
BDirectory targetDir;
|
||||||
BDiskDevice device;
|
BDiskDevice device;
|
||||||
BPartition *partition;
|
BPartition* partition;
|
||||||
BVolume targetVolume;
|
BVolume targetVolume;
|
||||||
status_t err = B_OK;
|
status_t err = B_OK;
|
||||||
int32 entries = 0;
|
int32 entries = 0;
|
||||||
@ -250,8 +250,8 @@ WorkerThread::_PerformInstall(BMenu *srcMenu, BMenu *targetMenu)
|
|||||||
BMessenger messenger(fWindow);
|
BMessenger messenger(fWindow);
|
||||||
CopyEngine engine(messenger, new BMessage(MSG_STATUS_MESSAGE));
|
CopyEngine engine(messenger, new BMessage(MSG_STATUS_MESSAGE));
|
||||||
|
|
||||||
PartitionMenuItem *targetItem = (PartitionMenuItem *)targetMenu->FindMarked();
|
PartitionMenuItem* targetItem = (PartitionMenuItem*)targetMenu->FindMarked();
|
||||||
PartitionMenuItem *srcItem = (PartitionMenuItem *)srcMenu->FindMarked();
|
PartitionMenuItem* srcItem = (PartitionMenuItem*)srcMenu->FindMarked();
|
||||||
if (!srcItem || !targetItem) {
|
if (!srcItem || !targetItem) {
|
||||||
ERR("bad menu items\n");
|
ERR("bad menu items\n");
|
||||||
goto error;
|
goto error;
|
||||||
@ -381,7 +381,12 @@ WorkerThread::_PerformInstall(BMenu *srcMenu, BMenu *targetMenu)
|
|||||||
}
|
}
|
||||||
if (entries != 0
|
if (entries != 0
|
||||||
&& ((new BAlert("", "The target volume is not empty. Are you sure you "
|
&& ((new BAlert("", "The target volume is not empty. Are you sure you "
|
||||||
"want to install anyway?", "Install Anyway", "Cancel", 0,
|
"want to install anyway?\n\nNote: The 'system' folder will be a "
|
||||||
|
"clean copy from the source volume, all other folders will be "
|
||||||
|
"merged, whereas files and links that exist on both the source "
|
||||||
|
"and target volume will be overwritten with the source volume "
|
||||||
|
"version.",
|
||||||
|
"Install Anyway", "Cancel", 0,
|
||||||
B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go() != 0)) {
|
B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go() != 0)) {
|
||||||
err = B_CANCELED;
|
err = B_CANCELED;
|
||||||
goto error;
|
goto error;
|
||||||
|
Loading…
Reference in New Issue
Block a user