[haiku-commits] BRANCH HaikuPM-github.package-management - src/servers/package src/add-ons/kernel/file_systems/packagefs headers/private/package

  • From: HaikuPM-github.package-management <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 6 Apr 2013 04:30:32 +0200 (CEST)

added 2 changesets to branch 'refs/remotes/HaikuPM-github/package-management'
old head: 91586bd3b651574c9f0d3010567d4bcc40f4c092
new head: 26296b0aa4ddcc1b8baf1e6c380d0f8634730068
overview: https://github.com/haiku/HaikuPM/compare/91586bd...26296b0

----------------------------------------------------------------------------

0c6927b: packagefs: Add ioctl to get basic volume information
  
  Also rename the MountType enum and members, since they are no longer
  packagefs private.

26296b0: Add the humble beginnings of the package daemon
  
  It doesn't really do anything yet save for tracking what packagefs
  volumes are mounted and unmounted.

                                    [ Ingo Weinhold <ingo_weinhold@xxxxxx> ]

----------------------------------------------------------------------------

20 files changed, 1158 insertions(+), 31 deletions(-)
build/jam/HaikuImage                             |   3 +-
data/system/boot/Bootscript                      |   2 +
headers/private/package/packagefs.h              |  38 +++
.../kernel/file_systems/packagefs/Jamfile        |   2 +-
.../file_systems/packagefs/PackageFSRoot.cpp     |  12 +-
.../packagefs/PackageLinkSymlink.cpp             |   8 +-
.../kernel/file_systems/packagefs/Volume.cpp     |  48 +++-
.../kernel/file_systems/packagefs/Volume.h       |  12 +-
.../file_systems/packagefs/kernel_interface.cpp  |  18 +-
src/servers/Jamfile                              |   1 +
src/servers/package/DebugSupport.cpp             | 150 +++++++++++
src/servers/package/DebugSupport.h               | 184 +++++++++++++
src/servers/package/Jamfile                      |  17 ++
src/servers/package/PackageDaemon.cpp            | 267 +++++++++++++++++++
src/servers/package/PackageDaemon.h              |  57 ++++
src/servers/package/Root.cpp                     | 145 ++++++++++
src/servers/package/Root.h                       |  56 ++++
src/servers/package/Volume.cpp                   |  99 +++++++
src/servers/package/Volume.h                     |  55 ++++
src/servers/package/package_daemon.rdef          |  15 ++

############################################################################

Commit:      0c6927b5d7c8f73abd7663168f5f437b39661c6c
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr  6 02:26:40 2013 UTC

packagefs: Add ioctl to get basic volume information

Also rename the MountType enum and members, since they are no longer
packagefs private.

----------------------------------------------------------------------------

diff --git a/headers/private/package/packagefs.h 
b/headers/private/package/packagefs.h
new file mode 100644
index 0000000..790ac3a
--- /dev/null
+++ b/headers/private/package/packagefs.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
+ */
+#ifndef _PACKAGE__PRIVATE__PACKAGE_FS_H_
+#define _PACKAGE__PRIVATE__PACKAGE_FS_H_
+
+
+#include <Drivers.h>
+
+
+enum PackageFSMountType {
+       PACKAGE_FS_MOUNT_TYPE_SYSTEM,
+       PACKAGE_FS_MOUNT_TYPE_COMMON,
+       PACKAGE_FS_MOUNT_TYPE_HOME,
+       PACKAGE_FS_MOUNT_TYPE_CUSTOM
+};
+
+
+enum {
+       PACKAGE_FS_OPERATION_GET_VOLUME_INFO    = B_DEVICE_OP_CODES_END + 1
+};
+
+
+struct PackageFSVolumeInfo {
+       PackageFSMountType      mountType;
+
+       // device and node id of the respective package FS root scope (e.g. 
"/boot"
+       // for the three standard volumes)
+       dev_t                           rootDeviceID;
+       ino_t                           rootDirectoryID;
+};
+
+
+#endif // _PACKAGE__PRIVATE__PACKAGE_FS_H_
diff --git a/src/add-ons/kernel/file_systems/packagefs/Jamfile 
b/src/add-ons/kernel/file_systems/packagefs/Jamfile
index d0576a0..9396497 100644
--- a/src/add-ons/kernel/file_systems/packagefs/Jamfile
+++ b/src/add-ons/kernel/file_systems/packagefs/Jamfile
@@ -3,7 +3,7 @@ SubDir HAIKU_TOP src add-ons kernel file_systems packagefs ;
 
 UseLibraryHeaders zlib ;
 UsePrivateKernelHeaders ;
-UsePrivateHeaders shared storage ;
+UsePrivateHeaders package shared storage ;
 
 
 HAIKU_PACKAGE_FS_SOURCES =
diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageFSRoot.cpp 
b/src/add-ons/kernel/file_systems/packagefs/PackageFSRoot.cpp
index a520416..74ee53b 100644
--- a/src/add-ons/kernel/file_systems/packagefs/PackageFSRoot.cpp
+++ b/src/add-ons/kernel/file_systems/packagefs/PackageFSRoot.cpp
@@ -96,14 +96,14 @@ PackageFSRoot::RegisterVolume(Volume* volume)
        const char* relativeRootPath = NULL;
 
        switch (volume->MountType()) {
-               case MOUNT_TYPE_SYSTEM:
-               case MOUNT_TYPE_COMMON:
+               case PACKAGE_FS_MOUNT_TYPE_SYSTEM:
+               case PACKAGE_FS_MOUNT_TYPE_COMMON:
                        relativeRootPath = "..";
                        break;
-               case MOUNT_TYPE_HOME:
+               case PACKAGE_FS_MOUNT_TYPE_HOME:
                        relativeRootPath = "../..";
                        break;
-               case MOUNT_TYPE_CUSTOM:
+               case PACKAGE_FS_MOUNT_TYPE_CUSTOM:
                default:
                        break;
        }
