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