8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 20:03:02 +01:00

Added operator include to config files

This commit is contained in:
alexpeshkoff 2013-03-27 11:45:02 +00:00
parent 850e529c81
commit e4356e4b46
22 changed files with 471 additions and 107 deletions

View File

@ -1516,6 +1516,16 @@ C --
PARAMETER (GDS__no_output_format = 335545051) PARAMETER (GDS__no_output_format = 335545051)
INTEGER*4 GDS__item_finish INTEGER*4 GDS__item_finish
PARAMETER (GDS__item_finish = 335545052) PARAMETER (GDS__item_finish = 335545052)
INTEGER*4 GDS__miss_config
PARAMETER (GDS__miss_config = 335545053)
INTEGER*4 GDS__conf_line
PARAMETER (GDS__conf_line = 335545054)
INTEGER*4 GDS__conf_include
PARAMETER (GDS__conf_include = 335545055)
INTEGER*4 GDS__include_depth
PARAMETER (GDS__include_depth = 335545056)
INTEGER*4 GDS__include_miss
PARAMETER (GDS__include_miss = 335545057)
INTEGER*4 GDS__gfix_db_name INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929) PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw INTEGER*4 GDS__gfix_invalid_sw

View File

@ -765,6 +765,11 @@ const
gds_wrong_message_length = 335545050; gds_wrong_message_length = 335545050;
gds_no_output_format = 335545051; gds_no_output_format = 335545051;
gds_item_finish = 335545052; gds_item_finish = 335545052;
gds_miss_config = 335545053;
gds_conf_line = 335545054;
gds_conf_include = 335545055;
gds_include_depth = 335545056;
gds_include_miss = 335545057;
gds_gfix_db_name = 335740929; gds_gfix_db_name = 335740929;
gds_gfix_invalid_sw = 335740930; gds_gfix_invalid_sw = 335740930;
gds_gfix_incmp_sw = 335740932; gds_gfix_incmp_sw = 335740932;

View File

@ -28,6 +28,8 @@
#include "../common/config/ConfigCache.h" #include "../common/config/ConfigCache.h"
#include "../common/config/config_file.h" #include "../common/config/config_file.h"
#include "gen/iberror.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -37,38 +39,49 @@
#include <errno.h> #include <errno.h>
#endif #endif
ConfigCache::ConfigCache(Firebird::MemoryPool& p, const Firebird::PathName& fName) using namespace Firebird;
: PermanentStorage(p), fileName(getPool(), fName), fileTime(0)
{ ConfigCache::ConfigCache(MemoryPool& p, const PathName& fName)
} : PermanentStorage(p), files(FB_NEW(getPool()) ConfigCache::File(getPool(), fName))
{ }
ConfigCache::~ConfigCache() ConfigCache::~ConfigCache()
{ {
delete files;
} }
void ConfigCache::checkLoadConfig() void ConfigCache::checkLoadConfig()
{ {
time_t newTime = getTime(); { // scope
if (fileTime == newTime) ReadLockGuard guard(rwLock, "ConfigCache::checkLoadConfig");
{ if (files->checkLoadConfig(false))
return; {
return;
}
} }
Firebird::WriteLockGuard guard(rwLock, "ConfigCache::checkLoadConfig"); WriteLockGuard guard(rwLock, "ConfigCache::checkLoadConfig");
// may be someone already reloaded? // may be someone already reloaded?
newTime = getTime(); if (files->checkLoadConfig(true))
if (fileTime == newTime)
{ {
return; return;
} }
fileTime = newTime; files->trim();
loadConfig(); loadConfig();
} }
time_t ConfigCache::getTime() void ConfigCache::addFile(const Firebird::PathName& fName)
{
files->add(fName);
}
Firebird::PathName ConfigCache::getFileName()
{
return files->fileName;
}
time_t ConfigCache::File::getTime()
{ {
struct stat st; struct stat st;
if (stat(fileName.c_str(), &st) != 0) if (stat(fileName.c_str(), &st) != 0)
@ -78,7 +91,58 @@ time_t ConfigCache::getTime()
// config file is missing, but this is not our problem // config file is missing, but this is not our problem
return 0; return 0;
} }
Firebird::system_call_failed::raise("stat"); system_call_failed::raise("stat");
} }
return st.st_mtime; return st.st_mtime;
} }
ConfigCache::File::File(MemoryPool& p, const PathName& fName)
: PermanentStorage(p), fileName(getPool(), fName), fileTime(0), next(NULL)
{ }
ConfigCache::File::~File()
{
delete next;
}
bool ConfigCache::File::checkLoadConfig(bool set)
{
time_t newTime = getTime();
if (fileTime == newTime)
{
return next ? next->checkLoadConfig(set) : true;
}
if (set)
{
fileTime = newTime;
if (next)
{
next->checkLoadConfig(set);
}
}
return false;
}
void ConfigCache::File::add(const PathName& fName)
{
if (fName == fileName)
{
return;
}
if (next)
{
next->add(fName);
}
else
{
next = FB_NEW(getPool()) ConfigCache::File(getPool(), fName);
}
}
void ConfigCache::File::trim()
{
delete next;
next = NULL;
}

View File

@ -39,19 +39,35 @@ public:
virtual ~ConfigCache(); virtual ~ConfigCache();
void checkLoadConfig(); void checkLoadConfig();
void addFile(const Firebird::PathName& fName);
Firebird::PathName getFileName();
protected: protected:
virtual void loadConfig() = 0; virtual void loadConfig() = 0;
private: private:
time_t getTime(); class File : public Firebird::PermanentStorage
{
public:
File(Firebird::MemoryPool& p, const Firebird::PathName& fName);
~File();
bool checkLoadConfig(bool set);
void add(const Firebird::PathName& fName);
void trim();
public:
Firebird::PathName fileName;
private:
volatile time_t fileTime;
File* next;
time_t getTime();
};
File* files;
public: public:
Firebird::RWLock rwLock; Firebird::RWLock rwLock;
Firebird::PathName fileName;
private:
volatile time_t fileTime;
}; };
#endif // COMMON_CONFIG_CASHE_H #endif // COMMON_CONFIG_CASHE_H

View File

@ -45,14 +45,24 @@ class ConfigImpl : public Firebird::PermanentStorage
{ {
public: public:
explicit ConfigImpl(Firebird::MemoryPool& p) explicit ConfigImpl(Firebird::MemoryPool& p)
: Firebird::PermanentStorage(p), confMessage(getPool()) : Firebird::PermanentStorage(p), missConf(false)
{ {
ConfigFile file(fb_utils::getPrefix(fb_utils::FB_DIR_CONF, CONFIG_FILE)); try
defaultConfig = new Config(file);
if (file.getMessage())
{ {
confMessage = file.getMessage(); ConfigFile file(fb_utils::getPrefix(fb_utils::FB_DIR_CONF, CONFIG_FILE));
defaultConfig = new Config(file);
}
catch (const Firebird::status_exception& ex)
{
if (ex.value()[1] != isc_miss_config)
{
throw;
}
missConf = true;
ConfigFile file(ConfigFile::USE_TEXT, "");
defaultConfig = new Config(file);
} }
} }
@ -66,9 +76,9 @@ public:
return defaultConfig; return defaultConfig;
} }
const char* getMessage() bool missFirebirdConf()
{ {
return confMessage.nullStr(); return missConf;
} }
private: private:
@ -77,7 +87,7 @@ private:
ConfigImpl(const ConfigImpl&); ConfigImpl(const ConfigImpl&);
void operator=(const ConfigImpl&); void operator=(const ConfigImpl&);
Firebird::string confMessage; bool missConf;
}; };
/****************************************************************************** /******************************************************************************
@ -196,7 +206,7 @@ Config::Config(const ConfigFile& file)
if (entries[i].data_type == TYPE_STRING && values[i]) if (entries[i].data_type == TYPE_STRING && values[i])
{ {
ConfigFile::String expand((const char*)values[i]); ConfigFile::String expand((const char*)values[i]);
if (file.macroParse(expand) && expand != (const char*) values[i]) if (file.macroParse(expand, NULL) && expand != (const char*) values[i])
{ {
ConfigFile::String& saved(tempStrings.add()); ConfigFile::String& saved(tempStrings.add());
saved = expand; saved = expand;
@ -313,9 +323,9 @@ const Firebird::RefPtr<Config> Config::getDefaultConfig()
return firebirdConf().getDefaultConfig(); return firebirdConf().getDefaultConfig();
} }
const char* Config::getMessage() bool Config::missFirebirdConf()
{ {
return firebirdConf().getMessage(); return firebirdConf().missFirebirdConf();
} }
const char* Config::getInstallDirectory() const char* Config::getInstallDirectory()

View File

@ -185,9 +185,9 @@ public:
Config(const ConfigFile& file, const Config& base); // use to build db-specific config Config(const ConfigFile& file, const Config& base); // use to build db-specific config
~Config(); ~Config();
// Check for errors in .conf file // Check for missing firebird.conf
static const char* getMessage(); static bool missFirebirdConf();
// Interface to support command line root specification. // Interface to support command line root specification.
// This ugly solution was required to make it possible to specify root // This ugly solution was required to make it possible to specify root

View File

@ -26,7 +26,9 @@
#include "../common/classes/auto.h" #include "../common/classes/auto.h"
#include "../common/config/config_file.h" #include "../common/config/config_file.h"
#include "../common/config/config.h" #include "../common/config/config.h"
#include "../common/config/ConfigCache.h"
#include "../common/os/path_utils.h" #include "../common/os/path_utils.h"
#include "../common/ScanDir.h"
#include <stdio.h> #include <stdio.h>
#ifdef HAVE_STDLIB_H #ifdef HAVE_STDLIB_H
@ -37,16 +39,36 @@ using namespace Firebird;
namespace { namespace {
bool hasWildCards(const PathName& s)
{
return s.find_first_of("?*") != PathName::npos;
}
void strip2slashes(ConfigFile::String& to)
{
// strip double slashes
char sep2[3];
sep2[0] = PathUtils::dir_sep;
sep2[1] = sep2[0];
sep2[2] = 0;
size_t pos = 0;
while((pos = to.find(sep2, pos)) != PathName::npos)
{
to.erase(pos, 1);
}
}
class MainStream : public ConfigFile::Stream class MainStream : public ConfigFile::Stream
{ {
public: public:
MainStream(const char* fname, PathName& errString) MainStream(const char* fname)
: file(fopen(fname, "rt")), l(0) : file(fopen(fname, "rt")), fileName(fname), l(0)
{ {
if (!file) if (!file)
{ {
// config file does not exist // config file does not exist
errString.printf("Missing configuration file: %s", fname); (Arg::Gds(isc_miss_config) << fname << Arg::OsError()).raise();
} }
} }
@ -65,7 +87,10 @@ public:
{ {
return false; return false;
} }
input.LoadFromFile(file); if (!input.LoadFromFile(file))
{
return false;
}
++l; ++l;
input.alltrim(" \t\r"); input.alltrim(" \t\r");
} while (input.isEmpty() || input[0] == '#'); } while (input.isEmpty() || input[0] == '#');
@ -74,8 +99,19 @@ public:
return true; return true;
} }
bool active()
{
return file.hasData();
}
const char* getFileName() const
{
return fileName.c_str();
}
private: private:
AutoPtr<FILE, FileClose> file; AutoPtr<FILE, FileClose> file;
Firebird::PathName fileName;
unsigned int l; unsigned int l;
}; };
@ -125,6 +161,11 @@ public:
return true; return true;
} }
const char* getFileName() const
{
return NULL;
}
private: private:
const char* s; const char* s;
unsigned int l; unsigned int l;
@ -133,8 +174,8 @@ private:
class SubStream : public ConfigFile::Stream class SubStream : public ConfigFile::Stream
{ {
public: public:
SubStream() SubStream(const char* fName)
: cnt(0) : fileName(fName), cnt(0)
{ } { }
bool getLine(ConfigFile::String& input, unsigned int& line) bool getLine(ConfigFile::String& input, unsigned int& line)
@ -157,65 +198,71 @@ public:
data.push(Line(input, line)); data.push(Line(input, line));
} }
const char* getFileName() const
{
return fileName;
}
private: private:
typedef Pair<Left<ConfigFile::String, unsigned int> > Line; typedef Pair<Left<ConfigFile::String, unsigned int> > Line;
ObjectsArray<Line> data; ObjectsArray<Line> data;
const char* fileName;
size_t cnt; size_t cnt;
}; };
} // anonymous namespace } // anonymous namespace
ConfigFile::ConfigFile(const Firebird::PathName& file, USHORT fl) ConfigFile::ConfigFile(const Firebird::PathName& file, USHORT fl, ConfigCache* cache)
: AutoStorage(), : AutoStorage(),
configFile(getPool(), file),
parameters(getPool()), parameters(getPool()),
flags(fl), flags(fl),
lastMessage(getPool()) includeLimit(0),
filesCache(cache)
{ {
MainStream s(configFile.c_str(), lastMessage); MainStream s(file.c_str());
parse(&s); parse(&s);
} }
ConfigFile::ConfigFile(const char* file, USHORT fl) ConfigFile::ConfigFile(const char* file, USHORT fl, ConfigCache* cache)
: AutoStorage(), : AutoStorage(),
configFile(getPool(), String(file)),
parameters(getPool()), parameters(getPool()),
flags(fl), flags(fl),
lastMessage(getPool()) includeLimit(0),
filesCache(cache)
{ {
MainStream s(configFile.c_str(), lastMessage); MainStream s(file);
parse(&s); parse(&s);
} }
ConfigFile::ConfigFile(UseText, const char* configText, USHORT fl) ConfigFile::ConfigFile(UseText, const char* configText, USHORT fl)
: AutoStorage(), : AutoStorage(),
configFile(getPool()),
parameters(getPool()), parameters(getPool()),
flags(fl), flags(fl),
lastMessage(getPool()) includeLimit(0),
filesCache(NULL)
{ {
TextStream s(configText); TextStream s(configText);
parse(&s); parse(&s);
} }
ConfigFile::ConfigFile(MemoryPool& p, const Firebird::PathName& file, USHORT fl) ConfigFile::ConfigFile(MemoryPool& p, const Firebird::PathName& file, USHORT fl, ConfigCache* cache)
: AutoStorage(p), : AutoStorage(p),
configFile(getPool(), file),
parameters(getPool()), parameters(getPool()),
flags(fl), flags(fl),
lastMessage(getPool()) includeLimit(0),
filesCache(cache)
{ {
MainStream s(configFile.c_str(), lastMessage); MainStream s(file.c_str());
parse(&s); parse(&s);
} }
ConfigFile::ConfigFile(MemoryPool& p, ConfigFile::Stream* s, USHORT fl, const Firebird::PathName& file) ConfigFile::ConfigFile(MemoryPool& p, ConfigFile::Stream* s, USHORT fl)
: AutoStorage(p), : AutoStorage(p),
configFile(getPool(), file),
parameters(getPool()), parameters(getPool()),
flags(fl), flags(fl),
lastMessage(getPool()) includeLimit(0),
filesCache(NULL)
{ {
parse(s); parse(s);
} }
@ -229,12 +276,14 @@ ConfigFile::Stream::~Stream()
* Parse line, taking quotes into account * Parse line, taking quotes into account
*/ */
ConfigFile::LineType ConfigFile::parseLine(const String& input, KeyType& key, String& value) ConfigFile::LineType ConfigFile::parseLine(const char* fileName, const String& input, KeyType& key, String& value)
{ {
int inString = 0; int inString = 0;
String::size_type valStart = 0; String::size_type valStart = 0;
String::size_type eol = String::npos; String::size_type eol = String::npos;
bool hasSub = false; bool hasSub = false;
const char* include = "include";
const unsigned incLen = strlen(include);
for (String::size_type n = 0; n < input.length(); ++n) for (String::size_type n = 0; n < input.length(); ++n)
{ {
@ -271,6 +320,22 @@ ConfigFile::LineType ConfigFile::parseLine(const String& input, KeyType& key, St
case ' ': case ' ':
case '\t': case '\t':
if (n == incLen && key.isEmpty())
{
KeyType inc = input.substr(0, n).ToNoCaseString();
if (inc == include)
{
value = input.substr(n);
value.alltrim(" \t\r");
if (!macroParse(value, fileName))
{
return LINE_BAD;
}
return LINE_INCLUDE;
}
}
// fall down ...
case '\r': case '\r':
break; break;
@ -317,7 +382,7 @@ ConfigFile::LineType ConfigFile::parseLine(const String& input, KeyType& key, St
} }
// Now expand macros in value // Now expand macros in value
if (!macroParse(value)) if (!macroParse(value, fileName))
{ {
return LINE_BAD; return LINE_BAD;
} }
@ -330,7 +395,7 @@ ConfigFile::LineType ConfigFile::parseLine(const String& input, KeyType& key, St
* Substitute macro values in a string * Substitute macro values in a string
*/ */
bool ConfigFile::macroParse(String& value) const bool ConfigFile::macroParse(String& value, const char* fileName) const
{ {
String::size_type subFrom; String::size_type subFrom;
@ -341,7 +406,7 @@ bool ConfigFile::macroParse(String& value) const
{ {
String macro; String macro;
String m = value.substr(subFrom + 2, subTo - (subFrom + 2)); String m = value.substr(subFrom + 2, subTo - (subFrom + 2));
if (! translate(m, macro)) if (! translate(fileName, m, macro))
{ {
return false; return false;
} }
@ -353,6 +418,7 @@ bool ConfigFile::macroParse(String& value) const
} }
} }
strip2slashes(value);
return true; return true;
} }
@ -361,7 +427,7 @@ bool ConfigFile::macroParse(String& value) const
* Find macro value * Find macro value
*/ */
bool ConfigFile::translate(const String& from, String& to) const bool ConfigFile::translate(const char* fileName, const String& from, String& to) const
{ {
if (from == "root") if (from == "root")
{ {
@ -373,28 +439,28 @@ bool ConfigFile::translate(const String& from, String& to) const
} }
else if (from == "this") else if (from == "this")
{ {
if (configFile.isEmpty()) if (!fileName)
{ {
return false; return false;
} }
PathName tempPath = configFile; PathName tempPath(fileName);
#ifdef UNIX #ifdef UNIX
if (PathUtils::isSymLink(tempPath)) if (PathUtils::isSymLink(tempPath))
{ {
// If $(this) is a symlink, expand it. // If $(this) is a symlink, expand it.
TEXT temp[MAXPATHLEN]; TEXT temp[MAXPATHLEN];
const int n = readlink(configFile.c_str(), temp, sizeof(temp)); const int n = readlink(fileName, temp, sizeof(temp));
if (n != -1 && n < sizeof(temp)) if (n != -1 && unsigned(n) < sizeof(temp))
{ {
tempPath = temp; tempPath = temp;
if (PathUtils::isRelative(tempPath)) if (PathUtils::isRelative(tempPath))
{ {
PathName parent; PathName parent;
PathUtils::splitLastComponent(parent, tempPath, configFile); PathUtils::splitLastComponent(parent, tempPath, fileName);
PathUtils::concatPath(tempPath, parent, temp); PathUtils::concatPath(tempPath, parent, temp);
} }
} }
@ -460,10 +526,9 @@ const ConfigFile::Parameter* ConfigFile::findParameter(const KeyType& name, cons
* Take into an account fault line * Take into an account fault line
*/ */
void ConfigFile::badLine(const String& line) void ConfigFile::badLine(const char* fileName, const String& line)
{ {
lastMessage.printf("%s: illegal line <%s>", (Arg::Gds(isc_conf_line) << (fileName ? fileName : "Passed text") << line).raise();
(configFile.hasData() ? configFile.c_str() : "Passed text"), line.c_str());
} }
/****************************************************************************** /******************************************************************************
@ -476,28 +541,33 @@ void ConfigFile::parse(Stream* stream)
String inputLine; String inputLine;
Parameter* previous = NULL; Parameter* previous = NULL;
unsigned int line; unsigned int line;
const char* streamName = stream->getFileName();
while (stream->getLine(inputLine, line)) while (stream->getLine(inputLine, line))
{ {
Parameter current; Parameter current;
current.line = line; current.line = line;
switch (parseLine(inputLine, current.name, current.value)) switch (parseLine(streamName, inputLine, current.name, current.value))
{ {
case LINE_BAD: case LINE_BAD:
badLine(inputLine); badLine(streamName, inputLine);
return; return;
case LINE_REGULAR: case LINE_REGULAR:
if (current.name.isEmpty()) if (current.name.isEmpty())
{ {
badLine(inputLine); badLine(streamName, inputLine);
return; return;
} }
previous = &parameters[parameters.add(current)]; previous = &parameters[parameters.add(current)];
break; break;
case LINE_INCLUDE:
include(streamName, current.value.ToPathName());
break;
case LINE_START_SUB: case LINE_START_SUB:
if (current.name.hasData()) if (current.name.hasData())
{ {
@ -506,7 +576,7 @@ void ConfigFile::parse(Stream* stream)
} }
{ // subconf scope { // subconf scope
SubStream subStream; SubStream subStream(stream->getFileName());
while (stream->getLine(inputLine, line)) while (stream->getLine(inputLine, line))
{ {
if (inputLine[0] == '}') if (inputLine[0] == '}')
@ -515,7 +585,7 @@ void ConfigFile::parse(Stream* stream)
s.ltrim(" \t\r"); s.ltrim(" \t\r");
if (s.hasData() && s[0] != '#') if (s.hasData() && s[0] != '#')
{ {
badLine(s); badLine(streamName, s);
return; return;
} }
break; break;
@ -523,20 +593,128 @@ void ConfigFile::parse(Stream* stream)
subStream.putLine(inputLine, line); subStream.putLine(inputLine, line);
} }
previous->sub = FB_NEW(getPool()) ConfigFile(getPool(), &subStream, previous->sub = FB_NEW(getPool())
flags & ~HAS_SUB_CONF, configFile); ConfigFile(getPool(), &subStream, flags & ~HAS_SUB_CONF);
} }
break; break;
} }
} }
} }
//#define DEBUG_INCLUDES
/****************************************************************************** /******************************************************************************
* *
* Check for parse/load error * Parse include operator
*/ */
const char* ConfigFile::getMessage() const void ConfigFile::include(const char* currentFileName, const PathName& parPath)
{ {
return lastMessage.nullStr(); // We should better limit include depth
AutoSetRestore<unsigned> depth(&includeLimit, includeLimit + 1);
if (includeLimit > INCLUDE_LIMIT)
{
(Arg::Gds(isc_conf_include) << currentFileName << parPath << Arg::Gds(isc_include_depth)).raise();
}
// for relative paths first of all prepend with current path (i.e. path of current conf file)
PathName path;
if (PathUtils::isRelative(parPath))
{
PathName curPath;
PathUtils::splitLastComponent(curPath, path /*dummy*/, currentFileName);
PathUtils::concatPath(path, curPath, parPath);
}
else
{
path = parPath;
}
// split path into components
PathName pathPrefix;
PathUtils::splitPrefix(path, pathPrefix);
PathName savedPath(path); // Expect no *? in prefix
FilesArray components;
while (path.hasData())
{
PathName cur, tmp;
PathUtils::splitLastComponent(tmp, cur, path);
#ifdef DEBUG_INCLUDES
fprintf(stderr, "include: path=%s cur=%s tmp=%s\n", path.c_str(), cur.c_str(), tmp.c_str());
#endif
components.push(cur);
path = tmp;
}
// analyze components for wildcards
if (!wildCards(currentFileName, pathPrefix, components))
{
// no matches found - check for presence of wild symbols in path
if (!hasWildCards(savedPath))
{
(Arg::Gds(isc_conf_include) << currentFileName << parPath << Arg::Gds(isc_include_miss)).raise();
}
}
}
/******************************************************************************
*
* Parse wildcards
* - calls parse for found files
* - fills filesCache
* - returns true if some match was found
*/
bool ConfigFile::wildCards(const char* currentFileName, const PathName& pathPrefix, FilesArray& components)
{
// Any change in directory can cause config change
PathName prefix(pathPrefix);
if(!pathPrefix.hasData())
prefix = ".";
bool found = false;
PathName next(components.pop());
#ifdef DEBUG_INCLUDES
fprintf(stderr, "wildCards: prefix=%s next=%s left=%d\n",
prefix.c_str(), next.c_str(), components.getCount());
#endif
ScanDir list(prefix.c_str(), next.c_str());
while (list.next())
{
PathName name;
const PathName fileName = list.getFileName();
if (fileName == ".")
continue;
if (fileName[0] == '.' && next[0] != '.')
continue;
PathUtils::concatPath(name, pathPrefix, fileName);
#ifdef DEBUG_INCLUDES
fprintf(stderr, "in Scan: name=%s pathPrefix=%s list.fileName=%s\n",
name.c_str(), pathPrefix.c_str(), fileName.c_str());
#endif
if (filesCache)
filesCache->addFile(name);
if (components.hasData()) // should be directory
{
found = found || wildCards(currentFileName, name, components);
}
else
{
MainStream include(name.c_str());
if (include.active())
{
found = true;
parse(&include);
}
}
}
return found;
} }

View File

@ -46,6 +46,8 @@
(common/config/config.cpp) and server-side alias manager (common/db_alias.cpp). (common/config/config.cpp) and server-side alias manager (common/db_alias.cpp).
**/ **/
class ConfigCache;
class ConfigFile : public Firebird::AutoStorage, public Firebird::RefCounted class ConfigFile : public Firebird::AutoStorage, public Firebird::RefCounted
{ {
public: public:
@ -65,6 +67,7 @@ public:
public: public:
virtual ~Stream(); virtual ~Stream();
virtual bool getLine(String&, unsigned int&) = 0; virtual bool getLine(String&, unsigned int&) = 0;
virtual const char* getFileName() const = 0;
}; };
struct Parameter : public AutoStorage struct Parameter : public AutoStorage
@ -90,15 +93,16 @@ public:
typedef Firebird::SortedObjectsArray<Parameter, Firebird::InlineStorage<Parameter*, 100>, typedef Firebird::SortedObjectsArray<Parameter, Firebird::InlineStorage<Parameter*, 100>,
KeyType, Parameter> Parameters; KeyType, Parameter> Parameters;
typedef Firebird::ObjectsArray<Firebird::PathName> FilesArray;
ConfigFile(const Firebird::PathName& file, USHORT fl = 0); ConfigFile(const Firebird::PathName& file, USHORT fl = 0, ConfigCache* cache = NULL);
ConfigFile(const char* file, USHORT fl = 0); ConfigFile(const char* file, USHORT fl = 0, ConfigCache* cache = NULL);
ConfigFile(UseText, const char* configText, USHORT fl = 0); ConfigFile(UseText, const char* configText, USHORT fl = 0);
ConfigFile(MemoryPool& p, const Firebird::PathName& file, USHORT fl = 0); ConfigFile(MemoryPool& p, const Firebird::PathName& file, USHORT fl = 0, ConfigCache* cache = NULL);
private: private:
ConfigFile(MemoryPool& p, ConfigFile::Stream* s, USHORT fl, const Firebird::PathName& file); ConfigFile(MemoryPool& p, ConfigFile::Stream* s, USHORT fl);
public: public:
// key and value management // key and value management
@ -111,26 +115,25 @@ public:
return parameters; return parameters;
} }
// was there some error parsing config file?
const char* getMessage() const;
// Substitute macro values in a string // Substitute macro values in a string
bool macroParse(String& value) const; bool macroParse(String& value, const char* fileName) const;
private: private:
enum LineType {LINE_BAD, LINE_REGULAR, LINE_START_SUB}; enum LineType {LINE_BAD, LINE_REGULAR, LINE_START_SUB, LINE_INCLUDE};
Firebird::PathName configFile;
Parameters parameters; Parameters parameters;
USHORT flags; USHORT flags;
USHORT badLinesCount; unsigned includeLimit;
Firebird::PathName lastMessage; ConfigCache* filesCache;
static const unsigned INCLUDE_LIMIT = 64;
// utilities // utilities
void parse(Stream* stream); void parse(Stream* stream);
LineType parseLine(const String& input, KeyType& key, String& value); LineType parseLine(const char* fileName, const String& input, KeyType& key, String& value);
bool translate(const String& from, String& to) const; bool translate(const char* fileName, const String& from, String& to) const;
void badLine(const String& line); void badLine(const char* fileName, const String& line);
void include(const char* currentFileName, const Firebird::PathName& path);
bool wildCards(const char* currentFileName, const Firebird::PathName& pathPrefix, FilesArray& components);
}; };
#endif // CONFIG_CONFIG_FILE_H #endif // CONFIG_CONFIG_FILE_H

View File

@ -198,7 +198,7 @@ namespace
} }
databases.clear(); databases.clear();
ConfigFile aliasConfig(fileName, ConfigFile::HAS_SUB_CONF); ConfigFile aliasConfig(getFileName(), ConfigFile::HAS_SUB_CONF, this);
const ConfigFile::Parameters& params = aliasConfig.getParameters(); const ConfigFile::Parameters& params = aliasConfig.getParameters();
for (n = 0; n < params.getCount(); ++n) for (n = 0; n < params.getCount(); ++n)

View File

@ -147,6 +147,13 @@ public:
static void splitLastComponent(Firebird::PathName&, Firebird::PathName&, static void splitLastComponent(Firebird::PathName&, Firebird::PathName&,
const Firebird::PathName&); const Firebird::PathName&);
/** splitPrefix takes a path as the first argument, splits OS-dependent prefix
from it (something like C:\, D: or \ in windows or / in posix),
and returns stripped path inplace, i.e. as first argument.
Prefix is returned as the second argument.
**/
static void splitPrefix(Firebird::PathName& path, Firebird::PathName& prefix);
/** This is the factory method for allocating dir_iterator objects. /** This is the factory method for allocating dir_iterator objects.
It takes a reference to a memory pool to use for all heap allocations, It takes a reference to a memory pool to use for all heap allocations,
and the path of the directory to iterate (in that order). It is the and the path of the directory to iterate (in that order). It is the

View File

@ -118,6 +118,16 @@ void PathUtils::splitLastComponent(Firebird::PathName& path, Firebird::PathName&
file.append(orgPath, pos + 1, orgPath.length() - pos - 1); file.append(orgPath, pos + 1, orgPath.length() - pos - 1);
} }
void PathUtils::splitPrefix(Firebird::PathName& path, Firebird::PathName& prefix)
{
prefix.erase();
while (path[0] == dir_sep)
{
prefix = dir_sep;
path.erase(0, 1);
}
}
void PathUtils::concatPath(Firebird::PathName& result, void PathUtils::concatPath(Firebird::PathName& result,
const Firebird::PathName& first, const Firebird::PathName& first,
const Firebird::PathName& second) const Firebird::PathName& second)

View File

@ -754,6 +754,11 @@ static const struct {
{"wrong_message_length", 335545050}, {"wrong_message_length", 335545050},
{"no_output_format", 335545051}, {"no_output_format", 335545051},
{"item_finish", 335545052}, {"item_finish", 335545052},
{"miss_config", 335545053},
{"conf_line", 335545054},
{"conf_include", 335545055},
{"include_depth", 335545056},
{"include_miss", 335545057},
{"gfix_db_name", 335740929}, {"gfix_db_name", 335740929},
{"gfix_invalid_sw", 335740930}, {"gfix_invalid_sw", 335740930},
{"gfix_incmp_sw", 335740932}, {"gfix_incmp_sw", 335740932},

View File

@ -788,6 +788,11 @@ const ISC_STATUS isc_bad_result_set = 335545049L;
const ISC_STATUS isc_wrong_message_length = 335545050L; const ISC_STATUS isc_wrong_message_length = 335545050L;
const ISC_STATUS isc_no_output_format = 335545051L; const ISC_STATUS isc_no_output_format = 335545051L;
const ISC_STATUS isc_item_finish = 335545052L; const ISC_STATUS isc_item_finish = 335545052L;
const ISC_STATUS isc_miss_config = 335545053L;
const ISC_STATUS isc_conf_line = 335545054L;
const ISC_STATUS isc_conf_include = 335545055L;
const ISC_STATUS isc_include_depth = 335545056L;
const ISC_STATUS isc_include_miss = 335545057L;
const ISC_STATUS isc_gfix_db_name = 335740929L; const ISC_STATUS isc_gfix_db_name = 335740929L;
const ISC_STATUS isc_gfix_invalid_sw = 335740930L; const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
const ISC_STATUS isc_gfix_incmp_sw = 335740932L; const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
@ -1232,7 +1237,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
const ISC_STATUS isc_trace_switch_param_miss = 337182758L; const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L; const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L; const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
const ISC_STATUS isc_err_max = 1176; const ISC_STATUS isc_err_max = 1181;
#else /* c definitions */ #else /* c definitions */
@ -1990,6 +1995,11 @@ const ISC_STATUS isc_err_max = 1176;
#define isc_wrong_message_length 335545050L #define isc_wrong_message_length 335545050L
#define isc_no_output_format 335545051L #define isc_no_output_format 335545051L
#define isc_item_finish 335545052L #define isc_item_finish 335545052L
#define isc_miss_config 335545053L
#define isc_conf_line 335545054L
#define isc_conf_include 335545055L
#define isc_include_depth 335545056L
#define isc_include_miss 335545057L
#define isc_gfix_db_name 335740929L #define isc_gfix_db_name 335740929L
#define isc_gfix_invalid_sw 335740930L #define isc_gfix_invalid_sw 335740930L
#define isc_gfix_incmp_sw 335740932L #define isc_gfix_incmp_sw 335740932L
@ -2434,7 +2444,7 @@ const ISC_STATUS isc_err_max = 1176;
#define isc_trace_switch_param_miss 337182758L #define isc_trace_switch_param_miss 337182758L
#define isc_trace_param_act_notcompat 337182759L #define isc_trace_param_act_notcompat 337182759L
#define isc_trace_mandatory_switch_miss 337182760L #define isc_trace_mandatory_switch_miss 337182760L
#define isc_err_max 1176 #define isc_err_max 1181
#endif #endif

View File

@ -757,6 +757,11 @@ Data source : @4"}, /* eds_statement */
{335545050, "Message length passed from user application does not match set of columns"}, /* wrong_message_length */ {335545050, "Message length passed from user application does not match set of columns"}, /* wrong_message_length */
{335545051, "Resultset is missing output format information"}, /* no_output_format */ {335545051, "Resultset is missing output format information"}, /* no_output_format */
{335545052, "Message metadata not ready - item @1 is not finished"}, /* item_finish */ {335545052, "Message metadata not ready - item @1 is not finished"}, /* item_finish */
{335545053, "Missing configuration file: @1"}, /* miss_config */
{335545054, "@1: illegal line <@2>"}, /* conf_line */
{335545055, "Invalid include operator in @1 for <@2>"}, /* conf_include */
{335545056, "Include depth too big"}, /* include_depth */
{335545057, "File to include not found"}, /* include_miss */
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */ {335740929, "data base file name (@1) already given"}, /* gfix_db_name */
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */ {335740930, "invalid switch @1"}, /* gfix_invalid_sw */
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */ {335740932, "incompatible switch combination"}, /* gfix_incmp_sw */

View File

@ -753,6 +753,11 @@ static const struct {
{335545050, -804}, /* 730 wrong_message_length */ {335545050, -804}, /* 730 wrong_message_length */
{335545051, -804}, /* 731 no_output_format */ {335545051, -804}, /* 731 no_output_format */
{335545052, -804}, /* 732 item_finish */ {335545052, -804}, /* 732 item_finish */
{335545053, -902}, /* 733 miss_config */
{335545054, -902}, /* 734 conf_line */
{335545055, -902}, /* 735 conf_include */
{335545056, -902}, /* 736 include_depth */
{335545057, -902}, /* 737 include_miss */
{335740929, -901}, /* 1 gfix_db_name */ {335740929, -901}, /* 1 gfix_db_name */
{335740930, -901}, /* 2 gfix_invalid_sw */ {335740930, -901}, /* 2 gfix_invalid_sw */
{335740932, -901}, /* 4 gfix_incmp_sw */ {335740932, -901}, /* 4 gfix_incmp_sw */

View File

@ -753,6 +753,11 @@ static const struct {
{335545050, "07000"}, // 730 wrong_message_length {335545050, "07000"}, // 730 wrong_message_length
{335545051, "07000"}, // 731 no_output_format {335545051, "07000"}, // 731 no_output_format
{335545052, "HY021"}, // 732 item_finish {335545052, "HY021"}, // 732 item_finish
{335545053, "XX000"}, // 733 miss_config
{335545054, "XX000"}, // 734 conf_line
{335545055, "XX000"}, // 735 conf_include
{335545056, "XX000"}, // 736 include_depth
{335545057, "XX000"}, // 737 include_miss
{335740929, "00000"}, // 1 gfix_db_name {335740929, "00000"}, // 1 gfix_db_name
{335740930, "00000"}, // 2 gfix_invalid_sw {335740930, "00000"}, // 2 gfix_invalid_sw
{335740932, "00000"}, // 4 gfix_incmp_sw {335740932, "00000"}, // 4 gfix_incmp_sw

View File

@ -1,7 +1,7 @@
/* MAX_NUMBER is the next number to be used, always one more than the highest message number. */ /* MAX_NUMBER is the next number to be used, always one more than the highest message number. */
set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?); set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?);
-- --
('2013-02-21 18:12:38', 'JRD', 0, 733) ('2013-03-26 17:52:41', 'JRD', 0, 738)
('2012-01-23 20:10:30', 'QLI', 1, 532) ('2012-01-23 20:10:30', 'QLI', 1, 532)
('2009-07-16 05:26:11', 'GFIX', 3, 121) ('2009-07-16 05:26:11', 'GFIX', 3, 121)
('1996-11-07 13:39:40', 'GPRE', 4, 1) ('1996-11-07 13:39:40', 'GPRE', 4, 1)

View File

@ -840,6 +840,11 @@ Data source : @4', NULL, NULL)
('wrong_message_length', NULL, 'why.cpp', NULL, 0, 730, NULL, 'Message length passed from user application does not match set of columns', NULL, NULL); ('wrong_message_length', NULL, 'why.cpp', NULL, 0, 730, NULL, 'Message length passed from user application does not match set of columns', NULL, NULL);
('no_output_format', NULL, 'why.cpp', NULL, 0, 731, NULL, 'Resultset is missing output format information', NULL, NULL); ('no_output_format', NULL, 'why.cpp', NULL, 0, 731, NULL, 'Resultset is missing output format information', NULL, NULL);
('item_finish', NULL, 'MsgMetadata.cpp', NULL, 0, 732, NULL, 'Message metadata not ready - item @1 is not finished', NULL, NULL); ('item_finish', NULL, 'MsgMetadata.cpp', NULL, 0, 732, NULL, 'Message metadata not ready - item @1 is not finished', NULL, NULL);
('miss_config', NULL, 'config_file.cpp', NULL, 0, 733, NULL, 'Missing configuration file: @1', NULL, NULL);
('conf_line', NULL, 'config_file.cpp', NULL, 0, 734, NULL, '@1: illegal line <@2>', NULL, NULL);
('conf_include', NULL, 'config_file.cpp', NULL, 0, 735, NULL, 'Invalid include operator in @1 for <@2>', NULL, NULL);
('include_depth', NULL, 'config_file.cpp', NULL, 0, 736, NULL, 'Include depth too big', NULL, NULL);
('include_miss', NULL, 'config_file.cpp', NULL, 0, 737, NULL, 'File to include not found', NULL, NULL);
-- QLI -- QLI
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL); (NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL); (NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);

View File

@ -739,6 +739,11 @@ set bulk_insert INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, FA
(-804, '07', '000', 0, 730, 'wrong_message_length', NULL, NULL) (-804, '07', '000', 0, 730, 'wrong_message_length', NULL, NULL)
(-804, '07', '000', 0, 731, 'no_output_format', NULL, NULL) (-804, '07', '000', 0, 731, 'no_output_format', NULL, NULL)
(-804, 'HY', '021', 0, 732, 'item_finish', NULL, NULL) (-804, 'HY', '021', 0, 732, 'item_finish', NULL, NULL)
(-902, 'XX', '000', 0, 733, 'miss_config', NULL, NULL)
(-902, 'XX', '000', 0, 734, 'conf_line', NULL, NULL)
(-902, 'XX', '000', 0, 735, 'conf_include', NULL, NULL)
(-902, 'XX', '000', 0, 736, 'include_depth', NULL, NULL)
(-902, 'XX', '000', 0, 737, 'include_miss', NULL, NULL)
-- GFIX -- GFIX
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL) (-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL) (-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)

View File

@ -39,6 +39,7 @@
#include "../jrd/ibase.h" #include "../jrd/ibase.h"
#include "../common/classes/init.h" #include "../common/classes/init.h"
#include "../common/config/config.h" #include "../common/config/config.h"
#include "../common/os/fbsyslog.h"
#include <sys/param.h> #include <sys/param.h>
#ifdef HAVE_SYS_TYPES_H #ifdef HAVE_SYS_TYPES_H
@ -156,6 +157,8 @@ int CLIB_ROUTINE main( int argc, char** argv)
* Run the server with apollo mailboxes. * Run the server with apollo mailboxes.
* *
**************************************/ **************************************/
try
{
RemPortPtr port; RemPortPtr port;
// 01 Sept 2003, Nickolay Samofatov // 01 Sept 2003, Nickolay Samofatov
@ -339,6 +342,13 @@ int CLIB_ROUTINE main( int argc, char** argv)
divorce_terminal(mask); divorce_terminal(mask);
} }
// check firebird.conf presence - must be for server
if (Config::missFirebirdConf())
{
Firebird::Syslog::Record(Firebird::Syslog::Error, "Missing master config file firebird.conf");
exit(STARTUP_ERROR);
}
if (super || standaloneClassic) if (super || standaloneClassic)
{ {
try try
@ -424,6 +434,21 @@ int CLIB_ROUTINE main( int argc, char** argv)
fb_shutdown(10000, fb_shutrsn_exit_called); fb_shutdown(10000, fb_shutrsn_exit_called);
return FINI_OK; return FINI_OK;
}
catch(const Firebird::Exception& ex)
{
ISC_STATUS_ARRAY status;
ex.stuff_exception(status);
char s[100];
const ISC_STATUS* st = status;
fb_interpret(s, sizeof(s), &st);
Firebird::Syslog::Record(Firebird::Syslog::Error, "Firebird startup error");
Firebird::Syslog::Record(Firebird::Syslog::Error, s);
exit(STARTUP_ERROR);
}
} }
} // extern "C" } // extern "C"

View File

@ -206,10 +206,10 @@ int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE /*hPrevInst*/, LPSTR lpszArgs,
return STARTUP_ERROR; // see /common/common.h return STARTUP_ERROR; // see /common/common.h
} }
// Check for errors/missing firebird.conf // Check for missing firebird.conf
const char* anyError = Config::getMessage(); if (Config::missFirebirdConf())
if (anyError)
{ {
const char* anyError = "Missing master config file firebird.conf";
Syslog::Record(Syslog::Error, anyError); Syslog::Record(Syslog::Error, anyError);
MessageBox(NULL, anyError, "Firebird server failure", MessageBox(NULL, anyError, "Firebird server failure",
MB_OK | MB_ICONHAND | MB_SYSTEMMODAL | MB_DEFAULT_DESKTOP_ONLY); MB_OK | MB_ICONHAND | MB_SYSTEMMODAL | MB_DEFAULT_DESKTOP_ONLY);

View File

@ -92,10 +92,6 @@ namespace
void TraceCfgReader::readConfig() void TraceCfgReader::readConfig()
{ {
ConfigFile cfgFile(ConfigFile::USE_TEXT, m_text, ConfigFile::HAS_SUB_CONF); ConfigFile cfgFile(ConfigFile::USE_TEXT, m_text, ConfigFile::HAS_SUB_CONF);
if (cfgFile.getMessage())
{
fatal_exception::raiseFmt(ERROR_PREFIX"%s", cfgFile.getMessage());
}
m_subpatterns[0].start = 0; m_subpatterns[0].start = 0;
m_subpatterns[0].end = m_databaseName.length(); m_subpatterns[0].end = m_databaseName.length();