main.cpp (encfs-1.9.4) | : | main.cpp (encfs-1.9.5) | ||
---|---|---|---|---|
skipping to change at line 31 | skipping to change at line 31 | |||
#include <cstdlib> | #include <cstdlib> | |||
#include <cstring> | #include <cstring> | |||
#include <ctime> | #include <ctime> | |||
#include <exception> | #include <exception> | |||
#include <getopt.h> | #include <getopt.h> | |||
#include <iostream> | #include <iostream> | |||
#include <memory> | #include <memory> | |||
#include <pthread.h> | #include <pthread.h> | |||
#include <sstream> | #include <sstream> | |||
#include <string> | #include <string> | |||
#ifdef __CYGWIN__ | ||||
#include <sys/cygwin.h> | ||||
#endif | ||||
#include <sys/stat.h> | #include <sys/stat.h> | |||
#include <sys/time.h> | #include <sys/time.h> | |||
#include <unistd.h> | #include <unistd.h> | |||
#include "Context.h" | #include "Context.h" | |||
#include "Error.h" | #include "Error.h" | |||
#include "FileUtils.h" | #include "FileUtils.h" | |||
#include "MemoryPool.h" | #include "MemoryPool.h" | |||
#include "autosprintf.h" | #include "autosprintf.h" | |||
#include "config.h" | #include "config.h" | |||
#include "encfs.h" | #include "encfs.h" | |||
#include "fuse.h" | #include "fuse.h" | |||
#include "i18n.h" | #include "i18n.h" | |||
#include "openssl.h" | #include "openssl.h" | |||
/* Arbitrary identifiers for long options that do | /* Arbitrary identifiers for long options that do | |||
* not have a short version */ | * not have a short version */ | |||
#define LONG_OPT_ANNOTATE 513 | #define LONG_OPT_ANNOTATE 513 | |||
#define LONG_OPT_NOCACHE 514 | #define LONG_OPT_NOCACHE 514 | |||
#define LONG_OPT_REQUIRE_MAC 515 | #define LONG_OPT_NODATACACHE 515 | |||
#define LONG_OPT_NOATTRCACHE 516 | ||||
#define LONG_OPT_REQUIRE_MAC 517 | ||||
#define LONG_OPT_INSECURE 518 | ||||
using namespace std; | using namespace std; | |||
using namespace encfs; | using namespace encfs; | |||
using gnu::autosprintf; | using gnu::autosprintf; | |||
namespace encfs { | namespace encfs { | |||
class DirNode; | class DirNode; | |||
// Maximum number of arguments that we're going to pass on to fuse. Doesn't | // Maximum number of arguments that we're going to pass on to fuse. Doesn't | |||
skipping to change at line 165 | skipping to change at line 171 | |||
" --forcedecode\t\t" | " --forcedecode\t\t" | |||
"decode data even if an error is detected\n" | "decode data even if an error is detected\n" | |||
"\t\t\t(for filesystems using MAC block headers)\n") | "\t\t\t(for filesystems using MAC block headers)\n") | |||
<< _(" --public\t\t" | << _(" --public\t\t" | |||
"act as a typical multi-user filesystem\n" | "act as a typical multi-user filesystem\n" | |||
"\t\t\t(encfs must be run as root)\n") | "\t\t\t(encfs must be run as root)\n") | |||
<< _(" --reverse\t\t" | << _(" --reverse\t\t" | |||
"reverse encryption\n") | "reverse encryption\n") | |||
<< _(" --reversewrite\t\t" | << _(" --reversewrite\t\t" | |||
"reverse encryption with writes enabled\n") | "reverse encryption with writes enabled\n") | |||
<< _(" -c, --config=path\t\t" | ||||
"specifies config file (overrides ENV variable)\n") | ||||
<< _(" -u, --unmount\t\t" | ||||
"unmounts specified mountPoint\n") | ||||
// xgroup(usage) | // xgroup(usage) | |||
<< _(" --extpass=program\tUse external program for password prompt\n" | << _(" --extpass=program\tUse external program for password prompt\n" | |||
"\n" | "\n" | |||
"Example, to mount at ~/crypt with raw storage in ~/.crypt :\n" | "Example, to mount at ~/crypt with raw storage in ~/.crypt :\n" | |||
" encfs ~/.crypt ~/crypt\n" | " encfs ~/.crypt ~/crypt\n" | |||
"\n") | "\n") | |||
// xgroup(usage) | // xgroup(usage) | |||
<< _("For more information, see the man page encfs(1)") << "\n" | << _("For more information, see the man page encfs(1)") << "\n" | |||
<< endl; | << endl; | |||
skipping to change at line 220 | skipping to change at line 230 | |||
out->fuseArgc = 0; | out->fuseArgc = 0; | |||
out->syslogTag = "encfs"; | out->syslogTag = "encfs"; | |||
out->opts->idleTracking = false; | out->opts->idleTracking = false; | |||
out->opts->checkKey = true; | out->opts->checkKey = true; | |||
out->opts->forceDecode = false; | out->opts->forceDecode = false; | |||
out->opts->ownerCreate = false; | out->opts->ownerCreate = false; | |||
out->opts->useStdin = false; | out->opts->useStdin = false; | |||
out->opts->annotate = false; | out->opts->annotate = false; | |||
out->opts->reverseEncryption = false; | out->opts->reverseEncryption = false; | |||
out->opts->requireMac = false; | out->opts->requireMac = false; | |||
out->opts->insecure = false; | ||||
out->opts->unmount = false; | ||||
bool useDefaultFlags = true; | bool useDefaultFlags = true; | |||
// pass executable name through | // pass executable name through | |||
out->fuseArgv[0] = lastPathElement(argv[0]); | out->fuseArgv[0] = lastPathElement(argv[0]); | |||
++out->fuseArgc; | ++out->fuseArgc; | |||
// leave a space for mount point, as FUSE expects the mount point before | // leave a space for mount point, as FUSE expects the mount point before | |||
// any flags | // any flags | |||
out->fuseArgv[1] = nullptr; | out->fuseArgv[1] = nullptr; | |||
skipping to change at line 250 | skipping to change at line 262 | |||
{"no-default-flags", 0, nullptr, 'N'}, // don't use default fuse flags | {"no-default-flags", 0, nullptr, 'N'}, // don't use default fuse flags | |||
{"ondemand", 0, nullptr, 'm'}, // mount on-demand | {"ondemand", 0, nullptr, 'm'}, // mount on-demand | |||
{"delaymount", 0, nullptr, 'M'}, // delay initial mount until use | {"delaymount", 0, nullptr, 'M'}, // delay initial mount until use | |||
{"public", 0, nullptr, 'P'}, // public mode | {"public", 0, nullptr, 'P'}, // public mode | |||
{"extpass", 1, nullptr, 'p'}, // external password program | {"extpass", 1, nullptr, 'p'}, // external password program | |||
// {"single-thread", 0, 0, 's'}, // single-threaded mode | // {"single-thread", 0, 0, 's'}, // single-threaded mode | |||
{"stdinpass", 0, nullptr, 'S'}, // read password from stdin | {"stdinpass", 0, nullptr, 'S'}, // read password from stdin | |||
{"syslogtag", 1, nullptr, 't'}, // syslog tag | {"syslogtag", 1, nullptr, 't'}, // syslog tag | |||
{"annotate", 0, nullptr, | {"annotate", 0, nullptr, | |||
LONG_OPT_ANNOTATE}, // Print annotation lines to stderr | LONG_OPT_ANNOTATE}, // Print annotation lines to stderr | |||
{"nocache", 0, nullptr, LONG_OPT_NOCACHE}, // disable caching | {"nocache", 0, nullptr, LONG_OPT_NOCACHE}, // disable all caching | |||
{"nodatacache", 0, nullptr, LONG_OPT_NODATACACHE}, // disable data caching | ||||
{"noattrcache", 0, nullptr, LONG_OPT_NOATTRCACHE}, // disable attr caching | ||||
{"verbose", 0, nullptr, 'v'}, // verbose mode | {"verbose", 0, nullptr, 'v'}, // verbose mode | |||
{"version", 0, nullptr, 'V'}, // version | {"version", 0, nullptr, 'V'}, // version | |||
{"reverse", 0, nullptr, 'r'}, // reverse encryption | {"reverse", 0, nullptr, 'r'}, // reverse encryption | |||
{"reversewrite", 0, nullptr, 'R'}, // reverse encryption with wri te enabled | {"reversewrite", 0, nullptr, 'R'}, // reverse encryption with wri te enabled | |||
{"standard", 0, nullptr, '1'}, // standard configuration | {"standard", 0, nullptr, '1'}, // standard configuration | |||
{"paranoia", 0, nullptr, '2'}, // standard configuration | {"paranoia", 0, nullptr, '2'}, // standard configuration | |||
{"require-macs", 0, nullptr, LONG_OPT_REQUIRE_MAC}, // require MACs | {"require-macs", 0, nullptr, LONG_OPT_REQUIRE_MAC}, // require MACs | |||
{"insecure", 0, nullptr, LONG_OPT_INSECURE},// allows to use null data enc | ||||
ryption | ||||
{"config", 1, nullptr, 'c'}, // command-line-supplied confi | ||||
g location | ||||
{"unmount", 1, nullptr, 'u'}, // unmount | ||||
{nullptr, 0, nullptr, 0}}; | {nullptr, 0, nullptr, 0}}; | |||
while (true) { | while (true) { | |||
int option_index = 0; | int option_index = 0; | |||
// 's' : single-threaded mode | // 's' : single-threaded mode | |||
// 'f' : foreground mode | // 'f' : foreground mode | |||
// 'v' : verbose mode (same as --verbose) | // 'v' : verbose mode (same as --verbose) | |||
// 'd' : fuse debug mode (same as --fusedebug) | // 'd' : fuse debug mode (same as --fusedebug) | |||
// 'i' : idle-timeout, takes argument | // 'i' : idle-timeout, takes argument | |||
// 'm' : mount-on-demand | // 'm' : mount-on-demand | |||
// 'S' : password from stdin | // 'S' : password from stdin | |||
// 'o' : arguments meant for fuse | // 'o' : arguments meant for fuse | |||
// 't' : syslog tag | // 't' : syslog tag | |||
// 'c' : configuration file | ||||
// 'u' : unmount | ||||
int res = | int res = | |||
getopt_long(argc, argv, "HsSfvdmi:o:t:", long_options, &option_index); | getopt_long(argc, argv, "HsSfvdmi:o:t:c:u", long_options, &option_index) ; | |||
if (res == -1) { | if (res == -1) { | |||
break; | break; | |||
} | } | |||
switch (res) { | switch (res) { | |||
case '1': | case '1': | |||
out->opts->configMode = Config_Standard; | out->opts->configMode = Config_Standard; | |||
break; | break; | |||
case '2': | case '2': | |||
skipping to change at line 301 | skipping to change at line 320 | |||
break; | break; | |||
case 't': | case 't': | |||
out->syslogTag = optarg; | out->syslogTag = optarg; | |||
break; | break; | |||
case LONG_OPT_ANNOTATE: | case LONG_OPT_ANNOTATE: | |||
out->opts->annotate = true; | out->opts->annotate = true; | |||
break; | break; | |||
case LONG_OPT_REQUIRE_MAC: | case LONG_OPT_REQUIRE_MAC: | |||
out->opts->requireMac = true; | out->opts->requireMac = true; | |||
break; | break; | |||
case LONG_OPT_INSECURE: | ||||
out->opts->insecure = true; | ||||
break; | ||||
case 'c': | ||||
/* Take config file path from command | ||||
* line instead of ENV variable */ | ||||
out->opts->config.assign(optarg); | ||||
break; | ||||
case 'u': | ||||
//we want to log to console, not to syslog, in case of error | ||||
out->isDaemon = false; | ||||
out->opts->unmount = true; | ||||
break; | ||||
case 'f': | case 'f': | |||
out->isDaemon = false; | out->isDaemon = false; | |||
// this option was added in fuse 2.x | // this option was added in fuse 2.x | |||
PUSHARG("-f"); | PUSHARG("-f"); | |||
break; | break; | |||
case 'v': | case 'v': | |||
out->isVerbose = true; | out->isVerbose = true; | |||
break; | break; | |||
case 'd': | case 'd': | |||
PUSHARG("-d"); | PUSHARG("-d"); | |||
skipping to change at line 360 | skipping to change at line 392 | |||
* Causes reverse grow tests to fail because short reads | * Causes reverse grow tests to fail because short reads | |||
* are returned */ | * are returned */ | |||
out->opts->noCache = true; | out->opts->noCache = true; | |||
/* Disable kernel stat() cache | /* Disable kernel stat() cache | |||
* Causes reverse grow tests to fail because stale stat() data | * Causes reverse grow tests to fail because stale stat() data | |||
* is returned */ | * is returned */ | |||
PUSHARG("-oattr_timeout=0"); | PUSHARG("-oattr_timeout=0"); | |||
/* Disable kernel dentry cache | /* Disable kernel dentry cache | |||
* Fallout unknown, disabling for safety */ | * Fallout unknown, disabling for safety */ | |||
PUSHARG("-oentry_timeout=0"); | PUSHARG("-oentry_timeout=0"); | |||
#ifdef __CYGWIN__ | ||||
// Should be enforced due to attr_timeout=0, but does not seem to work c | ||||
orrectly | ||||
// https://github.com/billziss-gh/winfsp/issues/155 | ||||
PUSHARG("-oFileInfoTimeout=0"); | ||||
#endif | ||||
break; | ||||
case LONG_OPT_NODATACACHE: | ||||
out->opts->noCache = true; | ||||
break; | ||||
case LONG_OPT_NOATTRCACHE: | ||||
PUSHARG("-oattr_timeout=0"); | ||||
PUSHARG("-oentry_timeout=0"); | ||||
#ifdef __CYGWIN__ | ||||
PUSHARG("-oFileInfoTimeout=0"); | ||||
#endif | ||||
break; | break; | |||
case 'm': | case 'm': | |||
out->opts->mountOnDemand = true; | out->opts->mountOnDemand = true; | |||
break; | break; | |||
case 'M': | case 'M': | |||
out->opts->delayMount = true; | out->opts->delayMount = true; | |||
break; | break; | |||
case 'N': | case 'N': | |||
useDefaultFlags = false; | useDefaultFlags = false; | |||
break; | break; | |||
case 'o': | case 'o': | |||
PUSHARG("-o"); | PUSHARG("-o"); | |||
PUSHARG(optarg); | PUSHARG(optarg); | |||
break; | break; | |||
case 'p': | case 'p': | |||
out->opts->passwordProgram.assign(optarg); | out->opts->passwordProgram.assign(optarg); | |||
break; | break; | |||
case 'P': | case 'P': | |||
if (geteuid() != 0) { | if (geteuid() != 0) { | |||
RLOG(WARNING) << "option '--public' ignored for non-root user"; | cerr << "option '--public' ignored for non-root user"; | |||
} else { | } else { | |||
out->opts->ownerCreate = true; | out->opts->ownerCreate = true; | |||
// add 'allow_other' option | // add 'allow_other' option | |||
// add 'default_permissions' option (default) | // add 'default_permissions' option (default) | |||
PUSHARG("-o"); | PUSHARG("-o"); | |||
PUSHARG("allow_other"); | PUSHARG("allow_other"); | |||
} | } | |||
break; | break; | |||
case 'V': | case 'V': | |||
// xgroup(usage) | // xgroup(usage) | |||
skipping to change at line 410 | skipping to change at line 457 | |||
FuseUsage(); | FuseUsage(); | |||
exit(EXIT_SUCCESS); | exit(EXIT_SUCCESS); | |||
break; | break; | |||
case '?': | case '?': | |||
// invalid options.. | // invalid options.. | |||
break; | break; | |||
case ':': | case ':': | |||
// missing parameter for option.. | // missing parameter for option.. | |||
break; | break; | |||
default: | default: | |||
RLOG(WARNING) << "getopt error: " << res; | cerr << "getopt error: " << res; | |||
break; | break; | |||
} | } | |||
} | } | |||
if (!out->isThreaded) { | if (!out->isThreaded) { | |||
PUSHARG("-s"); | PUSHARG("-s"); | |||
} | } | |||
// for --unmount, we should have exactly 1 argument - the mount point | ||||
if (out->opts->unmount) { | ||||
if (optind + 1 == argc) { | ||||
// unmountPoint is kept as given by the user : in Cygwin, it is used | ||||
// by pkill to terminate the correct process. We can't then use a | ||||
// Linux-converted Windows-style mountPoint to unmount... | ||||
out->opts->unmountPoint = string(argv[optind++]); | ||||
return true; | ||||
} | ||||
// no mount point specified | ||||
cerr << _("Expecting one argument, aborting.") << endl; | ||||
return false; | ||||
} | ||||
// we should have at least 2 arguments left over - the source directory and | // we should have at least 2 arguments left over - the source directory and | |||
// the mount point. | // the mount point. | |||
if (optind + 2 <= argc) { | if (optind + 2 <= argc) { | |||
// both rootDir and mountPoint are assumed to be slash terminated in the | // both rootDir and mountPoint are assumed to be slash terminated in the | |||
// rest of the code. | // rest of the code. | |||
out->opts->rootDir = slashTerminate(argv[optind++]); | out->opts->rootDir = slashTerminate(argv[optind++]); | |||
out->opts->mountPoint = slashTerminate(argv[optind++]); | out->opts->unmountPoint = string(argv[optind++]); | |||
out->opts->mountPoint = slashTerminate(out->opts->unmountPoint); | ||||
} else { | } else { | |||
// no mount point specified | // no mount point specified | |||
cerr << _("Missing one or more arguments, aborting."); | cerr << _("Missing one or more arguments, aborting.") << endl; | |||
return false; | return false; | |||
} | } | |||
// If there are still extra unparsed arguments, pass them onto FUSE.. | // If there are still extra unparsed arguments, pass them onto FUSE.. | |||
if (optind < argc) { | if (optind < argc) { | |||
rAssert(out->fuseArgc < MaxFuseArgs); | rAssert(out->fuseArgc < MaxFuseArgs); | |||
while (optind < argc) { | while (optind < argc) { | |||
rAssert(out->fuseArgc < MaxFuseArgs); | rAssert(out->fuseArgc < MaxFuseArgs); | |||
out->fuseArgv[out->fuseArgc++] = argv[optind]; | out->fuseArgv[out->fuseArgc++] = argv[optind]; | |||
skipping to change at line 467 | skipping to change at line 529 | |||
PUSHARG("default_permissions"); | PUSHARG("default_permissions"); | |||
#if defined(__APPLE__) | #if defined(__APPLE__) | |||
// With OSXFuse, the 'local' flag selects a local filesystem mount icon in | // With OSXFuse, the 'local' flag selects a local filesystem mount icon in | |||
// Finder. | // Finder. | |||
PUSHARG("-o"); | PUSHARG("-o"); | |||
PUSHARG("local"); | PUSHARG("local"); | |||
#endif | #endif | |||
} | } | |||
#ifdef __CYGWIN__ | ||||
// Windows users may use Windows paths | ||||
// https://cygwin.com/cygwin-api/cygwin-functions.html | ||||
out->opts->mountPoint = string((char *)cygwin_create_path(CCP_WIN_A_TO_POSIX | | ||||
CCP_RELATIVE, out->opts->mountPoint.c_str())); | ||||
out->opts->rootDir = string((char *)cygwin_create_path(CCP_WIN_A_TO_POSIX | CC | ||||
P_RELATIVE, out->opts->rootDir.c_str())); | ||||
#endif | ||||
// sanity check | // sanity check | |||
if (out->isDaemon && (!isAbsolutePath(out->opts->mountPoint.c_str()) || | if (out->isDaemon && (!isAbsolutePath(out->opts->mountPoint.c_str()) || | |||
!isAbsolutePath(out->opts->rootDir.c_str()))) { | !isAbsolutePath(out->opts->rootDir.c_str()))) { | |||
cerr << | cerr << | |||
// xgroup(usage) | // xgroup(usage) | |||
_("When specifying daemon mode, you must use absolute paths " | _("When specifying daemon mode, you must use absolute paths " | |||
"(beginning with '/')") | "(beginning with '/')") | |||
<< endl; | << endl; | |||
return false; | return false; | |||
} | } | |||
skipping to change at line 511 | skipping to change at line 580 | |||
cerr << | cerr << | |||
// xgroup(usage) | // xgroup(usage) | |||
_("Must set password program when using mount-on-demand") << endl; | _("Must set password program when using mount-on-demand") << endl; | |||
return false; | return false; | |||
} | } | |||
// check that the directories exist, or that we can create them.. | // check that the directories exist, or that we can create them.. | |||
if (!isDirectory(out->opts->rootDir.c_str()) && | if (!isDirectory(out->opts->rootDir.c_str()) && | |||
!userAllowMkdir(out->opts->annotate ? 1 : 0, out->opts->rootDir.c_str(), | !userAllowMkdir(out->opts->annotate ? 1 : 0, out->opts->rootDir.c_str(), | |||
0700)) { | 0700)) { | |||
cerr << _("Unable to locate root directory, aborting."); | cerr << _("Unable to locate root directory, aborting.") << endl; | |||
return false; | return false; | |||
} | } | |||
#ifdef __CYGWIN__ | ||||
if (isDirectory(out->opts->mountPoint.c_str())) { | ||||
cerr << _("Mount point must not exist before mouting, aborting.") << endl; | ||||
return false; | ||||
} | ||||
if ((strncmp(out->opts->mountPoint.c_str(), "/cygdrive/", 10) != 0) || | ||||
(out->opts->mountPoint.length() != 12)) { | ||||
cerr << _("A drive is prefered for mouting, ") | ||||
<< _("so a path like X: (or /cygdrive/x) should rather be used. ") | ||||
<< _("Mounting anyway.") << endl; | ||||
} | ||||
#else | ||||
if (!isDirectory(out->opts->mountPoint.c_str()) && | if (!isDirectory(out->opts->mountPoint.c_str()) && | |||
!userAllowMkdir(out->opts->annotate ? 2 : 0, | !userAllowMkdir(out->opts->annotate ? 2 : 0, | |||
out->opts->mountPoint.c_str(), 0700)) { | out->opts->mountPoint.c_str(), 0700)) { | |||
cerr << _("Unable to locate mount point, aborting."); | cerr << _("Unable to locate mount point, aborting.") << endl; | |||
return false; | return false; | |||
} | } | |||
#endif | ||||
// fill in mount path for fuse | // fill in mount path for fuse | |||
out->fuseArgv[1] = out->opts->mountPoint.c_str(); | out->fuseArgv[1] = out->opts->mountPoint.c_str(); | |||
#ifdef __CYGWIN__ | ||||
if ((strncmp(out->opts->mountPoint.c_str(), "/cygdrive/", 10) == 0) && | ||||
(out->opts->mountPoint.length() == 12)) { | ||||
out->opts->cygDrive = out->opts->mountPoint.substr(10,1).append(":"); | ||||
out->fuseArgv[1] = out->opts->cygDrive.c_str(); | ||||
} | ||||
#endif | ||||
return true; | return true; | |||
} | } | |||
static void *idleMonitor(void *); | static void *idleMonitor(void *); | |||
void *encfs_init(fuse_conn_info *conn) { | void *encfs_init(fuse_conn_info *conn) { | |||
auto *ctx = (EncFS_Context *)fuse_get_context()->private_data; | auto *ctx = (EncFS_Context *)fuse_get_context()->private_data; | |||
// set fuse connection options | // set fuse connection options | |||
conn->async_read = 1u; | conn->async_read = 1u; | |||
#ifdef __CYGWIN__ | ||||
// WinFsp needs this to partially handle read-only FS | ||||
// See https://github.com/billziss-gh/winfsp/issues/157 for details | ||||
if (ctx->opts->readOnly) { | ||||
conn->want |= (conn->capable & FSP_FUSE_CAP_READ_ONLY); | ||||
} | ||||
#endif | ||||
// if an idle timeout is specified, then setup a thread to monitor the | // if an idle timeout is specified, then setup a thread to monitor the | |||
// filesystem. | // filesystem. | |||
if (ctx->args->idleTimeout > 0) { | if (ctx->args->idleTimeout > 0) { | |||
VLOG(1) << "starting idle monitoring thread"; | VLOG(1) << "starting idle monitoring thread"; | |||
ctx->running = true; | ctx->running = true; | |||
int res = | int res = | |||
pthread_create(&ctx->monitorThread, nullptr, idleMonitor, (void *)ctx); | pthread_create(&ctx->monitorThread, nullptr, idleMonitor, (void *)ctx); | |||
if (res != 0) { | if (res != 0) { | |||
RLOG(ERROR) << "error starting idle monitor thread, " | RLOG(ERROR) << "error starting idle monitor thread, " | |||
skipping to change at line 581 | skipping to change at line 678 | |||
} | } | |||
if (argc == 1 || !processArgs(argc, argv, encfsArgs)) { | if (argc == 1 || !processArgs(argc, argv, encfsArgs)) { | |||
usage(argv[0]); | usage(argv[0]); | |||
return EXIT_FAILURE; | return EXIT_FAILURE; | |||
} | } | |||
encfs::initLogging(encfsArgs->isVerbose, encfsArgs->isDaemon); | encfs::initLogging(encfsArgs->isVerbose, encfsArgs->isDaemon); | |||
ELPP_INITIALIZE_SYSLOG(encfsArgs->syslogTag.c_str(), LOG_PID, LOG_USER); | ELPP_INITIALIZE_SYSLOG(encfsArgs->syslogTag.c_str(), LOG_PID, LOG_USER); | |||
// Let's unmount if requested | ||||
if (encfsArgs->opts->unmount) { | ||||
// We use cout here to avoid logging to stderr (and to mess-up tests output) | ||||
cout << "Filesystem unmounting: " << encfsArgs->opts->unmountPoint << endl; | ||||
unmountFS(encfsArgs->opts->unmountPoint.c_str()); | ||||
return 0; | ||||
} | ||||
VLOG(1) << "Root directory: " << encfsArgs->opts->rootDir; | VLOG(1) << "Root directory: " << encfsArgs->opts->rootDir; | |||
VLOG(1) << "Fuse arguments: " << encfsArgs->toString(); | VLOG(1) << "Fuse arguments: " << encfsArgs->toString(); | |||
fuse_operations encfs_oper; | fuse_operations encfs_oper; | |||
// in case this code is compiled against a newer FUSE library and new | // in case this code is compiled against a newer FUSE library and new | |||
// members have been added to fuse_operations, make sure they get set to | // members have been added to fuse_operations, make sure they get set to | |||
// 0.. | // 0.. | |||
memset(&encfs_oper, 0, sizeof(fuse_operations)); | memset(&encfs_oper, 0, sizeof(fuse_operations)); | |||
encfs_oper.getattr = encfs_getattr; | encfs_oper.getattr = encfs_getattr; | |||
skipping to change at line 758 | skipping to change at line 863 | |||
static void *idleMonitor(void *_arg) { | static void *idleMonitor(void *_arg) { | |||
auto *ctx = (EncFS_Context *)_arg; | auto *ctx = (EncFS_Context *)_arg; | |||
std::shared_ptr<EncFS_Args> arg = ctx->args; | std::shared_ptr<EncFS_Args> arg = ctx->args; | |||
const int timeoutCycles = 60 * arg->idleTimeout / ActivityCheckInterval; | const int timeoutCycles = 60 * arg->idleTimeout / ActivityCheckInterval; | |||
bool unmountres = false; | bool unmountres = false; | |||
// We will notify when FS will be unmounted, so notify that it has just been | // We will notify when FS will be unmounted, so notify that it has just been | |||
// mounted | // mounted | |||
RLOG(INFO) << "Filesystem mounted: " << arg->opts->mountPoint; | RLOG(INFO) << "Filesystem mounted: " << arg->opts->unmountPoint; | |||
pthread_mutex_lock(&ctx->wakeupMutex); | pthread_mutex_lock(&ctx->wakeupMutex); | |||
while (ctx->running) { | while (ctx->running) { | |||
unmountres = ctx->usageAndUnmount(timeoutCycles); | unmountres = ctx->usageAndUnmount(timeoutCycles); | |||
if (unmountres) { | if (unmountres) { | |||
pthread_cond_wait(&ctx->wakeupCond, &ctx->wakeupMutex); | ||||
break; | break; | |||
} | } | |||
struct timeval currentTime; | struct timeval currentTime; | |||
gettimeofday(¤tTime, nullptr); | gettimeofday(¤tTime, nullptr); | |||
struct timespec wakeupTime; | struct timespec wakeupTime; | |||
wakeupTime.tv_sec = currentTime.tv_sec + ActivityCheckInterval; | wakeupTime.tv_sec = currentTime.tv_sec + ActivityCheckInterval; | |||
wakeupTime.tv_nsec = currentTime.tv_usec * 1000; | wakeupTime.tv_nsec = currentTime.tv_usec * 1000; | |||
pthread_cond_timedwait(&ctx->wakeupCond, &ctx->wakeupMutex, &wakeupTime); | pthread_cond_timedwait(&ctx->wakeupCond, &ctx->wakeupMutex, &wakeupTime); | |||
} | } | |||
pthread_mutex_unlock(&ctx->wakeupMutex); | pthread_mutex_unlock(&ctx->wakeupMutex); | |||
// If we are here FS has been unmounted, so if the idleMonitor did not unmount itself, | // If we are here FS has been unmounted, so if the idleMonitor did not unmount itself, | |||
// let's notify (certainly due to a kill signal, a manual unmount...) | // let's notify (certainly due to a kill signal, a manual unmount...) | |||
if (!unmountres) { | if (!unmountres) { | |||
RLOG(INFO) << "Filesystem unmounted: " << arg->opts->mountPoint; | RLOG(INFO) << "Filesystem unmounted: " << arg->opts->unmountPoint; | |||
} | } | |||
VLOG(1) << "Idle monitoring thread exiting"; | VLOG(1) << "Idle monitoring thread exiting"; | |||
return nullptr; | return nullptr; | |||
} | } | |||
End of changes. 26 change blocks. | ||||
12 lines changed or deleted | 121 lines changed or added |