/***************************************************************************** * Author: Valient Gough * ***************************************************************************** * Copyright (c) 2007, Valient Gough * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include "fs/Context.h" #include "base/Error.h" #include "fs/FileNode.h" #include "fs/FileUtils.h" #include "fs/DirNode.h" namespace encfs { EncFS_Context::EncFS_Context() : publicFilesystem(false), running(false) { #ifdef CMAKE_USE_PTHREADS_INIT pthread_cond_init(&wakeupCond, 0); #endif usageCount = 0; } EncFS_Context::~EncFS_Context() { #ifdef CMAKE_USE_PTHREADS_INIT pthread_cond_destroy(&wakeupCond); #endif // release all entries from map openFiles.clear(); } shared_ptr EncFS_Context::getRoot(int *errCode) { shared_ptr ret; do { { Lock lock(contextMutex); ret = root; ++usageCount; } if (!ret) { int res = remountFS(this); if (res != 0) { *errCode = res; break; } } } while (!ret); return ret; } void EncFS_Context::setRoot(const shared_ptr &r) { Lock lock(contextMutex); root = r; if (r) rootCipherDir = r->rootDirectory(); } bool EncFS_Context::isMounted() const { return root; } int EncFS_Context::getAndResetUsageCounter() { Lock lock(contextMutex); int count = usageCount; usageCount = 0; return count; } int EncFS_Context::openFileCount() const { Lock lock(contextMutex); return openFiles.size(); } shared_ptr EncFS_Context::lookupNode(const char *path) { Lock lock(contextMutex); FileMap::iterator it = openFiles.find(std::string(path)); if (it != openFiles.end()) { // all the items in the set point to the same node.. so just use the // first return (*it->second.begin())->node; } else { return shared_ptr(); } } void EncFS_Context::renameNode(const char *from, const char *to) { Lock lock(contextMutex); FileMap::iterator it = openFiles.find(std::string(from)); if (it != openFiles.end()) { std::set val = it->second; openFiles.erase(it); openFiles[std::string(to)] = val; } } shared_ptr EncFS_Context::getNode(void *pl) { Placeholder *ph = static_cast(pl); return ph->node; } void *EncFS_Context::putNode(const char *path, const shared_ptr &node) { Lock lock(contextMutex); Placeholder *pl = new Placeholder(node); openFiles[std::string(path)].insert(pl); return (void *)pl; } void EncFS_Context::eraseNode(const char *path, void *pl) { Lock lock(contextMutex); Placeholder *ph = static_cast(pl); FileMap::iterator it = openFiles.find(std::string(path)); rAssert(it != openFiles.end()); int rmCount = it->second.erase(ph); rAssert(rmCount == 1); // if no more references to this file, remove the record all together if (it->second.empty()) { // attempts to make use of shallow copy to clear memory used to hold // unencrypted filenames.. not sure this does any good.. std::string storedName = it->first; openFiles.erase(it); storedName.assign(storedName.length(), '\0'); } delete ph; } } // namespace encfs