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