[haiku-development] Re: chroot and package daemon bug

  • From: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Thu, 18 Aug 2016 07:18:04 +0200

On Wed, Aug 17, 2016 at 08:21:58PM +0200, Ingo Weinhold wrote:

So there's initially a Root object for "/" and as soon as a packagefs for a
(future or already existing) chroot is mounted a Root object for the chroot
base directory will be created. So you don't have to create it; it should
already exist.

I'm afraid, I don't understand, why you trying that. Maybe I'm missing
something, but the approach you proposed in your previous mail sounded good.
If you've implemented step 2) (adding the node_ref to the client's message),
implementing step 3) should be fairly simple: In the
B_MESSAGE_GET_INSTALLATION_LOCATION_INFO/B_MESSAGE_COMMIT_TRANSACTION case
in PackageDaemon::MessageReceived() extract the node_ref from the message,
use _FindRoot() to get the corresponding Root object and call
HandleRequest() on it (instead of on fSystemRoot).

Thanks, I somehow missed that I could use _FindRoot directly.

So, I have a first version of this working. There was, however, one
extra problem. In the chroot, there is no package volume mounted in
/home/config. The package kit does not expect that, and throws an
exception. I have added try/catch blocks to get it working, but I don't
know if they are at the right place. If that is the right thing to do,
I'll commit the changes.

