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