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