osquery-1/osquery/events/pathset.h
Jesse Kornblum c7355b19aa Update osquery licensing wording (#5452)
Summary:
Pull Request resolved: https://github.com/facebook/osquery/pull/5452

As suggested in another diff, this diff updates the language we use to describe the osquery licensing terms. We are changing all instances of

//This source code is licensed as defined on the LICENSE file found in the root directory of this source tree.//

to

//This source code is licensed in accordance with the terms specified in the LICENSE file found in the root directory of this source tree.//

We accomplish this with a codemod:

  $ codemod -md xplat/osquery/oss --extensions cpp,h,in,py,sh,mm,ps1 "(.\s+)This source code is licensed as defined on the LICENSE file found in the(.*)root directory of this source tree\." "\1This source code is licensed in accordance with the terms specified in\2the LICENSE file found in the root directory of this source tree."

Reviewed By: fmanco

Differential Revision: D14131290

fbshipit-source-id: 52c90da342263e2a80f5a678ecd760c19cf7513e
2019-02-19 10:59:48 -08:00

158 lines
3.7 KiB
C++

/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed in accordance with the terms specified in
* the LICENSE file found in the root directory of this source tree.
*/
#pragma once
#include <mutex>
#include <set>
#include <string>
#include <vector>
#include <boost/noncopyable.hpp>
#include <boost/tokenizer.hpp>
#include <osquery/core.h>
#include <osquery/filesystem/filesystem.h>
namespace osquery {
/**
* @brief multiset based implementation for path search.
*
* 'multiset' is used because with patterns we can serach for equivalent keys.
* Since '/This/Path/is' ~= '/This/Path/%' ~= '/This/Path/%%' (equivalent).
*
* multiset is protected by lock. It is threadsafe.
*
* PathSet can take any of the two policies -
* 1. patternedPath - Path can contain pattern '%' and '%%'.
* Path components containing only '%' and '%%' are supported
* e.g. '/This/Path/%'.
* Path components containing partial patterns are not
* supported e.g. '/This/Path/xyz%' ('xyz%' will not be
* treated as pattern).
*/
template <typename PathType>
class PathSet : private boost::noncopyable {
public:
void insert(const std::string& str) {
auto pattern = str;
replaceGlobWildcards(pattern);
auto vpath = PathType::createVPath(pattern);
WriteLock lock(mset_lock_);
for (auto& path : vpath) {
paths_.insert(std::move(path));
}
}
bool find(const std::string& str) const {
auto path = PathType::createPath(str);
ReadLock lock(mset_lock_);
if (paths_.find(path) != paths_.end()) {
return true;
}
return false;
}
void clear() {
WriteLock lock(mset_lock_);
paths_.clear();
}
bool empty() const {
ReadLock lock(mset_lock_);
return paths_.empty();
}
private:
typedef typename PathType::Path Path;
typedef typename PathType::Compare Compare;
std::multiset<Path, Compare> paths_;
mutable Mutex mset_lock_;
};
class patternedPath {
public:
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
typedef std::vector<std::string> Path;
typedef std::vector<Path> VPath;
struct Compare {
bool operator()(const Path& lhs, const Path& rhs) const {
size_t psize = (lhs.size() < rhs.size()) ? lhs.size() : rhs.size();
unsigned ndx;
for (ndx = 0; ndx < psize; ++ndx) {
if (lhs[ndx] == "**" || rhs[ndx] == "**") {
return false;
}
if (lhs[ndx] == "*" || rhs[ndx] == "*") {
continue;
}
int rc = lhs[ndx].compare(rhs[ndx]);
if (rc > 0) {
return false;
}
if (rc < 0) {
return true;
}
}
if ((ndx == rhs.size() && rhs[ndx - 1] == "*") ||
(ndx == lhs.size() && lhs[ndx - 1] == "*")) {
return false;
}
return (lhs.size() < rhs.size());
}
};
static Path createPath(const std::string& str) {
boost::char_separator<char> sep{"/"};
tokenizer tokens(str, sep);
Path path;
if (str == "/") {
path.push_back("");
}
for (std::string component : tokens) {
path.push_back(std::move(component));
}
return path;
}
static VPath createVPath(const std::string& str) {
boost::char_separator<char> sep{"/"};
tokenizer tokens(str, sep);
VPath vpath;
Path path;
if (str == "/") {
path.push_back("");
}
for (std::string component : tokens) {
if (component == "**") {
vpath.push_back(path);
path.push_back(std::move(component));
break;
}
path.push_back(std::move(component));
}
vpath.push_back(std::move(path));
return vpath;
}
};
} // namespace osquery