diff --git a/encfs/Context.cpp b/encfs/Context.cpp index 7ebebaa..61ab7ed 100644 --- a/encfs/Context.cpp +++ b/encfs/Context.cpp @@ -171,6 +171,15 @@ void EncFS_Context::eraseNode(const char *path, Lock lock(contextMutex); auto it = openFiles.find(std::string(path)); +#ifdef __CYGWIN__ + // When renaming a file, Windows first opens it, renames it and then closes it + // Filenode may have then been renamed too + if (it == openFiles.end()) { + RLOG(WARNING) << "Filenode to erase not found, file has certainly be renamed: " + << path; + return; + } +#endif rAssert(it != openFiles.end()); auto &list = it->second; diff --git a/encfs/DirNode.cpp b/encfs/DirNode.cpp index 649681e..ff71f18 100644 --- a/encfs/DirNode.cpp +++ b/encfs/DirNode.cpp @@ -599,11 +599,26 @@ int DirNode::rename(const char *fromPlaintext, const char *toPlaintext) { if (renameOp) { renameOp->undo(); } - } else if (preserve_mtime) { - struct utimbuf ut; - ut.actime = st.st_atime; - ut.modtime = st.st_mtime; - ::utime(toCName.c_str(), &ut); + } + else { +#ifdef __CYGWIN__ + // When renaming a file, Windows first opens it, renames it and then closes it + // We then must decrease the target openFiles count + // We could recreate the source so that close will not (silently) fails, + // however it will update modification time of the file, so break what we do below. + // Let's simply warn in eraseNode(). + if (!isDirectory(toCName.c_str())) { + std::shared_ptr toNode = findOrCreate(toPlaintext); + ctx->eraseNode(toPlaintext, toNode); + //ctx->putNode(fromPlaintext, toNode); + } +#endif + if (preserve_mtime) { + struct utimbuf ut; + ut.actime = st.st_atime; + ut.modtime = st.st_mtime; + ::utime(toCName.c_str(), &ut); + } } } catch (encfs::Error &err) { // exception from renameNode, just show the error and continue.. diff --git a/encfs/encfs.cpp b/encfs/encfs.cpp index 38eec09..a7c9c34 100644 --- a/encfs/encfs.cpp +++ b/encfs/encfs.cpp @@ -167,6 +167,13 @@ static int withFileNode(const char *opName, const char *path, if (fi != nullptr && fi->fh != 0) { auto node = ctx->lookupFuseFh(fi->fh); if (node == nullptr) { +#ifdef __CYGWIN__ + if (strcmp(opName, "flush") == 0) { + RLOG(WARNING) << "Filenode to flush not found, file has certainly be renamed: " + << path; + return 0; + } +#endif auto msg = "fh=" + std::to_string(fi->fh) + " not found in fuseFhMap"; throw Error(msg.c_str()); }