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