diff --git a/src/apps/installer/CopyEngine.cpp b/src/apps/installer/CopyEngine.cpp index 8b14883bf5..38dadb4ae6 100644 --- a/src/apps/installer/CopyEngine.cpp +++ b/src/apps/installer/CopyEngine.cpp @@ -19,7 +19,6 @@ #include #include -#include "InstallerDefs.h" #include "SemaphoreLocker.h" #include "ProgressReporter.h" @@ -27,7 +26,18 @@ using std::nothrow; -CopyEngine::CopyEngine(ProgressReporter* reporter) +// #pragma mark - EntryFilter + + +CopyEngine::EntryFilter::~EntryFilter() +{ +} + + +// #pragma mark - CopyEngine + + +CopyEngine::CopyEngine(ProgressReporter* reporter, EntryFilter* entryFilter) : fBufferQueue(), fWriterThread(-1), @@ -48,7 +58,8 @@ CopyEngine::CopyEngine(ProgressReporter* reporter) fCurrentTargetFolder(NULL), fCurrentItem(NULL), - fProgressReporter(reporter) + fProgressReporter(reporter), + fEntryFilter(entryFilter) { fWriterThread = spawn_thread(_WriteThreadEntry, "buffer writer", B_NORMAL_PRIORITY, this); @@ -97,19 +108,6 @@ CopyEngine::ResetTargets(const char* source) fCurrentTargetFolder = NULL; fCurrentItem = NULL; - - // init BEntry pointing to /var - // There is no other way to retrieve the path to the var folder - // on the source volume. Using find_directory() with - // B_COMMON_VAR_DIRECTORY will only ever get the var folder on the - // current /boot volume regardless of the volume of "source", which - // makes sense, since passing a volume is meant to folders that are - // volume specific, like "trash". - BPath path(source); - if (path.Append(kSwapFilePath) == B_OK) - fSwapFileEntry.SetTo(path.Path()); - else - fSwapFileEntry.Unset(); } @@ -244,8 +242,10 @@ CopyEngine::_CollectCopyInfo(const char* _source, int32& level, if (ret < B_OK) return ret; - if (!_ShouldCopyEntry(entry, name, statInfo, level)) + if (fEntryFilter != NULL + && !fEntryFilter->ShouldCopyEntry(entry, name, statInfo, level)) { continue; + } if (S_ISDIR(statInfo.st_mode)) { // handle recursive directory copy @@ -315,8 +315,10 @@ CopyEngine::_CopyFolder(const char* _source, const char* _destination, struct stat statInfo; entry.GetStat(&statInfo); - if (!_ShouldCopyEntry(entry, name, statInfo, level)) + if (fEntryFilter != NULL + && !fEntryFilter->ShouldCopyEntry(entry, name, statInfo, level)) { continue; + } fItemsCopied++; fCurrentItem = name; @@ -331,9 +333,11 @@ CopyEngine::_CopyFolder(const char* _source, const char* _destination, if (copy.Exists()) { ret = B_OK; if (copy.IsDirectory()) { - if (_ShouldClobberFolder(name, statInfo, level)) + if (fEntryFilter + && fEntryFilter->ShouldClobberFolder(entry, name, + statInfo, level)) { ret = _RemoveFolder(copy); - else { + } else { // Do not overwrite attributes on folders that exist. // This should work better when the install target // already contains a Haiku installation. @@ -502,57 +506,6 @@ CopyEngine::_UpdateProgress() } -bool -CopyEngine::_ShouldCopyEntry(const BEntry& entry, const char* name, - const struct stat& statInfo, int32 level) const -{ - if (level == 1 && S_ISDIR(statInfo.st_mode)) { - if (strcmp(kPackagesDirectoryPath, name) == 0) { - printf("ignoring '%s'.\n", name); - return false; - } - if (strcmp(kSourcesDirectoryPath, name) == 0) { - printf("ignoring '%s'.\n", name); - return false; - } - if (strcmp("rr_moved", name) == 0) { - printf("ignoring '%s'.\n", name); - return false; - } - } - if (level == 1 && S_ISREG(statInfo.st_mode)) { - if (strcmp("boot.catalog", name) == 0) { - printf("ignoring '%s'.\n", name); - return false; - } - if (strcmp("haiku-boot-floppy.image", name) == 0) { - printf("ignoring '%s'.\n", name); - return false; - } - } - if (fSwapFileEntry == entry) { - // current location of var - printf("ignoring swap file\n"); - return false; - } - return true; -} - - -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; - } - } - return false; -} - - int32 CopyEngine::_WriteThreadEntry(void* cookie) { diff --git a/src/apps/installer/CopyEngine.h b/src/apps/installer/CopyEngine.h index 61558e7128..855f1dc7a8 100644 --- a/src/apps/installer/CopyEngine.h +++ b/src/apps/installer/CopyEngine.h @@ -20,7 +20,11 @@ class ProgressReporter; class CopyEngine { public: - CopyEngine(ProgressReporter* reporter); + class EntryFilter; + +public: + CopyEngine(ProgressReporter* reporter, + EntryFilter* entryFilter); virtual ~CopyEngine(); void ResetTargets(const char* source); @@ -42,15 +46,6 @@ private: const char* destination, int32& level, sem_id cancelSemaphore); - bool _ShouldCopyEntry(const BEntry& entry, - const char* name, - const struct stat& statInfo, - int32 level) const; - - bool _ShouldClobberFolder(const char* name, - const struct stat& statInfo, - int32 level) const; - status_t _RemoveFolder(BEntry& entry); void _UpdateProgress(); @@ -107,10 +102,22 @@ private: const char* fCurrentItem; ProgressReporter* fProgressReporter; + EntryFilter* fEntryFilter; +}; - // TODO: Should be made into a list of BEntris to be ignored, perhaps. - // settable by method... - BEntry fSwapFileEntry; + +class CopyEngine::EntryFilter { +public: + virtual ~EntryFilter(); + + virtual bool ShouldCopyEntry(const BEntry& entry, + const char* name, + const struct stat& statInfo, + int32 level) const = 0; + virtual bool ShouldClobberFolder(const BEntry& entry, + const char* name, + const struct stat& statInfo, + int32 level) const = 0; }; diff --git a/src/apps/installer/WorkerThread.cpp b/src/apps/installer/WorkerThread.cpp index 064375a24d..3de1f40467 100644 --- a/src/apps/installer/WorkerThread.cpp +++ b/src/apps/installer/WorkerThread.cpp @@ -81,6 +81,81 @@ private: // #pragma mark - WorkerThread +class WorkerThread::EntryFilter : public CopyEngine::EntryFilter { +public: + EntryFilter(const char* sourceDirectory) + { + // init BEntry pointing to /var + // There is no other way to retrieve the path to the var folder + // on the source volume. Using find_directory() with + // B_COMMON_VAR_DIRECTORY will only ever get the var folder on the + // current /boot volume regardless of the volume of "source", which + // makes sense, since passing a volume is meant to folders that are + // volume specific, like "trash". + BPath path(sourceDirectory); + if (path.Append(kSwapFilePath) == B_OK) + fSwapFileEntry.SetTo(path.Path()); + else + fSwapFileEntry.Unset(); + } + + virtual bool ShouldCopyEntry(const BEntry& entry, const char* name, + const struct stat& statInfo, int32 level) const + { + if (level == 1 && S_ISDIR(statInfo.st_mode)) { + if (strcmp(kPackagesDirectoryPath, name) == 0) { + printf("ignoring '%s'.\n", name); + return false; + } + if (strcmp(kSourcesDirectoryPath, name) == 0) { + printf("ignoring '%s'.\n", name); + return false; + } + if (strcmp("rr_moved", name) == 0) { + printf("ignoring '%s'.\n", name); + return false; + } + } + if (level == 1 && S_ISREG(statInfo.st_mode)) { + if (strcmp("boot.catalog", name) == 0) { + printf("ignoring '%s'.\n", name); + return false; + } + if (strcmp("haiku-boot-floppy.image", name) == 0) { + printf("ignoring '%s'.\n", name); + return false; + } + } + if (fSwapFileEntry == entry) { + // current location of var + printf("ignoring swap file\n"); + return false; + } + return true; + } + + virtual bool ShouldClobberFolder(const BEntry& entry, 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; + } + } + return false; + } + +private: + // TODO: Should be made into a list of BEntris to be ignored, perhaps. + // settable by method... + BEntry fSwapFileEntry; +}; + + +// #pragma mark - WorkerThread + + WorkerThread::WorkerThread(InstallerWindow *window) : BLooper("copy_engine"), @@ -266,11 +341,6 @@ WorkerThread::_PerformInstall(BMenu* srcMenu, BMenu* targetMenu) const char* mountError = B_TRANSLATE("The disk can't be mounted. Please " "choose a different disk."); - BMessenger messenger(fWindow); - ProgressReporter reporter(messenger, new BMessage(MSG_STATUS_MESSAGE)); - CopyEngine engine(&reporter); - BList unzipEngines; - PartitionMenuItem* targetItem = (PartitionMenuItem*)targetMenu->FindMarked(); PartitionMenuItem* srcItem = (PartitionMenuItem*)srcMenu->FindMarked(); if (!srcItem || !targetItem) { @@ -401,6 +471,13 @@ WorkerThread::_PerformInstall(BMenu* srcMenu, BMenu* targetMenu) // Begin actual installation + { + BMessenger messenger(fWindow); + ProgressReporter reporter(messenger, new BMessage(MSG_STATUS_MESSAGE)); + EntryFilter entryFilter(srcDirectory.Path()); + CopyEngine engine(&reporter, &entryFilter); + BList unzipEngines; + _LaunchInitScript(targetDirectory); // Create the default indices which should always be present on a proper @@ -480,6 +557,8 @@ WorkerThread::_PerformInstall(BMenu* srcMenu, BMenu* targetMenu) BMessenger(fWindow).SendMessage(MSG_INSTALL_FINISHED); return; + } + error: BMessage statusMessage(MSG_RESET); if (err == B_CANCELED) diff --git a/src/apps/installer/WorkerThread.h b/src/apps/installer/WorkerThread.h index e5103b715c..6ab633075e 100644 --- a/src/apps/installer/WorkerThread.h +++ b/src/apps/installer/WorkerThread.h @@ -55,6 +55,10 @@ private: void _SetStatusMessage(const char* status); +private: + class EntryFilter; + +private: InstallerWindow* fWindow; BDiskDeviceRoster fDDRoster; BList* fPackages;