Index: ppapi/examples/filesystem_provider/memfilesystem.cc |
diff --git a/ppapi/examples/filesystem_provider/memfilesystem.cc b/ppapi/examples/filesystem_provider/memfilesystem.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..93bc7dd21e20665c9c5b3d11c02b12b2dcb1facf |
--- /dev/null |
+++ b/ppapi/examples/filesystem_provider/memfilesystem.cc |
@@ -0,0 +1,456 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "memfilesystem.h" |
+ |
+#include <deque> |
+ |
+namespace filesystem{ |
+ |
+Filesystem::Filesystem() |
+ :currentInode_(1), |
+ root_path("/") { |
+ // Adding root directory |
+ root_inode = GetNextInodeNumber(); |
+ InodeDirectory* root_directory = new InodeDirectory(this, root_inode); |
+ |
+ // Add it to the list and increment ref count |
+ if (root_directory){ |
+ PutInode(root_directory->inode_number(), root_directory); |
+ AddLink(root_directory->inode_number()); |
+ } |
+} |
+ |
+Filesystem::~Filesystem() { |
+ for (ListOfInodesIterator it(inodesList_.begin()); |
+ it != inodesList_.end(); it++) |
+ delete it->second.second; |
+ |
+ inodesList_.clear(); |
+} |
+ |
+int Filesystem::GetMetadata( |
+ const std::string& path, |
+ Filesystem::NameInodePair &meta) { |
+ std::string filePath = path.substr(path.find_last_of("/")+1); |
+ Inode* inode = nullptr; |
+ |
+ if(path.size()==0)//root |
+ inode = GetInode(root_inode); |
+ else |
+ inode = GetInode( GetInodeFromPath(path) ); |
+ |
+ if (inode==nullptr) |
+ return File_System_Error_NOT_FOUND; |
+ |
+ meta.first = filePath; |
+ meta.second = inode; |
+ |
+ return File_System_Error_NONE; |
+} |
+ |
+ |
+int Filesystem::CreateDirectory(const std::string& path, bool recursive) { |
+ if (path.size() == 0 || |
+ path[0] != '/') |
+ return File_System_Error_NOT_FOUND; |
+ |
+ std::deque<std::string> tree_entries; |
+ size_t position = path.find_first_of("/"); |
+ std::string rest = path.substr( position + 1 ); |
+ |
+ // Break the path into components |
+ // starting rigth after "/". |
+ while (1) { |
+ position = rest.find_first_of("/"); |
+ tree_entries.push_back(rest.substr(0, position) ); |
+ if (std::string::npos == position) |
+ break; |
+ rest = rest.substr(position + 1); |
+ } |
+ |
+ std::string current_dir = ""; |
+ unsigned long long workingInode = root_inode; |
+ InodeDirectory* |
+ current_inode = static_cast<InodeDirectory*>(GetInode(workingInode)); |
+ |
+ if (current_inode==nullptr|| |
+ current_inode->file_type()!=Inode::FILE_TYPE_DIR) |
+ return File_System_Error_FAILED; |
+ |
+ // At this point we have the root inode |
+ // and we will traverse the path downwards and create |
+ // if recursive is true intermediate directories |
+ while (tree_entries.size() > 0) { |
+ current_dir = tree_entries.front(); |
+ tree_entries.pop_front(); |
+ if (tree_entries.size() == 0) { // the new dir |
+ InodeDirectory *new_dir = |
+ new InodeDirectory(this, GetNextInodeNumber()); |
+ if (new_dir==nullptr) |
+ return File_System_Error_FAILED; |
+ // Add to the inode list |
+ PutInode(new_dir->inode_number(), new_dir); |
+ current_inode->AddEntry(current_dir, new_dir->inode_number()); |
+ return File_System_Error_NONE; |
+ } else { |
+ if ((workingInode = |
+ current_inode->GetInodeFromName(current_dir))== Inode::NO_INODE) { |
+ if (recursive == false) // all dirs must exist |
+ return File_System_Error_NOT_FOUND; |
+ else { |
+ InodeDirectory *new_dir = |
+ new InodeDirectory(this, GetNextInodeNumber()); |
+ if (new_dir==nullptr) |
+ return File_System_Error_FAILED; |
+ PutInode(new_dir->inode_number(), new_dir); |
+ current_inode->AddEntry(current_dir, new_dir->inode_number()); |
+ // Hop into to the just created directory |
+ current_inode = new_dir; |
+ workingInode = new_dir->inode_number(); |
+ } |
+ } else { |
+ // hope into the directory |
+ current_inode = static_cast<InodeDirectory*>( GetInode(workingInode) ); |
+ if(current_inode->file_type()!=Inode::FILE_TYPE_DIR) |
+ return File_System_Error_NOT_FOUND; |
+ } |
+ } |
+ } |
+ return File_System_Error_FAILED; |
+} |
+ |
+int Filesystem::MoveEntry( |
+ const std::string& sourcePath, |
+ const std::string& targetPath) { |
+ std::string sourceDir = sourcePath.substr(0, sourcePath.find_last_of("/")); |
+ std::string targetDir = targetPath.substr(0, targetPath.find_last_of("/")); |
+ |
+ std::string sourceFile = sourcePath.substr(sourcePath.find_last_of("/")+1); |
+ std::string targetFile = targetPath.substr(targetPath.find_last_of("/") + 1); |
+ |
+ if (sourceFile.size() == 0 || |
+ targetFile.size() == 0) |
+ return File_System_Error_FAILED; |
+ |
+ if (sourceDir.size() == 0) |
+ sourceDir = "/"; |
+ if (targetDir.size() == 0) |
+ targetDir = "/"; |
+ |
+ // Point to the parent dirs |
+ InodeDirectory *srcInode = |
+ static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(sourceDir))); |
+ InodeDirectory *dstInode = |
+ static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(targetDir))); |
+ |
+ if (nullptr == srcInode || |
+ srcInode->file_type()!=Inode::FILE_TYPE_DIR|| |
+ nullptr == dstInode|| |
+ dstInode->file_type()!=Inode::FILE_TYPE_DIR) |
+ return File_System_Error_NOT_FOUND; |
+ |
+ unsigned long long toBeMoved = srcInode->GetInodeFromName(sourceFile); |
+ if (toBeMoved == Inode::NO_INODE) |
+ return File_System_Error_FAILED; |
+ |
+ dstInode->AddEntry(targetFile, toBeMoved); // adds link |
+ srcInode->DeleteEntry(sourceFile, toBeMoved); // removes link |
+ |
+ return File_System_Error_NONE; |
+} |
+ |
+int Filesystem::CopyEntry( |
+ const std::string& sourcePath, |
+ const std::string& targetPath) { |
+ std::string sourceDir = sourcePath.substr(0, sourcePath.find_last_of("/")); |
+ std::string targetDir = targetPath.substr(0, targetPath.find_last_of("/")); |
+ |
+ std::string sourceFile = sourcePath.substr(sourcePath.find_last_of("/") + 1); |
+ std::string targetFile = targetPath.substr(targetPath.find_last_of("/") + 1); |
+ |
+ if (sourceFile.size() == 0 || |
+ targetFile.size() == 0) |
+ return File_System_Error_FAILED; |
+ |
+ if (sourceDir.size() == 0) |
+ sourceDir = "/"; |
+ if (targetDir.size() == 0) |
+ targetDir = "/"; |
+ |
+ InodeDirectory *srcInode = |
+ static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(sourceDir))); |
+ InodeDirectory *dstInode = |
+ static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(targetDir))); |
+ |
+ if (nullptr == srcInode || |
+ srcInode->file_type()!=Inode::FILE_TYPE_DIR|| |
+ nullptr == dstInode|| |
+ dstInode->file_type()!=Inode::FILE_TYPE_DIR) |
+ return File_System_Error_NOT_FOUND; |
+ |
+ unsigned long long toBeCopied = srcInode->GetInodeFromName(sourceFile); |
+ if (toBeCopied == Inode::NO_INODE) |
+ return File_System_Error_FAILED; |
+ |
+ Inode* old_inode = GetInode(toBeCopied); |
+ |
+ if (nullptr == old_inode) |
+ return File_System_Error_NOT_FOUND; |
+ |
+ Inode* new_inode = nullptr; |
+ if (old_inode->file_type() == Inode::FILE_TYPE_FILE) { |
+ InodeFile *temp = static_cast<InodeFile*>(old_inode); |
+ new_inode = new InodeFile(*temp); |
+ if (nullptr == new_inode) |
+ return File_System_Error_FAILED; |
+ } |
+ else if (old_inode->file_type() == Inode::FILE_TYPE_DIR) { |
+ InodeDirectory *temp = static_cast<InodeDirectory*>(old_inode); |
+ new_inode = new InodeDirectory(*temp); |
+ if (nullptr == new_inode) |
+ return File_System_Error_FAILED; |
+ } |
+ |
+ new_inode->set_inode_number(GetNextInodeNumber()); |
+ PutInode(new_inode->inode_number(), new_inode); |
+ new_inode->set_inode_modified(); |
+ |
+ dstInode->AddEntry(targetFile, new_inode->inode_number()); |
+ return File_System_Error_NONE; |
+} |
+ |
+ |
+int Filesystem::DeleteEntry(const std::string& path, bool recursive) { |
+ unsigned long long workingInode = GetInodeFromPath(path); |
+ Inode* current_inode = GetInode(workingInode); |
+ |
+ if (nullptr == current_inode) |
+ return File_System_Error_NOT_FOUND; |
+ |
+ if (current_inode->file_type() == Inode::FILE_TYPE_DIR && |
+ !recursive) |
+ return File_System_Error_NOT_FOUND; |
+ |
+ std::string dir = path.substr(0, path.find_last_of("/")); |
+ if (dir.size() == 0) |
+ dir = "/"; |
+ |
+ InodeDirectory* parent_inode = |
+ static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(dir))); |
+ if (nullptr == parent_inode|| |
+ parent_inode->file_type()!=Inode::FILE_TYPE_DIR) |
+ return File_System_Error_NOT_FOUND; |
+ parent_inode->DeleteEntry( |
+ path.substr(path.find_last_of("/")+1), workingInode); |
+ |
+ return File_System_Error_NONE; |
+} |
+ |
+int Filesystem::ReadDirectory ( |
+ const std::string& path, |
+ std::vector<NameInodePair>& metas){ |
+ |
+ InodeDirectory* inode_directory = |
+ static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(path))); |
+ |
+ if (nullptr==inode_directory|| |
+ inode_directory->file_type()!=Inode::FILE_TYPE_DIR) |
+ return File_System_Error_FAILED; |
+ std::vector< InodeDirectory::EntryPair > listOfEntries; |
+ inode_directory->GetAllInodes(listOfEntries); |
+ Inode* inode = nullptr; |
+ for (std::vector< InodeDirectory::EntryPair >::iterator |
+ it(listOfEntries.begin()); |
+ it != listOfEntries.end(); it++) { |
+ inode = GetInode(it->second); |
+ if (nullptr != inode) |
+ metas.push_back(NameInodePair(it->first, inode)); |
+ } |
+ return File_System_Error_NONE; |
+} |
+ |
+int Filesystem::CreateFile(const std::string& filePath) { |
+ std::string targetDir = filePath.substr(0, filePath.find_last_of("/")); |
+ std::string filename = filePath.substr(filePath.find_last_of("/") + 1); |
+ |
+ if (targetDir.size() == 0) |
+ targetDir = "/"; |
+ if (filename.size()==0) |
+ return File_System_Error_FAILED; |
+ InodeDirectory* inode_directory = |
+ static_cast<InodeDirectory*>(GetInode(GetInodeFromPath(targetDir))); |
+ if (nullptr == inode_directory|| |
+ inode_directory->file_type()!=Inode::FILE_TYPE_DIR) |
+ return File_System_Error_FAILED; |
+ |
+ InodeFile* inode_file = new InodeFile(GetNextInodeNumber()); |
+ if (nullptr == inode_file) |
+ return File_System_Error_FAILED; |
+ |
+ PutInode(inode_file->inode_number(), inode_file); |
+ inode_directory->AddEntry(filename, inode_file->inode_number()); |
+ return File_System_Error_NONE; |
+} |
+ |
+int Filesystem::Truncate(const std::string &filePath, size_t length) { |
+ InodeFile *inode_file = |
+ static_cast<InodeFile*>( GetInode( GetInodeFromPath(filePath) ) ); |
+ if (inode_file==nullptr || |
+ inode_file->file_type() != Inode::FILE_TYPE_FILE) |
+ return File_System_Error_NOT_FOUND; |
+ |
+ inode_file->Truncate(length); |
+ return File_System_Error_NONE; |
+} |
+ |
+int Filesystem::WriteToFile( |
+ const std::string &filePath, |
+ size_t offset, |
+ size_t dataSize, |
+ const char *data) { |
+ InodeFile *inode_file = |
+ static_cast<InodeFile*>( GetInode( GetInodeFromPath(filePath) ) ); |
+ if(inode_file==nullptr|| |
+ inode_file->file_type()!=Inode::FILE_TYPE_FILE) |
+ return File_System_Error_NOT_FOUND; |
+ |
+ if( inode_file->Write(data, offset, dataSize) ) |
+ return File_System_Error_NONE; |
+ return File_System_Error_FAILED; |
+} |
+ |
+int Filesystem::ReadFromFile(const std::string &filePath, |
+ size_t offset, |
+ size_t* inOutLength, |
+ const char** outData) { |
+ InodeFile *inode_file = |
+ static_cast<InodeFile*>( GetInode( GetInodeFromPath(filePath) ) ); |
+ if (inode_file==nullptr|| |
+ inode_file->file_type()!=Inode::FILE_TYPE_FILE) |
+ return File_System_Error_NOT_FOUND; |
+ |
+ if (inode_file->Read(offset, inOutLength, outData )) |
+ return File_System_Error_NONE; |
+ return File_System_Error_FAILED; |
+} |
+ |
+void Filesystem::AddLink(unsigned long long inode) { |
+ ListOfInodesIterator it(inodesList_.find(inode)); |
+ if (it != inodesList_.end()) { |
+ it->second.first++; |
+ // If directory add a reference for each entry it contains |
+ if (it->second.second->file_type() == Inode::FILE_TYPE_DIR) { |
+ InodeDirectory* inode_directory = |
+ static_cast<InodeDirectory*>(it->second.second); |
+ if (nullptr == inode_directory) |
+ return; |
+ std::vector<InodeDirectory::EntryPair> entries; |
+ inode_directory->GetAllInodes(entries); |
+ for (std::vector<InodeDirectory::EntryPair>::iterator |
+ entry = entries.begin(); |
+ entry != entries.end(); ++entry) { |
+ AddLink(entry->second); |
+ } |
+ } |
+ } |
+} |
+void Filesystem::RemoveLink(unsigned long long inode_number) { |
+ ListOfInodesIterator it(inodesList_.find(inode_number)); |
+ if (it != inodesList_.end()) { |
+ Inode* inode = it->second.second; |
+ if (nullptr == inode) |
+ return; |
+ if (inode->file_type() == Inode::FILE_TYPE_DIR) { |
+ InodeDirectory* inode_directory = |
+ static_cast<InodeDirectory*>(inode); |
+ if (nullptr == inode_directory) |
+ return; |
+ // Get all inodes and remove their reference |
+ std::vector<InodeDirectory::EntryPair> entries; |
+ inode_directory->GetAllInodes(entries); |
+ for (std::vector<InodeDirectory::EntryPair>::iterator |
+ entry = entries.begin(); |
+ entry != entries.end(); entry++) { |
+ RemoveLink(entry->second); |
+ } |
+ } |
+ // If current reference is down to 0 |
+ // then remove it |
+ if (--it->second.first==0) { |
+ delete inode; |
+ inodesList_.erase(it); |
+ } |
+ } |
+} |
+ |
+Inode* Filesystem::GetInode(unsigned long long inode) { |
+ ListOfInodesIterator it = inodesList_.find(inode); |
+ if (it == inodesList_.end()) |
+ return nullptr; |
+ return it->second.second; |
+} |
+ |
+void Filesystem::PutInode(unsigned long long inode_number, Inode* inode) { |
+ inodesList_.insert(std::pair<unsigned long long,InodePair >( |
+ inode_number, InodePair( 0, inode) ) ); |
+} |
+void Filesystem::RemoveInode(unsigned long long inode) { |
+ ListOfInodesIterator it = inodesList_.find(inode); |
+ inodesList_.erase(it); |
+} |
+ |
+unsigned long long Filesystem::GetInodeFromPath(const std::string& path){ |
+ if (path.size() == 0 || |
+ path[0] != '/') |
+ return File_System_Error_NOT_FOUND; |
+ |
+ std::deque<std::string> tree_entries; |
+ std::string::size_type position = 0; |
+ std::string rest = path.substr(1); |
+ std::string temp; |
+ |
+ while (1) { |
+ position = rest.find_first_of("/"); |
+ temp = rest.substr(0, position); |
+ if (temp.size()!=0) |
+ tree_entries.push_back(temp); |
+ if (std::string::npos == position) |
+ break; |
+ rest = rest.substr(position + 1); |
+ } |
+ |
+ std::string current_dir = ""; |
+ unsigned long long workingInode = root_inode; |
+ InodeDirectory* current_inode = |
+ static_cast<InodeDirectory*>(GetInode(workingInode)); |
+ if (current_inode==nullptr|| |
+ current_inode->file_type()!=Inode::FILE_TYPE_DIR) |
+ return Inode::NO_INODE; |
+ while ( tree_entries.size() > 0) { |
+ current_dir = tree_entries.front(); |
+ tree_entries.pop_front(); |
+ |
+ workingInode = current_inode->GetInodeFromName(current_dir); |
+ if (workingInode == Inode::NO_INODE) |
+ return File_System_Error_NOT_FOUND; |
+ if (tree_entries.size() > 0) { |
+ current_inode = |
+ static_cast<InodeDirectory*>(GetInode(workingInode)); |
+ if (current_inode==nullptr|| |
+ current_inode->file_type()!=Inode::FILE_TYPE_DIR) |
+ return Inode::NO_INODE; |
+ } |
+ } |
+ return workingInode; |
+} |
+ |
+unsigned long long Filesystem::GetNextInodeNumber(){ |
+ if (++currentInode_ == Inode::NO_INODE) |
+ return ++currentInode_; |
+ return currentInode_; |
+} |
+ |
+ |
+}// namespace filesystem |