1 // Copyright (C) 2005 OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #include "LightApp_Driver.h"
21 #include <TCollection_AsciiString.hxx>
23 #include <OSD_Path.hxx>
24 #include <OSD_File.hxx>
25 #include <OSD_Directory.hxx>
26 #include <OSD_Process.hxx>
27 #include <OSD_Directory.hxx>
28 #include <OSD_Protection.hxx>
29 #include <OSD_SingleProtection.hxx>
30 #include <OSD_FileIterator.hxx>
32 #include <qfileinfo.h>
40 LightApp_Driver::LightApp_Driver()
46 LightApp_Driver::~LightApp_Driver()
53 Save in file 'theFileName' datas from this driver
55 bool LightApp_Driver::SaveDatasInFile( const char* theFileName, bool isMultiFile )
58 std::map<std::string, ListOfFiles>::const_iterator it;
59 for (it = myMap.begin(); it != myMap.end(); ++it)
62 unsigned char** aBuffer = new unsigned char*[aNbModules];
63 long* aBufferSize = new long[aNbModules];
64 char** aModuleName = new char*[aNbModules];
66 if(aBuffer == NULL || aBufferSize == NULL || aModuleName == NULL)
69 int aFileBufferSize = 4; //4 bytes for a number of the modules that will be written to the stream;
71 for (it = myMap.begin(); it != myMap.end(); ++it) {
72 aModuleName[i] = const_cast<char*>(it->first.c_str());//(it->first);
73 aFileBufferSize += 4; //Add 4 bytes: a length of the module name
74 aFileBufferSize += strlen(aModuleName[i])+1;
75 std::string aName(aModuleName[i]);
76 PutFilesToStream(aName, aBuffer[i], aBufferSize[i], isMultiFile);
77 aFileBufferSize += 8; //Add 8 bytes: a length of the buffer
78 aFileBufferSize += aBufferSize[i];
83 unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];
84 if(aFileBuffer == NULL)
87 myTmpDir = QDir::convertSeparators( QFileInfo( theFileName ).dirPath( true ) + "/" ).latin1() ;
91 //Initialize 4 bytes of the buffer by 0
92 memset(aFileBuffer, 0, 4);
93 //Copy the number of modules that will be written to the stream
94 memcpy(aFileBuffer, &aNbModules, ((sizeof(int) > 4) ? 4 : sizeof(int)));
97 int aBufferNameSize = 0;
98 for (i = 0; i < n; i++) {
99 aBufferNameSize = strlen(aModuleName[i])+1;
100 //Initialize 4 bytes of the buffer by 0
101 memset((aFileBuffer + aCurrentPos), 0, 4);
102 //Copy the length of the module name to the buffer
103 memcpy((aFileBuffer + aCurrentPos), &aBufferNameSize, ((sizeof(int) > 4) ? 4 : sizeof(int)));
105 //Copy the module name to the buffer
106 memcpy((aFileBuffer + aCurrentPos), aModuleName[i], aBufferNameSize);
107 aCurrentPos += aBufferNameSize;
109 //Initialize 8 bytes of the buffer by 0
110 memset((aFileBuffer + aCurrentPos), 0, 8);
111 //Copy the length of the module buffer to the buffer
112 memcpy((aFileBuffer + aCurrentPos), (aBufferSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));
114 //Copy the module buffer to the buffer
115 memcpy((aFileBuffer + aCurrentPos), aBuffer[i], aBufferSize[i]);
116 aCurrentPos += aBufferSize[i];
120 ofstream aFile(theFileName, ios::out | ios::binary);
122 ofstream aFile(theFileName);
124 aFile.write((char*)aFileBuffer, aFileBufferSize);
128 delete[] aBufferSize;
129 delete[] aModuleName;
130 delete[] aFileBuffer;
136 Filling current driver from file 'theFileName'
138 bool LightApp_Driver::ReadDatasFromFile( const char* theFileName, bool isMultiFile )
141 ifstream aFile(theFileName, ios::binary);
143 ifstream aFile(theFileName);
146 myTmpDir = QDir::convertSeparators( QFileInfo( theFileName ).dirPath( true ) + "/" ).latin1() ;
148 aFile.seekg(0, ios::end);
149 int aFileBufferSize = aFile.tellg();
150 unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];
151 aFile.seekg(0, ios::beg);
152 aFile.read((char*)aFileBuffer, aFileBufferSize);
156 //Copy the number of files in the stream
157 memcpy(&aNbModules, aFileBuffer, sizeof(int));
158 long aCurrentPos = 4;
161 for (int i = 0; i < aNbModules; i++) {
162 //Put a length of the module name to aModuleNameSize
163 memcpy(&aModuleNameSize, (aFileBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int)));
166 char *aModuleName = new char[aModuleNameSize];
167 //Put a module name to aModuleName
168 memcpy(aModuleName, (aFileBuffer + aCurrentPos), aModuleNameSize);
169 aCurrentPos += aModuleNameSize;
171 //Put a length of the file buffer to aBufferSize
173 memcpy(&aBufferSize, (aFileBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long)));
175 unsigned char *aBuffer = new unsigned char[aBufferSize];
177 //Put a buffer for current module to aBuffer
178 memcpy(aBuffer, (aFileBuffer + aCurrentPos), aBufferSize);
179 aCurrentPos += aBufferSize;
181 // Put buffer to aListOfFiles and set to myMap
182 ListOfFiles aListOfFiles = PutStreamToFiles(aBuffer, aBufferSize, isMultiFile);
183 SetListOfFiles(aModuleName, aListOfFiles);
185 delete[] aModuleName;
189 delete[] aFileBuffer;
195 \return temp directory for path 'theURL'
197 std::string LightApp_Driver::GetTmpDir (const char* theURL, const bool isMultiFile)
199 std::string anURLDir = GetDirFromPath(theURL);
200 std::string aTmpDir = isMultiFile ? anURLDir : GetTmpDir();
206 \return list of files for module with name 'theModuleName'
208 LightApp_Driver::ListOfFiles LightApp_Driver::GetListOfFiles( const char* theModuleName )
210 ListOfFiles aListOfFiles;
212 std::string aName(theModuleName);
213 if (myMap.count(aName))
214 aListOfFiles = myMap[aName];
220 Sets list of files for module with name 'theModuleName'
222 void LightApp_Driver::SetListOfFiles( const char* theModuleName, const ListOfFiles theListOfFiles )
224 std::string aName (theModuleName);
225 myMap[aName] = theListOfFiles;
229 Converts files which was created from module <theModuleName> into a byte sequence unsigned char
231 void LightApp_Driver::PutFilesToStream( const std::string& theModuleName, unsigned char*& theBuffer,
232 long& theBufferSize, bool theNamesOnly )
234 ListOfFiles aFiles = myMap[theModuleName];
235 // aFiles must contain temporary directory name in its first item
236 // and names of files (relatively the temporary directory) in the others
238 int i, aLength = aFiles.size() - 1;
241 theBuffer = new unsigned char[theBufferSize];
244 //Get a temporary directory for saved a file
245 TCollection_AsciiString aTmpDir(const_cast<char*>(aFiles[0].c_str()));
247 long aBufferSize = 0;
250 int* aFileNameSize= new int[aLength];
251 long* aFileSize= new long[aLength];
253 //Determine the required size of the buffer
254 TCollection_AsciiString aFileName;
255 for (i = 0; i < aLength; i++) {
256 char* aFName = const_cast<char*>(aFiles[i+1].c_str());
258 //Check if the file exists
259 if (!theNamesOnly) { // mpv 15.01.2003: if only file names must be stroed, then size of files is zero
260 TCollection_AsciiString aFullPath = aTmpDir + aFileName;
261 OSD_Path anOSDPath(aFullPath);
262 OSD_File anOSDFile(anOSDPath);
263 if(!anOSDFile.Exists()) continue;
265 ifstream aFile(aFullPath.ToCString(), ios::binary);
267 ifstream aFile(aFullPath.ToCString());
269 aFile.seekg(0, ios::end);
270 aFileSize[i] = aFile.tellg();
271 aBufferSize += aFileSize[i]; //Add a space to store the file
273 aFileNameSize[i] = strlen(aFName) + 1;
274 aBufferSize += aFileNameSize[i]; //Add a space to store the file name
275 aBufferSize += (theNamesOnly)?4:12; //Add 4 bytes: a length of the file name,
276 // 8 bytes: length of the file itself
280 aBufferSize += 4; //4 bytes for a number of the files that will be written to the stream;
281 theBuffer = new unsigned char[aBufferSize];
282 if(theBuffer == NULL) {
287 //Initialize 4 bytes of the buffer by 0
288 memset(theBuffer, 0, 4);
289 //Copy the number of files that will be written to the stream
290 memcpy(theBuffer, &aNbFiles, ((sizeof(int) > 4) ? 4 : sizeof(int)));
294 for(i = 0; i < aLength; i++) {
296 if (!theNamesOnly) { // mpv 15.01.2003: we don't open any file if theNamesOnly = true
297 TCollection_AsciiString aName(const_cast<char*>(aFiles[i+1].c_str()));
298 TCollection_AsciiString aFullPath = aTmpDir + aName;
299 OSD_Path anOSDPath(aFullPath);
300 OSD_File anOSDFile(anOSDPath);
301 if(!anOSDFile.Exists()) continue;
303 aFile = new ifstream(aFullPath.ToCString(), ios::binary);
305 aFile = new ifstream(aFullPath.ToCString());
308 //Initialize 4 bytes of the buffer by 0
309 memset((theBuffer + aCurrentPos), 0, 4);
310 //Copy the length of the file name to the buffer
311 memcpy((theBuffer + aCurrentPos), (aFileNameSize + i), ((sizeof(int) > 4) ? 4 : sizeof(int)));
314 //Copy the file name to the buffer
315 char* aFName = const_cast<char*>(aFiles[i+1].c_str());
316 memcpy((theBuffer + aCurrentPos), aFName, aFileNameSize[i]);
317 aCurrentPos += aFileNameSize[i];
319 if (!theNamesOnly) { // mpv 15.01.2003: we don't copy file content to the buffer if !theNamesOnly
320 //Initialize 8 bytes of the buffer by 0
321 memset((theBuffer + aCurrentPos), 0, 8);
322 //Copy the length of the file to the buffer
323 memcpy((theBuffer + aCurrentPos), (aFileSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));
326 aFile->seekg(0, ios::beg);
327 aFile->read((char *)(theBuffer + aCurrentPos), aFileSize[i]);
330 aCurrentPos += aFileSize[i];
333 delete[] aFileNameSize;
336 theBufferSize = aBufferSize;
340 Converts a byte sequence <theBuffer> to files and return list of them
342 LightApp_Driver::ListOfFiles LightApp_Driver::PutStreamToFiles( const unsigned char* theBuffer,
343 const long theBufferSize, bool theNamesOnly )
345 if(theBufferSize == 0 || theBuffer == 0)
346 return ListOfFiles();
348 // Create a temporary directory for the component's data files
349 std::string aDir = GetTmpDir();
351 // Remember that the files are in a temporary location that should be deleted
352 // when a study is closed
353 SetIsTemporary( true );
355 //Get a temporary directory for saving a file
356 TCollection_AsciiString aTmpDir(const_cast<char*>(aDir.c_str()));
358 long aFileSize, aCurrentPos = 4;
359 int i, aFileNameSize, aNbFiles = 0;
361 //Copy the number of files in the stream
362 memcpy(&aNbFiles, theBuffer, sizeof(int));
364 const int n = aNbFiles + 1;
365 ListOfFiles aFiles(n);
368 for(i = 0; i < aNbFiles; i++) {
369 //Put a length of the file name to aFileNameSize
370 memcpy(&aFileNameSize, (theBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int)));
373 char *aFileName = new char[aFileNameSize];
374 //Put a file name to aFileName
375 memcpy(aFileName, (theBuffer + aCurrentPos), aFileNameSize);
376 aCurrentPos += aFileNameSize;
378 //Put a length of the file to aFileSize
380 memcpy(&aFileSize, (theBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long)));
383 TCollection_AsciiString aFullPath = aTmpDir + aFileName;
386 ofstream aFile(aFullPath.ToCString(), ios::out | ios::binary);
388 ofstream aFile(aFullPath.ToCString());
391 aFile.write((char *)(theBuffer+aCurrentPos), aFileSize);
393 aCurrentPos += aFileSize;
395 std::string aStrFileName(aFileName);
396 aFiles[i+1] = aStrFileName;
403 Remove files. First item in <theFiles> is a directory with slash at the end.
404 Other items are names of files. If <IsDirDeleted> is true,
405 then the directory is also deleted.
407 void LightApp_Driver::RemoveFiles( const ListOfFiles& theFiles, const bool IsDirDeleted)
409 int i, aLength = theFiles.size() - 1;
413 //Get a temporary directory for saved a file
414 TCollection_AsciiString aDirName(const_cast<char*>(theFiles[0].c_str()));
416 for(i = 0; i < aLength; i++) {
417 TCollection_AsciiString aFile(aDirName);
418 aFile += const_cast<char*>(theFiles[i+1].c_str());
419 OSD_Path anOSDPath(aFile);
420 OSD_File anOSDFile(anOSDPath);
421 if(!anOSDFile.Exists()) continue;
427 OSD_Path aPath(aDirName);
428 OSD_Directory aDir(aPath);
429 // san -- Using a special code block below is essential - it ensures that
430 // OSD_FileIterator instance is destroyed by the moment when
431 // OSD_Directory::Remove() is called.
432 // Otherwise, the directory remains locked (at least on Windows)
433 // by the iterator and cannot be removed.
435 OSD_FileIterator anIterator(aPath, '*');
436 if(!aDir.Exists() || anIterator.More())
444 Removes files which was created from module theModuleName if
445 <IsDirDeleted> is true tmp directory is also deleted if it is empty
447 void LightApp_Driver::RemoveTemporaryFiles( const char* theModuleName, const bool IsDirDeleted )
449 std::string aModuleName(theModuleName);
450 ListOfFiles aFiles = myMap[aModuleName];
451 // aFiles must contain temporary directory name in its first item
452 // and names of files (relatively the temporary directory) in the others
453 RemoveFiles( aFiles, IsDirDeleted );
458 Clears map of list files
460 void LightApp_Driver::ClearDriverContents()
462 std::map<std::string, ListOfFiles>::iterator it;
463 for ( it = myMap.begin(); it != myMap.end(); ++it )
465 const char* aModuleName = const_cast<char*>(it->first.c_str());
466 // If the driver contains temporary files -
467 // remove them along with the temporary directory
468 RemoveTemporaryFiles( aModuleName, IsTemporary() );
471 // Reset the "temporary" flag
472 SetIsTemporary( false );
476 \return a temp directory to store created files like "/tmp/sub_dir/"
478 std::string LightApp_Driver::GetTmpDir()
480 if ( myTmpDir.length() != 0 )
483 //Find a temporary directory to store a file
484 TCollection_AsciiString aTmpDir;
486 char *Tmp_dir = getenv("SALOME_TMP_DIR");
488 Tmp_dir = getenv ( "TEMP" );
490 Tmp_dir = getenv ( "TMP" );
493 aTmpDir = TCollection_AsciiString(Tmp_dir);
495 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
497 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
503 aTmpDir = TCollection_AsciiString("C:\\");
505 aTmpDir = TCollection_AsciiString("/tmp/");
509 srand((unsigned int)time(NULL));
510 int aRND = 999 + (int)(100000.0*rand()/(RAND_MAX+1.0)); //Get a random number to present a name of a sub directory
511 TCollection_AsciiString aSubDir(aRND);
512 if(aSubDir.Length() <= 1) aSubDir = TCollection_AsciiString("123409876");
514 aTmpDir += aSubDir; //Get RND sub directory
517 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
519 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
522 OSD_Path aPath(aTmpDir);
523 OSD_Directory aDir(aPath);
525 for(aRND = 0; aDir.Exists(); aRND++) {
526 aTmpDir.Insert((aTmpDir.Length() - 1), TCollection_AsciiString(aRND)); //Build a unique directory name
527 aPath = OSD_Path(aTmpDir);
528 aDir = OSD_Directory(aPath);
532 // Workaround for OSD_Protection bug on Windows
533 OSD_Protection aProtection(OSD_RWXD, OSD_RWXD, OSD_RWXD, OSD_RWXD);
535 OSD_Protection aProtection(OSD_RX, OSD_RWXD, OSD_RX, OSD_RX);
537 aDir.Build(aProtection);
539 myTmpDir = aTmpDir.ToCString();
541 return aTmpDir.ToCString();
545 \return the dir by the path
547 std::string LightApp_Driver::GetDirFromPath( const std::string& thePath ) {
550 OSD_Path aPath = OSD_Path(TCollection_AsciiString(const_cast<char*>(thePath.c_str())));
551 TCollection_AsciiString aDirString(aPath.Trek());
552 aDirString.ChangeAll('|','/');
553 return aDirString.ToCString();