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