1/*
2 * Copyright 2009-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "UnpackingDirectory.h"
8
9#include "DebugSupport.h"
10#include "EmptyAttributeDirectoryCookie.h"
11#include "UnpackingAttributeCookie.h"
12#include "UnpackingAttributeDirectoryCookie.h"
13#include "Utils.h"
14
15
16// #pragma mark - UnpackingDirectory
17
18
19UnpackingDirectory::UnpackingDirectory(ino_t id)
20	:
21	Directory(id)
22{
23}
24
25
26UnpackingDirectory::~UnpackingDirectory()
27{
28}
29
30
31status_t
32UnpackingDirectory::VFSInit(dev_t deviceID)
33{
34	status_t error = NodeInitVFS(deviceID, fID, fPackageDirectories.Head());
35	if (error == B_OK)
36		Directory::VFSInit(deviceID);
37
38	return error;
39}
40
41
42void
43UnpackingDirectory::VFSUninit()
44{
45	NodeUninitVFS(fPackageDirectories.Head(), fFlags);
46	Directory::VFSUninit();
47}
48
49
50mode_t
51UnpackingDirectory::Mode() const
52{
53	if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
54		return packageDirectory->Mode();
55	return S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
56}
57
58
59uid_t
60UnpackingDirectory::UserID() const
61{
62	if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
63		return packageDirectory->UserID();
64	return 0;
65}
66
67
68gid_t
69UnpackingDirectory::GroupID() const
70{
71	if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
72		return packageDirectory->GroupID();
73	return 0;
74}
75
76
77timespec
78UnpackingDirectory::ModifiedTime() const
79{
80	if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
81		return packageDirectory->ModifiedTime();
82
83	timespec time = { 0, 0 };
84	return time;
85}
86
87
88off_t
89UnpackingDirectory::FileSize() const
90{
91	return 0;
92}
93
94
95Node*
96UnpackingDirectory::GetNode()
97{
98	return this;
99}
100
101
102status_t
103UnpackingDirectory::AddPackageNode(PackageNode* packageNode, dev_t deviceID)
104{
105	if (!S_ISDIR(packageNode->Mode()))
106		return B_BAD_VALUE;
107
108	PackageDirectory* packageDirectory
109		= dynamic_cast<PackageDirectory*>(packageNode);
110
111	PackageDirectory* other = fPackageDirectories.Head();
112	bool overridesHead = other == NULL
113		|| packageDirectory->HasPrecedenceOver(other);
114
115	if (overridesHead) {
116		fPackageDirectories.InsertBefore(other, packageDirectory);
117		NodeReinitVFS(deviceID, fID, packageDirectory, other, fFlags);
118	} else
119		fPackageDirectories.Add(packageDirectory);
120
121	return B_OK;
122}
123
124
125void
126UnpackingDirectory::RemovePackageNode(PackageNode* packageNode, dev_t deviceID)
127{
128	bool isNewest = packageNode == fPackageDirectories.Head();
129	fPackageDirectories.Remove(dynamic_cast<PackageDirectory*>(packageNode));
130
131	// when removing the newest node, we need to find the next node (the list
132	// is not sorted)
133	PackageDirectory* newestNode = fPackageDirectories.Head();
134	if (isNewest && newestNode != NULL) {
135		PackageDirectoryList::Iterator it = fPackageDirectories.GetIterator();
136		it.Next();
137			// skip the first one
138		while (PackageDirectory* otherNode = it.Next()) {
139			if (otherNode->HasPrecedenceOver(newestNode))
140				newestNode = otherNode;
141		}
142
143		fPackageDirectories.Remove(newestNode);
144		fPackageDirectories.InsertBefore(fPackageDirectories.Head(), newestNode);
145		NodeReinitVFS(deviceID, fID, newestNode, packageNode, fFlags);
146	}
147}
148
149
150PackageNode*
151UnpackingDirectory::GetPackageNode()
152{
153	return fPackageDirectories.Head();
154}
155
156
157bool
158UnpackingDirectory::IsOnlyPackageNode(PackageNode* node) const
159{
160	return node == fPackageDirectories.Head()
161		&& node == fPackageDirectories.Tail();
162}
163
164
165bool
166UnpackingDirectory::WillBeFirstPackageNode(PackageNode* packageNode) const
167{
168	PackageDirectory* packageDirectory
169		= dynamic_cast<PackageDirectory*>(packageNode);
170	if (packageDirectory == NULL)
171		return false;
172
173	PackageDirectory* other = fPackageDirectories.Head();
174	return other == NULL || packageDirectory->HasPrecedenceOver(other);
175}
176
177
178void
179UnpackingDirectory::PrepareForRemoval()
180{
181	fPackageDirectories.MakeEmpty();
182}
183
184
185status_t
186UnpackingDirectory::OpenAttributeDirectory(AttributeDirectoryCookie*& _cookie)
187{
188	if (HasVFSInitError())
189		return B_ERROR;
190
191	return UnpackingAttributeDirectoryCookie::Open(fPackageDirectories.Head(),
192		_cookie);
193}
194
195
196status_t
197UnpackingDirectory::OpenAttribute(const StringKey& name, int openMode,
198	AttributeCookie*& _cookie)
199{
200	if (HasVFSInitError())
201		return B_ERROR;
202
203	return UnpackingAttributeCookie::Open(fPackageDirectories.Head(), name,
204		openMode, _cookie);
205}
206
207
208status_t
209UnpackingDirectory::IndexAttribute(AttributeIndexer* indexer)
210{
211	return UnpackingAttributeCookie::IndexAttribute(fPackageDirectories.Head(),
212		indexer);
213}
214
215
216void*
217UnpackingDirectory::IndexCookieForAttribute(const StringKey& name) const
218{
219	if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
220		return packageDirectory->IndexCookieForAttribute(name);
221	return NULL;
222}
223
224
225// #pragma mark - RootDirectory
226
227
228RootDirectory::RootDirectory(ino_t id, const timespec& modifiedTime)
229	:
230	UnpackingDirectory(id),
231	fModifiedTime(modifiedTime)
232{
233}
234
235
236status_t
237RootDirectory::OpenAttributeDirectory(AttributeDirectoryCookie*& _cookie)
238{
239	if (HasVFSInitError())
240		return B_ERROR;
241
242	_cookie = new(std::nothrow) EmptyAttributeDirectoryCookie;
243	if (_cookie == nullptr)
244		return B_NO_MEMORY;
245	return B_OK;
246}
247
248
249timespec
250RootDirectory::ModifiedTime() const
251{
252	return fModifiedTime;
253}
254