2 * Copyright 2013, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Ingo Weinhold <ingo_weinhold@gmx.de>
10 #include "PackageDaemon.h"
15 #include <Directory.h>
16 #include <NodeMonitor.h>
18 #include <AutoDeleter.h>
19 #include <package/DaemonDefs.h>
21 #include "DebugSupport.h"
26 using namespace BPackageKit::BPrivate
;
29 PackageDaemon::PackageDaemon(status_t
* _error
)
31 BServer(B_PACKAGE_DAEMON_APP_SIGNATURE
, false, _error
),
39 PackageDaemon::~PackageDaemon()
47 status_t error
= fVolumeWatcher
.StartWatching(BMessenger(this, this));
49 ERROR("PackageDaemon::Init(): failed to start volume watching: %s\n",
53 // register all packagefs volumes
54 for (int32 cookie
= 0;;) {
55 dev_t device
= next_dev(&cookie
);
59 _RegisterVolume(device
);
67 PackageDaemon::MessageReceived(BMessage
* message
)
69 switch (message
->what
) {
73 if (message
->FindInt32("opcode", &opcode
) != B_OK
)
76 if (opcode
== B_DEVICE_MOUNTED
)
77 _HandleVolumeMounted(message
);
78 else if (opcode
== B_DEVICE_UNMOUNTED
)
79 _HandleVolumeUnmounted(message
);
83 case B_MESSAGE_GET_INSTALLATION_LOCATION_INFO
:
84 case B_MESSAGE_COMMIT_TRANSACTION
:
89 // Get the node_ref of the filesystem root to see which one it is
90 error
= message
->FindInt32("volume", &nodeRef
.device
);
92 error
= message
->FindInt64("root", &nodeRef
.node
);
94 if (fSystemRoot
!= NULL
&& (error
!= B_OK
95 || fSystemRoot
->NodeRef() == nodeRef
)) {
96 fSystemRoot
->HandleRequest(DetachCurrentMessage());
97 } else if (error
== B_OK
) {
98 Root
* root
= _FindRoot(nodeRef
);
100 root
->HandleRequest(DetachCurrentMessage());
107 BServer::MessageReceived(message
);
114 PackageDaemon::_RegisterVolume(dev_t deviceID
)
116 // get the FS info and check whether this is a package FS volume at all
118 status_t error
= fs_stat_dev(deviceID
, &info
);
122 if (strcmp(info
.fsh_name
, "packagefs") != 0)
123 RETURN_ERROR(B_BAD_VALUE
);
126 Volume
* volume
= new(std::nothrow
) Volume(this);
128 RETURN_ERROR(B_NO_MEMORY
);
129 ObjectDeleter
<Volume
> volumeDeleter(volume
);
132 error
= volume
->Init(node_ref(info
.dev
, info
.root
), rootRef
);
136 if (volume
->MountType() == PACKAGE_FS_MOUNT_TYPE_CUSTOM
) {
137 // TODO: Or maybe not?
138 INFORM("skipping custom mounted volume at \"%s\"\n",
139 volume
->Path().String());
143 // get the root for the volume and register it
145 error
= _GetOrCreateRoot(rootRef
, root
);
149 error
= root
->RegisterVolume(volume
);
154 volumeDeleter
.Detach();
156 INFORM("volume at \"%s\" registered\n", volume
->Path().String());
163 PackageDaemon::_UnregisterVolume(Volume
* volume
)
167 INFORM("volume at \"%s\" unregistered\n", volume
->Path().String());
169 Root
* root
= volume
->GetRoot();
170 root
->UnregisterVolume(volume
);
177 PackageDaemon::_GetOrCreateRoot(const node_ref
& nodeRef
, Root
*& _root
)
179 Root
* root
= _FindRoot(nodeRef
);
181 root
->AcquireReference();
183 root
= new(std::nothrow
) Root
;
185 RETURN_ERROR(B_NO_MEMORY
);
186 ObjectDeleter
<Root
> rootDeleter(root
);
188 bool isSystemRoot
= false;
189 if (fSystemRoot
== NULL
) {
191 isSystemRoot
= stat("/boot", &st
) == 0
192 && node_ref(st
.st_dev
, st
.st_ino
) == nodeRef
;
195 status_t error
= root
->Init(nodeRef
, isSystemRoot
);
199 if (!fRoots
.AddItem(root
))
200 RETURN_ERROR(B_NO_MEMORY
);
202 rootDeleter
.Detach();
207 INFORM("root at \"%s\" (device: %" B_PRIdDEV
", node: %" B_PRIdINO
") "
208 "registered\n", root
->Path().String(), nodeRef
.device
,
218 PackageDaemon::_FindRoot(const node_ref
& nodeRef
) const
220 for (int32 i
= 0; Root
* root
= fRoots
.ItemAt(i
); i
++) {
221 if (root
->NodeRef() == nodeRef
)
230 PackageDaemon::_PutRoot(Root
* root
)
232 if (root
->ReleaseReference() == 1) {
233 INFORM("root at \"%s\" unregistered\n", root
->Path().String());
234 fRoots
.RemoveItem(root
, true);
235 // deletes the object
241 PackageDaemon::_FindVolume(dev_t deviceID
) const
243 for (int32 i
= 0; Root
* root
= fRoots
.ItemAt(i
); i
++) {
244 if (Volume
* volume
= root
->FindVolume(deviceID
))
253 PackageDaemon::_HandleVolumeMounted(const BMessage
* message
)
256 if (message
->FindInt32("new device", &device
) != B_OK
)
259 // _RegisterVolume() also checks whether it is a package FS volume, so we
260 // don't need to bother.
261 _RegisterVolume(device
);
266 PackageDaemon::_HandleVolumeUnmounted(const BMessage
* message
)
269 if (message
->FindInt32("device", &device
) != B_OK
)
272 if (Volume
* volume
= _FindVolume(device
))
273 _UnregisterVolume(volume
);
281 main(int argc
, const char* const* argv
)
284 PackageDaemon
daemon(&error
);
286 error
= daemon
.Init();
288 FATAL("failed to init server application: %s\n", strerror(error
));