@@ -217,8 +217,10 @@ PackageFSRoot::_AddVolume(Volume* volume)
        fVolumes.Add(volume);
                // TODO: Correct order?
 
-       if (fSystemVolume == NULL && volume->MountType() == MOUNT_TYPE_SYSTEM)
+       if (fSystemVolume == NULL && volume->MountType()
+                       == PACKAGE_FS_MOUNT_TYPE_SYSTEM) {
                fSystemVolume = volume;
+       }
 
        return B_OK;
 }
diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.cpp 
b/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.cpp
index ca3e83e..ed674e2 100644
--- a/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.cpp
+++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinkSymlink.cpp
@@ -28,13 +28,13 @@ static const char*
 link_path_for_mount_type(MountType type)
 {
        switch (type) {
-               case MOUNT_TYPE_SYSTEM:
+               case PACKAGE_FS_MOUNT_TYPE_SYSTEM:
                        return kSystemLinkPath;
-               case MOUNT_TYPE_COMMON:
+               case PACKAGE_FS_MOUNT_TYPE_COMMON:
                        return kCommonLinkPath;
-               case MOUNT_TYPE_HOME:
+               case PACKAGE_FS_MOUNT_TYPE_HOME:
                        return kHomeLinkPath;
-               case MOUNT_TYPE_CUSTOM:
+               case PACKAGE_FS_MOUNT_TYPE_CUSTOM:
                default:
                        return "?";
        }
diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp 
b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp
index 1a4f1bc..6d89b4e 100644
--- a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp
+++ b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp
@@ -648,16 +648,16 @@ Volume::Mount(const char* parameterString)
        // If no volume name is given, infer it from the mount type.
        if (volumeName == NULL) {
                switch (fMountType) {
-                       case MOUNT_TYPE_SYSTEM:
+                       case PACKAGE_FS_MOUNT_TYPE_SYSTEM:
                                volumeName = "system";
                                break;
-                       case MOUNT_TYPE_COMMON:
+                       case PACKAGE_FS_MOUNT_TYPE_COMMON:
                                volumeName = "common";
                                break;
-                       case MOUNT_TYPE_HOME:
+                       case PACKAGE_FS_MOUNT_TYPE_HOME:
                                volumeName = "home";
                                break;
-                       case MOUNT_TYPE_CUSTOM:
+                       case PACKAGE_FS_MOUNT_TYPE_CUSTOM:
                        default:
                                volumeName = "Package FS";
                                break;
@@ -728,6 +728,28 @@ Volume::Unmount()
 }
 
 
+status_t
+Volume::IOCtl(Node* node, uint32 operation, void* buffer, size_t size)
+{
+       switch (operation) {
+               case PACKAGE_FS_OPERATION_GET_VOLUME_INFO:
+               {
+                       if (size != sizeof(PackageFSVolumeInfo))
+                               return B_BAD_VALUE;
+
+                       PackageFSVolumeInfo info;
+                       info.mountType = fMountType;
+                       info.rootDeviceID = fPackageFSRoot->DeviceID();
+                       info.rootDirectoryID = fPackageFSRoot->NodeID();
+                       return user_memcpy(buffer, &info, sizeof(info));
+               }
+
+               default:
+                       return B_BAD_VALUE;
+       }
+}
+
+
 void
 Volume::AddNodeListener(NodeListener* listener, Node* node)
 {
@@ -1664,15 +1686,15 @@ status_t
 Volume::_InitMountType(const char* mountType)
 {
        if (mountType == NULL)
-               fMountType = MOUNT_TYPE_CUSTOM;
+               fMountType = PACKAGE_FS_MOUNT_TYPE_CUSTOM;
        else if (strcmp(mountType, "system") == 0)
-               fMountType = MOUNT_TYPE_SYSTEM;
+               fMountType = PACKAGE_FS_MOUNT_TYPE_SYSTEM;
        else if (strcmp(mountType, "common") == 0)
-               fMountType = MOUNT_TYPE_COMMON;
+               fMountType = PACKAGE_FS_MOUNT_TYPE_COMMON;
        else if (strcmp(mountType, "home") == 0)
-               fMountType = MOUNT_TYPE_HOME;
+               fMountType = PACKAGE_FS_MOUNT_TYPE_HOME;
        else if (strcmp(mountType, "custom") == 0)
-               fMountType = MOUNT_TYPE_CUSTOM;
+               fMountType = PACKAGE_FS_MOUNT_TYPE_CUSTOM;
        else
                RETURN_ERROR(B_BAD_VALUE);
 
@@ -1714,16 +1736,16 @@ Volume::_CreateShineThroughDirectories(const char* 
shineThroughSetting)
        if (shineThroughSetting == NULL) {
                // nothing specified -- derive from mount type
                switch (fMountType) {
-                       case MOUNT_TYPE_SYSTEM:
+                       case PACKAGE_FS_MOUNT_TYPE_SYSTEM:
                                directories = kSystemShineThroughDirectories;
                                break;
-                       case MOUNT_TYPE_COMMON:
+                       case PACKAGE_FS_MOUNT_TYPE_COMMON:
                                directories = kCommonShineThroughDirectories;
                                break;
-                       case MOUNT_TYPE_HOME:
+                       case PACKAGE_FS_MOUNT_TYPE_HOME:
                                directories = kHomeShineThroughDirectories;
                                break;
-                       case MOUNT_TYPE_CUSTOM:
+                       case PACKAGE_FS_MOUNT_TYPE_CUSTOM:
                                return B_OK;
                }
        } else if (strcmp(shineThroughSetting, "system") == 0)
diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.h 
b/src/add-ons/kernel/file_systems/packagefs/Volume.h
index d235618..38a6097 100644
--- a/src/add-ons/kernel/file_systems/packagefs/Volume.h
+++ b/src/add-ons/kernel/file_systems/packagefs/Volume.h
@@ -14,6 +14,8 @@
 #include <util/DoublyLinkedList.h>
 #include <util/KMessage.h>
 
+#include <packagefs.h>
+
 #include "Index.h"
 #include "Node.h"
 #include "NodeListener.h"
@@ -29,12 +31,7 @@ class UnpackingNode;
 typedef IndexHashTable::Iterator IndexDirIterator;
 
 
-enum MountType {
-       MOUNT_TYPE_SYSTEM,
-       MOUNT_TYPE_COMMON,
-       MOUNT_TYPE_HOME,
-       MOUNT_TYPE_CUSTOM
-};
+typedef PackageFSMountType MountType;
 
 
 class Volume : public DoublyLinkedListLinkImpl<Volume>,
@@ -70,6 +67,9 @@ public:
                        Node*                           FindNode(ino_t nodeID) 
const
                                                                        { 
return fNodes.Lookup(nodeID); }
 
+                       status_t                        IOCtl(Node* node, 
uint32 operation,
+                                                                       void* 
buffer, size_t size);
+
                        // node listeners -- volume must be write-locked
                        void                            
AddNodeListener(NodeListener* listener,
                                                                        Node* 
node);
diff --git a/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp 
b/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp
index 35f5a24..2e330d0 100644
--- a/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp
+++ b/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp
@@ -284,6 +284,22 @@ packagefs_io(fs_volume* fsVolume, fs_vnode* fsNode, void* 
cookie,
 // #pragma mark - Nodes
 
 
+status_t
+packagefs_ioctl(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
+       uint32 operation, void* buffer, size_t size)
+{
+       Volume* volume = (Volume*)fsVolume->private_volume;
+       Node* node = (Node*)fsNode->private_node;
+
+       FUNCTION("volume: %p, node: %p (%lld), cookie: %p, operation: %" 
B_PRI32u
+               ", buffer: %p, size: %zu\n", volume, node, node->ID(), cookie,
+               operation, buffer, size);
+       TOUCH(cookie);
+
+       return volume->IOCtl(node, operation, buffer, size);
+}
+
+
 static status_t
 packagefs_read_symlink(fs_volume* fsVolume, fs_vnode* fsNode, char* buffer,
        size_t* _bufferSize)
@@ -1179,7 +1195,7 @@ fs_vnode_ops gPackageFSVnodeOps = {
 
        NULL,   // get_file_map,
 
-       NULL,   // ioctl,
+       &packagefs_ioctl,
        NULL,   // set_flags,
        NULL,   // select,
        NULL,   // deselect,

############################################################################

Commit:      26296b0aa4ddcc1b8baf1e6c380d0f8634730068
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr  6 02:29:34 2013 UTC

Add the humble beginnings of the package daemon

It doesn't really do anything yet save for tracking what packagefs
volumes are mounted and unmounted.

----------------------------------------------------------------------------

diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage
index 835c1a7..799cc0c 100644
--- a/build/jam/HaikuImage
+++ b/build/jam/HaikuImage
@@ -106,7 +106,8 @@ PRIVATE_SYSTEM_LIBS =
 ;
 SYSTEM_SERVERS = app_server cddb_daemon debug_server input_server mail_daemon
        media_addon_server media_server midi_server mount_server net_server
-       notification_server power_daemon print_server print_addon_server 
registrar syslog_daemon
+       notification_server package_daemon power_daemon print_server
+       print_addon_server registrar syslog_daemon
 ;
 
 SYSTEM_NETWORK_DEVICES = ethernet loopback ;
diff --git a/data/system/boot/Bootscript b/data/system/boot/Bootscript
index 8dc3db3..3e4b1f1 100644
--- a/data/system/boot/Bootscript
+++ b/data/system/boot/Bootscript
@@ -98,6 +98,8 @@ launch $SERVERS/registrar _roster_thread_     # launch 
registrar
 
 launch $SERVERS/debug_server                           # launch debug_server
 
+launch $SERVERS/package_daemon
+
 # Init Network
 if [ "$SAFEMODE" != "yes" ]; then
        launch $SERVERS/net_server                              # launch 
net_server
diff --git a/src/servers/Jamfile b/src/servers/Jamfile
index 141a8ad..e906f7f 100644
--- a/src/servers/Jamfile
+++ b/src/servers/Jamfile
@@ -13,6 +13,7 @@ SubInclude HAIKU_TOP src servers midi ;
 SubInclude HAIKU_TOP src servers mount ;
 SubInclude HAIKU_TOP src servers net ;
 SubInclude HAIKU_TOP src servers notification ;
+SubInclude HAIKU_TOP src servers package ;
 SubInclude HAIKU_TOP src servers power ;
 SubInclude HAIKU_TOP src servers print ;
 SubInclude HAIKU_TOP src servers print_addon ;
diff --git a/src/servers/package/DebugSupport.cpp 
b/src/servers/package/DebugSupport.cpp
new file mode 100644
index 0000000..8377cf3
--- /dev/null
+++ b/src/servers/package/DebugSupport.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2003-2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "DebugSupport.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <OS.h>
+
+
+/*!
+       \file Debug.cpp
+       \brief Defines debug output function with printf() signature printing
+                  into a file.
+
+       \note The initialization is not thread safe!
+*/
+
+
+// locking support
+static int32 init_counter = 0;
+static sem_id dbg_printf_sem = -1;
+static thread_id dbg_printf_thread = -1;
+static int dbg_printf_nesting = 0;
+
+
+#if DEBUG_PRINT
+static int out = -1;
+#endif
+
+
+status_t
+init_debugging()
+{
+       status_t error = B_OK;
+       if (init_counter++ == 0) {
+               // open the file
+               #if DEBUG_PRINT
+                       out = open(DEBUG_PRINT_FILE, O_RDWR | O_CREAT | 
O_TRUNC);
+                       if (out < 0) {
+                               error = errno;
+                               init_counter--;
+                       }
+               #endif  // DEBUG_PRINT
+               // allocate the semaphore
+               if (error == B_OK) {
+                       dbg_printf_sem = create_sem(1, "dbg_printf");
+                       if (dbg_printf_sem < 0)
+                               error = dbg_printf_sem;
+               }
+               if (error == B_OK) {
+                       #if DEBUG
+                               
__out("##################################################\n");
+                       #endif
+               } else
+                       exit_debugging();
+       }
+       return error;
+}
+
+
+status_t
+exit_debugging()
+{
+       status_t error = B_OK;
+       if (--init_counter == 0) {
+               #if DEBUG_PRINT
+                       close(out);
+                       out = -1;
+               #endif  // DEBUG_PRINT
+               delete_sem(dbg_printf_sem);
+       } else
+               error = B_NO_INIT;
+       return error;
+}
+
+
+static inline bool
+dbg_printf_lock()
+{
+       thread_id thread = find_thread(NULL);
+       if (thread != dbg_printf_thread) {
+               if (acquire_sem(dbg_printf_sem) != B_OK)
+                       return false;
+               dbg_printf_thread = thread;
+       }
+       dbg_printf_nesting++;
+       return true;
+}
+
+
+static inline void
+dbg_printf_unlock()
+{
+       thread_id thread = find_thread(NULL);
+       if (thread != dbg_printf_thread)
+               return;
+       dbg_printf_nesting--;
+       if (dbg_printf_nesting == 0) {
+               dbg_printf_thread = -1;
+               release_sem(dbg_printf_sem);
+       }
+}
+
+
+void
+dbg_printf_begin()
+{
+       dbg_printf_lock();
+}
+
+
+void
+dbg_printf_end()
+{
+       dbg_printf_unlock();
+}
+
+
+#if DEBUG_PRINT
+
+void
+dbg_printf(const char *format,...)
+{
+       if (!dbg_printf_lock())
+               return;
+       char buffer[1024];
+       va_list args;
+       va_start(args, format);
+       // no vsnprintf() on PPC and in kernel
+       #if defined(__INTEL__) && USER
+               vsnprintf(buffer, sizeof(buffer) - 1, format, args);
+       #else
+               vsprintf(buffer, format, args);
+       #endif
+       va_end(args);
+       buffer[sizeof(buffer) - 1] = '\0';
+       write(out, buffer, strlen(buffer));
+       dbg_printf_unlock();
+}
+
+#endif // DEBUG_PRINT
diff --git a/src/servers/package/DebugSupport.h 
b/src/servers/package/DebugSupport.h
new file mode 100644
index 0000000..25592d4
--- /dev/null
+++ b/src/servers/package/DebugSupport.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2003-2009, Ingo Weinhold, ingo_weinhold@xxxxxx.
+ * Copyright 200?, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef DEBUG_SUPPORT_H
+#define DEBUG_SUPPORT_H
+
+
+#include <string.h>
+
+
+// define all macros we work with -- undefined macros are set to defaults
+#ifndef USER
+#      ifdef _KERNEL_MODE
+#              define USER 0
+#      else
+#              define USER 1
+#      endif
+#endif
+#ifndef DEBUG
+#      define DEBUG 0
+#endif
+#if !DEBUG
+#      undef DEBUG_PRINT
+#      define DEBUG_PRINT 0
+#endif
+#ifndef DEBUG_PRINT
+#      define DEBUG_PRINT 0
+#endif
+#ifndef DEBUG_APP
+#      define DEBUG_APP        "package_daemon"
+#endif
+#ifndef DEBUG_PRINT_FILE
+#      define DEBUG_PRINT_FILE "/var/log/" DEBUG_APP ".log"
+#endif
+
+
+#if !USER
+#      include <KernelExport.h>
+#endif
+#include <OS.h>
+#include <SupportDefs.h>
+
+
+// define the debug output function
+#if USER
+#      include <stdio.h>
+#      if DEBUG_PRINT
+#              define __out dbg_printf
+#      else
+#              define __out debug_printf
+#      endif
+#else
+#      include <KernelExport.h>
+#      include <null.h>
+#      if DEBUG_PRINT
+#              define __out dbg_printf
+#      else
+#              define __out dprintf
+#      endif
+#endif
+
+
+// define the PANIC() macro
+#ifndef PANIC
+#      if USER
+#              define PANIC(str)       debugger(str)
+#      else
+#              define PANIC(str)       panic(str)
+#      endif
+#endif
+
+
+// functions exported by this module
+status_t init_debugging();
+status_t exit_debugging();
+void dbg_printf_begin();
+void dbg_printf_end();
+#if DEBUG_PRINT
+       void dbg_printf(const char *format,...);
+#else
+       static inline void dbg_printf(const char *,...) {}
+#endif
+
+
+// Short overview over the debug output macros:
+//     PRINT()
+//             is for general messages that very unlikely should appear in a 
release
+//             build
+//     FATAL()
+//             this is for fatal messages, when something has really gone wrong
+//     INFORM()
+//             general information, as disk size, etc.
+//     REPORT_ERROR(status_t)
+//             prints out error information
+//     RETURN_ERROR(status_t)
+//             calls REPORT_ERROR() and return the value
+//     D()
+//             the statements in D() are only included if DEBUG is defined
+
+
+#define DEBUG_THREAD   find_thread(NULL)
+#define DEBUG_CONTEXT(x)                                                       
                                                \
+{                                                                              
                                                                        \
+       dbg_printf_begin();                                                     
                                                        \
+       __out(DEBUG_APP " [%Ld: %5ld] ", system_time(), DEBUG_THREAD);          
        \
+       x;                                                                      
                                                                        \
+       dbg_printf_end();                                                       
                                                        \
+}
+#define DEBUG_CONTEXT_FUNCTION(prefix, x)                                      
                                \
+{                                                                              
                                                                        \
+       dbg_printf_begin();                                                     
                                                        \
+       __out(DEBUG_APP " [%Ld: %5ld] %s" prefix, system_time(), DEBUG_THREAD,  
\
+               __PRETTY_FUNCTION__);                                           
                                                \
+       x;                                                                      
                                                                        \
+       dbg_printf_end();                                                       
                                                        \
+}
+#define DEBUG_CONTEXT_LINE(x)                                                  
                                        \
+{                                                                              
                                                                        \
+       dbg_printf_begin();                                                     
                                                        \
+       __out(DEBUG_APP " [%Ld: %5ld] %s:%d: ", system_time(), DEBUG_THREAD,    
\
+               __PRETTY_FUNCTION__, __LINE__);                                 
                                        \
+       x;                                                                      
                                                                        \
+       dbg_printf_end();                                                       
                                                        \
+}
+
+#define TPRINT(x...)   DEBUG_CONTEXT( __out(x) )
+#define TREPORT_ERROR(status)                                                  
                                        \
+       DEBUG_CONTEXT_LINE( __out("%s\n", strerror(status)) )
+#define TRETURN_ERROR(err)                                                     
                                                \
+{                                                                              
                                                                        \
+       status_t _status = err;                                                 
                                                \
+       if (_status < B_OK)                                                     
                                                        \
+               TREPORT_ERROR(_status);                                         
                                                \
+       return _status;                                                         
                                                        \
+}
+#define TSET_ERROR(var, err)                                                   
                                        \
+{                                                                              
                                                                        \
+       status_t _status = err;                                                 
                                                \
+       if (_status < B_OK)                                                     
                                                        \
+               TREPORT_ERROR(_status);                                         
                                                \
+               var = _status;                                                  
                                                        \
+}
+#define TFUNCTION(x...)                DEBUG_CONTEXT_FUNCTION( ": ", __out(x) )
+#define TFUNCTION_START()      DEBUG_CONTEXT_FUNCTION( "\n",  )
+#define TFUNCTION_END()                DEBUG_CONTEXT_FUNCTION( " done\n",  )
+
+#if DEBUG
+       #define PRINT(x...)                             TPRINT(x)
+       #define REPORT_ERROR(status)    TREPORT_ERROR(status)
+       #define RETURN_ERROR(err)               TRETURN_ERROR(err)
+       #define SET_ERROR(var, err)             TSET_ERROR(var, err)
+       #define FATAL(x...)                             DEBUG_CONTEXT( __out(x) 
)
+       #define ERROR(x...)                             DEBUG_CONTEXT( __out(x) 
)
+       #define WARN(x...)                              DEBUG_CONTEXT( __out(x) 
)
+       #define INFORM(x...)                    DEBUG_CONTEXT( __out(x) )
+       #define FUNCTION(x...)                  TFUNCTION(x)
+       #define FUNCTION_START()                TFUNCTION_START()
+       #define FUNCTION_END()                  TFUNCTION_END()
+       #define DARG(x)                                 x
+       #define D(x)                                    {x;};
+#else
+       #define PRINT(x...)                             ;
+       #define REPORT_ERROR(status)    ;
+       #define RETURN_ERROR(status)    return status;
+       #define SET_ERROR(var, err)             var = err;
+       #define FATAL(x...)                             DEBUG_CONTEXT( __out(x) 
)
+       #define ERROR(x...)                             DEBUG_CONTEXT( __out(x) 
)
+       #define WARN(x...)                              DEBUG_CONTEXT( __out(x) 
)
+       #define INFORM(x...)                    DEBUG_CONTEXT( __out(x) )
+       #define FUNCTION(x...)                  ;
+       #define FUNCTION_START()                ;
+       #define FUNCTION_END()                  ;
+       #define DARG(x)
+       #define D(x)                                    ;
+#endif
+
+#ifndef TOUCH
+#define TOUCH(var) (void)var
+#endif
+
+
+#endif // DEBUG_SUPPORT_H
diff --git a/src/servers/package/Jamfile b/src/servers/package/Jamfile
new file mode 100644
index 0000000..099f966
--- /dev/null
+++ b/src/servers/package/Jamfile
@@ -0,0 +1,17 @@
+SubDir HAIKU_TOP src servers package ;
+
+UsePrivateSystemHeaders ;
+UsePrivateHeaders app package shared ;
+
+Server package_daemon
+       :
+       DebugSupport.cpp
+       PackageDaemon.cpp
+       Root.cpp
+       Volume.cpp
+       :
+       be package
+       $(TARGET_LIBSTDC++)
+       :
+       package_daemon.rdef
+;
diff --git a/src/servers/package/PackageDaemon.cpp 
b/src/servers/package/PackageDaemon.cpp
new file mode 100644
index 0000000..0942049
--- /dev/null
+++ b/src/servers/package/PackageDaemon.cpp
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
+ */
+
+
+#include "PackageDaemon.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include <Directory.h>
+#include <NodeMonitor.h>
+
+#include <AutoDeleter.h>
+
+#include "DebugSupport.h"
+#include "Root.h"
+#include "Volume.h"
+
+
+PackageDaemon::PackageDaemon(status_t* _error)
+       :
+       BServer("application/x-vnd.haiku-package_daemon", false, _error),
+       fSystemRoot(NULL),
+       fRoots(10, true),
+       fVolumeWatcher()
+{
+}
+
+
+PackageDaemon::~PackageDaemon()
+{
+//     delete fSystemRoot;
+}
+
+
+status_t
+PackageDaemon::Init()
+{
+       status_t error = fVolumeWatcher.StartWatching(BMessenger(this, this));
+       if (error != B_OK) {
+               ERROR("PackageDaemon::Init(): failed to start volume watching: 
%s\n",
+                       strerror(error));
+       }
+
+       // register all packagefs volumes
+       for (int32 cookie = 0;;) {
+               dev_t device = next_dev(&cookie);
+               if (device < 0)
+                       break;
+
+               _RegisterVolume(device);
+       }
+
+       return B_OK;
+}
+
+
+void
+PackageDaemon::MessageReceived(BMessage* message)
+{
+       switch (message->what) {
+               case B_NODE_MONITOR:
+               {
+                       int32 opcode;
+                       if (message->FindInt32("opcode", &opcode) != B_OK)
+                               break;
+                       if (opcode == B_DEVICE_MOUNTED)
+                               _HandleVolumeMounted(message);
+                       else if (opcode == B_DEVICE_UNMOUNTED)
+                               _HandleVolumeUnmounted(message);
+                       break;
+               }
+               default:
+                       BServer::MessageReceived(message);
+                       break;
+       }
+}
+
+
+status_t
+PackageDaemon::_RegisterVolume(dev_t deviceID)
+{
+       // get the FS info and check whether this is a package FS volume at all
+       fs_info info;
+       status_t error = fs_stat_dev(deviceID, &info);
+       if (error != 0)
+               RETURN_ERROR(error);
+
+       if (strcmp(info.fsh_name, "packagefs") != 0)
+               RETURN_ERROR(B_BAD_VALUE);
+
+       // open the root directory of the volume
+       node_ref nodeRef;
+       nodeRef.device = info.dev;
+       nodeRef.node = info.root;
+       BDirectory directory;
+       error = directory.SetTo(&nodeRef);
+       if (error != B_OK) {
+               ERROR("PackageDaemon::_RegisterVolume(): failed to open root: 
%s\n",
+                       strerror(error));
+               return error;
+       }
+
+       // create a volume
+       Volume* volume = new(std::nothrow) Volume;
+       if (volume == NULL)
+               RETURN_ERROR(B_NO_MEMORY);
+       ObjectDeleter<Volume> volumeDeleter(volume);
+
+       dev_t rootDeviceID;
+       ino_t rootNodeID;
+       error = volume->Init(directory, rootDeviceID, rootNodeID);
+       if (error != B_OK)
+               RETURN_ERROR(error);
+
+       if (volume->MountType() == PACKAGE_FS_MOUNT_TYPE_CUSTOM) {
+// TODO: Or maybe not?
+               INFORM("skipping custom mounted volume at \"%s\"\n",
+                       volume->Path().String());
+               return B_OK;
+       }
+
+       // get the root for the volume and register it
+       Root* root;
+       error = _GetOrCreateRoot(rootDeviceID, rootNodeID, root);
+       if (error != B_OK)
+               RETURN_ERROR(error);
+
+       error = root->RegisterVolume(volume);
+       if (error != B_OK) {
+               _PutRoot(root);
+               RETURN_ERROR(error);
+       }
+       volumeDeleter.Detach();
+
+       INFORM("volume at \"%s\" registered\n", volume->Path().String());
+
+       return B_OK;
+}
+
+
+void
+PackageDaemon::_UnregisterVolume(Volume* volume)
+{
+       Root* root = volume->GetRoot();
+       root->UnregisterVolume(volume);
+
+       INFORM("volume at \"%s\" unregistered\n", volume->Path().String());
+
+       delete volume;
+       _PutRoot(root);
+}
+
+
+status_t
+PackageDaemon::_GetOrCreateRoot(dev_t deviceID, ino_t nodeID, Root*& _root)
+{
+       Root* root = _FindRoot(deviceID, nodeID);
+       if (root != NULL) {
+               root->AcquireReference();
+       } else {
+               root = new(std::nothrow) Root;
+               if (root == NULL)
+                       RETURN_ERROR(B_NO_MEMORY);
+               ObjectDeleter<Root> rootDeleter(root);
+
+               status_t error = root->Init(deviceID, nodeID);
+               if (error != B_OK)
+                       RETURN_ERROR(error);
+
+               if (!fRoots.AddItem(root))
+                       RETURN_ERROR(B_NO_MEMORY);
+
+               rootDeleter.Detach();
+
+               INFORM("root at \"%s\" (device: %" B_PRIdDEV ", node: %" 
B_PRIdINO ") "
+                       "registered\n", root->Path().String(), deviceID, 
nodeID);
+       }
+
+       _root = root;
+       return B_OK;
+}
+
+
+Root*
+PackageDaemon::_FindRoot(dev_t deviceID, ino_t nodeID) const
+{
+       for (int32 i = 0; Root* root = fRoots.ItemAt(i); i++) {
+               if (root->DeviceID() == deviceID && root->NodeID() == nodeID)
+                       return root;
+       }
+
+       return NULL;
+}
+
+
+void
+PackageDaemon::_PutRoot(Root* root)
+{
+       if (root->ReleaseReference() == 1) {
+               INFORM("root at \"%s\" unregistered\n", root->Path().String());
+               fRoots.RemoveItem(root, true);
+                       // deletes the object
+       }
+}
+
+
+Volume*
+PackageDaemon::_FindVolume(dev_t deviceID) const
+{
+       for (int32 i = 0; Root* root = fRoots.ItemAt(i); i++) {
+               if (Volume* volume = root->FindVolume(deviceID))
+                       return volume;
+       }
+
+       return NULL;
+}
+
+
+void
+PackageDaemon::_HandleVolumeMounted(const BMessage* message)
+{
+       int32 device;
+       if (message->FindInt32("new device", &device) != B_OK)
+               return;
+
+       // _RegisterVolume() also checks whether it is a package FS volume, so 
we
+       // don't need to bother.
+       _RegisterVolume(device);
+}
+
+
+void
+PackageDaemon::_HandleVolumeUnmounted(const BMessage* message)
+{
+       int32 device;
+       if (message->FindInt32("device", &device) != B_OK)
+               return;
+
+       if (Volume* volume = _FindVolume(device))
+               _UnregisterVolume(volume);
+}
+
+
+// #pragma mark -
+
+
+int
+main(int argc, const char* const* argv)
+{
+       status_t error;
+       PackageDaemon daemon(&error);
+       if (error == B_OK)
+               error = daemon.Init();
+       if (error != B_OK) {
+               FATAL("failed to init server application: %s\n", 
strerror(error));
+               return 1;
+       }
+
+       daemon.Run();
+       return 0;
+}
diff --git a/src/servers/package/PackageDaemon.h 
b/src/servers/package/PackageDaemon.h
new file mode 100644
index 0000000..86c6f4c
--- /dev/null
+++ b/src/servers/package/PackageDaemon.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
+ */
+#ifndef PACKAGE_DAEMON_H
+#define PACKAGE_DAEMON_H
+
+
+#include <fs_info.h>
+#include <ObjectList.h>
+#include <VolumeRoster.h>
+
+#include <Server.h>
+
+
+class Root;
+class Volume;
+
+
+class PackageDaemon : public BServer {
+public:
+                                                               
PackageDaemon(status_t* _error);
+       virtual                                         ~PackageDaemon();
+
+                       status_t                        Init();
+
+       virtual void                            MessageReceived(BMessage* 
message);
+
+private:
+                       typedef BObjectList<Root> RootList;
+
+private:
+                       status_t                        _RegisterVolume(dev_t 
device);
+                       void                            
_UnregisterVolume(Volume* volume);
+
+                       status_t                        _GetOrCreateRoot(dev_t 
deviceID, ino_t nodeID,
+                                                                       Root*& 
_root);
+                       Root*                           _FindRoot(dev_t 
deviceID, ino_t nodeID) const;
+                       void                            _PutRoot(Root* root);
+
+                       Volume*                         _FindVolume(dev_t 
deviceID) const;
+
+                       void                            
_HandleVolumeMounted(const BMessage* message);
+                       void                            
_HandleVolumeUnmounted(const BMessage* message);
+
+private:
+                       Root*                           fSystemRoot;
+                       RootList                        fRoots;
+                       BVolumeRoster           fVolumeWatcher;
+};
+
+
+
+#endif // PACKAGE_DAEMON_H
diff --git a/src/servers/package/Root.cpp b/src/servers/package/Root.cpp
new file mode 100644
index 0000000..bf7fec9
--- /dev/null
+++ b/src/servers/package/Root.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
+ */
+
+
+#include "Root.h"
+
+#include <Directory.h>
+#include <Entry.h>
+#include <Path.h>
+
+#include "DebugSupport.h"
+#include "Volume.h"
+
+
+Root::Root()
+       :
+       fDeviceID(-1),
+       fNodeID(-1),
+       fPath(),
+       fSystemVolume(NULL),
+       fCommonVolume(NULL),
+       fHomeVolume(NULL)
+{
+}
+
+
+Root::~Root()
+{
+}
+
+
+status_t
+Root::Init(dev_t deviceID, ino_t nodeID)
+{
+       fDeviceID = deviceID;
+       fNodeID = nodeID;
+
+       // get the path
+       node_ref nodeRef;
+       nodeRef.device = fDeviceID;
+       nodeRef.node = fNodeID;
+       BDirectory directory;
+       status_t error = directory.SetTo(&nodeRef);
+       if (error != B_OK) {
+               ERROR("Root::Init(): failed to open directory: %s\n", 
strerror(error));
+               return error;
+       }
+
+       BEntry entry;
+       error = directory.GetEntry(&entry);
+
+       BPath path;
+       if (error == B_OK)
+               error = entry.GetPath(&path);
+
+       if (error != B_OK) {
+               ERROR("Root::Init(): failed to get directory path: %s\n",
+                       strerror(error));
+               RETURN_ERROR(error);
+       }
+
+       fPath = path.Path();
+       if (fPath.IsEmpty())
+               RETURN_ERROR(B_NO_MEMORY);
+
+       return B_OK;
+}
+
+
+status_t
+Root::RegisterVolume(Volume* volume)
+{
+       Volume** volumeToSet = _GetVolume(volume->MountType());
+       if (volumeToSet == NULL)
+               return B_BAD_VALUE;
+
+       if (*volumeToSet != NULL) {
+               ERROR("Root::RegisterVolume(): can't register volume at \"%s\", 
since "
+                       "there's already volume at \"%s\" with the same 
type.\n",
+                       volume->Path().String(), 
(*volumeToSet)->Path().String());
+               return B_BAD_VALUE;
+       }
+
+       *volumeToSet = volume;
+       volume->SetRoot(this);
+
+       return B_OK;
+}
+
+
+void
+Root::UnregisterVolume(Volume* volume)
+{
+       Volume** volumeToSet = _GetVolume(volume->MountType());
+       if (volumeToSet == NULL || *volumeToSet != volume) {
+               ERROR("Root::UnregisterVolume(): can't unregister unknown 
volume at "
+                       "\"%s.\n", volume->Path().String());
+               return;
+       }
+
+       *volumeToSet = NULL;
+       volume->SetRoot(NULL);
+}
+
+
+Volume*
+Root::FindVolume(dev_t deviceID) const
+{
+       Volume* volumes[] = { fSystemVolume, fCommonVolume, fHomeVolume };
+       for (size_t i = 0; i < sizeof(volumes) / sizeof(volumes[0]); i++) {
+               Volume* volume = volumes[i];
+               if (volume != NULL && volume->DeviceID() == deviceID)
+                       return volume;
+       }
+
+       return NULL;
+}
+
+
+void
+Root::LastReferenceReleased()
+{
+}
+
+
+Volume**
+Root::_GetVolume(PackageFSMountType mountType)
+{
+       switch (mountType) {
+               case PACKAGE_FS_MOUNT_TYPE_SYSTEM:
+                       return &fSystemVolume;
+               case PACKAGE_FS_MOUNT_TYPE_COMMON:
+                       return &fCommonVolume;
+               case PACKAGE_FS_MOUNT_TYPE_HOME:
+                       return &fHomeVolume;
+               case PACKAGE_FS_MOUNT_TYPE_CUSTOM:
+               default:
+                       return NULL;
+       }
+}
diff --git a/src/servers/package/Root.h b/src/servers/package/Root.h
new file mode 100644
index 0000000..940f99c
--- /dev/null
+++ b/src/servers/package/Root.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
+ */
+#ifndef ROOT_H
+#define ROOT_H
+
+
+#include <fs_info.h>
+#include <String.h>
+
+#include <Referenceable.h>
+
+#include <packagefs.h>
+
+
+class Volume;
+
+
+class Root : public BReferenceable {
+public:
+                                                               Root();
+       virtual                                         ~Root();
+
+                       status_t                        Init(dev_t deviceID, 
ino_t nodeID);
+
+                       dev_t                           DeviceID() const        
{ return fDeviceID; }
+                       ino_t                           NodeID() const          
{ return fNodeID; }
+                       const BString&          Path() const
+                                                                       { 
return fPath; }
+
+                       status_t                        RegisterVolume(Volume* 
volume);
+                       void                            
UnregisterVolume(Volume* volume);
+
+                       Volume*                         FindVolume(dev_t 
deviceID) const;
+
+protected:
+       virtual void                            LastReferenceReleased();
+
+private:
+                       Volume**                        
_GetVolume(PackageFSMountType mountType);
+
+private:
+                       dev_t                           fDeviceID;
+                       ino_t                           fNodeID;
+                       BString                         fPath;
+                       Volume*                         fSystemVolume;
+                       Volume*                         fCommonVolume;
+                       Volume*                         fHomeVolume;
+};
+
+
+#endif // ROOT_H
diff --git a/src/servers/package/Volume.cpp b/src/servers/package/Volume.cpp
new file mode 100644
index 0000000..4d17279
--- /dev/null
+++ b/src/servers/package/Volume.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
+ */
+
+
+#include "Volume.h"
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <Directory.h>
+#include <Entry.h>
+#include <Path.h>
+
+#include "DebugSupport.h"
+
+
+Volume::Volume()
+       :
+       fPath(),
+       fMountType(PACKAGE_FS_MOUNT_TYPE_CUSTOM),
+       fDeviceID(-1),
+       fRootDirectoryID(1),
+       fRoot(NULL)
+{
+}
+
+
+Volume::~Volume()
+{
+}
+
+
+status_t
+Volume::Init(BDirectory& directory, dev_t& _rootDeviceID, ino_t& _rootNodeID)
+{
+       // get the directory path
+       BEntry entry;
+       status_t error = directory.GetEntry(&entry);
+
+       BPath path;
+       if (error == B_OK)
+               error = entry.GetPath(&path);
+
+       if (error != B_OK) {
+               ERROR("Volume::Init(): failed to get root directory path: %s\n",
+                       strerror(error));
+               RETURN_ERROR(error);
+       }
+
+       fPath = path.Path();
+       if (fPath.IsEmpty())
+               RETURN_ERROR(B_NO_MEMORY);
+
+       // stat() the directory
+       struct stat st;
+       error = directory.GetStat(&st);
+       if (error != B_OK) {
+               ERROR("Volume::Init(): failed to stat root directory: %s\n",
+                       strerror(error));
+               RETURN_ERROR(error);
+       }
+
+       fDeviceID = st.st_dev;
+       fRootDirectoryID = st.st_ino;
+
+       // get a volume info from the FS
+       int fd = directory.Dup();
+       if (fd < 0) {
+               ERROR("Volume::Init(): failed to get root directory FD: %s\n",
+                       strerror(fd));
+               RETURN_ERROR(fd);
+       }
+
+       PackageFSVolumeInfo info;
+       if (ioctl(fd, PACKAGE_FS_OPERATION_GET_VOLUME_INFO, &info, sizeof(info))
+                       != 0) {
+               error = errno;
+               close(fd);
+               if (error != B_OK) {
+                       ERROR("Volume::Init(): failed to get volume info: %s\n",
+                               strerror(error));
+                       RETURN_ERROR(error);
+               }
+       }
+
+       close(fd);
+
+       fMountType = info.mountType;
+       _rootDeviceID = info.rootDeviceID;
+       _rootNodeID = info.rootDirectoryID;
+
+       return B_OK;
+}
diff --git a/src/servers/package/Volume.h b/src/servers/package/Volume.h
new file mode 100644
index 0000000..aa90a29
--- /dev/null
+++ b/src/servers/package/Volume.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
+ */
+#ifndef VOLUME_H
+#define VOLUME_H
+
+
+#include <fs_info.h>
+#include <String.h>
+
+#include <packagefs.h>
+
+
+class BDirectory;
+
+class Root;
+
+
+class Volume {
+public:
+                                                               Volume();
+                                                               ~Volume();
+
+                       status_t                        Init(BDirectory& 
directory,
+                                                                       dev_t& 
_rootDeviceID, ino_t& _rootNodeID);
+
+                       const BString&          Path() const
+                                                                       { 
return fPath; }
+                       PackageFSMountType      MountType() const
+                                                                       { 
return fMountType; }
+                       dev_t                           DeviceID() const
+                                                                       { 
return fDeviceID; }
+                       ino_t                           RootDirectoryID() const
+                                                                       { 
return fRootDirectoryID; }
+
+                       Root*                           GetRoot() const
+                                                                       { 
return fRoot; }
+                       void                            SetRoot(Root* root)
+                                                                       { fRoot 
= root; }
+
+private:
+                       BString                         fPath;
+                       PackageFSMountType      fMountType;
+                       dev_t                           fDeviceID;
+                       ino_t                           fRootDirectoryID;
+                       Root*                           fRoot;
+};
+
+
+
+#endif // VOLUME_H
diff --git a/src/servers/package/package_daemon.rdef 
b/src/servers/package/package_daemon.rdef
new file mode 100644
index 0000000..ad88e3c
--- /dev/null
+++ b/src/servers/package/package_daemon.rdef
@@ -0,0 +1,15 @@
+resource app_signature "application/x-vnd.haiku-package_daemon";
+
+resource app_flags B_EXCLUSIVE_LAUNCH | B_BACKGROUND_APP;
+
+resource app_version {
+       major  = 1,
+       middle = 0,
+       minor  = 0,
+
+       variety = B_APPV_ALPHA,
+       internal = 0,
+
+       short_info = "package_daemon",
+       long_info = "package_daemon ©2013 Haiku, Inc."
+};


Other related posts: