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 "UnpackingLeafNode.h" 8 9 #include <string.h> 10 11 #include <algorithm> 12 #include <new> 13 14 #include "UnpackingAttributeCookie.h" 15 #include "UnpackingAttributeDirectoryCookie.h" 16 #include "Utils.h" 17 18 19 UnpackingLeafNode::UnpackingLeafNode(ino_t id) 20 : 21 Node(id), 22 fFinalPackageNode(NULL) 23 { 24 } 25 26 27 UnpackingLeafNode::~UnpackingLeafNode() 28 { 29 if (fFinalPackageNode != NULL) 30 fFinalPackageNode->ReleaseReference(); 31 } 32 33 34 status_t 35 UnpackingLeafNode::VFSInit(dev_t deviceID) 36 { 37 status_t error = NodeInitVFS(deviceID, fID, _ActivePackageNode()); 38 if (error == B_OK) 39 Node::VFSInit(deviceID); 40 41 return error; 42 } 43 44 45 void 46 UnpackingLeafNode::VFSUninit() 47 { 48 NodeUninitVFS(_ActivePackageNode(), fFlags); 49 Node::VFSUninit(); 50 } 51 52 53 mode_t 54 UnpackingLeafNode::Mode() const 55 { 56 if (PackageLeafNode* packageNode = _ActivePackageNode()) 57 return packageNode->Mode(); 58 return S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; 59 } 60 61 62 uid_t 63 UnpackingLeafNode::UserID() const 64 { 65 if (PackageLeafNode* packageNode = _ActivePackageNode()) 66 return packageNode->UserID(); 67 return 0; 68 } 69 70 71 gid_t 72 UnpackingLeafNode::GroupID() const 73 { 74 if (PackageLeafNode* packageNode = _ActivePackageNode()) 75 return packageNode->GroupID(); 76 return 0; 77 } 78 79 80 timespec 81 UnpackingLeafNode::ModifiedTime() const 82 { 83 if (PackageLeafNode* packageNode = _ActivePackageNode()) 84 return packageNode->ModifiedTime(); 85 86 timespec time = { 0, 0 }; 87 return time; 88 } 89 90 91 off_t 92 UnpackingLeafNode::FileSize() const 93 { 94 if (PackageLeafNode* packageNode = _ActivePackageNode()) { 95 if (S_ISLNK(packageNode->Mode())) 96 return strlen(packageNode->SymlinkPath()); 97 return packageNode->FileSize(); 98 } 99 return 0; 100 } 101 102 103 Node* 104 UnpackingLeafNode::GetNode() 105 { 106 return this; 107 } 108 109 110 status_t 111 UnpackingLeafNode::AddPackageNode(PackageNode* packageNode, dev_t deviceID) 112 { 113 ASSERT(fFinalPackageNode == NULL); 114 115 if (S_ISDIR(packageNode->Mode())) 116 return B_BAD_VALUE; 117 118 PackageLeafNode* packageLeafNode 119 = dynamic_cast<PackageLeafNode*>(packageNode); 120 121 PackageLeafNode* headNode = fPackageNodes.Head(); 122 bool overridesHead = headNode == NULL 123 || packageLeafNode->HasPrecedenceOver(headNode); 124 125 if (overridesHead) { 126 fPackageNodes.Add(packageLeafNode); 127 NodeReinitVFS(deviceID, fID, packageLeafNode, headNode, fFlags); 128 } else { 129 // add after the head 130 fPackageNodes.RemoveHead(); 131 fPackageNodes.Add(packageLeafNode); 132 fPackageNodes.Add(headNode); 133 } 134 135 return B_OK; 136 } 137 138 139 void 140 UnpackingLeafNode::RemovePackageNode(PackageNode* packageNode, dev_t deviceID) 141 { 142 ASSERT(fFinalPackageNode == NULL); 143 144 bool isNewest = packageNode == fPackageNodes.Head(); 145 fPackageNodes.Remove(dynamic_cast<PackageLeafNode*>(packageNode)); 146 147 // when removing the newest node, we need to find the next node (the list 148 // is not sorted) 149 PackageLeafNode* newestNode = fPackageNodes.Head(); 150 if (isNewest && newestNode != NULL) { 151 PackageLeafNodeList::Iterator it = fPackageNodes.GetIterator(); 152 it.Next(); 153 // skip the first one 154 while (PackageLeafNode* otherNode = it.Next()) { 155 if (otherNode->HasPrecedenceOver(newestNode)) 156 newestNode = otherNode; 157 } 158 159 // re-add the newest node to the head 160 fPackageNodes.Remove(newestNode); 161 fPackageNodes.Add(newestNode); 162 NodeReinitVFS(deviceID, fID, newestNode, packageNode, fFlags); 163 } 164 } 165 166 167 PackageNode* 168 UnpackingLeafNode::GetPackageNode() 169 { 170 return _ActivePackageNode(); 171 } 172 173 174 bool 175 UnpackingLeafNode::IsOnlyPackageNode(PackageNode* node) const 176 { 177 ASSERT(fFinalPackageNode == NULL); 178 179 PackageLeafNode* head = fPackageNodes.Head(); 180 return node == head && fPackageNodes.GetNext(head) == NULL; 181 } 182 183 184 bool 185 UnpackingLeafNode::WillBeFirstPackageNode(PackageNode* packageNode) const 186 { 187 PackageLeafNode* packageLeafNode 188 = dynamic_cast<PackageLeafNode*>(packageNode); 189 if (packageLeafNode == NULL) 190 return false; 191 192 PackageLeafNode* headNode = fPackageNodes.Head(); 193 return headNode == NULL 194 || packageLeafNode->HasPrecedenceOver(headNode); 195 } 196 197 void 198 UnpackingLeafNode::PrepareForRemoval() 199 { 200 ASSERT(fFinalPackageNode == NULL); 201 202 fFinalPackageNode = fPackageNodes.Head(); 203 if (fFinalPackageNode != NULL) { 204 fFinalPackageNode->AcquireReference(); 205 fPackageNodes.MakeEmpty(); 206 } 207 } 208 209 210 status_t 211 UnpackingLeafNode::CloneTransferPackageNodes(ino_t id, UnpackingNode*& _newNode) 212 { 213 ASSERT(fFinalPackageNode == NULL); 214 215 UnpackingLeafNode* clone = new(std::nothrow) UnpackingLeafNode(id); 216 if (clone == NULL) 217 return B_NO_MEMORY; 218 219 status_t error = clone->Init(Parent(), Name()); 220 if (error != B_OK) { 221 delete clone; 222 return error; 223 } 224 225 // We keep the old head as fFinalPackageNode, which will make us to behave 226 // exactly as before with respect to FS operations. 227 fFinalPackageNode = fPackageNodes.Head(); 228 if (fFinalPackageNode != NULL) { 229 fFinalPackageNode->AcquireReference(); 230 clone->fPackageNodes.MoveFrom(&fPackageNodes); 231 } 232 233 _newNode = clone; 234 return B_OK; 235 } 236 237 238 status_t 239 UnpackingLeafNode::Read(off_t offset, void* buffer, size_t* bufferSize) 240 { 241 if (HasVFSInitError()) 242 return B_ERROR; 243 244 if (PackageLeafNode* packageNode = _ActivePackageNode()) 245 return packageNode->Read(offset, buffer, bufferSize); 246 return B_ERROR; 247 } 248 249 250 status_t 251 UnpackingLeafNode::Read(io_request* request) 252 { 253 if (HasVFSInitError()) 254 return B_ERROR; 255 256 if (PackageLeafNode* packageNode = _ActivePackageNode()) 257 return packageNode->Read(request); 258 return EBADF; 259 } 260 261 262 status_t 263 UnpackingLeafNode::ReadSymlink(void* buffer, size_t* bufferSize) 264 { 265 if (HasVFSInitError()) 266 return B_ERROR; 267 268 PackageLeafNode* packageNode = _ActivePackageNode(); 269 if (packageNode == NULL) 270 return B_BAD_VALUE; 271 272 const String& linkPath = packageNode->SymlinkPath(); 273 if (linkPath[0] == '\0') { 274 *bufferSize = 0; 275 return B_OK; 276 } 277 278 size_t linkLength = strnlen(linkPath, B_PATH_NAME_LENGTH); 279 280 size_t bytesToCopy = std::min(linkLength, *bufferSize); 281 282 *bufferSize = linkLength; 283 284 memcpy(buffer, linkPath, bytesToCopy); 285 return B_OK; 286 } 287 288 289 status_t 290 UnpackingLeafNode::OpenAttributeDirectory(AttributeDirectoryCookie*& _cookie) 291 { 292 if (HasVFSInitError()) 293 return B_ERROR; 294 295 return UnpackingAttributeDirectoryCookie::Open(_ActivePackageNode(), 296 _cookie); 297 } 298 299 300 status_t 301 UnpackingLeafNode::OpenAttribute(const StringKey& name, int openMode, 302 AttributeCookie*& _cookie) 303 { 304 if (HasVFSInitError()) 305 return B_ERROR; 306 307 return UnpackingAttributeCookie::Open(_ActivePackageNode(), name, openMode, 308 _cookie); 309 } 310 311 312 status_t 313 UnpackingLeafNode::IndexAttribute(AttributeIndexer* indexer) 314 { 315 return UnpackingAttributeCookie::IndexAttribute(_ActivePackageNode(), 316 indexer); 317 } 318 319 320 void* 321 UnpackingLeafNode::IndexCookieForAttribute(const StringKey& name) const 322 { 323 if (PackageLeafNode* packageNode = _ActivePackageNode()) 324 return packageNode->IndexCookieForAttribute(name); 325 return NULL; 326 } 327 328 329 PackageLeafNode* 330 UnpackingLeafNode::_ActivePackageNode() const 331 { 332 if (PackageLeafNode* packageNode = fPackageNodes.Head()) 333 return packageNode; 334 return fFinalPackageNode; 335 } 336