[haiku-commits] Change in haiku[master]: installer/CopyEngine: now only exposes a Copy() method

  • From: Gerrit <review@xxxxxxxxxxxxxxxxxxx>
  • To: waddlesplash <waddlesplash@xxxxxxxxx>, haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 22 Mar 2020 19:20:34 +0000

From leorize <leorize+oss@xxxxxxxxxxx>:

leorize has uploaded this change for review. ( 
https://review.haiku-os.org/c/haiku/+/2399 ;)


Change subject: installer/CopyEngine: now only exposes a Copy() method
......................................................................

installer/CopyEngine: now only exposes a Copy() method

Previously this class exposes two methods:
- CopyFile(): only copy the file data, nothing else.
- CopyFolder(): copy files & directories between two folders, while
                preserving the attributes as well as symlinks.

With this commit, everything is unified into one method: Copy(). This
method can handle files, directories, symlinks and optionally also copy
attributes. Since most of the logic was just moved around, we can be
rather certain that this won't disrupt CopyEngine behaviors by much.

In the future we should look into using BCopyEngine to replace the
copying part of CopyEngine, as they seems to be compatible.

This change allows the Installer to make use of CopyEngine as a
general-purpose copier, in preparation for optional .hpkg installation
support.

Change-Id: Iad5ba2ebc9f34b7822e550b415308fd2b43eed47
---
M src/apps/installer/CopyEngine.cpp
M src/apps/installer/CopyEngine.h
M src/apps/installer/WorkerThread.cpp
3 files changed, 156 insertions(+), 147 deletions(-)



  git pull ssh://git.haiku-os.org:22/haiku refs/changes/99/2399/1

diff --git a/src/apps/installer/CopyEngine.cpp 
b/src/apps/installer/CopyEngine.cpp
index bd798fe..7678fac 100644
--- a/src/apps/installer/CopyEngine.cpp
+++ b/src/apps/installer/CopyEngine.cpp
@@ -128,16 +128,28 @@


 status_t
-CopyEngine::CopyFolder(const char* source, const char* destination,
-       sem_id cancelSemaphore)
+CopyEngine::Copy(const char* _source, const char* _destination,
+       sem_id cancelSemaphore, bool copyAttributes)
 {
        int32 level = 0;
-       return _CopyFolder(source, destination, level, cancelSemaphore);
+       status_t ret;
+
+       BEntry source(_source);
+       ret = source.InitCheck();
+       if (ret != B_OK)
+               return ret;
+
+       BEntry destination(_destination);
+       ret = destination.InitCheck();
+       if (ret != B_OK)
+               return ret;
+
+       return _Copy(source, destination, level, cancelSemaphore, 
copyAttributes);
 }


 status_t
-CopyEngine::CopyFile(const BEntry& _source, const BEntry& _destination,
+CopyEngine::_CopyData(const BEntry& _source, const BEntry& _destination,
        sem_id cancelSemaphore)
 {
        SemaphoreLocker lock(cancelSemaphore);
@@ -282,157 +294,153 @@


 status_t
-CopyEngine::_CopyFolder(const char* _source, const char* _destination,
-       int32& level, sem_id cancelSemaphore)
+CopyEngine::_Copy(BEntry &source, BEntry &destination,
+       int32& level, sem_id cancelSemaphore, bool copyAttributes)
 {
        level++;

-       BDirectory source(_source);
-       status_t ret = source.InitCheck();
-       if (ret < B_OK)
+       struct stat sourceInfo;
+       status_t ret = source.GetStat(&sourceInfo);
+       if (ret != B_OK)
                return ret;

-       ret = create_directory(_destination, 0777);
-       if (ret < B_OK && ret != B_FILE_EXISTS) {
-               fprintf(stderr, "Could not create '%s': %s\n", _destination,
-                       strerror(ret));
-               return ret;
+       SemaphoreLocker lock(cancelSemaphore);
+       if (cancelSemaphore >= 0 && !lock.IsLocked()) {
+               // We are supposed to quit
+               return B_CANCELED;
        }

-       BDirectory destination(_destination);
-       ret = destination.InitCheck();
-       if (ret < B_OK)
+       BPath sourcePath(&source);
+       ret = sourcePath.InitCheck();
+       if (ret != B_OK)
                return ret;

-       BEntry entry;
-       while (source.GetNextEntry(&entry) == B_OK) {
-               SemaphoreLocker lock(cancelSemaphore);
-               if (cancelSemaphore >= 0 && !lock.IsLocked()) {
-                       // We are supposed to quit
-                       return B_CANCELED;
-               }
+       BPath destPath(&destination);
+       ret = destPath.InitCheck();
+       if (ret != B_OK)
+               return ret;

-               const char* name = entry.Name();
-               BPath sourceEntryPath;
-               status_t ret = entry.GetPath(&sourceEntryPath);
+       const char *relativeSourcePath = _RelativeEntryPath(sourcePath.Path());
+       if (fEntryFilter != NULL
+               && !fEntryFilter->ShouldCopyEntry(source, relativeSourcePath,
+                       sourceInfo, level)) {
+               // Silently skip the filtered entry.
+               return B_OK;
+       }
+
+       if (cancelSemaphore >= 0)
+               lock.Unlock();
+
+       if (S_ISDIR(sourceInfo.st_mode)) {
+               BDirectory sourceDirectory(&source);
+               ret = sourceDirectory.InitCheck();
                if (ret != B_OK)
                        return ret;
-               const char* relativeSourceEntryPath
-                       = _RelativeEntryPath(sourceEntryPath.Path());

-               struct stat statInfo;
-               entry.GetStat(&statInfo);
+               if (destination.Exists()) {
+                       if (destination.IsDirectory()) {
+                               if (fEntryFilter
+                                       && 
fEntryFilter->ShouldClobberFolder(source,
+                                               relativeSourcePath, sourceInfo, 
level)) {
+                                       ret = _RemoveFolder(destination);
+                               } 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 = destination.Remove();
+                       }

-               if (fEntryFilter != NULL
-                       && !fEntryFilter->ShouldCopyEntry(entry, 
relativeSourceEntryPath,
-                               statInfo, level)) {
-                       continue;
+                       if (ret != B_OK) {
+                               fprintf(stderr, "Failed to make room for folder 
'%s': "
+                                       "%s\n", sourcePath.Path(), 
strerror(ret));
+                               return ret;
+                       }
+               } else {
+                       ret = create_directory(destPath.Path(), 0777);
+                       if (ret != B_OK && ret != B_FILE_EXISTS) {
+                               fprintf(stderr, "Could not create '%s': %s\n", 
destPath.Path(),
+                                       strerror(ret));
+                               return ret;
+                       }
+               }
+
+               BDirectory destDirectory(&destination);
+               ret = destDirectory.InitCheck();
+               if (ret != B_OK)
+                       return ret;
+
+               BEntry entry;
+               while (sourceDirectory.GetNextEntry(&entry) == B_OK) {
+                       BEntry dest(&destDirectory, entry.Name());
+                       ret = dest.InitCheck();
+                       if (ret != B_OK)
+                               return ret;
+                       ret = _Copy(entry, dest, level,
+                                       cancelSemaphore, copyAttributes);
+                       if (ret != B_OK)
+                               return ret;
+               }
+       } else {
+               if (destination.Exists()) {
+                       if (destination.IsDirectory())
+                               ret = _RemoveFolder(destination);
+                       else
+                               ret = destination.Remove();
+                       if (ret != B_OK) {
+                               fprintf(stderr, "Failed to make room for entry 
'%s': "
+                                       "%s\n", sourcePath.Path(), 
strerror(ret));
+                               return ret;
+                       }
                }

                fItemsCopied++;
-               fCurrentItem = name;
-               fCurrentTargetFolder = _destination;
-               _UpdateProgress();
-
-               BEntry copy(&destination, name);
-               bool copyAttributes = true;
-
-               if (S_ISDIR(statInfo.st_mode)) {
-                       // handle recursive directory copy
-
-                       if (copy.Exists()) {
-                               ret = B_OK;
-                               if (copy.IsDirectory()) {
-                                       if (fEntryFilter
-                                               && 
fEntryFilter->ShouldClobberFolder(entry,
-                                                       
relativeSourceEntryPath, statInfo, level)) {
-                                               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 dstFolder;
-                       ret = copy.GetPath(&dstFolder);
-                       if (ret < B_OK)
-                               return ret;
-
-                       if (cancelSemaphore >= 0)
-                               lock.Unlock();
-
-                       ret = _CopyFolder(sourceEntryPath.Path(), 
dstFolder.Path(), level,
-                               cancelSemaphore);
-                       if (ret < B_OK)
-                               return ret;
-
-                       if (cancelSemaphore >= 0 && !lock.Lock()) {
-                               // We are supposed to quit
-                               return B_CANCELED;
-                       }
-               } else {
-                       if (copy.Exists()) {
-                               if (copy.IsDirectory())
-                                       ret = _RemoveFolder(copy);
-                               else
-                                       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)
-                       continue;
-
-               ret = copy.SetTo(&destination, name);
+               BPath destDirectory;
+               ret = destPath.GetParent(&destDirectory);
                if (ret != B_OK)
                        return ret;
+               fCurrentTargetFolder = destDirectory.Path();
+               fCurrentItem = sourcePath.Leaf();
+               _UpdateProgress();

+               if (S_ISLNK(sourceInfo.st_mode)) {
+                       // copy symbolic links
+                       BSymLink srcLink(&source);
+                       ret = srcLink.InitCheck();
+                       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;
+
+                       BDirectory dstFolder;
+                       ret = destination.GetParent(&dstFolder);
+                       if (ret != B_OK)
+                               return ret;
+                       ret = dstFolder.CreateSymLink(sourcePath.Leaf(), 
linkPath, NULL);
+                       if (ret != B_OK)
+                               return ret;
+               } else {
+                       // copy file data
+                       // NOTE: Do not pass the locker, we simply keep holding 
the lock!
+                       ret = _CopyData(source, destination);
+                       if (ret != B_OK)
+                               return ret;
+               }
+       }
+
+       if (copyAttributes) {
                // copy attributes
-               BNode sourceNode(&entry);
-               BNode targetNode(&copy);
+               BNode sourceNode(&source);
+               BNode targetNode(&destination);
                char attrName[B_ATTR_NAME_LENGTH];
                while (sourceNode.GetNextAttrName(attrName) == B_OK) {
                        attr_info info;
-                       if (sourceNode.GetAttrInfo(attrName, &info) < B_OK)
+                       if (sourceNode.GetAttrInfo(attrName, &info) != B_OK)
                                continue;
                        size_t size = 4096;
                        uint8 buffer[size];
@@ -452,11 +460,11 @@
                }

                // copy basic attributes
-               copy.SetPermissions(statInfo.st_mode);
-               copy.SetOwner(statInfo.st_uid);
-               copy.SetGroup(statInfo.st_gid);
-               copy.SetModificationTime(statInfo.st_mtime);
-               copy.SetCreationTime(statInfo.st_crtime);
+               destination.SetPermissions(sourceInfo.st_mode);
+               destination.SetOwner(sourceInfo.st_uid);
+               destination.SetGroup(sourceInfo.st_gid);
+               destination.SetModificationTime(sourceInfo.st_mtime);
+               destination.SetCreationTime(sourceInfo.st_crtime);
        }

        level--;
diff --git a/src/apps/installer/CopyEngine.h b/src/apps/installer/CopyEngine.h
index 2989772..f988577 100644
--- a/src/apps/installer/CopyEngine.h
+++ b/src/apps/installer/CopyEngine.h
@@ -32,20 +32,21 @@
                        status_t                        CollectTargets(const 
char* source,
                                                                        sem_id 
cancelSemaphore = -1);

-                       status_t                        CopyFolder(const char* 
source,
+                       status_t                        Copy(const char* source,
                                                                        const 
char* destination,
-                                                                       sem_id 
cancelSemaphore = -1);
-
-                       status_t                        CopyFile(const BEntry& 
entry,
-                                                                       const 
BEntry& destination,
-                                                                       sem_id 
cancelSemaphore = -1);
+                                                                       sem_id 
cancelSemaphore = -1,
+                                                                       bool 
copyAttributes = true);

 private:
                        status_t                        _CollectCopyInfo(const 
char* source,
                                                                        int32& 
level, sem_id cancelSemaphore);
-                       status_t                        _CopyFolder(const char* 
source,
-                                                                       const 
char* destination,
-                                                                       int32& 
level, sem_id cancelSemaphore);
+                       status_t                        _Copy(BEntry& source,
+                                                                       BEntry& 
destination,
+                                                                       int32& 
level, sem_id cancelSemaphore,
+                                                                       bool 
copyAttributes);
+                       status_t                        _CopyData(const BEntry& 
entry,
+                                                                       const 
BEntry& destination,
+                                                                       sem_id 
cancelSemaphore = -1);

                        status_t                        _RemoveFolder(BEntry& 
entry);

diff --git a/src/apps/installer/WorkerThread.cpp 
b/src/apps/installer/WorkerThread.cpp
index f289f5b..9cb87e0 100644
--- a/src/apps/installer/WorkerThread.cpp
+++ b/src/apps/installer/WorkerThread.cpp
@@ -534,7 +534,7 @@
        reporter.StartTimer();

        // copy source volume
-       err = engine.CopyFolder(srcDirectory.Path(), targetDirectory.Path(),
+       err = engine.Copy(srcDirectory.Path(), targetDirectory.Path(),
                fCancelSemaphore);
        if (err != B_OK)
                return _InstallationError(err);
@@ -546,7 +546,7 @@
                for (int32 i = 0; i < count; i++) {
                        Package *p = 
static_cast<Package*>(fPackages->ItemAt(i));
                        BPath packageDir(pkgRootDir.Path(), p->Folder());
-                       err = engine.CopyFolder(packageDir.Path(), 
targetDirectory.Path(),
+                       err = engine.Copy(packageDir.Path(), 
targetDirectory.Path(),
                                fCancelSemaphore);
                        if (err != B_OK)
                                return _InstallationError(err);

--
To view, visit https://review.haiku-os.org/c/haiku/+/2399
To unsubscribe, or for help writing mail filters, visit 
https://review.haiku-os.org/settings

Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: Iad5ba2ebc9f34b7822e550b415308fd2b43eed47
Gerrit-Change-Number: 2399
Gerrit-PatchSet: 1
Gerrit-Owner: leorize <leorize+oss@xxxxxxxxxxx>
Gerrit-MessageType: newchange

Other related posts:

  • » [haiku-commits] Change in haiku[master]: installer/CopyEngine: now only exposes a Copy() method - Gerrit