1/*
2 * Copyright 2009-2011, 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 "UnpackingAttributeCookie.h"
11#include "UnpackingAttributeDirectoryCookie.h"
12#include "Utils.h"
13
14
15// #pragma mark - UnpackingDirectory
16
17
18UnpackingDirectory::UnpackingDirectory(ino_t id)
19	:
20	Directory(id)
21{
22}
23
24
25UnpackingDirectory::~UnpackingDirectory()
26{
27}
28
29
30mode_t
31UnpackingDirectory::Mode() const
32{
33	if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
34		return packageDirectory->Mode();
35	return S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
36}
37
38
39uid_t
40UnpackingDirectory::UserID() const
41{
42	if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
43		return packageDirectory->UserID();
44	return 0;
45}
46
47
48gid_t
49UnpackingDirectory::GroupID() const
50{
51	if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
52		return packageDirectory->GroupID();
53	return 0;
54}
55
56
57timespec
58UnpackingDirectory::ModifiedTime() const
59{
60	if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
61		return packageDirectory->ModifiedTime();
62
63	timespec time = { 0, 0 };
64	return time;
65}
66
67
68off_t
69UnpackingDirectory::FileSize() const
70{
71	return 0;
72}
73
74
75Node*
76UnpackingDirectory::GetNode()
77{
78	return this;
79}
80
81
82status_t
83UnpackingDirectory::AddPackageNode(PackageNode* packageNode)
84{
85	if (!S_ISDIR(packageNode->Mode()))
86		return B_BAD_VALUE;
87
88	PackageDirectory* packageDirectory
89		= dynamic_cast<PackageDirectory*>(packageNode);
90
91	PackageDirectory* other = fPackageDirectories.Head();
92	bool isNewest = other == NULL
93		|| packageDirectory->ModifiedTime() > other->ModifiedTime();
94
95	if (isNewest)
96		fPackageDirectories.Insert(other, packageDirectory);
97	else
98		fPackageDirectories.Add(packageDirectory);
99
100	return B_OK;
101}
102
103
104void
105UnpackingDirectory::RemovePackageNode(PackageNode* packageNode)
106{
107	bool isNewest = packageNode == fPackageDirectories.Head();
108	fPackageDirectories.Remove(dynamic_cast<PackageDirectory*>(packageNode));
109
110	// when removing the newest node, we need to find the next node (the list
111	// is not sorted)
112	PackageDirectory* newestNode = fPackageDirectories.Head();
113	if (isNewest && newestNode != NULL) {
114		PackageDirectoryList::Iterator it = fPackageDirectories.GetIterator();
115		it.Next();
116			// skip the first one
117		while (PackageDirectory* otherNode = it.Next()) {
118			if (otherNode->ModifiedTime() > newestNode->ModifiedTime())
119				newestNode = otherNode;
120		}
121
122		fPackageDirectories.Remove(newestNode);
123		fPackageDirectories.Insert(fPackageDirectories.Head(), newestNode);
124	}
125}
126
127
128PackageNode*
129UnpackingDirectory::GetPackageNode()
130{
131	return fPackageDirectories.Head();
132}
133
134
135bool
136UnpackingDirectory::IsOnlyPackageNode(PackageNode* node) const
137{
138	return node == fPackageDirectories.Head()
139		&& node == fPackageDirectories.Tail();
140}
141
142
143bool
144UnpackingDirectory::WillBeFirstPackageNode(PackageNode* packageNode) const
145{
146	PackageDirectory* packageDirectory
147		= dynamic_cast<PackageDirectory*>(packageNode);
148	if (packageDirectory == NULL)
149		return false;
150
151	PackageDirectory* other = fPackageDirectories.Head();
152	return other == NULL
153		|| packageDirectory->ModifiedTime() > other->ModifiedTime();
154}
155
156
157void
158UnpackingDirectory::PrepareForRemoval()
159{
160	fPackageDirectories.MakeEmpty();
161}
162
163
164status_t
165UnpackingDirectory::OpenAttributeDirectory(AttributeDirectoryCookie*& _cookie)
166{
167	return UnpackingAttributeDirectoryCookie::Open(fPackageDirectories.Head(),
168		_cookie);
169}
170
171
172status_t
173UnpackingDirectory::OpenAttribute(const char* name, int openMode,
174	AttributeCookie*& _cookie)
175{
176	return UnpackingAttributeCookie::Open(fPackageDirectories.Head(), name,
177		openMode, _cookie);
178}
179
180
181status_t
182UnpackingDirectory::IndexAttribute(AttributeIndexer* indexer)
183{
184	return UnpackingAttributeCookie::IndexAttribute(fPackageDirectories.Head(),
185		indexer);
186}
187
188
189void*
190UnpackingDirectory::IndexCookieForAttribute(const char* name) const
191{
192	if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
193		return packageDirectory->IndexCookieForAttribute(name);
194	return NULL;
195}
196
197
198// #pragma mark - RootDirectory
199
200
201RootDirectory::RootDirectory(ino_t id, const timespec& modifiedTime)
202	:
203	UnpackingDirectory(id),
204	fModifiedTime(modifiedTime)
205{
206}
207
208
209timespec
210RootDirectory::ModifiedTime() const
211{
212	return fModifiedTime;
213}
214