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_NOT_A_DIRECTORY; 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