1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-21 10:13:43 +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

@ -180,12 +180,21 @@ is
-- If the resource does not exist, it is created. -- If the resource does not exist, it is created.
---Level: Public ---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. ---Category: Private methods.
Load (me: mutable ; Load (me: mutable ;
aDirectory: in out AsciiString from TCollection; aPath: in out AsciiString from TCollection;
aName: in out AsciiString from TCollection; aMap: in out DataMapOfAsciiStringAsciiString)
aMap: in out DataMapOfAsciiStringAsciiString)
is static private; is static private;
---Level: Internal ---Level: Internal

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

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