xref: /haiku/src/add-ons/kernel/file_systems/packagefs/nodes/UnpackingDirectory.cpp (revision f967e2c0c73efb25581afdc95a838f7633e8c03b)
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 
19 UnpackingDirectory::UnpackingDirectory(ino_t id)
20 	:
21 	Directory(id)
22 {
23 }
24 
25 
26 UnpackingDirectory::~UnpackingDirectory()
27 {
28 }
29 
30 
31 status_t
32 UnpackingDirectory::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 
42 void
43 UnpackingDirectory::VFSUninit()
44 {
45 	NodeUninitVFS(fPackageDirectories.Head(), fFlags);
46 	Directory::VFSUninit();
47 }
48 
49 
50 mode_t
51 UnpackingDirectory::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 
59 uid_t
60 UnpackingDirectory::UserID() const
61 {
62 	if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
63 		return packageDirectory->UserID();
64 	return 0;
65 }
66 
67 
68 gid_t
69 UnpackingDirectory::GroupID() const
70 {
71 	if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
72 		return packageDirectory->GroupID();
73 	return 0;
74 }
75 
76 
77 timespec
78 UnpackingDirectory::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 
88 off_t
89 UnpackingDirectory::FileSize() const
90 {
91 	return 0;
92 }
93 
94 
95 Node*
96 UnpackingDirectory::GetNode()
97 {
98 	return this;
99 }
100 
101 
102 status_t
103 UnpackingDirectory::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 
125 void
126 UnpackingDirectory::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 
150 PackageNode*
151 UnpackingDirectory::GetPackageNode()
152 {
153 	return fPackageDirectories.Head();
154 }
155 
156 
157 bool
158 UnpackingDirectory::IsOnlyPackageNode(PackageNode* node) const
159 {
160 	return node == fPackageDirectories.Head()
161 		&& node == fPackageDirectories.Tail();
162 }
163 
164 
165 bool
166 UnpackingDirectory::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 
178 void
179 UnpackingDirectory::PrepareForRemoval()
180 {
181 	fPackageDirectories.MakeEmpty();
182 }
183 
184 
185 status_t
186 UnpackingDirectory::OpenAttributeDirectory(AttributeDirectoryCookie*& _cookie)
187 {
188 	if (HasVFSInitError())
189 		return B_ERROR;
190 
191 	return UnpackingAttributeDirectoryCookie::Open(fPackageDirectories.Head(),
192 		_cookie);
193 }
194 
195 
196 status_t
197 UnpackingDirectory::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 
208 status_t
209 UnpackingDirectory::IndexAttribute(AttributeIndexer* indexer)
210 {
211 	return UnpackingAttributeCookie::IndexAttribute(fPackageDirectories.Head(),
212 		indexer);
213 }
214 
215 
216 void*
217 UnpackingDirectory::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 
228 RootDirectory::RootDirectory(ino_t id, const timespec& modifiedTime)
229 	:
230 	UnpackingDirectory(id),
231 	fModifiedTime(modifiedTime)
232 {
233 }
234 
235 
236 status_t
237 RootDirectory::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 
249 timespec
250 RootDirectory::ModifiedTime() const
251 {
252 	return fModifiedTime;
253 }
254