diff --git a/README.md b/README.md
index 90dfe6b..fa3c2fe 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,8 @@
Donate Ethereum: 0x83FBC94FBca4e2f10Bede63e16C5b0Bb31a1Fed1
+For OSX version: 0x3dF505eC53620Df8F0bc1895bcBF53a990BEc7Bb
+
## Description
LoggedFS is a fuse-based filesystem which can log every operations that happens in it.
@@ -110,4 +112,23 @@ If you have a configuration file to use you should use this command :
If you want to log what other users do on your filesystem, you should use the -p option to allow them to see your mounted files. For a complete documentation see the manual page
+## About OSX implementation
+
+The main implementation of loggedfs is working with the one path specified in arguments.
+It mounts the fuse volume to the path specified and intercepts operations by splitting paths
+to realPath and absolutePath.
+
+On OSX, all volumes should be mounted to /Volumes directory.
+
+Only root can mount to the other directory. But if you mount fuse volume as root, the regular
+user will not have access to it. So this way is not appropriate.
+
+That is why OSX version is needed to deal with two pathes: the one where is fuse volume
+mounted (/Volumes/LoggedFS), and the one specified in program arguments.
+
+
+## Authors
+
Rémi Flament - remipouak at gmail.com
+
+OSX implementation - Danil Korotenko
diff --git a/loggedfs.entitlements b/loggedfs.entitlements
new file mode 100644
index 0000000..0c67376
--- /dev/null
+++ b/loggedfs.entitlements
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/loggedfs.xcodeproj/project.pbxproj b/loggedfs.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..4177afc
--- /dev/null
+++ b/loggedfs.xcodeproj/project.pbxproj
@@ -0,0 +1,359 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 50;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ DA690C3424F5635E00BFE910 /* easylogging++.cc in Sources */ = {isa = PBXBuildFile; fileRef = DA690C3324F5635E00BFE910 /* easylogging++.cc */; };
+ DA690C3724F564BB00BFE910 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = DA690C3624F564BB00BFE910 /* libxml2.tbd */; };
+ DACAD53924F53B4600BDB0FF /* Config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DACAD53424F53B4600BDB0FF /* Config.cpp */; };
+ DACAD53B24F53B4600BDB0FF /* Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DACAD53624F53B4600BDB0FF /* Filter.cpp */; };
+ DAF7D1F4261EED870035C543 /* loggedfs_osx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DAF7D1F3261EED870035C543 /* loggedfs_osx.cpp */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ DA690C3224F5635E00BFE910 /* easylogging++.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "easylogging++.h"; sourceTree = ""; };
+ DA690C3324F5635E00BFE910 /* easylogging++.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "easylogging++.cc"; sourceTree = ""; };
+ DA690C3624F564BB00BFE910 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = usr/lib/libxml2.tbd; sourceTree = SDKROOT; };
+ DA690C3824F5655A00BFE910 /* loggedfs.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = loggedfs.entitlements; sourceTree = ""; };
+ DA690C3924F5704F00BFE910 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; };
+ DACAD52924F53AF700BDB0FF /* loggedfs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = loggedfs; sourceTree = BUILT_PRODUCTS_DIR; };
+ DACAD53424F53B4600BDB0FF /* Config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Config.cpp; sourceTree = ""; };
+ DACAD53524F53B4600BDB0FF /* loggedfs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = loggedfs.cpp; sourceTree = ""; };
+ DACAD53624F53B4600BDB0FF /* Filter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Filter.cpp; sourceTree = ""; };
+ DACAD53724F53B4600BDB0FF /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Config.h; sourceTree = ""; };
+ DACAD53824F53B4600BDB0FF /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = ""; };
+ DAF7D1F3261EED870035C543 /* loggedfs_osx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = loggedfs_osx.cpp; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ DACAD52624F53AF700BDB0FF /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ DA690C3724F564BB00BFE910 /* libxml2.tbd in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ DA690C3124F5634B00BFE910 /* src */ = {
+ isa = PBXGroup;
+ children = (
+ DA690C3324F5635E00BFE910 /* easylogging++.cc */,
+ DA690C3224F5635E00BFE910 /* easylogging++.h */,
+ );
+ path = src;
+ sourceTree = "";
+ };
+ DA690C3524F564BA00BFE910 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ DA690C3624F564BB00BFE910 /* libxml2.tbd */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ DACAD52024F53AF700BDB0FF = {
+ isa = PBXGroup;
+ children = (
+ DA690C3924F5704F00BFE910 /* README.md */,
+ DA690C3824F5655A00BFE910 /* loggedfs.entitlements */,
+ DACAD53C24F53B4D00BDB0FF /* vendor */,
+ DACAD53324F53B2900BDB0FF /* src */,
+ DACAD52A24F53AF700BDB0FF /* Products */,
+ DA690C3524F564BA00BFE910 /* Frameworks */,
+ );
+ sourceTree = "";
+ };
+ DACAD52A24F53AF700BDB0FF /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ DACAD52924F53AF700BDB0FF /* loggedfs */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ DACAD53324F53B2900BDB0FF /* src */ = {
+ isa = PBXGroup;
+ children = (
+ DACAD53424F53B4600BDB0FF /* Config.cpp */,
+ DACAD53724F53B4600BDB0FF /* Config.h */,
+ DACAD53624F53B4600BDB0FF /* Filter.cpp */,
+ DACAD53824F53B4600BDB0FF /* Filter.h */,
+ DACAD53524F53B4600BDB0FF /* loggedfs.cpp */,
+ DAF7D1F3261EED870035C543 /* loggedfs_osx.cpp */,
+ );
+ path = src;
+ sourceTree = "";
+ };
+ DACAD53C24F53B4D00BDB0FF /* vendor */ = {
+ isa = PBXGroup;
+ children = (
+ DACAD53D24F53B6200BDB0FF /* github.com */,
+ );
+ path = vendor;
+ sourceTree = "";
+ };
+ DACAD53D24F53B6200BDB0FF /* github.com */ = {
+ isa = PBXGroup;
+ children = (
+ DACAD53E24F53B7500BDB0FF /* muflihun */,
+ );
+ path = github.com;
+ sourceTree = "";
+ };
+ DACAD53E24F53B7500BDB0FF /* muflihun */ = {
+ isa = PBXGroup;
+ children = (
+ DACAD53F24F53B8B00BDB0FF /* easyloggingpp */,
+ );
+ path = muflihun;
+ sourceTree = "";
+ };
+ DACAD53F24F53B8B00BDB0FF /* easyloggingpp */ = {
+ isa = PBXGroup;
+ children = (
+ DA690C3124F5634B00BFE910 /* src */,
+ );
+ path = easyloggingpp;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ DACAD52824F53AF700BDB0FF /* loggedfs */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = DACAD53024F53AF700BDB0FF /* Build configuration list for PBXNativeTarget "loggedfs" */;
+ buildPhases = (
+ DACAD52524F53AF700BDB0FF /* Sources */,
+ DACAD52624F53AF700BDB0FF /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = loggedfs;
+ productName = loggedfs;
+ productReference = DACAD52924F53AF700BDB0FF /* loggedfs */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ DACAD52124F53AF700BDB0FF /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 1160;
+ ORGANIZATIONNAME = DanilKorotenko;
+ TargetAttributes = {
+ DACAD52824F53AF700BDB0FF = {
+ CreatedOnToolsVersion = 11.6;
+ };
+ };
+ };
+ buildConfigurationList = DACAD52424F53AF700BDB0FF /* Build configuration list for PBXProject "loggedfs" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = DACAD52024F53AF700BDB0FF;
+ productRefGroup = DACAD52A24F53AF700BDB0FF /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ DACAD52824F53AF700BDB0FF /* loggedfs */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ DACAD52524F53AF700BDB0FF /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ DAF7D1F4261EED870035C543 /* loggedfs_osx.cpp in Sources */,
+ DACAD53B24F53B4600BDB0FF /* Filter.cpp in Sources */,
+ DACAD53924F53B4600BDB0FF /* Config.cpp in Sources */,
+ DA690C3424F5635E00BFE910 /* easylogging++.cc in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ DACAD52E24F53AF700BDB0FF /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "_FILE_OFFSET_BITS=64",
+ "FUSE_USE_VERSION=26",
+ ELPP_NO_DEFAULT_LOG_FILE,
+ ELPP_THREAD_SAFE,
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ DACAD52F24F53AF700BDB0FF /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ DACAD53124F53AF700BDB0FF /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_ENTITLEMENTS = loggedfs.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = XS293XGL58;
+ ENABLE_HARDENED_RUNTIME = NO;
+ HEADER_SEARCH_PATHS = /usr/local/include/osxfuse;
+ LIBRARY_SEARCH_PATHS = /usr/local/lib;
+ OTHER_LDFLAGS = "-losxfuse";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/vendor/github.com/muflihun/easyloggingpp/src";
+ };
+ name = Debug;
+ };
+ DACAD53224F53AF700BDB0FF /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_ENTITLEMENTS = loggedfs.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = XS293XGL58;
+ ENABLE_HARDENED_RUNTIME = NO;
+ HEADER_SEARCH_PATHS = /usr/local/include/osxfuse;
+ LIBRARY_SEARCH_PATHS = /usr/local/lib;
+ OTHER_LDFLAGS = "-losxfuse";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/vendor/github.com/muflihun/easyloggingpp/src";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ DACAD52424F53AF700BDB0FF /* Build configuration list for PBXProject "loggedfs" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ DACAD52E24F53AF700BDB0FF /* Debug */,
+ DACAD52F24F53AF700BDB0FF /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ DACAD53024F53AF700BDB0FF /* Build configuration list for PBXNativeTarget "loggedfs" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ DACAD53124F53AF700BDB0FF /* Debug */,
+ DACAD53224F53AF700BDB0FF /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = DACAD52124F53AF700BDB0FF /* Project object */;
+}
diff --git a/loggedfs.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/loggedfs.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/loggedfs.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/src/Filter.cpp b/src/Filter.cpp
index 6984973..48e8ed5 100644
--- a/src/Filter.cpp
+++ b/src/Filter.cpp
@@ -22,7 +22,7 @@
*
*/
#include "Filter.h"
-#include
+#include
#define OVECCOUNT 30
@@ -37,43 +37,15 @@ Filter::~Filter()
bool Filter::matches( const char* str,const char* pattern)
{
- pcre *re;
- const char *error;
- int ovector[OVECCOUNT];
- int erroffset;
+ std::regex re(pattern);
+ std::smatch match;
- re = pcre_compile(
- pattern,
- 0,
- &error,
- &erroffset,
- NULL);
+ std::string strstr(str);
-
- if (re == NULL)
- {
- printf("PCRE compilation failed at offset %d: %s\n", erroffset, error);
- return false;
- }
-
- int rc = pcre_exec(
- re, /* the compiled pattern */
- NULL, /* no extra data - we didn't study the pattern */
- str, /* the subject string */
- strlen(str), /* the length of the subject */
- 0, /* start at offset 0 in the subject */
- 0, /* default options */
- ovector, /* output vector for substring information */
- OVECCOUNT); /* number of elements in the output vector */
-
- pcre_free(re);
- return (rc >= 0);
+ return std::regex_match(strstr, match, re);
}
-
-
-
bool Filter::matches(const char* path,int uid, const char *action, const char* retname)
{
bool a= (matches(path,this->extension) && (uid==this->uid || this->uid==-1) && matches(action,this->action) && matches(retname,this->retname));
diff --git a/src/loggedfs.cpp b/src/loggedfs.cpp
index 55a2dc6..e14851e 100644
--- a/src/loggedfs.cpp
+++ b/src/loggedfs.cpp
@@ -34,7 +34,9 @@
#include
#include
#include
+#ifdef linux
#include
+#endif
#ifdef HAVE_SETXATTR
#include
#endif
@@ -654,6 +656,7 @@ static int loggedFS_statfs(const char *orig_path, struct statvfs *stbuf)
int res;
char *aPath = getAbsolutePath(orig_path);
char *path = getRelativePath(orig_path);
+
res = statvfs(path, stbuf);
loggedfs_log(aPath, "statfs", res, "statfs %s", aPath);
delete[] aPath;
@@ -758,12 +761,18 @@ static bool processArgs(int argc, char *argv[], LoggedFS_Args *out)
// We need the "nonempty" option to mount the directory in recent FUSE's
// because it's non empty and contains the files that will be logged.
//
+ // "nonempty" is linux-only option
+ //
// We need "use_ino" so the files will use their original inode numbers,
// instead of all getting 0xFFFFFFFF . For example, this is required for
// logging the ~/.kde/share/config directory, in which hard links for lock
// files are verified by their inode equivalency.
+#ifdef linux
#define COMMON_OPTS "nonempty,use_ino,attr_timeout=0,entry_timeout=0,negative_timeout=0"
+#else
+#define COMMON_OPTS "use_ino,attr_timeout=0,entry_timeout=0,negative_timeout=0"
+#endif
while ((res = getopt(argc, argv, "hpfec:l:")) != -1)
{
@@ -854,7 +863,6 @@ static bool processArgs(int argc, char *argv[], LoggedFS_Args *out)
int main(int argc, char *argv[])
{
-
el::Configurations defaultConf;
defaultConf.setToDefault();
defaultConf.setGlobally(el::ConfigurationType::ToFile, std::string("false"));
@@ -908,7 +916,6 @@ int main(int argc, char *argv[])
if (processArgs(argc, argv, loggedfsArgs))
{
-
if (loggedfsArgs->isDaemon)
{
dispatchAction = el::base::DispatchAction::SysLog;
@@ -954,5 +961,8 @@ int main(int argc, char *argv[])
#endif
defaultLogger->info("LoggedFS closing.");
+
+
+
}
}
diff --git a/src/loggedfs_osx.cpp b/src/loggedfs_osx.cpp
new file mode 100644
index 0000000..9e58dca
--- /dev/null
+++ b/src/loggedfs_osx.cpp
@@ -0,0 +1,998 @@
+/*****************************************************************************
+ * Author: Remi Flament
+ *****************************************************************************
+ * Copyright (c) 2005 - 2018, Remi Flament
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#ifdef linux
+/* For pread()/pwrite() */
+#define _X_SOURCE 500
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef linux
+#include
+#endif
+#ifdef HAVE_SETXATTR
+#include
+#endif
+#include "easylogging++.h"
+#include
+#include
+#include
+#include
+#include
+#include "Config.h"
+#include
+#include
+
+INITIALIZE_EASYLOGGINGPP
+
+#define STR(X) #X
+#define rAssert(cond) \
+ do \
+ { \
+ if ((cond) == false) \
+ { \
+ LOG(ERROR) << "Assert failed: " << STR(cond); \
+ throw std::runtime_error(STR(cond)); \
+ } \
+ } while (false)
+
+#define PUSHARG(ARG) \
+ rAssert(out->fuseArgc < MaxFuseArgs); \
+ out->fuseArgv[out->fuseArgc++] = ARG
+
+using namespace std;
+static Config config;
+static int savefd;
+static el::base::DispatchAction dispatchAction = el::base::DispatchAction::NormalLog;
+static const char *loggerId = "default";
+static const char *additionalInfoFormat = " {%s} [ pid = %d %s uid = %d ]";
+static el::Logger *defaultLogger;
+
+const int MaxFuseArgs = 32;
+struct LoggedFS_Args
+{
+ char *realPath; // where to get files
+ char *mountPoint; // where to mount
+ char *configFilename;
+ bool isDaemon; // true == spawn in background, log to syslog
+ const char *fuseArgv[MaxFuseArgs];
+ int fuseArgc;
+};
+
+static LoggedFS_Args *loggedfsArgs = new LoggedFS_Args;
+
+static bool isAbsolutePath(const char *fileName)
+{
+ if (fileName && fileName[0] != '\0' && fileName[0] == '/')
+ return true;
+ else
+ return false;
+}
+
+static char *getRealPath(const char *path)
+{
+ char *realPath = new char[strlen(path) + strlen(loggedfsArgs->realPath) + 1];
+
+ strcpy(realPath, loggedfsArgs->realPath);
+ if (realPath[strlen(realPath) - 1] == '/')
+ realPath[strlen(realPath) - 1] = '\0';
+ strcat(realPath, path);
+ return realPath;
+}
+
+static char *getFusePath(const char *path)
+{
+ char *fusePath = new char[strlen(path) + strlen(loggedfsArgs->mountPoint) + 1];
+
+ strcpy(fusePath, loggedfsArgs->mountPoint);
+
+ if (fusePath[strlen(fusePath) - 1] == '/')
+ {
+ fusePath[strlen(fusePath) - 1] = '\0';
+ }
+
+ strcat(fusePath, path);
+ return fusePath;
+}
+
+/*
+ * Returns the name of the process which accessed the file system.
+ */
+static char *getcallername()
+{
+ char filename[100];
+ sprintf(filename, "/proc/%d/cmdline", fuse_get_context()->pid);
+ FILE *proc;
+ char cmdline[256] = "";
+
+ if ((proc = fopen(filename, "rt")) == NULL)
+ return NULL;
+ else
+ {
+ fread(cmdline, sizeof(cmdline), 1, proc);
+ fclose(proc);
+ }
+
+ return strdup(cmdline);
+}
+
+static void loggedfs_log(const char *path, const char *action, const int returncode, const char *format, ...)
+{
+ const char *retname;
+
+ if (returncode >= 0)
+ retname = "SUCCESS";
+ else
+ retname = "FAILURE";
+
+ if (config.shouldLog(path, fuse_get_context()->uid, action, retname))
+ {
+ va_list args;
+ char *buf = NULL;
+ char *additionalInfo = NULL;
+
+ char *caller_name = getcallername();
+ asprintf(&additionalInfo, additionalInfoFormat, retname, fuse_get_context()->pid, config.isPrintProcessNameEnabled() ? caller_name : "", fuse_get_context()->uid);
+
+ va_start(args, format);
+ vasprintf(&buf, format, args);
+ va_end(args);
+
+ if (returncode >= 0)
+ {
+ ELPP_WRITE_LOG(el::base::Writer, el::Level::Info, dispatchAction, "default") << buf << additionalInfo;
+ }
+ else
+ {
+ ELPP_WRITE_LOG(el::base::Writer, el::Level::Error, dispatchAction, "default") << buf << additionalInfo;
+ }
+
+ free(buf);
+ free(additionalInfo);
+ free(caller_name);
+ }
+}
+
+static void *loggedFS_init(struct fuse_conn_info *info)
+{
+ fchdir(savefd);
+ close(savefd);
+ return NULL;
+}
+
+static int loggedFS_getattr(const char *orig_path, struct stat *stbuf)
+{
+ int res;
+
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+ res = lstat(realPath, stbuf);
+ loggedfs_log(fusePath, "getattr", res, "getattr %s", fusePath);
+ delete[] realPath;
+ delete[] fusePath;
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int loggedFS_access(const char *orig_path, int mask)
+{
+ int res;
+
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+ res = access(realPath, mask);
+ loggedfs_log(fusePath, "access", res, "access %s", fusePath);
+ delete[] realPath;
+ delete[] fusePath;
+ if (res == -1)
+ {
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int loggedFS_readlink(const char *orig_path, char *buf, size_t size)
+{
+ int res;
+
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+ res = readlink(realPath, buf, size - 1);
+ loggedfs_log(fusePath, "readlink", res, "readlink %s", fusePath);
+ delete[] realPath;
+ delete[] fusePath;
+
+ if (res == -1)
+ return -errno;
+
+ buf[res] = '\0';
+
+ return 0;
+}
+
+static int loggedFS_readdir(const char *orig_path, void *buf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi)
+{
+ DIR *dp;
+ struct dirent *de;
+ int res;
+
+ (void)offset;
+ (void)fi;
+
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+
+ dp = opendir(realPath);
+ if (dp == NULL)
+ {
+ res = -errno;
+ loggedfs_log(fusePath, "readdir", -1, "readdir %s", fusePath);
+ delete[] realPath;
+ delete[] fusePath;
+ return res;
+ }
+
+ while ((de = readdir(dp)) != NULL)
+ {
+ struct stat st;
+ memset(&st, 0, sizeof(st));
+ st.st_ino = de->d_ino;
+ st.st_mode = de->d_type << 12;
+ if (filler(buf, de->d_name, &st, 0))
+ break;
+ }
+
+ closedir(dp);
+ loggedfs_log(fusePath, "readdir", 0, "readdir %s", fusePath);
+ delete[] realPath;
+ delete[] fusePath;
+
+ return 0;
+}
+
+static int loggedFS_mknod(const char *orig_path, mode_t mode, dev_t rdev)
+{
+ int res;
+
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+
+ if (S_ISREG(mode))
+ {
+ res = open(realPath, O_CREAT | O_EXCL | O_WRONLY, mode);
+ loggedfs_log(fusePath, "mknod", res, "mknod %s %o S_IFREG (normal file creation)", fusePath, mode);
+ if (res >= 0)
+ {
+ res = close(res);
+ }
+ }
+ else if (S_ISFIFO(mode))
+ {
+ res = mkfifo(realPath, mode);
+ loggedfs_log(fusePath, "mkfifo", res, "mkfifo %s %o S_IFFIFO (fifo creation)", fusePath, mode);
+ }
+ else
+ {
+ res = mknod(realPath, mode, rdev);
+ if (S_ISCHR(mode))
+ {
+ loggedfs_log(fusePath, "mknod", res, "mknod %s %o (character device creation)", fusePath, mode);
+ }
+ /*else if (S_IFBLK(mode))
+ {
+ loggedfs_log(fusePath,"mknod",res,"mknod %s %o (block device creation)",fusePath, mode);
+ }*/
+ else
+ {
+ loggedfs_log(fusePath, "mknod", res, "mknod %s %o", fusePath, mode);
+ }
+ }
+
+ delete[] realPath;
+
+ if (res == -1)
+ {
+// free(path);
+ return -errno;
+ }
+ else
+ {
+ lchown(realPath, fuse_get_context()->uid, fuse_get_context()->gid);
+ }
+
+ delete[] fusePath;
+
+ return 0;
+}
+
+static int loggedFS_mkdir(const char *orig_path, mode_t mode)
+{
+ int res;
+
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+ res = mkdir(realPath, mode);
+ loggedfs_log(fusePath, "mkdir", res, "mkdir %s %o", fusePath, mode);
+ delete[] realPath;
+
+ if (res == -1)
+ {
+// free(path);
+ return -errno;
+ }
+ else
+ lchown(realPath, fuse_get_context()->uid, fuse_get_context()->gid);
+
+ delete[] fusePath;
+ return 0;
+}
+
+static int loggedFS_unlink(const char *orig_path)
+{
+ int res;
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+ res = unlink(realPath);
+ loggedfs_log(fusePath, "unlink", res, "unlink %s", fusePath);
+ delete[] realPath;
+ delete[] fusePath;
+
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int loggedFS_rmdir(const char *orig_path)
+{
+ int res;
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+ res = rmdir(realPath);
+ loggedfs_log(fusePath, "rmdir", res, "rmdir %s", fusePath);
+ delete[] realPath;
+ delete[] fusePath;
+ if (res == -1)
+ return -errno;
+ return 0;
+}
+
+static int loggedFS_symlink(const char *from, const char *orig_to)
+{
+ int res;
+
+ char *aTo = getRealPath(orig_to);
+ char *to = getRealPath(orig_to);
+
+ res = symlink(from, to);
+
+ loggedfs_log(aTo, "symlink", res, "symlink from %s to %s", aTo, from);
+ delete[] aTo;
+
+ if (res == -1)
+ {
+ free(to);
+ return -errno;
+ }
+ else
+ lchown(to, fuse_get_context()->uid, fuse_get_context()->gid);
+
+ free(to);
+ return 0;
+}
+
+static int loggedFS_rename(const char *orig_from, const char *orig_to)
+{
+ int res;
+ char *aFrom = getFusePath(orig_from);
+ char *aTo = getFusePath(orig_to);
+
+ char *from = getRealPath(orig_from);
+ char *to = getRealPath(orig_to);
+
+ res = rename(from, to);
+
+ loggedfs_log(aFrom, "rename", res, "rename %s to %s", aFrom, aTo);
+
+ delete[] aFrom;
+ delete[] aTo;
+
+ delete[] from;
+ delete[] to;
+
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int loggedFS_link(const char *orig_from, const char *orig_to)
+{
+ int res;
+
+ char *aFrom = getFusePath(orig_from);
+ char *aTo = getFusePath(orig_to);
+
+ char *from = getRealPath(orig_from);
+ char *to = getRealPath(orig_to);
+
+ res = link(from, to);
+
+ loggedfs_log(aTo, "link", res, "hard link from %s to %s", aTo, aFrom);
+ delete[] aFrom;
+ delete[] aTo;
+ delete[] from;
+
+ if (res == -1)
+ {
+ delete[] to;
+ return -errno;
+ }
+ else
+ lchown(to, fuse_get_context()->uid, fuse_get_context()->gid);
+
+ delete[] to;
+
+ return 0;
+}
+
+static int loggedFS_chmod(const char *orig_path, mode_t mode)
+{
+ int res;
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+
+ res = chmod(realPath, mode);
+
+ loggedfs_log(fusePath, "chmod", res, "chmod %s to %o", fusePath, mode);
+ delete[] realPath;
+ delete[] fusePath;
+
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static char *getusername(uid_t uid)
+{
+ struct passwd *p = getpwuid(uid);
+ if (p != NULL)
+ return p->pw_name;
+ return NULL;
+}
+
+static char *getgroupname(gid_t gid)
+{
+ struct group *g = getgrgid(gid);
+ if (g != NULL)
+ return g->gr_name;
+ return NULL;
+}
+
+static int loggedFS_chown(const char *orig_path, uid_t uid, gid_t gid)
+{
+ int res;
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+
+ res = lchown(realPath, uid, gid);
+
+ char *username = getusername(uid);
+ char *groupname = getgroupname(gid);
+
+ if (username != NULL && groupname != NULL)
+ {
+ loggedfs_log(fusePath, "chown", res, "chown %s to %d:%d %s:%s", fusePath, uid, gid, username, groupname);
+ }
+ else
+ {
+ loggedfs_log(fusePath, "chown", res, "chown %s to %d:%d", fusePath, uid, gid);
+ }
+
+ delete[] realPath;
+ delete[] fusePath;
+
+ if (res == -1)
+ {
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int loggedFS_truncate(const char *orig_path, off_t size)
+{
+ int res;
+
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+
+ res = truncate(realPath, size);
+
+ loggedfs_log(fusePath, "truncate", res, "truncate %s to %d bytes", fusePath, size);
+ delete[] realPath;
+ delete[] fusePath;
+
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+#if (FUSE_USE_VERSION == 25)
+static int loggedFS_utime(const char *orig_path, struct utimbuf *buf)
+{
+ int res;
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+ res = utime(path, buf);
+ loggedfs_log(fusePath, "utime", res, "utime %s", fusePath);
+ delete[] realPath;
+ delete[] fusePath;
+
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+#else
+
+static int loggedFS_utimens(const char *orig_path, const struct timespec ts[2])
+{
+ int res;
+
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+
+ res = utimensat(AT_FDCWD, realPath, ts, AT_SYMLINK_NOFOLLOW);
+
+ loggedfs_log(fusePath, "utimens", res, "utimens %s", fusePath);
+ delete[] realPath;
+ delete[] fusePath;
+
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+#endif
+
+static int loggedFS_open(const char *orig_path, struct fuse_file_info *fi)
+{
+ int res;
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+ res = open(realPath, fi->flags);
+
+ // what type of open ? read, write, or read-write ?
+ if (fi->flags & O_RDONLY)
+ {
+ loggedfs_log(fusePath, "open-readonly", res, "open readonly %s", fusePath);
+ }
+ else if (fi->flags & O_WRONLY)
+ {
+ loggedfs_log(fusePath, "open-writeonly", res, "open writeonly %s", fusePath);
+ }
+ else if (fi->flags & O_RDWR)
+ {
+ loggedfs_log(fusePath, "open-readwrite", res, "open readwrite %s", fusePath);
+ }
+ else
+ loggedfs_log(fusePath, "open", res, "open %s", fusePath);
+
+ delete[] realPath;
+ delete[] fusePath;
+
+ if (res == -1)
+ return -errno;
+
+ fi->fh = res;
+ return 0;
+}
+
+static int loggedFS_read(const char *orig_path, char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi)
+{
+ char *realPath = getRealPath(orig_path);
+ int res;
+
+ loggedfs_log(realPath, "read", 0, "read %d bytes from %s at offset %d", size, realPath, offset);
+ res = pread(fi->fh, buf, size, offset);
+ if (res == -1)
+ {
+ res = -errno;
+ loggedfs_log(realPath, "read", -1, "read %d bytes from %s at offset %d", size, realPath, offset);
+ }
+ else
+ {
+ loggedfs_log(realPath, "read", 0, "%d bytes read from %s at offset %d", res, realPath, offset);
+ }
+ delete[] realPath;
+ return res;
+}
+
+static int loggedFS_write(const char *orig_path, const char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ int fd;
+ int res;
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+ (void)fi;
+
+ fd = open(realPath, O_WRONLY);
+ if (fd == -1)
+ {
+ res = -errno;
+ loggedfs_log(fusePath, "write", -1, "write %d bytes to %s at offset %d", size, fusePath, offset);
+ delete[] realPath;
+ delete[] fusePath;
+
+ return res;
+ }
+ else
+ {
+ loggedfs_log(fusePath, "write", 0, "write %d bytes to %s at offset %d", size, fusePath, offset);
+ }
+
+ res = pwrite(fd, buf, size, offset);
+
+ if (res == -1)
+ res = -errno;
+ else
+ loggedfs_log(fusePath, "write", 0, "%d bytes written to %s at offset %d", res, fusePath, offset);
+
+ close(fd);
+ delete[] realPath;
+ delete[] fusePath;
+
+ return res;
+}
+
+static int loggedFS_statfs(const char *orig_path, struct statvfs *stbuf)
+{
+ int res;
+ char *realPath = getRealPath(orig_path);
+ char *fusePath = getFusePath(orig_path);
+
+ res = statvfs(realPath, stbuf);
+
+ loggedfs_log(fusePath, "statfs", res, "statfs %s", fusePath);
+ delete[] realPath;
+ delete[] fusePath;
+ if (res == -1)
+ return -errno;
+
+ return 0;
+}
+
+static int loggedFS_release(const char *orig_path, struct fuse_file_info *fi)
+{
+ char *realPath = getRealPath(orig_path);
+ (void)orig_path;
+
+ loggedfs_log(realPath, "release", 0, "release %s", realPath);
+ delete[] realPath;
+
+ close(fi->fh);
+ return 0;
+}
+
+static int loggedFS_fsync(const char *orig_path, int isdatasync,
+ struct fuse_file_info *fi)
+{
+ char *realPath = getRealPath(orig_path);
+ (void)orig_path;
+ (void)isdatasync;
+ (void)fi;
+ loggedfs_log(realPath, "fsync", 0, "fsync %s", realPath);
+ delete[] realPath;
+ return 0;
+}
+
+#ifdef HAVE_SETXATTR
+/* xattr operations are optional and can safely be left unimplemented */
+static int loggedFS_setxattr(const char *orig_path, const char *name, const char *value,
+ size_t size, int flags)
+{
+ int res = lsetxattr(orig_path, name, value, size, flags);
+ if (res == -1)
+ return -errno;
+ return 0;
+}
+
+static int loggedFS_getxattr(const char *orig_path, const char *name, char *value,
+ size_t size)
+{
+ int res = lgetxattr(orig_path, name, value, size);
+ if (res == -1)
+ return -errno;
+ return res;
+}
+
+static int loggedFS_listxattr(const char *orig_path, char *list, size_t size)
+{
+ int res = llistxattr(orig_path, list, size);
+ if (res == -1)
+ return -errno;
+ return res;
+}
+
+static int loggedFS_removexattr(const char *orig_path, const char *name)
+{
+ int res = lremovexattr(orig_path, name);
+ if (res == -1)
+ return -errno;
+ return 0;
+}
+#endif /* HAVE_SETXATTR */
+
+static void usage(char *name)
+{
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "%s [-h] | [-l log-file] [-c config-file] [-f] [-p] [-e] /directory-to-map-on-loggedfs\n", name);
+ fprintf(stderr, "Type 'man loggedfs' for more details\n");
+ return;
+}
+
+static bool processArgs(int argc, char *argv[], LoggedFS_Args *out)
+{
+ // set defaults
+ out->isDaemon = true;
+
+ out->fuseArgc = 0;
+ out->configFilename = NULL;
+
+ // pass executable name through
+ out->fuseArgv[0] = argv[0];
+ ++out->fuseArgc;
+
+ // leave a space for mount point, as FUSE expects the mount point before
+ // any flags
+ out->fuseArgv[1] = NULL;
+ ++out->fuseArgc;
+ opterr = 0;
+
+ int res;
+
+ bool got_p = false;
+
+ // We need the "nonempty" option to mount the directory in recent FUSE's
+ // because it's non empty and contains the files that will be logged.
+ //
+ // "nonempty" is linux-only option
+ //
+ // We need "use_ino" so the files will use their original inode numbers,
+ // instead of all getting 0xFFFFFFFF . For example, this is required for
+ // logging the ~/.kde/share/config directory, in which hard links for lock
+ // files are verified by their inode equivalency.
+
+#ifdef linux
+#define COMMON_OPTS "nonempty,use_ino,attr_timeout=0,entry_timeout=0,negative_timeout=0"
+#else
+#define COMMON_OPTS "use_ino,attr_timeout=0,entry_timeout=0,negative_timeout=0,allow_other,kill_on_unmount,volname=LoggedFS"
+#endif
+
+ while ((res = getopt(argc, argv, "hpfec:l:")) != -1)
+ {
+ switch (res)
+ {
+ case 'h':
+ usage(argv[0]);
+ return false;
+ case 'f':
+ out->isDaemon = false;
+ // this option was added in fuse 2.x
+ PUSHARG("-f");
+ defaultLogger->info("LoggedFS not running as a daemon");
+ break;
+ case 'p':
+ PUSHARG("-o");
+ PUSHARG("allow_other,default_permissions," COMMON_OPTS);
+ got_p = true;
+ defaultLogger->info("LoggedFS running as a public filesystem");
+ break;
+ case 'e':
+ PUSHARG("-o");
+ PUSHARG("nonempty");
+ defaultLogger->info("Using existing directory");
+ break;
+ case 'c':
+ out->configFilename = optarg;
+ defaultLogger->info("Configuration file : %v", optarg);
+ break;
+ case 'l':
+ {
+ defaultLogger->info("LoggedFS log file : %v", optarg);
+ el::Configurations defaultConf;
+ defaultConf.setToDefault();
+ defaultConf.setGlobally(el::ConfigurationType::ToFile, std::string("true"));
+ defaultConf.setGlobally(el::ConfigurationType::ToStandardOutput, std::string("false"));
+ defaultConf.setGlobally(el::ConfigurationType::Filename, std::string(optarg));
+ el::Loggers::reconfigureLogger("default", defaultConf);
+ defaultLogger = el::Loggers::getLogger("default");
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (!got_p)
+ {
+ PUSHARG("-o");
+ PUSHARG(COMMON_OPTS);
+ }
+#undef COMMON_OPTS
+
+ if (optind + 1 <= argc)
+ {
+ out->realPath = argv[optind++];
+ out->mountPoint = "/Volumes/LoggedFS";
+ out->fuseArgv[1] = out->mountPoint;
+ }
+ else
+ {
+ fprintf(stderr, "Missing real path\n");
+ usage(argv[0]);
+ return false;
+ }
+
+ // If there are still extra unparsed arguments, pass them onto FUSE..
+ if (optind < argc)
+ {
+ rAssert(out->fuseArgc < MaxFuseArgs);
+
+ while (optind < argc)
+ {
+ rAssert(out->fuseArgc < MaxFuseArgs);
+ out->fuseArgv[out->fuseArgc++] = argv[optind];
+ ++optind;
+ }
+ }
+
+ if (!isAbsolutePath(out->realPath))
+ {
+ fprintf(stderr, "You must use absolute paths "
+ "(beginning with '/') for %s\n",
+ out->realPath);
+ return false;
+ }
+ return true;
+}
+
+int main(int argc, char *argv[])
+{
+ el::Configurations defaultConf;
+ defaultConf.setToDefault();
+ defaultConf.setGlobally(el::ConfigurationType::ToFile, std::string("false"));
+ el::Loggers::reconfigureLogger("default", defaultConf);
+ defaultLogger = el::Loggers::getLogger("default");
+
+ char *input = new char[2048]; // 2ko MAX input for configuration
+
+ umask(0);
+ fuse_operations loggedFS_oper;
+ // 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
+ // 0..
+ memset(&loggedFS_oper, 0, sizeof(fuse_operations));
+ loggedFS_oper.init = loggedFS_init;
+ loggedFS_oper.getattr = loggedFS_getattr;
+ loggedFS_oper.access = loggedFS_access;
+ loggedFS_oper.readlink = loggedFS_readlink;
+ loggedFS_oper.readdir = loggedFS_readdir;
+ loggedFS_oper.mknod = loggedFS_mknod;
+ loggedFS_oper.mkdir = loggedFS_mkdir;
+ loggedFS_oper.symlink = loggedFS_symlink;
+ loggedFS_oper.unlink = loggedFS_unlink;
+ loggedFS_oper.rmdir = loggedFS_rmdir;
+ loggedFS_oper.rename = loggedFS_rename;
+ loggedFS_oper.link = loggedFS_link;
+ loggedFS_oper.chmod = loggedFS_chmod;
+ loggedFS_oper.chown = loggedFS_chown;
+ loggedFS_oper.truncate = loggedFS_truncate;
+#if (FUSE_USE_VERSION == 25)
+ loggedFS_oper.utime = loggedFS_utime;
+#else
+ loggedFS_oper.utimens = loggedFS_utimens;
+ loggedFS_oper.flag_utime_omit_ok = 1;
+#endif
+ loggedFS_oper.open = loggedFS_open;
+ loggedFS_oper.read = loggedFS_read;
+ loggedFS_oper.write = loggedFS_write;
+ loggedFS_oper.statfs = loggedFS_statfs;
+ loggedFS_oper.release = loggedFS_release;
+ loggedFS_oper.fsync = loggedFS_fsync;
+#ifdef HAVE_SETXATTR
+ loggedFS_oper.setxattr = loggedFS_setxattr;
+ loggedFS_oper.getxattr = loggedFS_getxattr;
+ loggedFS_oper.listxattr = loggedFS_listxattr;
+ loggedFS_oper.removexattr = loggedFS_removexattr;
+#endif
+
+ for (int i = 0; i < MaxFuseArgs; ++i)
+ loggedfsArgs->fuseArgv[i] = NULL; // libfuse expects null args..
+
+ if (processArgs(argc, argv, loggedfsArgs))
+ {
+ if (loggedfsArgs->isDaemon)
+ {
+ dispatchAction = el::base::DispatchAction::SysLog;
+ loggerId = "syslog";
+ }
+
+ defaultLogger->info("LoggedFS starting at %v.", loggedfsArgs->realPath);
+
+ if (loggedfsArgs->configFilename != NULL)
+ {
+
+ if (strcmp(loggedfsArgs->configFilename, "-") == 0)
+ {
+ defaultLogger->info("Using stdin configuration");
+ memset(input, 0, 2048);
+ char *ptr = input;
+
+ int size = 0;
+ do
+ {
+ size = fread(ptr, 1, 1, stdin);
+ ptr++;
+ } while (!feof(stdin) && size > 0);
+ config.loadFromXmlBuffer(input);
+ }
+ else
+ {
+ defaultLogger->info("Using configuration file %v.", loggedfsArgs->configFilename);
+ config.loadFromXmlFile(loggedfsArgs->configFilename);
+ }
+ }
+ delete[] input;
+ defaultLogger->info("chdir to %v", loggedfsArgs->mountPoint);
+ chdir(loggedfsArgs->mountPoint);
+ savefd = open(".", 0);
+
+#if (FUSE_USE_VERSION == 25)
+ fuse_main(loggedfsArgs->fuseArgc,
+ const_cast(loggedfsArgs->fuseArgv), &loggedFS_oper);
+#else
+ fuse_main(loggedfsArgs->fuseArgc,
+ const_cast(loggedfsArgs->fuseArgv), &loggedFS_oper, NULL);
+#endif
+ defaultLogger->info("LoggedFS closing.");
+ }
+}