* Prevent to copy the "var" and "_packages_" folders from the source volume

root folder as before switching the CopyEngine.
* Add a button "Write Boot Sector" that makes the selected target volume
  bootable without performing an installation. Adjusted the status message
  after installation to be more descriptive.
* Small improvements in the CopyEngine, collecting the source size should be
  even a bit faster now since we can use the file size from the already
  performed stat().


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30395 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2009-04-25 15:35:49 +00:00
parent 803d0234c1
commit 7b293a3e93
6 changed files with 176 additions and 25 deletions
+67 -3
View File
@@ -75,15 +75,61 @@ CopyEngine::CopyEngine(InstallerWindow *window)
void
CopyEngine::MessageReceived(BMessage*msg)
CopyEngine::MessageReceived(BMessage* message)
{
CALLED();
switch (msg->what) {
switch (message->what) {
case ENGINE_START:
{
Start(fWindow->GetSourceMenu(), fWindow->GetTargetMenu());
break;
case kWriteBootSector:
{
int32 id;
if (message->FindInt32("id", &id) != B_OK) {
SetStatusMessage("Boot sector not written because of an "
" internal error.");
break;
}
// TODO: Refactor with Start()
BPath targetDirectory;
BDiskDevice device;
BPartition* partition;
if (fDDRoster.GetPartitionWithID(id, &device, &partition) == B_OK) {
if (!partition->IsMounted()) {
if (partition->Mount() < B_OK) {
SetStatusMessage("The partition can't be mounted. "
"Please choose a different partition.");
break;
}
}
if (partition->GetMountPoint(&targetDirectory) != B_OK) {
SetStatusMessage("The mount point could not be retrieve.");
break;
}
} else if (fDDRoster.GetDeviceWithID(id, &device) == B_OK) {
if (!device.IsMounted()) {
if (device.Mount() < B_OK) {
SetStatusMessage("The disk can't be mounted. Please "
"choose a different disk.");
break;
}
}
if (device.GetMountPoint(&targetDirectory) != B_OK) {
SetStatusMessage("The mount point could not be retrieve.");
break;
}
}
LaunchFinishScript(targetDirectory);
// TODO: Get error from executing script!
SetStatusMessage("Boot sector successfully written.");
}
default:
BLooper::MessageReceived(message);
}
}
@@ -398,6 +444,24 @@ CopyEngine::Cancel()
}
void
CopyEngine::WriteBootSector(BMenu* targetMenu)
{
// Executed in window thread.
CALLED();
PartitionMenuItem* item = (PartitionMenuItem*)targetMenu->FindMarked();
if (item == NULL) {
ERR("bad menu items\n");
return;
}
BMessage message(kWriteBootSector);
message.AddInt32("id", item->ID());
PostMessage(&message, this);
}
// #pragma mark -
+2
View File
@@ -29,6 +29,8 @@ class CopyEngine : public BLooper {
void SetSpaceRequired(off_t bytes) { fSpaceRequired = bytes; };
bool Cancel();
void SetLock(BLocker* lock) { fCancelLock = lock; }
void WriteBootSector(BMenu *targetMenu);
private:
void LaunchInitScript(BPath &path);
void LaunchFinishScript(BPath &path);
+65 -17
View File
@@ -14,6 +14,8 @@
#include <SymLink.h>
#include "AutoLocker.h"
#include "InstallerWindow.h"
// TODO: For PACKAGES_DIRECTORY and VAR_DIRECTORY, not so nice...
using std::nothrow;
@@ -80,7 +82,8 @@ CopyEngine2::CopyFolder(const char* source, const char* destination,
fCurrentTargetFolder = NULL;
fCurrentItem = NULL;
status_t ret = _CollectCopyInfo(source);
int32 level = 0;
status_t ret = _CollectCopyInfo(source, level);
if (ret < B_OK)
return ret;
@@ -92,7 +95,8 @@ CopyEngine2::CopyFolder(const char* source, const char* destination,
printf("%lld bytes to read in %lld files\n", fBytesToCopy, fItemsToCopy);
return _CopyFolder(source, destination, locker);
level = 0;
return _CopyFolder(source, destination, level, locker);
}
@@ -180,8 +184,10 @@ printf("CopyFile - cancled\n");
status_t
CopyEngine2::_CollectCopyInfo(const char* _source)
CopyEngine2::_CollectCopyInfo(const char* _source, int32& level)
{
level++;
BDirectory source(_source);
status_t ret = source.InitCheck();
if (ret < B_OK)
@@ -192,6 +198,14 @@ CopyEngine2::_CollectCopyInfo(const char* _source)
struct stat statInfo;
entry.GetStat(&statInfo);
char name[B_FILE_NAME_LENGTH];
status_t ret = entry.GetName(name);
if (ret < B_OK)
return ret;
if (!_ShouldCopyEntry(name, statInfo, level))
continue;
if (S_ISDIR(statInfo.st_mode)) {
// handle recursive directory copy
BPath srcFolder;
@@ -199,31 +213,29 @@ CopyEngine2::_CollectCopyInfo(const char* _source)
if (ret < B_OK)
return ret;
ret = _CollectCopyInfo(srcFolder.Path());
ret = _CollectCopyInfo(srcFolder.Path(), level);
if (ret < B_OK)
return ret;
} else if (S_ISLNK(statInfo.st_mode)) {
// link, ignore size
} else {
// file data
off_t size;
ret = entry.GetSize(&size);
if (ret < B_OK)
return ret;
fBytesToCopy += size;
fBytesToCopy += statInfo.st_size;
}
fItemsToCopy++;
}
level--;
return B_OK;
}
status_t
CopyEngine2::_CopyFolder(const char* _source, const char* _destination,
BLocker* locker)
int32& level, BLocker* locker)
{
level++;
fCurrentTargetFolder = _destination;
BDirectory source(_source);
@@ -253,18 +265,29 @@ CopyEngine2::_CopyFolder(const char* _source, const char* _destination,
if (ret < B_OK)
return ret;
fItemsCopied++;
fCurrentItem = name;
_UpdateProgress();
struct stat statInfo;
entry.GetStat(&statInfo);
if (!_ShouldCopyEntry(name, statInfo, level))
continue;
fItemsCopied++;
fCurrentItem = name;
_UpdateProgress();
BEntry copy(&destination, name);
bool copyAttributes = true;
if (S_ISDIR(statInfo.st_mode)) {
// handle recursive directory copy
if (copy.Exists()) {
// Do not overwrite attributes on folders that exist.
// This should work better when the install target already
// contains a Haiku installation.
copyAttributes = false;
}
BPath srcFolder;
ret = entry.GetPath(&srcFolder);
if (ret < B_OK)
@@ -278,7 +301,8 @@ CopyEngine2::_CopyFolder(const char* _source, const char* _destination,
if (locker != NULL)
lock.Unlock();
ret = _CopyFolder(srcFolder.Path(), dstFolder.Path(), locker);
ret = _CopyFolder(srcFolder.Path(), dstFolder.Path(), level,
locker);
if (ret < B_OK)
return ret;
@@ -312,6 +336,9 @@ CopyEngine2::_CopyFolder(const char* _source, const char* _destination,
return ret;
}
if (!copyAttributes)
continue;
// copy attributes
BNode sourceNode(&entry);
BNode targetNode(&copy);
@@ -325,6 +352,8 @@ CopyEngine2::_CopyFolder(const char* _source, const char* _destination,
off_t offset = 0;
ssize_t read = sourceNode.ReadAttr(attrName, info.type,
offset, buffer, min_c(size, info.size));
// NOTE: It's important to still write the attribute even if
// we have read 0 bytes!
while (read >= 0) {
targetNode.WriteAttr(attrName, info.type, offset, buffer, read);
offset += read;
@@ -343,6 +372,7 @@ CopyEngine2::_CopyFolder(const char* _source, const char* _destination,
copy.SetCreationTime(statInfo.st_crtime);
}
level--;
return B_OK;
}
@@ -363,6 +393,24 @@ CopyEngine2::_UpdateProgress()
}
bool
CopyEngine2::_ShouldCopyEntry(const char* name, const struct stat& statInfo,
int32 level) const
{
if (level == 1 && S_ISDIR(statInfo.st_mode)) {
if (strcmp(VAR_DIRECTORY, name) == 0) {
printf("ignoring '%s'.\n", name);
return false;
}
if (strcmp(PACKAGES_DIRECTORY, name) == 0) {
printf("ignoring '%s'.\n", name);
return false;
}
}
return true;
}
int32
CopyEngine2::_WriteThreadEntry(void* cookie)
{
+7 -1
View File
@@ -28,11 +28,17 @@ public:
BLocker* locker = NULL);
private:
status_t _CollectCopyInfo(const char* source);
status_t _CollectCopyInfo(const char* source,
int32& level);
status_t _CopyFolder(const char* source,
const char* destination,
int32& level,
BLocker* locker = NULL);
bool _ShouldCopyEntry(const char* name,
const struct stat& statInfo,
int32 level) const;
void _UpdateProgress();
static int32 _WriteThreadEntry(void* cookie);
+32 -4
View File
@@ -264,6 +264,10 @@ InstallerWindow::InstallerWindow()
fSetupButton = new BButton("setup_button",
"Setup partitions" B_UTF8_ELLIPSIS, new BMessage(SETUP_MESSAGE));
fMakeBootableButton = new BButton("makebootable_button",
"Write Boot Sector", new BMessage(kWriteBootSector));
fMakeBootableButton->SetEnabled(false);
SetLayout(new BGroupLayout(B_HORIZONTAL));
AddChild(BGroupLayoutBuilder(B_VERTICAL)
.Add(BGroupLayoutBuilder(B_HORIZONTAL)
@@ -286,8 +290,9 @@ InstallerWindow::InstallerWindow()
.Add(fSizeView, 0, 6, 2)
)
.Add(BGroupLayoutBuilder(B_HORIZONTAL)
.Add(BGroupLayoutBuilder(B_HORIZONTAL, 10)
.Add(fSetupButton)
.Add(fMakeBootableButton)
.AddGlue()
.Add(fBeginButton)
)
@@ -437,8 +442,10 @@ InstallerWindow::MessageReceived(BMessage *msg)
}
case STATUS_MESSAGE:
{
if (fInstallStatus != kInstalling)
break;
// TODO: Was this supposed to prevent status messages still arriving
// after the copy engine was shut down?
// if (fInstallStatus != kInstalling)
// break;
float progress;
if (msg->FindFloat("progress", &progress) == B_OK) {
const char* currentItem;
@@ -466,17 +473,27 @@ InstallerWindow::MessageReceived(BMessage *msg)
break;
}
case INSTALL_FINISHED:
{
delete fCopyEngineLock;
fCopyEngineLock = NULL;
fBeginButton->SetLabel("Quit");
_SetStatusMessage("Installation completed.");
PartitionMenuItem* dstItem
= (PartitionMenuItem*)fDestMenu->FindMarked();
char status[1024];
snprintf(status, sizeof(status), "Installation completed. "
"Boot sector has been written to '%s'. Press Quit to reboot "
"or chose a new target volume to perform another "
"installation.", dstItem ? dstItem->Name() : "???");
_SetStatusMessage(status);
fInstallStatus = kFinished;
_DisableInterface(false);
fProgressLayoutItem->SetVisible(false);
fPkgSwitchLayoutItem->SetVisible(true);
_ShowOptionalPackages();
break;
}
case B_SOME_APP_LAUNCHED:
case B_SOME_APP_QUIT:
{
@@ -495,6 +512,10 @@ InstallerWindow::MessageReceived(BMessage *msg)
}
break;
}
case kWriteBootSector:
fCopyEngine->WriteBootSector(fDestMenu);
break;
default:
BWindow::MessageReceived(msg);
break;
@@ -643,6 +664,13 @@ InstallerWindow::_UpdateControls()
fInstallStatus = kReadyForInstall;
fBeginButton->SetLabel("Begin");
fBeginButton->SetEnabled(srcItem && dstItem);
// adjust "Write Boot Sector" button
label = "Write Boot Sector";
if (dstItem)
label << " to \'" <<dstItem->Name() << '\'';
fMakeBootableButton->SetEnabled(dstItem);
fMakeBootableButton->SetLabel(label.String());
}
+3
View File
@@ -35,6 +35,8 @@ enum InstallStatus {
const uint32 STATUS_MESSAGE = 'iSTM';
const uint32 INSTALL_FINISHED = 'iIFN';
const uint32 RESET_INSTALL = 'iRSI';
const uint32 kWriteBootSector = 'iWBS';
const char PACKAGES_DIRECTORY[] = "_packages_";
const char VAR_DIRECTORY[] = "var";
@@ -83,6 +85,7 @@ private:
BButton* fBeginButton;
BButton* fSetupButton;
BButton* fMakeBootableButton;
bool fNeedsToCenterOnScreen;