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