diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index 835c1a7553..799cc0c13b 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 8dc3db38a9..3e4b1f1e6d 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 141a8ad6ee..e906f7fb21 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 0000000000..8377cf340c --- /dev/null +++ b/src/servers/package/DebugSupport.cpp @@ -0,0 +1,150 @@ +/* + * Copyright 2003-2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "DebugSupport.h" + +#include +#include +#include +#include +#include +#include + +#include + + +/*! + \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 0000000000..25592d41cb --- /dev/null +++ b/src/servers/package/DebugSupport.h @@ -0,0 +1,184 @@ +/* + * Copyright 2003-2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 200?, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ +#ifndef DEBUG_SUPPORT_H +#define DEBUG_SUPPORT_H + + +#include + + +// 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 +#endif +#include +#include + + +// define the debug output function +#if USER +# include +# if DEBUG_PRINT +# define __out dbg_printf +# else +# define __out debug_printf +# endif +#else +# include +# include +# 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 0000000000..099f966092 --- /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 0000000000..0942049d0f --- /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 + */ + + +#include "PackageDaemon.h" + +#include +#include + +#include +#include + +#include + +#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 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 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 0000000000..86c6f4c2c0 --- /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 + */ +#ifndef PACKAGE_DAEMON_H +#define PACKAGE_DAEMON_H + + +#include +#include +#include + +#include + + +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 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 0000000000..bf7fec9939 --- /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 + */ + + +#include "Root.h" + +#include +#include +#include + +#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 0000000000..940f99c27f --- /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 + */ +#ifndef ROOT_H +#define ROOT_H + + +#include +#include + +#include + +#include + + +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 0000000000..4d17279fc0 --- /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 + */ + + +#include "Volume.h" + +#include +#include +#include + +#include +#include +#include + +#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 0000000000..aa90a29716 --- /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 + */ +#ifndef VOLUME_H +#define VOLUME_H + + +#include +#include + +#include + + +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 0000000000..ad88e3cba0 --- /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." +};