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