"Fossies" - the Fresh Open Source Software Archive

Member "encfs-1.9.5/encfs/Context.cpp" (27 Apr 2018, 6289 Bytes) of package /linux/misc/encfs-1.9.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Context.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.9.4_vs_1.9.5.

    1 /*****************************************************************************
    2  * Author:   Valient Gough <vgough@pobox.com>
    3  *
    4  *****************************************************************************
    5  * Copyright (c) 2007, Valient Gough
    6  *
    7  * This program is free software: you can redistribute it and/or modify it
    8  * under the terms of the GNU Lesser General Public License as published by the
    9  * Free Software Foundation, either version 3 of the License, or (at your
   10  * option) any later version.
   11  *
   12  * This program is distributed in the hope that it will be useful, but WITHOUT
   13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   15  * for more details.
   16  *
   17  * You should have received a copy of the GNU Lesser General Public License
   18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   19  */
   20 
   21 #include "easylogging++.h"
   22 #include <utility>
   23 
   24 #include "Context.h"
   25 #include "DirNode.h"
   26 #include "Error.h"
   27 #include "Mutex.h"
   28 
   29 namespace encfs {
   30 
   31 EncFS_Context::EncFS_Context() {
   32   pthread_cond_init(&wakeupCond, nullptr);
   33   pthread_mutex_init(&wakeupMutex, nullptr);
   34   pthread_mutex_init(&contextMutex, nullptr);
   35 
   36   usageCount = 0;
   37   idleCount = -1;
   38   isUnmounting = false;
   39   currentFuseFh = 1;
   40 }
   41 
   42 EncFS_Context::~EncFS_Context() {
   43   pthread_mutex_destroy(&contextMutex);
   44   pthread_mutex_destroy(&wakeupMutex);
   45   pthread_cond_destroy(&wakeupCond);
   46 
   47   // release all entries from map
   48   openFiles.clear();
   49 }
   50 
   51 std::shared_ptr<DirNode> EncFS_Context::getRoot(int *errCode) {
   52   return getRoot(errCode, false);
   53 }
   54 
   55 std::shared_ptr<DirNode> EncFS_Context::getRoot(int *errCode, bool skipUsageCount) {
   56   std::shared_ptr<DirNode> ret = nullptr;
   57   do {
   58     {
   59       Lock lock(contextMutex);
   60       if (isUnmounting) {
   61         *errCode = -EBUSY;
   62         break;          
   63       }
   64       ret = root;
   65       // On some system, stat of "/" is allowed even if the calling user is
   66       // not allowed to list / to go deeper. Do not then count this call.
   67       if (!skipUsageCount) {
   68         ++usageCount;
   69       }
   70     }
   71 
   72     if (!ret) {
   73       int res = remountFS(this);
   74       if (res != 0) {
   75         *errCode = res;
   76         break;
   77       }
   78     }
   79   } while (!ret);
   80 
   81   return ret;
   82 }
   83 
   84 void EncFS_Context::setRoot(const std::shared_ptr<DirNode> &r) {
   85   Lock lock(contextMutex);
   86 
   87   root = r;
   88   if (r) {
   89     rootCipherDir = r->rootDirectory();
   90   }
   91 }
   92 
   93 // This function is called periodically by the idle monitoring thread.
   94 // It checks for inactivity and unmount the FS after enough inactive cycles have passed.
   95 // Returns true if FS has really been unmounted, false otherwise.
   96 bool EncFS_Context::usageAndUnmount(int timeoutCycles) {
   97   Lock lock(contextMutex);
   98 
   99   if (root != nullptr) {
  100 
  101     if (usageCount == 0) {
  102       ++idleCount;
  103     }
  104     else {
  105       idleCount = 0;
  106     }
  107     VLOG(1) << "idle cycle count: " << idleCount << ", timeout at "
  108             << timeoutCycles;
  109 
  110     usageCount = 0;
  111 
  112     if (idleCount < timeoutCycles) {
  113       return false;
  114     }
  115 
  116     if (!openFiles.empty()) {
  117       if (idleCount % timeoutCycles == 0) {
  118         RLOG(WARNING) << "Filesystem inactive, but " << openFiles.size()
  119                       << " files opened: " << this->opts->unmountPoint;
  120       }
  121       return false;
  122     }
  123     if (!this->opts->mountOnDemand) {
  124       isUnmounting = true;
  125     }
  126     lock.~Lock();
  127     return unmountFS(this);
  128 
  129   }
  130   return false;
  131 }
  132 
  133 std::shared_ptr<FileNode> EncFS_Context::lookupNode(const char *path) {
  134   Lock lock(contextMutex);
  135 
  136   auto it = openFiles.find(std::string(path));
  137   if (it != openFiles.end()) {
  138     // every entry in the list is fine... so just use the
  139     // first
  140     return it->second.front();
  141   }
  142   return std::shared_ptr<FileNode>();
  143 }
  144 
  145 void EncFS_Context::renameNode(const char *from, const char *to) {
  146   Lock lock(contextMutex);
  147 
  148   auto it = openFiles.find(std::string(from));
  149   if (it != openFiles.end()) {
  150     auto val = it->second;
  151     openFiles.erase(it);
  152     openFiles[std::string(to)] = val;
  153   }
  154 }
  155 
  156 // putNode stores "node" under key "path" in the "openFiles" map. It
  157 // increments the reference count if the key already exists.
  158 void EncFS_Context::putNode(const char *path,
  159                             const std::shared_ptr<FileNode> &node) {
  160   Lock lock(contextMutex);
  161   auto &list = openFiles[std::string(path)];
  162   // The length of "list" serves as the reference count.
  163   list.push_front(node);
  164   fuseFhMap[node->fuseFh] = node;
  165 }
  166 
  167 // eraseNode is called by encfs_release in response to the RELEASE
  168 // FUSE-command we get from the kernel.
  169 void EncFS_Context::eraseNode(const char *path,
  170                               const std::shared_ptr<FileNode> &fnode) {
  171   Lock lock(contextMutex);
  172 
  173   auto it = openFiles.find(std::string(path));
  174 #ifdef __CYGWIN__
  175   // When renaming a file, Windows first opens it, renames it and then closes it
  176   // Filenode may have then been renamed too
  177   if (it == openFiles.end()) {
  178     RLOG(WARNING) << "Filenode to erase not found, file has certainly be renamed: "
  179                   << path;
  180     return;
  181   }
  182 #endif
  183   rAssert(it != openFiles.end());
  184   auto &list = it->second;
  185 
  186   // Find "fnode" in the list of FileNodes registered under this path.
  187   auto findIter = std::find(list.begin(), list.end(), fnode);
  188   rAssert(findIter != list.end());
  189   list.erase(findIter);
  190 
  191   // If no reference to "fnode" remains, drop the entry from fuseFhMap
  192   // and overwrite the canary.
  193   findIter = std::find(list.begin(), list.end(), fnode);
  194   if (findIter == list.end()) {
  195     fuseFhMap.erase(fnode->fuseFh);
  196     fnode->canary = CANARY_RELEASED;
  197   }
  198 
  199   // If no FileNode is registered at this path anymore, drop the entry
  200   // from openFiles.
  201   if (list.empty()) {
  202     openFiles.erase(it);
  203   }
  204 }
  205 
  206 // nextFuseFh returns the next unused uint64 to serve as the FUSE file
  207 // handle for the kernel.
  208 uint64_t EncFS_Context::nextFuseFh() {
  209   // This is thread-safe because currentFuseFh is declared as std::atomic
  210   return currentFuseFh++;
  211 }
  212 
  213 // lookupFuseFh finds "n" in "fuseFhMap" and returns the FileNode.
  214 std::shared_ptr<FileNode> EncFS_Context::lookupFuseFh(uint64_t n) {
  215   Lock lock(contextMutex);
  216   auto it = fuseFhMap.find(n);
  217   if (it == fuseFhMap.end()) {
  218     return nullptr;
  219   }
  220   return it->second;
  221 }
  222 
  223 }  // namespace encfs