diff --git a/src/broxygen/Document.cc b/src/broxygen/Document.cc index 1b9618f66b..41622aa41f 100644 --- a/src/broxygen/Document.cc +++ b/src/broxygen/Document.cc @@ -104,7 +104,7 @@ string IdentifierDocument::GetFieldComments(const string& field) const ScriptDocument::ScriptDocument(const string& arg_name) : Document(), name(arg_name), - is_pkg_loader(safe_basename(name) == PACKAGE_LOADER), + is_pkg_loader(SafeBasename(name).result == PACKAGE_LOADER), dependencies(), module_usages(), comments(), identifier_docs(), redefs() { } diff --git a/src/broxygen/Manager.cc b/src/broxygen/Manager.cc index 2165b57122..72ef0aab1e 100644 --- a/src/broxygen/Manager.cc +++ b/src/broxygen/Manager.cc @@ -142,7 +142,7 @@ void Manager::File(const string& path) if ( ! doc->IsPkgLoader() ) return; - name = safe_dirname(name); + name = SafeDirname(name).result; if ( packages.GetDocument(name) ) { diff --git a/src/scan.l b/src/scan.l index 2477afa645..3dc68a52cc 100644 --- a/src/scan.l +++ b/src/scan.l @@ -59,7 +59,7 @@ static string find_relative_file(const string& filename, const string& ext) return string(); if ( filename[0] == '.' ) - return find_file(filename, safe_dirname(::filename), ext); + return find_file(filename, SafeDirname(::filename).result, ext); else return find_file(filename, bro_path(), ext); } @@ -275,7 +275,7 @@ when return TOK_WHEN; @DEBUG return TOK_DEBUG; // marks input for debugger @DIR { - string rval = safe_dirname(::filename); + string rval = SafeDirname(::filename).result; if ( ! rval.empty() && rval[0] == '.' ) { @@ -291,15 +291,7 @@ when return TOK_WHEN; } @FILENAME { - char* filename_copy = copy_string(::filename); - const char* bname = basename(filename_copy); - - if ( ! bname ) - reporter->InternalError("basename failed: %s", strerror(errno)); - - StringVal* rval = new StringVal(bname); - delete [] filename_copy; - RET_CONST(rval); + RET_CONST(new StringVal(SafeBasename(::filename).result)); } @load{WS}{FILE} { diff --git a/src/util.cc b/src/util.cc index bf98bb9ed3..eacbf46eb7 100644 --- a/src/util.cc +++ b/src/util.cc @@ -944,34 +944,36 @@ FILE* open_package(string& path, const string& mode) return 0; } -string safe_dirname(const char* path) +SafePathOp::SafePathOp(PathOpFn fn, const char* path, bool error_aborts) { - if ( ! path ) - return "."; - return safe_dirname(string(path)); + DoFunc(fn, path ? path : "", error_aborts); } -string safe_dirname(const string& path) +SafePathOp::SafePathOp(PathOpFn fn, const string& path, bool error_aborts) + { + DoFunc(fn, path, error_aborts); + } + +void SafePathOp::DoFunc(PathOpFn fn, const string& path, bool error_aborts) { char* tmp = copy_string(path.c_str()); - string rval = dirname(tmp); - delete [] tmp; - return rval; - } + char* rval = fn(tmp); -string safe_basename(const char* path) - { - if ( ! path ) - return "."; - return safe_basename(string(path)); - } + if ( rval ) + { + result = rval; + error = false; + } + else + { + if ( error_aborts ) + reporter->InternalError("Path operation failed on %s: %s", + tmp ? tmp : "", strerror(errno)); + else + error = true; + } -string safe_basename(const string& path) - { - char* tmp = copy_string(path.c_str()); - string rval = basename(tmp); delete [] tmp; - return rval; } string flatten_script_name(const string& name, const string& prefix) @@ -981,8 +983,8 @@ string flatten_script_name(const string& name, const string& prefix) if ( ! rval.empty() ) rval.append("."); - if ( safe_basename(name) == PACKAGE_LOADER ) - rval.append(safe_dirname(name)); + if ( SafeBasename(name).result == PACKAGE_LOADER ) + rval.append(SafeDirname(name).result); else rval.append(name); diff --git a/src/util.h b/src/util.h index faca450cd8..17dfb9c217 100644 --- a/src/util.h +++ b/src/util.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "config.h" #if __STDC__ @@ -208,13 +209,42 @@ extern const char* bro_path(); extern const char* bro_magic_path(); extern std::string bro_prefixes(); -// Wrappers for dirname(3) that won't modify argument. -std::string safe_dirname(const char* path); -std::string safe_dirname(const std::string& path); +/** + * Wrapper class for functions like dirname(3) or basename(3) that won't + * modify the path argument and may optionally abort execution on error. + */ +class SafePathOp { +public: -// Wrappers for basename(3) that won't modify argument. -std::string safe_basename(const char* path); -std::string safe_basename(const std::string& path); + typedef char*(*PathOpFn)(char*); + + SafePathOp(PathOpFn fn, const char* path, bool error_aborts = true); + SafePathOp(PathOpFn fn, const std::string& path, bool error_aborts = true); + + std::string result; + bool error; + +private: + + void DoFunc(PathOpFn fn, const std::string& path, bool error_aborts = true); +}; + +class SafeDirname : public SafePathOp { +public: + + SafeDirname(const char* path, bool error_aborts = true) + : SafePathOp(&dirname, path, error_aborts) { } + SafeDirname(const std::string& path, bool error_aborts = true) + : SafePathOp(&dirname, path, error_aborts) { } +}; + +class SafeBasename : public SafePathOp { +public: + SafeBasename(const char* path, bool error_aborts = true) + : SafePathOp(&basename, path, error_aborts) { } + SafeBasename(const std::string& path, bool error_aborts = true) + : SafePathOp(&basename, path, error_aborts) { } +}; /** * Flatten a script name by replacing '/' path separators with '.'.