1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00

0026345: Shape Healer application crashes trying to run Shape Processing

Empty element, that was added to the Array, causes an exception while accessing myUserMap

LoadResourceManager is receives environment variable name, but stat is waiting for full path
This commit is contained in:
anv 2015-06-16 12:27:09 +03:00 committed by abv
parent bd7a454d6c
commit 72d472e0c7
3 changed files with 161 additions and 106 deletions

View File

@ -180,12 +180,21 @@ is
-- If the resource does not exist, it is created.
---Level: Public
GetResourcePath(myclass;
aPath: in out AsciiString from TCollection;
aName: CString from Standard;
isUserDefaults: Boolean from Standard);
---Purpose: Gets the resource file full path by its name.
-- If corresponding environment variable is not set
-- or file doesn't exist returns empty string.
---Level: Public
---Category: Private methods.
Load (me: mutable ;
aDirectory: in out AsciiString from TCollection;
aName: in out AsciiString from TCollection;
aMap: in out DataMapOfAsciiStringAsciiString)
aPath: in out AsciiString from TCollection;
aMap: in out DataMapOfAsciiStringAsciiString)
is static private;
---Level: Internal

View File

@ -33,8 +33,7 @@
#define END 0
#define EMPTY 1
#define COMMENT 2
#define INCLUDE 3
#define RESOURCE 4
#define RESOURCE 3
#define ERROR -1
static Standard_Integer WhatKindOfLine(OSD_File& aFile,
@ -51,14 +50,24 @@ Resource_Manager::Resource_Manager(const Standard_CString aName,
const Standard_Boolean Verbose) : myName(aName), myVerbose(Verbose)
{
if ( !aDefaultsDirectory.IsEmpty() ) {
Load(aDefaultsDirectory,myName,myRefMap);
OSD_Path anOSDPath(aDefaultsDirectory);
anOSDPath.DownTrek(anOSDPath.Name());
anOSDPath.SetName(aName);
TCollection_AsciiString aPath;
anOSDPath.SystemName(aPath);
Load(aPath,myRefMap);
}
else
if (myVerbose)
cout << "Resource Manager Warning: aDefaultsDirectory is empty." << endl;
if ( !anUserDefaultsDirectory.IsEmpty() ) {
Load(anUserDefaultsDirectory,myName,myRefMap);
OSD_Path anOSDPath(anUserDefaultsDirectory);
anOSDPath.DownTrek(anOSDPath.Name());
anOSDPath.SetName(aName);
TCollection_AsciiString aPath;
anOSDPath.SystemName(aPath);
Load(aPath,myRefMap);
}
else
if (myVerbose)
@ -70,44 +79,34 @@ Resource_Manager::Resource_Manager(const Standard_CString aName,
{
Debug = (getenv("ResourceDebug") != NULL) ;
TCollection_AsciiString EnvVar, CSF_ = "CSF_" ;
TCollection_AsciiString Directory ;
Standard_CString dir ;
if ( getenv ("CSF_ResourceVerbose") != NULL )
myVerbose = Standard_True;
EnvVar = CSF_ + aName + "Defaults" ;
if ((dir = getenv (EnvVar.ToCString())) != NULL) {
Directory = dir;
Load(Directory,myName,myRefMap);
}
else
if (myVerbose)
cout << "Resource Manager Warning: Environment variable \"" << EnvVar
<< "\" not set." << endl;
TCollection_AsciiString aPath,aUserPath;
GetResourcePath(aPath,aName,Standard_False);
GetResourcePath(aUserPath,aName,Standard_True);
EnvVar = CSF_ + aName + "UserDefaults" ;
if ((dir = getenv (EnvVar.ToCString())) != NULL) {
Directory = dir;
Load(Directory, myName, myUserMap);
}
else
if (myVerbose)
cout << "Resource Manager Warning: Environment variable \"" << EnvVar
<< "\" not set." << endl;
if (!aPath.IsEmpty())
Load(aPath,myRefMap);
else if (myVerbose)
cout << "Resource Manager Warning: Environment variable \"CSF_" << aName << "Defaults\" not set." << endl;
if (!aUserPath.IsEmpty())
Load(aUserPath,myRefMap);
else if (myVerbose)
cout << "Resource Manager Warning: Environment variable \"CSF_" << aName << "UserDefaults\" not set." << endl;
}
void Resource_Manager::Load(TCollection_AsciiString& aDirectory,
TCollection_AsciiString& aName,
Resource_DataMapOfAsciiStringAsciiString& aMap)
void Resource_Manager::Load(TCollection_AsciiString& aPath,
Resource_DataMapOfAsciiStringAsciiString& aMap)
{
Standard_Integer Kind, Pos;
Standard_Integer Kind;
TCollection_AsciiString Token1, Token2;
TCollection_AsciiString Directory, Name;
TCollection_AsciiString FileName;
FileName = aDirectory + "/" + aName;
OSD_File File = OSD_Path(FileName);
OSD_File File = OSD_Path(aPath);
File.Open(OSD_ReadOnly,OSD_Protection());
if (File.Failed()) {
if (myVerbose)
@ -121,15 +120,6 @@ void Resource_Manager::Load(TCollection_AsciiString& aDirectory,
case COMMENT :
case EMPTY :
break ;
case INCLUDE :
Directory = OSD_Path::AbsolutePath(aDirectory,Token1);
Pos = Directory.SearchFromEnd("/");
if (Pos != 0) {
Name = Directory.Split(Pos);
Directory.Trunc(Pos-1);
Load(Directory,Name,aMap);
}
break;
case RESOURCE :
if (!aMap.Bind(Token1,Token2))
aMap(Token1) = Token2;
@ -162,15 +152,6 @@ static Standard_Integer WhatKindOfLine(OSD_File& aFile,
if (Line.Value(1) == '!')
return COMMENT;
if (Line.Value(1) == '#') {
Line.Remove(1);
if ((Line.Token(" \t")).IsDifferent("include"))
return ERROR;
aToken1 = Line.Token(" \t\n",2);
return INCLUDE;
}
Pos1 = Line.FirstLocationNotInSet(WhiteSpace, 1, Line.Length());
if (Line.Value(Pos1) == '\n')
return EMPTY;
@ -236,43 +217,46 @@ static Standard_Integer GetLine(OSD_File& aFile,TCollection_AsciiString& aLine)
//=======================================================================
Standard_Boolean Resource_Manager::Save() const
{
Standard_Integer Index;
TCollection_AsciiString EnvVar, CSF_ = "CSF_";
TCollection_AsciiString anEnvVar("CSF_");
anEnvVar += myName;
anEnvVar += "UserDefaults";
Standard_CString dir;
EnvVar = CSF_ + myName + "UserDefaults";
if ((dir = getenv (EnvVar.ToCString())) == NULL) {
if ((dir = getenv (anEnvVar.ToCString())) == NULL) {
if (myVerbose)
cout << "Resource Manager Warning: environment variable \""
<< EnvVar << "\" not set. Cannot save resources." << endl ;
<< anEnvVar << "\" not set. Cannot save resources." << endl ;
return Standard_False;
}
TCollection_AsciiString FilePath = dir;
OSD_Directory Dir = OSD_Path(FilePath);
TCollection_AsciiString aFilePath(dir);
OSD_Path anOSDPath(aFilePath);
OSD_Directory Dir = anOSDPath;
Standard_Boolean Status = Standard_True;
if ( !Dir.Exists() ) {
{
try {
OCC_CATCH_SIGNALS
Dir.Build(OSD_Protection(OSD_RX, OSD_RWX, OSD_RX, OSD_RX));
Dir.Build(OSD_Protection(OSD_RX, OSD_RWX, OSD_RX, OSD_RX));
}
catch (Standard_Failure) {
Status = Standard_False;
Status = Standard_False;
}
}
Status = Status && !Dir.Failed();
if (!Status) {
if (myVerbose)
cout << "Resource Manager: Error opening or creating directory \"" << FilePath
<< "\". Permission denied. Cannot save resources." << endl;
cout << "Resource Manager: Error opening or creating directory \"" << aFilePath
<< "\". Permission denied. Cannot save resources." << endl;
return Standard_False;
}
}
FilePath += "/"; FilePath += myName;
OSD_Path Path(FilePath);
OSD_File File = Path;
anOSDPath.DownTrek(anOSDPath.Name());
anOSDPath.SetName(myName);
anOSDPath.SystemName(aFilePath);
OSD_File File = anOSDPath;
OSD_Protection theProt;
Status = Standard_True;
{
@ -287,41 +271,45 @@ Standard_Boolean Resource_Manager::Save() const
Status = Status && !File.Failed();
if (!Status) {
if (myVerbose)
cout << "Resource Manager: Error opening or creating file \"" << FilePath
cout << "Resource Manager: Error opening or creating file \"" << aFilePath
<< "\". Permission denied. Cannot save resources." << endl;
return Standard_False;
}
Resource_LexicalCompare Comp;
Standard_Integer NbKey = myUserMap.Extent();
TColStd_Array1OfAsciiString KeyArray(1,NbKey+1); // 1 more item is added to allow saving empty resource
Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString Iter(myUserMap);
const Standard_Integer NbKey = myUserMap.Extent();
if (NbKey)
{
TColStd_Array1OfAsciiString KeyArray(1,NbKey);
Resource_DataMapIteratorOfDataMapOfAsciiStringAsciiString Iter(myUserMap);
for ( Index = 1; Iter.More(); Iter.Next())
KeyArray(Index++)= Iter.Key();
Standard_Integer Index;
for ( Index = 1; Iter.More(); Iter.Next())
KeyArray(Index++)= Iter.Key();
Resource_QuickSortOfArray1::Sort(KeyArray, Comp);
Resource_LexicalCompare Comp;
Resource_QuickSortOfArray1::Sort(KeyArray, Comp);
TCollection_AsciiString Line, Value;
for (Index = 1 ; Index <= NbKey ; Index++) {
Value = myUserMap(KeyArray(Index));
if (!Value.IsEmpty())
switch(Value.Value(1)) {
case '\\' :
case ' ' :
case '\t' :
Value.Insert(1,'\\');
break;
}
Line = KeyArray(Index) + ":\t" + Value + "\n";
TCollection_AsciiString Line, Value;
for (Index = 1 ; Index <= NbKey ; Index++) {
Value = myUserMap(KeyArray(Index));
if (!Value.IsEmpty())
switch(Value.Value(1)) {
case '\\' :
case ' ' :
case '\t' :
Value.Insert(1,'\\');
break;
}
Line = KeyArray(Index) + ":\t" + Value + "\n";
if (Debug)
cout << "Line = '" << Line << "'" << endl;
if (Debug)
cout << "Line = '" << Line << "'" << endl;
File.Write(Line, Line.Length());
File.Write(Line, Line.Length());
}
if (myVerbose)
cout << "Resource Manager: Resources saved in file " << aFilePath << endl;
}
if (myVerbose)
cout << "Resource Manager: Resources saved in file " << FilePath << endl;
File.Close();
return Standard_True;
}
@ -468,3 +456,29 @@ Standard_Boolean Resource_Manager::Find(const Standard_CString aResource) const
return Standard_True;
return Standard_False;
}
//=======================================================================
//function : GetResourcePath
//purpose :
//=======================================================================
void Resource_Manager::GetResourcePath (TCollection_AsciiString& aPath, const Standard_CString aName, const Standard_Boolean isUserDefaults)
{
aPath.Clear();
TCollection_AsciiString anEnvVar("CSF_");
anEnvVar += aName;
anEnvVar += isUserDefaults?"UserDefaults":"Defaults";
Standard_CString dir;
if ((dir = getenv (anEnvVar.ToCString())) == NULL)
return;
TCollection_AsciiString aResPath(dir);
OSD_Path anOSDPath(aResPath);
anOSDPath.DownTrek(anOSDPath.Name());
anOSDPath.SetName(aName);
anOSDPath.SystemName(aPath);
}

View File

@ -67,28 +67,61 @@ Standard_Boolean ShapeProcess_Context::Init (const Standard_CString file,
//purpose :
//=======================================================================
Handle(Resource_Manager) ShapeProcess_Context::LoadResourceManager (const Standard_CString file)
Handle(Resource_Manager) ShapeProcess_Context::LoadResourceManager (const Standard_CString name)
{
// Optimisation of loading resource file: file is load only once
// and reloaded only if file date has changed
static Handle(Resource_Manager) sRC;
static Standard_Time mtime;
static TCollection_AsciiString name;
if ( ! sRC.IsNull() && ! name.IsEqual ( file ) ) sRC.Nullify();
if ( ! sRC.IsNull() ) {
struct stat buf;
if ( ! stat ( file, &buf ) && (Standard_Time)buf.st_mtime != mtime ) {
sRC.Nullify();
mtime = buf.st_mtime;
static Standard_Time sMtime, sUMtime;
static TCollection_AsciiString sName;
struct stat buf;
Standard_Time aMtime(0), aUMtime(0);
TCollection_AsciiString aPath,aUserPath;
Resource_Manager::GetResourcePath(aPath,name,Standard_False);
Resource_Manager::GetResourcePath(aUserPath,name,Standard_True);
if ( !aPath.IsEmpty() )
{
stat( aPath.ToCString(), &buf );
aMtime = (Standard_Time)buf.st_mtime;
}
if ( !aUserPath.IsEmpty() )
{
stat( aUserPath.ToCString(), &buf );
aUMtime = (Standard_Time)buf.st_mtime;
}
Standard_Boolean isFileModified = Standard_False;
if ( !sRC.IsNull() ) {
if ( sName.IsEqual ( name ) ) {
if ( sMtime != aMtime )
{
sMtime = aMtime;
isFileModified = Standard_True;
}
if ( sUMtime != aUMtime )
{
sUMtime = aUMtime;
isFileModified = Standard_True;
}
if (isFileModified)
sRC.Nullify();
}
else
sRC.Nullify();
}
if ( sRC.IsNull() ) {
#ifdef OCCT_DEBUG
cout << "Info: ShapeProcess_Context: Reload Resource_Manager: "
<< name.ToCString() << " -> " << file << endl;
<< sName.ToCString() << " -> " << name << endl;
#endif
sRC = new Resource_Manager ( file );
name = file;
sRC = new Resource_Manager ( name );
if (!isFileModified)
{
sName = name;
sMtime = aMtime;
sUMtime = aUMtime;
}
}
return sRC;
}
@ -401,5 +434,4 @@ void ShapeProcess_Context::SetTraceLevel (const Standard_Integer tracelev)
Standard_Integer ShapeProcess_Context::TraceLevel () const
{
return myTraceLev;
}
}