1/* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "PackageDomain.h" 8 9#include <errno.h> 10#include <fcntl.h> 11#include <stdlib.h> 12#include <string.h> 13 14#include <NodeMonitor.h> 15 16#include <AutoDeleter.h> 17 18#include <fs/node_monitor.h> 19#include <Notifications.h> 20 21#include "DebugSupport.h" 22 23 24PackageDomain::PackageDomain(::Volume* volume) 25 : 26 fVolume(volume), 27 fPath(NULL), 28 fDirFD(-1), 29 fListener(NULL) 30{ 31} 32 33 34PackageDomain::~PackageDomain() 35{ 36 PRINT("PackageDomain::~PackageDomain()\n"); 37 38 if (fListener != NULL) { 39 remove_node_listener(fDeviceID, fNodeID, *fListener); 40 delete fListener; 41 } 42 43 Package* package = fPackages.Clear(true); 44 while (package != NULL) { 45 Package* next = package->FileNameHashTableNext(); 46 package->ReleaseReference(); 47 package = next; 48 } 49 50 if (fDirFD >= 0) 51 close(fDirFD); 52 53 free(fPath); 54} 55 56 57status_t 58PackageDomain::Init(const char* path) 59{ 60 fPath = strdup(path); 61 if (fPath == NULL) 62 RETURN_ERROR(B_NO_MEMORY); 63 64 status_t error = fPackages.Init(); 65 if (error != B_OK) 66 return error; 67 68 return B_OK; 69} 70 71 72status_t 73PackageDomain::Prepare(NotificationListener* listener) 74{ 75 ObjectDeleter<NotificationListener> listenerDeleter(listener); 76 77 fDirFD = open(fPath, O_RDONLY); 78 if (fDirFD < 0) { 79 ERROR("Failed to open package domain \"%s\"\n", strerror(errno)); 80 return errno; 81 } 82 83 struct stat st; 84 if (fstat(fDirFD, &st) < 0) 85 RETURN_ERROR(errno); 86 87 fDeviceID = st.st_dev; 88 fNodeID = st.st_ino; 89 90 status_t error = add_node_listener(fDeviceID, fNodeID, B_WATCH_DIRECTORY, 91 *listener); 92 if (error != B_OK) 93 RETURN_ERROR(error); 94 fListener = listenerDeleter.Detach(); 95 96 return B_OK; 97} 98 99 100void 101PackageDomain::AddPackage(Package* package) 102{ 103 fPackages.Insert(package); 104 package->AcquireReference(); 105} 106 107 108void 109PackageDomain::RemovePackage(Package* package) 110{ 111 fPackages.Remove(package); 112 package->ReleaseReference(); 113} 114 115 116Package* 117PackageDomain::FindPackage(const char* fileName) const 118{ 119 return fPackages.Lookup(fileName); 120} 121