Attached (and online at http://pulkomandy.tk/drop/packages_chroot.diff)
is the new version of the patch.

-- 
Adrien.
diff --git a/src/bin/findpaths.cpp b/src/bin/findpaths.cpp
index e2beb59..0bf7950 100644
--- a/src/bin/findpaths.cpp
+++ b/src/bin/findpaths.cpp
@@ -10,11 +10,15 @@
 #include <string.h>
 
 #include <package/PackageResolvableExpression.h>
+#include <package/manager/Exceptions.h>
 #include <Path.h>
 #include <PathFinder.h>
 #include <StringList.h>
 
 
+using namespace BPackageKit::BManager::BPrivate;
+
+
 extern const char* __progname;
 const char* kCommandName = __progname;
 
@@ -245,25 +249,37 @@ main(int argc, const char* const* argv)
        }
 
        if (referencePath != NULL || resolvable != NULL) {
-               BPathFinder pathFinder;
-               if (referencePath != NULL) {
-                       pathFinder.SetTo(referencePath, dependency);
-               } else {
-                       pathFinder.SetTo(
-                               
BPackageKit::BPackageResolvableExpression(resolvable),
-                               dependency);
-               }
+               try {
+                       BPathFinder pathFinder;
+                       if (referencePath != NULL) {
+                               pathFinder.SetTo(referencePath, dependency);
+                       } else {
+                               pathFinder.SetTo(
+                                       
BPackageKit::BPackageResolvableExpression(resolvable),
+                                       dependency);
+                       }
 
-               BPath path;
-               status_t error = pathFinder.FindPath(architecture, 
baseDirectory,
-                       subPath, existingOnly ? B_FIND_PATH_EXISTING_ONLY : 0, 
path);
-               if (error != B_OK) {
-                       fprintf(stderr, "Error: Failed to find path: %s\n",
-                               strerror(error));
-                       exit(1);
-               }
+                       BPath path;
+                       status_t error = pathFinder.FindPath(architecture, 
baseDirectory,
+                               subPath, existingOnly ? 
B_FIND_PATH_EXISTING_ONLY : 0, path);
+                       if (error != B_OK) {
+                               fprintf(stderr, "Error: Failed to find path: 
%s\n",
+                                       strerror(error));
+                               exit(1);
+                       }
 
-               printf("%s\n", path.Path());
+                       printf("%s\n", path.Path());
+               } catch(BFatalErrorException& exception) {
+                       if (!exception.Details().IsEmpty())
+                               fprintf(stderr, "%s", 
exception.Details().String());
+                       if (exception.Error() == B_OK) {
+                               fprintf(stderr, "Error: %s\n", 
exception.Message().String());
+                       } else {
+                               fprintf(stderr, "Error: %s: %s\n", 
exception.Message().String(),
+                                       strerror(exception.Error()));
+                       }
+                       return 1;
+               }
        } else {
                BStringList paths;
                status_t error = BPathFinder::FindPaths(architecture, 
baseDirectory,
diff --git a/src/kits/package/DaemonClient.cpp 
b/src/kits/package/DaemonClient.cpp
index ee0e7c2..7a9ca03 100644
--- a/src/kits/package/DaemonClient.cpp
+++ b/src/kits/package/DaemonClient.cpp
@@ -45,12 +45,25 @@ BDaemonClient::GetInstallationLocationInfo(
        if (error != B_OK)
                return error;
 
-       // send the request
        BMessage request(B_MESSAGE_GET_INSTALLATION_LOCATION_INFO);
        error = request.AddInt32("location", location);
        if (error != B_OK)
                return error;
 
+       // Get our filesystem root node. If we are in a chroot this is not the 
same
+       // as the package_daemon root node, so we must provide it.
+       struct stat st;
+       if (stat("/boot", &st) == 0)
+       {
+               error = request.AddInt32("volume", st.st_dev);
+               if (error != B_OK)
+                       return error;
+               error = request.AddInt64("root", st.st_ino);
+               if (error != B_OK)
+                       return error;
+       }
+
+       // send the request
        BMessage reply;
        fDaemonMessenger.SendMessage(&request, &reply);
        if (reply.what != B_MESSAGE_GET_INSTALLATION_LOCATION_INFO_REPLY)
diff --git a/src/kits/package/manager/PackageManager.cpp 
b/src/kits/package/manager/PackageManager.cpp
index 901b856..6d9ccd8 100644
--- a/src/kits/package/manager/PackageManager.cpp
+++ b/src/kits/package/manager/PackageManager.cpp
@@ -110,8 +110,12 @@ BPackageManager::Init(uint32 flags)
                // well. But we can easily filter those out.
                _AddInstalledRepository(fSystemRepository);
 
-               if (!fSystemRepository->IsInstalled())
-                       _AddInstalledRepository(fHomeRepository);
+               try {
+                       if (!fSystemRepository->IsInstalled())
+                               _AddInstalledRepository(fHomeRepository);
+               } catch(BFatalErrorException& exception) {
+                       // No home repository found. This is ok for haikuporter 
chroots.
+               }
        }
 
        // add other repositories
@@ -787,11 +791,15 @@ BPackageManager::_AddLocalPackage(const char* fileName)
 bool
 BPackageManager::_NextSpecificInstallationLocation()
 {
-       if (fLocation == B_PACKAGE_INSTALLATION_LOCATION_SYSTEM) {
-               fLocation = B_PACKAGE_INSTALLATION_LOCATION_HOME;
-               fSystemRepository->SetInstalled(false);
-               _AddInstalledRepository(fHomeRepository);
-               return true;
+       try {
+               if (fLocation == B_PACKAGE_INSTALLATION_LOCATION_SYSTEM) {
+                       fLocation = B_PACKAGE_INSTALLATION_LOCATION_HOME;
+                       fSystemRepository->SetInstalled(false);
+                       _AddInstalledRepository(fHomeRepository);
+                       return true;
+               }
+       } catch (BFatalErrorException& e) {
+               // No home repo. This is acceptable for example when we are in 
an haikuporter chroot.
        }
 
        return false;
diff --git a/src/servers/package/PackageDaemon.cpp 
b/src/servers/package/PackageDaemon.cpp
index 0c05213..4b35cb1 100644
--- a/src/servers/package/PackageDaemon.cpp
+++ b/src/servers/package/PackageDaemon.cpp
@@ -83,8 +83,23 @@ PackageDaemon::MessageReceived(BMessage* message)
                case B_MESSAGE_GET_INSTALLATION_LOCATION_INFO:
                case B_MESSAGE_COMMIT_TRANSACTION:
                {
-                       if (fSystemRoot != NULL)
+                       status_t error;
+                       node_ref nodeRef;
+
+                       // Get the node_ref of the filesystem root to see which 
one it is
+                       error = message->FindInt32("volume", &nodeRef.device);
+                       if (error == B_OK)
+                               error = message->FindInt64("root", 
&nodeRef.node);
+
+                       if (fSystemRoot != NULL && (error != B_OK
+                                       || fSystemRoot->NodeRef() == nodeRef))
                                
fSystemRoot->HandleRequest(DetachCurrentMessage());
+                       else {
+                               Root* root = _FindRoot(nodeRef);
+                               if (root != NULL) {
+                                       
root->HandleRequest(DetachCurrentMessage());
+                               }
+                       }
                        break;
                }
 

Other related posts: