mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Merge remote-tracking branch 'origin/master' into topic/robin/dynamic-plugins-2.3
This commit is contained in:
commit
3f47c5bc87
277 changed files with 9933 additions and 4287 deletions
422
src/util.cc
422
src/util.cc
|
@ -590,6 +590,33 @@ const char* fmt_access_time(double t)
|
|||
return buf;
|
||||
}
|
||||
|
||||
bool ensure_intermediate_dirs(const char* dirname)
|
||||
{
|
||||
if ( ! dirname || strlen(dirname) == 0 )
|
||||
return false;
|
||||
|
||||
bool absolute = dirname[0] == '/';
|
||||
string path = normalize_path(dirname);
|
||||
|
||||
vector<string> path_components;
|
||||
tokenize_string(path, "/", &path_components);
|
||||
|
||||
string current_dir;
|
||||
|
||||
for ( size_t i = 0; i < path_components.size(); ++i )
|
||||
{
|
||||
if ( i > 0 || absolute )
|
||||
current_dir += "/";
|
||||
|
||||
current_dir += path_components[i];
|
||||
|
||||
if ( ! ensure_dir(current_dir.c_str()) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ensure_dir(const char *dirname)
|
||||
{
|
||||
struct stat st;
|
||||
|
@ -972,90 +999,162 @@ string bro_prefixes()
|
|||
|
||||
const char* PACKAGE_LOADER = "__load__.bro";
|
||||
|
||||
// If filename is pointing to a directory that contains a file called
|
||||
// PACKAGE_LOADER, returns the files path. Otherwise returns filename itself.
|
||||
// In both cases, the returned string is newly allocated.
|
||||
static const char* check_for_dir(const char* filename, bool load_pkgs)
|
||||
FILE* open_file(const string& path, const string& mode)
|
||||
{
|
||||
if ( load_pkgs && is_dir(filename) )
|
||||
{
|
||||
char init_filename_buf[1024];
|
||||
safe_snprintf(init_filename_buf, sizeof(init_filename_buf),
|
||||
"%s/%s", filename, PACKAGE_LOADER);
|
||||
if ( path.empty() )
|
||||
return 0;
|
||||
|
||||
if ( access(init_filename_buf, R_OK) == 0 )
|
||||
return copy_string(init_filename_buf);
|
||||
}
|
||||
FILE* rval = fopen(path.c_str(), mode.c_str());
|
||||
|
||||
return copy_string(filename);
|
||||
}
|
||||
|
||||
static FILE* open_file(const char* filename, const char** full_filename, bool load_pkgs)
|
||||
{
|
||||
filename = check_for_dir(filename, load_pkgs);
|
||||
|
||||
if ( full_filename )
|
||||
*full_filename = copy_string(filename);
|
||||
|
||||
FILE* f = fopen(filename, "r");
|
||||
|
||||
if ( ! f )
|
||||
if ( ! rval )
|
||||
{
|
||||
char buf[256];
|
||||
strerror_r(errno, buf, sizeof(buf));
|
||||
reporter->Error("Failed to open file %s: %s", filename, buf);
|
||||
}
|
||||
|
||||
delete [] filename;
|
||||
|
||||
return f;
|
||||
return rval;
|
||||
}
|
||||
|
||||
// Canonicalizes a given 'file' that lives in 'path' into a flattened,
|
||||
// dotted format. If the optional 'prefix' argument is given, it is
|
||||
// prepended to the dotted-format, separated by another dot.
|
||||
// If 'file' is __load__.bro, that part is discarded when constructing
|
||||
// the final dotted-format.
|
||||
string dot_canon(string path, string file, string prefix)
|
||||
static bool can_read(const string& path)
|
||||
{
|
||||
string dottedform(prefix);
|
||||
if ( prefix != "" )
|
||||
dottedform.append(".");
|
||||
dottedform.append(path);
|
||||
char* tmp = copy_string(file.c_str());
|
||||
char* bname = basename(tmp);
|
||||
if ( ! streq(bname, PACKAGE_LOADER) )
|
||||
return access(path.c_str(), R_OK) == 0;
|
||||
}
|
||||
|
||||
FILE* open_package(string& path, const string& mode)
|
||||
{
|
||||
string arg_path = path;
|
||||
path.append("/").append(PACKAGE_LOADER);
|
||||
|
||||
if ( can_read(path) )
|
||||
return open_file(path, mode);
|
||||
|
||||
reporter->Error("Failed to open package '%s': missing '%s' file",
|
||||
arg_path.c_str(), PACKAGE_LOADER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SafePathOp::CheckValid(const char* op_result, const char* path,
|
||||
bool error_aborts)
|
||||
{
|
||||
if ( op_result )
|
||||
{
|
||||
if ( path != "" )
|
||||
dottedform.append(".");
|
||||
dottedform.append(bname);
|
||||
result = op_result;
|
||||
error = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( error_aborts )
|
||||
reporter->InternalError("Path operation failed on %s: %s",
|
||||
path ? path : "<null>", strerror(errno));
|
||||
else
|
||||
error = true;
|
||||
}
|
||||
delete [] tmp;
|
||||
size_t n;
|
||||
while ( (n = dottedform.find("/")) != string::npos )
|
||||
dottedform.replace(n, 1, ".");
|
||||
return dottedform;
|
||||
}
|
||||
|
||||
// returns a normalized version of a path, removing duplicate slashes,
|
||||
// extraneous dots that refer to the current directory, and pops as many
|
||||
// parent directories referred to by "../" as possible
|
||||
const char* normalize_path(const char* path)
|
||||
SafeDirname::SafeDirname(const char* path, bool error_aborts)
|
||||
: SafePathOp()
|
||||
{
|
||||
DoFunc(path ? path : "", error_aborts);
|
||||
}
|
||||
|
||||
SafeDirname::SafeDirname(const string& path, bool error_aborts)
|
||||
: SafePathOp()
|
||||
{
|
||||
DoFunc(path, error_aborts);
|
||||
}
|
||||
|
||||
void SafeDirname::DoFunc(const string& path, bool error_aborts)
|
||||
{
|
||||
char* tmp = copy_string(path.c_str());
|
||||
CheckValid(dirname(tmp), tmp, error_aborts);
|
||||
delete [] tmp;
|
||||
}
|
||||
|
||||
SafeBasename::SafeBasename(const char* path, bool error_aborts)
|
||||
: SafePathOp()
|
||||
{
|
||||
DoFunc(path ? path : "", error_aborts);
|
||||
}
|
||||
|
||||
SafeBasename::SafeBasename(const string& path, bool error_aborts)
|
||||
: SafePathOp()
|
||||
{
|
||||
DoFunc(path, error_aborts);
|
||||
}
|
||||
|
||||
void SafeBasename::DoFunc(const string& path, bool error_aborts)
|
||||
{
|
||||
char* tmp = copy_string(path.c_str());
|
||||
CheckValid(basename(tmp), tmp, error_aborts);
|
||||
delete [] tmp;
|
||||
}
|
||||
|
||||
string implode_string_vector(const std::vector<std::string>& v,
|
||||
const std::string& delim)
|
||||
{
|
||||
string rval;
|
||||
|
||||
for ( size_t i = 0; i < v.size(); ++i )
|
||||
{
|
||||
if ( i > 0 )
|
||||
rval += delim;
|
||||
|
||||
rval += v[i];
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
string flatten_script_name(const string& name, const string& prefix)
|
||||
{
|
||||
string rval = prefix;
|
||||
|
||||
if ( ! rval.empty() )
|
||||
rval.append(".");
|
||||
|
||||
if ( SafeBasename(name).result == PACKAGE_LOADER )
|
||||
rval.append(SafeDirname(name).result);
|
||||
else
|
||||
rval.append(name);
|
||||
|
||||
size_t i;
|
||||
|
||||
while ( (i = rval.find('/')) != string::npos )
|
||||
rval[i] = '.';
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
vector<string>* tokenize_string(string input, const string& delim,
|
||||
vector<string>* rval)
|
||||
{
|
||||
if ( ! rval )
|
||||
rval = new vector<string>();
|
||||
|
||||
size_t n;
|
||||
|
||||
while ( (n = input.find(delim)) != string::npos )
|
||||
{
|
||||
rval->push_back(input.substr(0, n));
|
||||
input.erase(0, n + 1);
|
||||
}
|
||||
|
||||
rval->push_back(input);
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
string normalize_path(const string& path)
|
||||
{
|
||||
size_t n;
|
||||
string p(path);
|
||||
vector<string> components, final_components;
|
||||
string new_path;
|
||||
|
||||
if ( p[0] == '/' )
|
||||
if ( path[0] == '/' )
|
||||
new_path = "/";
|
||||
|
||||
while ( (n = p.find("/")) != string::npos )
|
||||
{
|
||||
components.push_back(p.substr(0, n));
|
||||
p.erase(0, n + 1);
|
||||
}
|
||||
components.push_back(p);
|
||||
tokenize_string(path, "/", &components);
|
||||
|
||||
vector<string>::const_iterator it;
|
||||
for ( it = components.begin(); it != components.end(); ++it )
|
||||
|
@ -1081,127 +1180,82 @@ const char* normalize_path(const char* path)
|
|||
if ( new_path.size() > 1 && new_path[new_path.size() - 1] == '/' )
|
||||
new_path.erase(new_path.size() - 1);
|
||||
|
||||
return copy_string(new_path.c_str());
|
||||
return new_path;
|
||||
}
|
||||
|
||||
// Returns the subpath of the root Bro script install/source/build directory in
|
||||
// which the loaded file is located. If it's not under a subpath of that
|
||||
// directory (e.g. cwd or custom path) then the full path is returned.
|
||||
void get_script_subpath(const std::string& full_filename, const char** subpath)
|
||||
string without_bropath_component(const string& path)
|
||||
{
|
||||
size_t p;
|
||||
std::string my_subpath(full_filename);
|
||||
string rval = normalize_path(path);
|
||||
|
||||
// get the parent directory of file (if not already a directory)
|
||||
if ( ! is_dir(full_filename.c_str()) )
|
||||
vector<string> paths;
|
||||
tokenize_string(bro_path(), ":", &paths);
|
||||
|
||||
for ( size_t i = 0; i < paths.size(); ++i )
|
||||
{
|
||||
char* tmp = copy_string(full_filename.c_str());
|
||||
my_subpath = dirname(tmp);
|
||||
delete [] tmp;
|
||||
string common = normalize_path(paths[i]);
|
||||
|
||||
if ( rval.find(common) != 0 )
|
||||
continue;
|
||||
|
||||
// Found the containing directory.
|
||||
rval.erase(0, common.size());
|
||||
|
||||
// Remove leading path separators.
|
||||
while ( rval.size() && rval[0] == '/' )
|
||||
rval.erase(0, 1);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
// first check if this is some subpath of the installed scripts root path,
|
||||
// if not check if it's a subpath of the script source root path,
|
||||
// then check if it's a subpath of the build directory (where BIF scripts
|
||||
// will get generated).
|
||||
// If none of those, will just use the given directory.
|
||||
if ( (p = my_subpath.find(BRO_SCRIPT_INSTALL_PATH)) != std::string::npos )
|
||||
my_subpath.erase(0, strlen(BRO_SCRIPT_INSTALL_PATH));
|
||||
else if ( (p = my_subpath.find(BRO_SCRIPT_SOURCE_PATH)) != std::string::npos )
|
||||
my_subpath.erase(0, strlen(BRO_SCRIPT_SOURCE_PATH));
|
||||
else if ( (p = my_subpath.find(BRO_BUILD_SOURCE_PATH)) != std::string::npos )
|
||||
my_subpath.erase(0, strlen(BRO_BUILD_SOURCE_PATH));
|
||||
else if ( (p = my_subpath.find(BRO_BUILD_SCRIPTS_PATH)) != std::string::npos )
|
||||
my_subpath.erase(0, strlen(BRO_BUILD_SCRIPTS_PATH));
|
||||
|
||||
// if root path found, remove path separators until next path component
|
||||
if ( p != std::string::npos )
|
||||
while ( my_subpath.size() && my_subpath[0] == '/' )
|
||||
my_subpath.erase(0, 1);
|
||||
|
||||
*subpath = normalize_path(my_subpath.c_str());
|
||||
return rval;
|
||||
}
|
||||
|
||||
extern string current_scanned_file_path;
|
||||
|
||||
FILE* search_for_file(const char* filename, const char* ext,
|
||||
const char** full_filename, bool load_pkgs,
|
||||
const char** bropath_subpath)
|
||||
static string find_file_in_path(const string& filename, const string& path,
|
||||
const string& opt_ext = "")
|
||||
{
|
||||
// If the file is a literal absolute path we don't have to search,
|
||||
// just return the result of trying to open it. If the file is
|
||||
// might be a relative path, check first if it's a real file that
|
||||
// can be referenced from cwd, else we'll try to search for it based
|
||||
// on what path the currently-loading script is in as well as the
|
||||
// standard BROPATH paths.
|
||||
if ( filename[0] == '/' ||
|
||||
(filename[0] == '.' && access(filename, R_OK) == 0) )
|
||||
if ( filename.empty() )
|
||||
return string();
|
||||
|
||||
// If file name is an absolute path, searching within *path* is pointless.
|
||||
if ( filename[0] == '/' )
|
||||
{
|
||||
if ( bropath_subpath )
|
||||
{
|
||||
char* tmp = copy_string(filename);
|
||||
*bropath_subpath = copy_string(dirname(tmp));
|
||||
delete [] tmp;
|
||||
}
|
||||
return open_file(filename, full_filename, load_pkgs);
|
||||
}
|
||||
|
||||
char path[1024], full_filename_buf[1024];
|
||||
|
||||
// Prepend the currently loading script's path to BROPATH so that
|
||||
// @loads can be referenced relatively.
|
||||
if ( current_scanned_file_path != "" && filename[0] == '.' )
|
||||
safe_snprintf(path, sizeof(path), "%s:%s",
|
||||
current_scanned_file_path.c_str(), bro_path().c_str());
|
||||
else
|
||||
safe_strncpy(path, bro_path().c_str(), sizeof(path));
|
||||
|
||||
char* dir_beginning = path;
|
||||
char* dir_ending = path;
|
||||
int more = *dir_beginning != '\0';
|
||||
|
||||
while ( more )
|
||||
{
|
||||
while ( *dir_ending && *dir_ending != ':' )
|
||||
++dir_ending;
|
||||
|
||||
if ( *dir_ending == ':' )
|
||||
*dir_ending = '\0';
|
||||
if ( can_read(filename) )
|
||||
return filename;
|
||||
else
|
||||
more = 0;
|
||||
|
||||
safe_snprintf(full_filename_buf, sizeof(full_filename_buf),
|
||||
"%s/%s.%s", dir_beginning, filename, ext);
|
||||
if ( access(full_filename_buf, R_OK) == 0 &&
|
||||
! is_dir(full_filename_buf) )
|
||||
{
|
||||
if ( bropath_subpath )
|
||||
get_script_subpath(full_filename_buf, bropath_subpath);
|
||||
return open_file(full_filename_buf, full_filename, load_pkgs);
|
||||
}
|
||||
|
||||
safe_snprintf(full_filename_buf, sizeof(full_filename_buf),
|
||||
"%s/%s", dir_beginning, filename);
|
||||
if ( access(full_filename_buf, R_OK) == 0 )
|
||||
{
|
||||
if ( bropath_subpath )
|
||||
get_script_subpath(full_filename_buf, bropath_subpath);
|
||||
return open_file(full_filename_buf, full_filename, load_pkgs);
|
||||
}
|
||||
|
||||
dir_beginning = ++dir_ending;
|
||||
return string();
|
||||
}
|
||||
|
||||
if ( full_filename )
|
||||
*full_filename = copy_string(filename);
|
||||
if ( bropath_subpath )
|
||||
{
|
||||
char* tmp = copy_string(filename);
|
||||
*bropath_subpath = copy_string(dirname(tmp));
|
||||
delete [] tmp;
|
||||
}
|
||||
string abs_path = path + '/' + filename;
|
||||
|
||||
return 0;
|
||||
if ( ! opt_ext.empty() )
|
||||
{
|
||||
string with_ext = abs_path + '.' + opt_ext;
|
||||
|
||||
if ( can_read(with_ext) )
|
||||
return with_ext;
|
||||
}
|
||||
|
||||
if ( can_read(abs_path) )
|
||||
return abs_path;
|
||||
|
||||
return string();
|
||||
}
|
||||
|
||||
string find_file(const string& filename, const string& path_set,
|
||||
const string& opt_ext)
|
||||
{
|
||||
vector<string> paths;
|
||||
tokenize_string(path_set, ":", &paths);
|
||||
|
||||
for ( size_t n = 0; n < paths.size(); ++n )
|
||||
{
|
||||
string f = find_file_in_path(filename, paths[n], opt_ext);
|
||||
|
||||
if ( ! f.empty() )
|
||||
return f;
|
||||
}
|
||||
|
||||
return string();
|
||||
}
|
||||
|
||||
FILE* rotate_file(const char* name, RecordVal* rotate_info)
|
||||
|
@ -1649,48 +1703,28 @@ void operator delete[](void* v)
|
|||
|
||||
#endif
|
||||
|
||||
// Being selective of which components of MAGIC_NO_CHECK_BUILTIN are actually
|
||||
// known to be problematic, but keeping rest of libmagic's builtin checks.
|
||||
#define DISABLE_LIBMAGIC_BUILTIN_CHECKS ( \
|
||||
/* MAGIC_NO_CHECK_COMPRESS | */ \
|
||||
/* MAGIC_NO_CHECK_TAR | */ \
|
||||
/* MAGIC_NO_CHECK_SOFT | */ \
|
||||
/* MAGIC_NO_CHECK_APPTYPE | */ \
|
||||
/* MAGIC_NO_CHECK_ELF | */ \
|
||||
/* MAGIC_NO_CHECK_TEXT | */ \
|
||||
MAGIC_NO_CHECK_CDF | \
|
||||
MAGIC_NO_CHECK_TOKENS \
|
||||
/* MAGIC_NO_CHECK_ENCODING */ \
|
||||
)
|
||||
|
||||
void bro_init_magic(magic_t* cookie_ptr, int flags)
|
||||
{
|
||||
if ( ! cookie_ptr || *cookie_ptr )
|
||||
return;
|
||||
|
||||
*cookie_ptr = magic_open(flags|DISABLE_LIBMAGIC_BUILTIN_CHECKS);
|
||||
*cookie_ptr = magic_open(flags);
|
||||
|
||||
// Use our custom database for mime types, but the default database
|
||||
// from libmagic for the verbose file type.
|
||||
const char* database = (flags & MAGIC_MIME) ? bro_magic_path() : 0;
|
||||
// Always use Bro's custom magic database.
|
||||
const char* database = bro_magic_path();
|
||||
|
||||
if ( ! *cookie_ptr )
|
||||
{
|
||||
const char* err = magic_error(*cookie_ptr);
|
||||
if ( ! err )
|
||||
err = "unknown";
|
||||
|
||||
reporter->InternalError("can't init libmagic: %s", err);
|
||||
reporter->InternalError("can't init libmagic: %s",
|
||||
err ? err : "unknown");
|
||||
}
|
||||
|
||||
else if ( magic_load(*cookie_ptr, database) < 0 )
|
||||
{
|
||||
const char* err = magic_error(*cookie_ptr);
|
||||
if ( ! err )
|
||||
err = "unknown";
|
||||
|
||||
const char* db_name = database ? database : "<default>";
|
||||
reporter->InternalError("can't load magic file %s: %s", db_name, err);
|
||||
reporter->InternalError("can't load magic file %s: %s", database,
|
||||
err ? err : "unknown");
|
||||
magic_close(*cookie_ptr);
|
||||
*cookie_ptr = 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue