OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "memfilesystem.h" |
| 6 |
| 7 #include <deque> |
| 8 |
| 9 namespace filesystem{ |
| 10 |
| 11 Filesystem::Filesystem() |
| 12 :currentInode_(1), |
| 13 root_path("/") { |
| 14 // Adding root directory |
| 15 root_inode = GetNextInodeNumber(); |
| 16 InodeDirectory* root_directory = new InodeDirectory(this, root_inode); |
| 17 |
| 18 // Add it to the list and increment ref count |
| 19 if (root_directory){ |
| 20 PutInode(root_directory->inode_number(), root_directory); |
| 21 AddLink(root_directory->inode_number()); |
| 22 } |
| 23 } |
| 24 |
| 25 Filesystem::~Filesystem() { |
| 26 for (ListOfInodesIterator it(inodesList_.begin()); |
| 27 it != inodesList_.end(); it++) |
| 28 delete it->second.second; |
| 29 |
| 30 inodesList_.clear(); |
| 31 } |
| 32 |
| 33 int Filesystem::GetMetadata( |
| 34 const std::string& path, |
| 35 Filesystem::NameInodePair &meta) { |
| 36 std::string filePath = path.substr(path.find_last_of("/")+1); |
| 37 Inode* inode = nullptr; |
| 38 |
| 39 if(path.size()==0)//root |
| 40 inode = GetInode(root_inode); |
| 41 else |
| 42 inode = GetInode( GetInodeFromPath(path) ); |
| 43 |
| 44 if (inode==nullptr) |
| 45 return File_System_Error_NOT_FOUND; |
| 46 |
| 47 meta.first = filePath; |
| 48 meta.second = inode; |
| 49 |
| 50 return File_System_Error_NONE; |
| 51 } |
| 52 |
| 53 |
| 54 int Filesystem::CreateDirectory(const std::string& path, bool recursive) { |
| 55 if (path.size() == 0 || |
| 56 path[0] != '/') |
| 57 return File_System_Error_NOT_FOUND; |
| 58 |
| 59 std::deque<std::string> tree_entries; |
| 60 size_t position = path.find_first_of("/"); |
| 61 std::string rest = path.substr( position + 1 ); |
| 62 |
| 63 // Break the path into components |
| 64 // starting rigth after "/". |
| 65 while (1) { |
| 66 position = rest.find_first_of("/"); |
| 67 tree_entries.push_back(rest.substr(0, position) ); |
| 68 if (std::string::npos == position) |
| 69 break; |
| 70 rest = rest.substr(position + 1); |
| 71 } |
| 72 |
| 73 std::string current_dir = ""; |
| 74 unsigned long long workingInode = root_inode; |
| 75 InodeDirectory* |
| 76 current_inode = static_cast<InodeDirectory*>(GetInode(workingInode)); |
| 77 |
| 78 if (current_inode==nullptr|| |
| 79 current_inode->file_type()!=Inode::FILE_TYPE_DIR) |
| 80 return File_System_Error_FAILED; |
| 81 |
| 82 // At this point we have the root inode |
| 83 // and we will traverse the path downwards and create |
| 84 // if recursive is true intermediate directories |
| 85 while (tree_entries.size() > 0) { |
| 86 current_dir = tree_entries.front(); |
| 87 tree_entries.pop_front(); |
| 88 if (tree_entries.size() == 0) { // the new dir |
| 89 InodeDirectory *new_dir = |
| 90 new InodeDirectory(this, GetNextInodeNumber()); |
| 91 if (new_dir==nullptr) |
| 92 return File_System_Error_FAILED; |
| 93 // Add to the inode list |
| 94 PutInode(new_dir->inode_number(), new_dir); |
| 95 current_inode->AddEntry(current_dir, new_dir->inode_number()); |
| 96 return File_System_Error_NONE; |
| 97 } else { |
| 98 if ((workingInode = |
| 99 current_inode->GetInodeFromName(current_dir))== Inode::NO_INODE) { |
| 100 if (recursive == false) // all dirs must exist |
| 101 return File_System_Error_NOT_FOUND; |
| 102 else { |
| 103 InodeDirectory *new_dir = |
| 104 new InodeDirectory(this, GetNextInodeNumber()); |
| 105 if (new_dir==nullptr) |
| 106 return File_System_Error_FAILED; |
| 107 PutInode(new_dir->inode_number(), new_dir); |
| 108 current_inode->AddEntry(current_dir, new_dir->inode_number()); |
| 109 // Hop into to the just created directory |
| 110 current_inode = new_dir; |
| 111 workingInode = new_dir->inode_number(); |
| 112 } |
| 113 } else { |
| 114 // hope into the directory |
| 115 current_inode = static_cast<InodeDirectory*>( GetInode(workingInode) ); |
| 116 if(current_inode->file_type()!=Inode::FILE_TYPE_DIR) |
| 117 return File_System_Error_NOT_FOUND; |
| 118 } |
| 119 } |
| 120 } |
| 121 return File_System_Error_FAILED; |
| 122 } |
| 123 |
| 124 int Filesystem::MoveEntry( |
| 125 const std::string& sourcePath, |
| 126 const std::string& targetPath) { |
| 127 std::string sourceDir = sourcePath.substr(0, sourcePath.find_last_of("/")); |
| 128 std::string targetDir = targetPath.substr(0, targetPath.find_last_of("/")); |
| 129 |
| 130 std::string sourceFile = sourcePath.substr(sourcePath.find_last_of("/")+1); |
| 131 std::string targetFile = targetPath.substr(targetPath.find_last_of("/") + 1); |
| 132 |
| 133 if (sourceFile.size() == 0 || |
| 134 targetFile.size() == 0) |
| 135 return File_System_Error_FAILED; |
| 136 |
| 137 if (sourceDir.size() == 0) |
| 138 sourceDir = "/"; |
| 139 if (targetDir.size() == 0) |
| 140 targetDir = "/"; |
| 141 |
| 142 // Point to the parent dirs |
| 143 InodeDirectory *srcInode = |
| 144 static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(sourceDir))); |
| 145 InodeDirectory *dstInode = |
| 146 static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(targetDir))); |
| 147 |
| 148 if (nullptr == srcInode || |
| 149 srcInode->file_type()!=Inode::FILE_TYPE_DIR|| |
| 150 nullptr == dstInode|| |
| 151 dstInode->file_type()!=Inode::FILE_TYPE_DIR) |
| 152 return File_System_Error_NOT_FOUND; |
| 153 |
| 154 unsigned long long toBeMoved = srcInode->GetInodeFromName(sourceFile); |
| 155 if (toBeMoved == Inode::NO_INODE) |
| 156 return File_System_Error_FAILED; |
| 157 |
| 158 dstInode->AddEntry(targetFile, toBeMoved); // adds link |
| 159 srcInode->DeleteEntry(sourceFile, toBeMoved); // removes link |
| 160 |
| 161 return File_System_Error_NONE; |
| 162 } |
| 163 |
| 164 int Filesystem::CopyEntry( |
| 165 const std::string& sourcePath, |
| 166 const std::string& targetPath) { |
| 167 std::string sourceDir = sourcePath.substr(0, sourcePath.find_last_of("/")); |
| 168 std::string targetDir = targetPath.substr(0, targetPath.find_last_of("/")); |
| 169 |
| 170 std::string sourceFile = sourcePath.substr(sourcePath.find_last_of("/") + 1); |
| 171 std::string targetFile = targetPath.substr(targetPath.find_last_of("/") + 1); |
| 172 |
| 173 if (sourceFile.size() == 0 || |
| 174 targetFile.size() == 0) |
| 175 return File_System_Error_FAILED; |
| 176 |
| 177 if (sourceDir.size() == 0) |
| 178 sourceDir = "/"; |
| 179 if (targetDir.size() == 0) |
| 180 targetDir = "/"; |
| 181 |
| 182 InodeDirectory *srcInode = |
| 183 static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(sourceDir))); |
| 184 InodeDirectory *dstInode = |
| 185 static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(targetDir))); |
| 186 |
| 187 if (nullptr == srcInode || |
| 188 srcInode->file_type()!=Inode::FILE_TYPE_DIR|| |
| 189 nullptr == dstInode|| |
| 190 dstInode->file_type()!=Inode::FILE_TYPE_DIR) |
| 191 return File_System_Error_NOT_FOUND; |
| 192 |
| 193 unsigned long long toBeCopied = srcInode->GetInodeFromName(sourceFile); |
| 194 if (toBeCopied == Inode::NO_INODE) |
| 195 return File_System_Error_FAILED; |
| 196 |
| 197 Inode* old_inode = GetInode(toBeCopied); |
| 198 |
| 199 if (nullptr == old_inode) |
| 200 return File_System_Error_NOT_FOUND; |
| 201 |
| 202 Inode* new_inode = nullptr; |
| 203 if (old_inode->file_type() == Inode::FILE_TYPE_FILE) { |
| 204 InodeFile *temp = static_cast<InodeFile*>(old_inode); |
| 205 new_inode = new InodeFile(*temp); |
| 206 if (nullptr == new_inode) |
| 207 return File_System_Error_FAILED; |
| 208 } |
| 209 else if (old_inode->file_type() == Inode::FILE_TYPE_DIR) { |
| 210 InodeDirectory *temp = static_cast<InodeDirectory*>(old_inode); |
| 211 new_inode = new InodeDirectory(*temp); |
| 212 if (nullptr == new_inode) |
| 213 return File_System_Error_FAILED; |
| 214 } |
| 215 |
| 216 new_inode->set_inode_number(GetNextInodeNumber()); |
| 217 PutInode(new_inode->inode_number(), new_inode); |
| 218 new_inode->set_inode_modified(); |
| 219 |
| 220 dstInode->AddEntry(targetFile, new_inode->inode_number()); |
| 221 return File_System_Error_NONE; |
| 222 } |
| 223 |
| 224 |
| 225 int Filesystem::DeleteEntry(const std::string& path, bool recursive) { |
| 226 unsigned long long workingInode = GetInodeFromPath(path); |
| 227 Inode* current_inode = GetInode(workingInode); |
| 228 |
| 229 if (nullptr == current_inode) |
| 230 return File_System_Error_NOT_FOUND; |
| 231 |
| 232 if (current_inode->file_type() == Inode::FILE_TYPE_DIR && |
| 233 !recursive) |
| 234 return File_System_Error_NOT_FOUND; |
| 235 |
| 236 std::string dir = path.substr(0, path.find_last_of("/")); |
| 237 if (dir.size() == 0) |
| 238 dir = "/"; |
| 239 |
| 240 InodeDirectory* parent_inode = |
| 241 static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(dir))); |
| 242 if (nullptr == parent_inode|| |
| 243 parent_inode->file_type()!=Inode::FILE_TYPE_DIR) |
| 244 return File_System_Error_NOT_FOUND; |
| 245 parent_inode->DeleteEntry( |
| 246 path.substr(path.find_last_of("/")+1), workingInode); |
| 247 |
| 248 return File_System_Error_NONE; |
| 249 } |
| 250 |
| 251 int Filesystem::ReadDirectory ( |
| 252 const std::string& path, |
| 253 std::vector<NameInodePair>& metas){ |
| 254 |
| 255 InodeDirectory* inode_directory = |
| 256 static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(path))); |
| 257 |
| 258 if (nullptr==inode_directory|| |
| 259 inode_directory->file_type()!=Inode::FILE_TYPE_DIR) |
| 260 return File_System_Error_FAILED; |
| 261 std::vector< InodeDirectory::EntryPair > listOfEntries; |
| 262 inode_directory->GetAllInodes(listOfEntries); |
| 263 Inode* inode = nullptr; |
| 264 for (std::vector< InodeDirectory::EntryPair >::iterator |
| 265 it(listOfEntries.begin()); |
| 266 it != listOfEntries.end(); it++) { |
| 267 inode = GetInode(it->second); |
| 268 if (nullptr != inode) |
| 269 metas.push_back(NameInodePair(it->first, inode)); |
| 270 } |
| 271 return File_System_Error_NONE; |
| 272 } |
| 273 |
| 274 int Filesystem::CreateFile(const std::string& filePath) { |
| 275 std::string targetDir = filePath.substr(0, filePath.find_last_of("/")); |
| 276 std::string filename = filePath.substr(filePath.find_last_of("/") + 1); |
| 277 |
| 278 if (targetDir.size() == 0) |
| 279 targetDir = "/"; |
| 280 if (filename.size()==0) |
| 281 return File_System_Error_FAILED; |
| 282 InodeDirectory* inode_directory = |
| 283 static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(targetDir))); |
| 284 if (nullptr == inode_directory|| |
| 285 inode_directory->file_type()!=Inode::FILE_TYPE_DIR) |
| 286 return File_System_Error_FAILED; |
| 287 |
| 288 InodeFile* inode_file = new InodeFile(GetNextInodeNumber()); |
| 289 if (nullptr == inode_file) |
| 290 return File_System_Error_FAILED; |
| 291 |
| 292 PutInode(inode_file->inode_number(), inode_file); |
| 293 inode_directory->AddEntry(filename, inode_file->inode_number()); |
| 294 return File_System_Error_NONE; |
| 295 } |
| 296 |
| 297 int Filesystem::Truncate(const std::string &filePath, size_t length) { |
| 298 InodeFile *inode_file = |
| 299 static_cast<InodeFile*>( GetInode( GetInodeFromPath(filePath) ) ); |
| 300 if (inode_file==nullptr || |
| 301 inode_file->file_type() != Inode::FILE_TYPE_FILE) |
| 302 return File_System_Error_NOT_FOUND; |
| 303 |
| 304 inode_file->Truncate(length); |
| 305 return File_System_Error_NONE; |
| 306 } |
| 307 |
| 308 int Filesystem::WriteToFile( |
| 309 const std::string &filePath, |
| 310 size_t offset, |
| 311 size_t dataSize, |
| 312 const char *data) { |
| 313 InodeFile *inode_file = |
| 314 static_cast<InodeFile*>( GetInode( GetInodeFromPath(filePath) ) ); |
| 315 if(inode_file==nullptr|| |
| 316 inode_file->file_type()!=Inode::FILE_TYPE_FILE) |
| 317 return File_System_Error_NOT_FOUND; |
| 318 |
| 319 if( inode_file->Write(data, offset, dataSize) ) |
| 320 return File_System_Error_NONE; |
| 321 return File_System_Error_FAILED; |
| 322 } |
| 323 |
| 324 int Filesystem::ReadFromFile(const std::string &filePath, |
| 325 size_t offset, |
| 326 size_t* inOutLength, |
| 327 const char** outData) { |
| 328 InodeFile *inode_file = |
| 329 static_cast<InodeFile*>( GetInode( GetInodeFromPath(filePath) ) ); |
| 330 if (inode_file==nullptr|| |
| 331 inode_file->file_type()!=Inode::FILE_TYPE_FILE) |
| 332 return File_System_Error_NOT_FOUND; |
| 333 |
| 334 if (inode_file->Read(offset, inOutLength, outData )) |
| 335 return File_System_Error_NONE; |
| 336 return File_System_Error_FAILED; |
| 337 } |
| 338 |
| 339 void Filesystem::AddLink(unsigned long long inode) { |
| 340 ListOfInodesIterator it(inodesList_.find(inode)); |
| 341 if (it != inodesList_.end()) { |
| 342 it->second.first++; |
| 343 // If directory add a reference for each entry it contains |
| 344 if (it->second.second->file_type() == Inode::FILE_TYPE_DIR) { |
| 345 InodeDirectory* inode_directory = |
| 346 static_cast<InodeDirectory*>(it->second.second); |
| 347 if (nullptr == inode_directory) |
| 348 return; |
| 349 std::vector<InodeDirectory::EntryPair> entries; |
| 350 inode_directory->GetAllInodes(entries); |
| 351 for (std::vector<InodeDirectory::EntryPair>::iterator |
| 352 entry = entries.begin(); |
| 353 entry != entries.end(); ++entry) { |
| 354 AddLink(entry->second); |
| 355 } |
| 356 } |
| 357 } |
| 358 } |
| 359 void Filesystem::RemoveLink(unsigned long long inode_number) { |
| 360 ListOfInodesIterator it(inodesList_.find(inode_number)); |
| 361 if (it != inodesList_.end()) { |
| 362 Inode* inode = it->second.second; |
| 363 if (nullptr == inode) |
| 364 return; |
| 365 if (inode->file_type() == Inode::FILE_TYPE_DIR) { |
| 366 InodeDirectory* inode_directory = |
| 367 static_cast<InodeDirectory*>(inode); |
| 368 if (nullptr == inode_directory) |
| 369 return; |
| 370 // Get all inodes and remove their reference |
| 371 std::vector<InodeDirectory::EntryPair> entries; |
| 372 inode_directory->GetAllInodes(entries); |
| 373 for (std::vector<InodeDirectory::EntryPair>::iterator |
| 374 entry = entries.begin(); |
| 375 entry != entries.end(); entry++) { |
| 376 RemoveLink(entry->second); |
| 377 } |
| 378 } |
| 379 // If current reference is down to 0 |
| 380 // then remove it |
| 381 if (--it->second.first==0) { |
| 382 delete inode; |
| 383 inodesList_.erase(it); |
| 384 } |
| 385 } |
| 386 } |
| 387 |
| 388 Inode* Filesystem::GetInode(unsigned long long inode) { |
| 389 ListOfInodesIterator it = inodesList_.find(inode); |
| 390 if (it == inodesList_.end()) |
| 391 return nullptr; |
| 392 return it->second.second; |
| 393 } |
| 394 |
| 395 void Filesystem::PutInode(unsigned long long inode_number, Inode* inode) { |
| 396 inodesList_.insert(std::pair<unsigned long long,InodePair >( |
| 397 inode_number, InodePair( 0, inode) ) ); |
| 398 } |
| 399 void Filesystem::RemoveInode(unsigned long long inode) { |
| 400 ListOfInodesIterator it = inodesList_.find(inode); |
| 401 inodesList_.erase(it); |
| 402 } |
| 403 |
| 404 unsigned long long Filesystem::GetInodeFromPath(const std::string& path){ |
| 405 if (path.size() == 0 || |
| 406 path[0] != '/') |
| 407 return File_System_Error_NOT_FOUND; |
| 408 |
| 409 std::deque<std::string> tree_entries; |
| 410 std::string::size_type position = 0; |
| 411 std::string rest = path.substr(1); |
| 412 std::string temp; |
| 413 |
| 414 while (1) { |
| 415 position = rest.find_first_of("/"); |
| 416 temp = rest.substr(0, position); |
| 417 if (temp.size()!=0) |
| 418 tree_entries.push_back(temp); |
| 419 if (std::string::npos == position) |
| 420 break; |
| 421 rest = rest.substr(position + 1); |
| 422 } |
| 423 |
| 424 std::string current_dir = ""; |
| 425 unsigned long long workingInode = root_inode; |
| 426 InodeDirectory* current_inode = |
| 427 static_cast<InodeDirectory*>(GetInode(workingInode)); |
| 428 if (current_inode==nullptr|| |
| 429 current_inode->file_type()!=Inode::FILE_TYPE_DIR) |
| 430 return Inode::NO_INODE; |
| 431 while ( tree_entries.size() > 0) { |
| 432 current_dir = tree_entries.front(); |
| 433 tree_entries.pop_front(); |
| 434 |
| 435 workingInode = current_inode->GetInodeFromName(current_dir); |
| 436 if (workingInode == Inode::NO_INODE) |
| 437 return File_System_Error_NOT_FOUND; |
| 438 if (tree_entries.size() > 0) { |
| 439 current_inode = |
| 440 static_cast<InodeDirectory*>(GetInode(workingInode)); |
| 441 if (current_inode==nullptr|| |
| 442 current_inode->file_type()!=Inode::FILE_TYPE_DIR) |
| 443 return Inode::NO_INODE; |
| 444 } |
| 445 } |
| 446 return workingInode; |
| 447 } |
| 448 |
| 449 unsigned long long Filesystem::GetNextInodeNumber(){ |
| 450 if (++currentInode_ == Inode::NO_INODE) |
| 451 return ++currentInode_; |
| 452 return currentInode_; |
| 453 } |
| 454 |
| 455 |
| 456 }// namespace filesystem |
OLD | NEW |