Repository: nifi-minifi-cpp
Updated Branches:
  refs/heads/master 380a98bb8 -> 488677321


http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/48867732/thirdparty/rocksdb/env/env_chroot.cc
----------------------------------------------------------------------
diff --git a/thirdparty/rocksdb/env/env_chroot.cc 
b/thirdparty/rocksdb/env/env_chroot.cc
new file mode 100644
index 0000000..6a1fda8
--- /dev/null
+++ b/thirdparty/rocksdb/env/env_chroot.cc
@@ -0,0 +1,324 @@
+//  Copyright (c) 2016-present, Facebook, Inc.  All rights reserved.
+//  This source code is licensed under both the GPLv2 (found in the
+//  COPYING file in the root directory) and Apache 2.0 License
+//  (found in the LICENSE.Apache file in the root directory).
+
+#if !defined(ROCKSDB_LITE) && !defined(OS_WIN)
+
+#include "env/env_chroot.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "rocksdb/status.h"
+
+namespace rocksdb {
+
+class ChrootEnv : public EnvWrapper {
+ public:
+  ChrootEnv(Env* base_env, const std::string& chroot_dir)
+      : EnvWrapper(base_env) {
+#if defined(OS_AIX)
+    char resolvedName[PATH_MAX];
+    char* real_chroot_dir = realpath(chroot_dir.c_str(), resolvedName);
+#else
+    char* real_chroot_dir = realpath(chroot_dir.c_str(), nullptr);
+#endif
+    // chroot_dir must exist so realpath() returns non-nullptr.
+    assert(real_chroot_dir != nullptr);
+    chroot_dir_ = real_chroot_dir;
+#if !defined(OS_AIX)
+    free(real_chroot_dir);
+#endif
+  }
+
+  virtual Status NewSequentialFile(const std::string& fname,
+                                   std::unique_ptr<SequentialFile>* result,
+                                   const EnvOptions& options) override {
+    auto status_and_enc_path = EncodePathWithNewBasename(fname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::NewSequentialFile(status_and_enc_path.second, result,
+                                         options);
+  }
+
+  virtual Status NewRandomAccessFile(const std::string& fname,
+                                     unique_ptr<RandomAccessFile>* result,
+                                     const EnvOptions& options) override {
+    auto status_and_enc_path = EncodePathWithNewBasename(fname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::NewRandomAccessFile(status_and_enc_path.second, result,
+                                           options);
+  }
+
+  virtual Status NewWritableFile(const std::string& fname,
+                                 unique_ptr<WritableFile>* result,
+                                 const EnvOptions& options) override {
+    auto status_and_enc_path = EncodePathWithNewBasename(fname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::NewWritableFile(status_and_enc_path.second, result,
+                                       options);
+  }
+
+  virtual Status ReuseWritableFile(const std::string& fname,
+                                   const std::string& old_fname,
+                                   unique_ptr<WritableFile>* result,
+                                   const EnvOptions& options) override {
+    auto status_and_enc_path = EncodePathWithNewBasename(fname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    auto status_and_old_enc_path = EncodePath(old_fname);
+    if (!status_and_old_enc_path.first.ok()) {
+      return status_and_old_enc_path.first;
+    }
+    return EnvWrapper::ReuseWritableFile(status_and_old_enc_path.second,
+                                         status_and_old_enc_path.second, 
result,
+                                         options);
+  }
+
+  virtual Status NewRandomRWFile(const std::string& fname,
+                                 unique_ptr<RandomRWFile>* result,
+                                 const EnvOptions& options) override {
+    auto status_and_enc_path = EncodePathWithNewBasename(fname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::NewRandomRWFile(status_and_enc_path.second, result,
+                                       options);
+  }
+
+  virtual Status NewDirectory(const std::string& dir,
+                              unique_ptr<Directory>* result) override {
+    auto status_and_enc_path = EncodePathWithNewBasename(dir);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::NewDirectory(status_and_enc_path.second, result);
+  }
+
+  virtual Status FileExists(const std::string& fname) override {
+    auto status_and_enc_path = EncodePathWithNewBasename(fname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::FileExists(status_and_enc_path.second);
+  }
+
+  virtual Status GetChildren(const std::string& dir,
+                             std::vector<std::string>* result) override {
+    auto status_and_enc_path = EncodePath(dir);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::GetChildren(status_and_enc_path.second, result);
+  }
+
+  virtual Status GetChildrenFileAttributes(
+      const std::string& dir, std::vector<FileAttributes>* result) override {
+    auto status_and_enc_path = EncodePath(dir);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::GetChildrenFileAttributes(status_and_enc_path.second,
+                                                 result);
+  }
+
+  virtual Status DeleteFile(const std::string& fname) override {
+    auto status_and_enc_path = EncodePath(fname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::DeleteFile(status_and_enc_path.second);
+  }
+
+  virtual Status CreateDir(const std::string& dirname) override {
+    auto status_and_enc_path = EncodePathWithNewBasename(dirname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::CreateDir(status_and_enc_path.second);
+  }
+
+  virtual Status CreateDirIfMissing(const std::string& dirname) override {
+    auto status_and_enc_path = EncodePathWithNewBasename(dirname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::CreateDirIfMissing(status_and_enc_path.second);
+  }
+
+  virtual Status DeleteDir(const std::string& dirname) override {
+    auto status_and_enc_path = EncodePath(dirname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::DeleteDir(status_and_enc_path.second);
+  }
+
+  virtual Status GetFileSize(const std::string& fname,
+                             uint64_t* file_size) override {
+    auto status_and_enc_path = EncodePath(fname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::GetFileSize(status_and_enc_path.second, file_size);
+  }
+
+  virtual Status GetFileModificationTime(const std::string& fname,
+                                         uint64_t* file_mtime) override {
+    auto status_and_enc_path = EncodePath(fname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::GetFileModificationTime(status_and_enc_path.second,
+                                               file_mtime);
+  }
+
+  virtual Status RenameFile(const std::string& src,
+                            const std::string& dest) override {
+    auto status_and_src_enc_path = EncodePath(src);
+    if (!status_and_src_enc_path.first.ok()) {
+      return status_and_src_enc_path.first;
+    }
+    auto status_and_dest_enc_path = EncodePathWithNewBasename(dest);
+    if (!status_and_dest_enc_path.first.ok()) {
+      return status_and_dest_enc_path.first;
+    }
+    return EnvWrapper::RenameFile(status_and_src_enc_path.second,
+                                  status_and_dest_enc_path.second);
+  }
+
+  virtual Status LinkFile(const std::string& src,
+                          const std::string& dest) override {
+    auto status_and_src_enc_path = EncodePath(src);
+    if (!status_and_src_enc_path.first.ok()) {
+      return status_and_src_enc_path.first;
+    }
+    auto status_and_dest_enc_path = EncodePathWithNewBasename(dest);
+    if (!status_and_dest_enc_path.first.ok()) {
+      return status_and_dest_enc_path.first;
+    }
+    return EnvWrapper::LinkFile(status_and_src_enc_path.second,
+                                status_and_dest_enc_path.second);
+  }
+
+  virtual Status LockFile(const std::string& fname, FileLock** lock) override {
+    auto status_and_enc_path = EncodePathWithNewBasename(fname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    // FileLock subclasses may store path (e.g., PosixFileLock stores it). We
+    // can skip stripping the chroot directory from this path because callers
+    // shouldn't use it.
+    return EnvWrapper::LockFile(status_and_enc_path.second, lock);
+  }
+
+  virtual Status GetTestDirectory(std::string* path) override {
+    // Adapted from PosixEnv's implementation since it doesn't provide a way to
+    // create directory in the chroot.
+    char buf[256];
+    snprintf(buf, sizeof(buf), "/rocksdbtest-%d", static_cast<int>(geteuid()));
+    *path = buf;
+
+    // Directory may already exist, so ignore return
+    CreateDir(*path);
+    return Status::OK();
+  }
+
+  virtual Status NewLogger(const std::string& fname,
+                           shared_ptr<Logger>* result) override {
+    auto status_and_enc_path = EncodePathWithNewBasename(fname);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::NewLogger(status_and_enc_path.second, result);
+  }
+
+  virtual Status GetAbsolutePath(const std::string& db_path,
+                                 std::string* output_path) override {
+    auto status_and_enc_path = EncodePath(db_path);
+    if (!status_and_enc_path.first.ok()) {
+      return status_and_enc_path.first;
+    }
+    return EnvWrapper::GetAbsolutePath(status_and_enc_path.second, 
output_path);
+  }
+
+ private:
+  // Returns status and expanded absolute path including the chroot directory.
+  // Checks whether the provided path breaks out of the chroot. If it returns
+  // non-OK status, the returned path should not be used.
+  std::pair<Status, std::string> EncodePath(const std::string& path) {
+    if (path.empty() || path[0] != '/') {
+      return {Status::InvalidArgument(path, "Not an absolute path"), ""};
+    }
+    std::pair<Status, std::string> res;
+    res.second = chroot_dir_ + path;
+#if defined(OS_AIX)
+    char resolvedName[PATH_MAX];
+    char* normalized_path = realpath(res.second.c_str(), resolvedName);
+#else
+    char* normalized_path = realpath(res.second.c_str(), nullptr);
+#endif
+    if (normalized_path == nullptr) {
+      res.first = Status::NotFound(res.second, strerror(errno));
+    } else if (strlen(normalized_path) < chroot_dir_.size() ||
+               strncmp(normalized_path, chroot_dir_.c_str(),
+                       chroot_dir_.size()) != 0) {
+      res.first = Status::IOError(res.second,
+                                  "Attempted to access path outside chroot");
+    } else {
+      res.first = Status::OK();
+    }
+#if !defined(OS_AIX)
+    free(normalized_path);
+#endif
+    return res;
+  }
+
+  // Similar to EncodePath() except assumes the basename in the path hasn't 
been
+  // created yet.
+  std::pair<Status, std::string> EncodePathWithNewBasename(
+      const std::string& path) {
+    if (path.empty() || path[0] != '/') {
+      return {Status::InvalidArgument(path, "Not an absolute path"), ""};
+    }
+    // Basename may be followed by trailing slashes
+    size_t final_idx = path.find_last_not_of('/');
+    if (final_idx == std::string::npos) {
+      // It's only slashes so no basename to extract
+      return EncodePath(path);
+    }
+
+    // Pull off the basename temporarily since realname(3) (used by
+    // EncodePath()) requires a path that exists
+    size_t base_sep = path.rfind('/', final_idx);
+    auto status_and_enc_path = EncodePath(path.substr(0, base_sep + 1));
+    status_and_enc_path.second.append(path.substr(base_sep + 1));
+    return status_and_enc_path;
+  }
+
+  std::string chroot_dir_;
+};
+
+Env* NewChrootEnv(Env* base_env, const std::string& chroot_dir) {
+  if (!base_env->FileExists(chroot_dir).ok()) {
+    return nullptr;
+  }
+  return new ChrootEnv(base_env, chroot_dir);
+}
+
+}  // namespace rocksdb
+
+#endif  // !defined(ROCKSDB_LITE) && !defined(OS_WIN)

Reply via email to