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 isNewest = other == NULL 112 || packageDirectory->ModifiedTime() > other->ModifiedTime(); 113 114 if (isNewest) { 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->ModifiedTime() > newestNode->ModifiedTime()) 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 174 || packageDirectory->ModifiedTime() > other->ModifiedTime(); 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 timespec 237 RootDirectory::ModifiedTime() const 238 { 239 return fModifiedTime; 240 } 241