1 // Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "LightApp_Driver.h"
25 #include <TCollection_AsciiString.hxx>
27 #include <OSD_Path.hxx>
28 #include <OSD_File.hxx>
29 #include <OSD_Directory.hxx>
30 #include <OSD_Protection.hxx>
31 #include <OSD_FileIterator.hxx>
43 LightApp_Driver::LightApp_Driver()
49 LightApp_Driver::~LightApp_Driver()
54 Save in file 'theFileName' datas from this driver
56 bool LightApp_Driver::SaveDatasInFile( const char* theFileName, bool isMultiFile )
59 std::map<std::string, ListOfFiles>::const_iterator it;
60 for (it = myMap.begin(); it != myMap.end(); ++it)
63 unsigned char** aBuffer = new unsigned char*[aNbModules];
64 long* aBufferSize = new long[aNbModules];
65 char** aModuleName = new char*[aNbModules];
67 if(aBuffer == NULL || aBufferSize == NULL || aModuleName == NULL)
70 int aFileBufferSize = 4; //4 bytes for a number of the modules that will be written to the stream;
72 for (it = myMap.begin(); it != myMap.end(); ++it) {
73 aModuleName[i] = const_cast<char*>(it->first.c_str());//(it->first);
74 aFileBufferSize += 4; //Add 4 bytes: a length of the module name
75 aFileBufferSize += strlen(aModuleName[i])+1;
76 std::string aName(aModuleName[i]);
77 PutFilesToStream(aName, aBuffer[i], aBufferSize[i], isMultiFile);
78 aFileBufferSize += 8; //Add 8 bytes: a length of the buffer
79 aFileBufferSize += aBufferSize[i];
84 unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];
85 if(aFileBuffer == NULL)
88 myTmpDir = QDir::toNativeSeparators( QFileInfo( theFileName ).absolutePath() + "/" ).toUtf8().constData() ;
92 //Initialize 4 bytes of the buffer by 0
93 memset(aFileBuffer, 0, 4);
94 //Copy the number of modules that will be written to the stream
95 memcpy(aFileBuffer, &aNbModules, ((sizeof(int) > 4) ? 4 : sizeof(int)));
98 int aBufferNameSize = 0;
99 for (i = 0; i < n; i++) {
100 aBufferNameSize = strlen(aModuleName[i])+1;
101 //Initialize 4 bytes of the buffer by 0
102 memset((aFileBuffer + aCurrentPos), 0, 4);
103 //Copy the length of the module name to the buffer
104 memcpy((aFileBuffer + aCurrentPos), &aBufferNameSize, ((sizeof(int) > 4) ? 4 : sizeof(int)));
106 //Copy the module name to the buffer
107 memcpy((aFileBuffer + aCurrentPos), aModuleName[i], aBufferNameSize);
108 aCurrentPos += aBufferNameSize;
110 //Initialize 8 bytes of the buffer by 0
111 memset((aFileBuffer + aCurrentPos), 0, 8);
112 //Copy the length of the module buffer to the buffer
113 memcpy((aFileBuffer + aCurrentPos), (aBufferSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));
115 //Copy the module buffer to the buffer
116 memcpy((aFileBuffer + aCurrentPos), aBuffer[i], aBufferSize[i]);
117 aCurrentPos += aBufferSize[i];
121 ofstream aFile(theFileName, ios::out | ios::binary);
123 ofstream aFile(theFileName);
125 aFile.write((char*)aFileBuffer, aFileBufferSize);
129 delete[] aBufferSize;
130 delete[] aModuleName;
131 delete[] aFileBuffer;
137 Filling current driver from file 'theFileName'
139 bool LightApp_Driver::ReadDatasFromFile( const char* theFileName, bool isMultiFile )
142 ifstream aFile(theFileName, ios::binary);
144 ifstream aFile(theFileName);
147 myTmpDir = QDir::toNativeSeparators( QFileInfo( theFileName ).absolutePath() + "/" ).toUtf8().constData() ;
149 aFile.seekg(0, ios::end);
150 int aFileBufferSize = aFile.tellg();
151 unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];
152 aFile.seekg(0, ios::beg);
153 aFile.read((char*)aFileBuffer, aFileBufferSize);
157 //Copy the number of files in the stream
158 memcpy(&aNbModules, aFileBuffer, sizeof(int));
159 long aCurrentPos = 4;
162 for (int i = 0; i < aNbModules; i++) {
163 //Put a length of the module name to aModuleNameSize
164 memcpy(&aModuleNameSize, (aFileBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int)));
167 char *aModuleName = new char[aModuleNameSize];
168 //Put a module name to aModuleName
169 memcpy(aModuleName, (aFileBuffer + aCurrentPos), aModuleNameSize);
170 aCurrentPos += aModuleNameSize;
172 //Put a length of the file buffer to aBufferSize
174 memcpy(&aBufferSize, (aFileBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long)));
176 unsigned char *aBuffer = new unsigned char[aBufferSize];
178 //Put a buffer for current module to aBuffer
179 memcpy(aBuffer, (aFileBuffer + aCurrentPos), aBufferSize);
180 aCurrentPos += aBufferSize;
182 // Put buffer to aListOfFiles and set to myMap
183 ListOfFiles aListOfFiles = PutStreamToFiles(aBuffer, aBufferSize, isMultiFile);
184 SetListOfFiles(aModuleName, aListOfFiles);
186 delete[] aModuleName;
190 delete[] aFileBuffer;
196 \return temp directory for path 'theURL'
198 std::string LightApp_Driver::GetTmpDir (const char* theURL, const bool isMultiFile)
200 std::string anURLDir = GetDirFromPath(theURL);
201 std::string aTmpDir = isMultiFile ? anURLDir : GetTmpDir();
207 \return list of files for module with name 'theModuleName'
209 LightApp_Driver::ListOfFiles LightApp_Driver::GetListOfFiles( const char* theModuleName )
211 ListOfFiles aListOfFiles;
213 std::string aName(theModuleName);
214 if (myMap.count(aName))
215 aListOfFiles = myMap[aName];
221 Sets list of files for module with name 'theModuleName'
223 void LightApp_Driver::SetListOfFiles( const char* theModuleName, const ListOfFiles theListOfFiles )
225 std::string aName (theModuleName);
226 myMap[aName] = theListOfFiles;
230 Converts files which was created from module <theModuleName> into a byte sequence unsigned char
232 void LightApp_Driver::PutFilesToStream( const std::string& theModuleName, unsigned char*& theBuffer,
233 long& theBufferSize, bool theNamesOnly )
235 ListOfFiles aFiles = myMap[theModuleName];
236 // aFiles must contain temporary directory name in its first item
237 // and names of files (relatively the temporary directory) in the others
239 int i, aLength = aFiles.size() - 1;
242 theBuffer = new unsigned char[theBufferSize];
245 //Get a temporary directory for saved a file
246 TCollection_AsciiString aTmpDir(const_cast<char*>(aFiles[0].c_str()));
248 long aBufferSize = 0;
251 int* aFileNameSize= new int[aLength];
252 long* aFileSize= new long[aLength];
254 //Determine the required size of the buffer
255 TCollection_AsciiString aFileName;
256 for (i = 0; i < aLength; i++) {
257 char* aFName = const_cast<char*>(aFiles[i+1].c_str());
259 //Check if the file exists
260 if (!theNamesOnly) { // mpv 15.01.2003: if only file names must be stroed, then size of files is zero
261 TCollection_AsciiString aFullPath = aTmpDir + aFileName;
262 OSD_Path anOSDPath(aFullPath);
263 OSD_File anOSDFile(anOSDPath);
264 if(!anOSDFile.Exists()) continue;
266 ifstream aFile(aFullPath.ToCString(), ios::binary);
268 ifstream aFile(aFullPath.ToCString());
270 aFile.seekg(0, ios::end);
271 aFileSize[i] = aFile.tellg();
272 aBufferSize += aFileSize[i]; //Add a space to store the file
274 aFileNameSize[i] = strlen(aFName) + 1;
275 aBufferSize += aFileNameSize[i]; //Add a space to store the file name
276 aBufferSize += (theNamesOnly)?4:12; //Add 4 bytes: a length of the file name,
277 // 8 bytes: length of the file itself
281 aBufferSize += 4; //4 bytes for a number of the files that will be written to the stream;
282 theBuffer = new unsigned char[aBufferSize];
283 if(theBuffer == NULL) {
288 //Initialize 4 bytes of the buffer by 0
289 memset(theBuffer, 0, 4);
290 //Copy the number of files that will be written to the stream
291 memcpy(theBuffer, &aNbFiles, ((sizeof(int) > 4) ? 4 : sizeof(int)));
295 for(i = 0; i < aLength; i++) {
297 if (!theNamesOnly) { // mpv 15.01.2003: we don't open any file if theNamesOnly = true
298 TCollection_AsciiString aName(const_cast<char*>(aFiles[i+1].c_str()));
299 TCollection_AsciiString aFullPath = aTmpDir + aName;
300 OSD_Path anOSDPath(aFullPath);
301 OSD_File anOSDFile(anOSDPath);
302 if(!anOSDFile.Exists()) continue;
304 aFile = new ifstream(aFullPath.ToCString(), ios::binary);
306 aFile = new ifstream(aFullPath.ToCString());
309 //Initialize 4 bytes of the buffer by 0
310 memset((theBuffer + aCurrentPos), 0, 4);
311 //Copy the length of the file name to the buffer
312 memcpy((theBuffer + aCurrentPos), (aFileNameSize + i), ((sizeof(int) > 4) ? 4 : sizeof(int)));
315 //Copy the file name to the buffer
316 char* aFName = const_cast<char*>(aFiles[i+1].c_str());
317 memcpy((theBuffer + aCurrentPos), aFName, aFileNameSize[i]);
318 aCurrentPos += aFileNameSize[i];
320 if (!theNamesOnly) { // mpv 15.01.2003: we don't copy file content to the buffer if !theNamesOnly
321 //Initialize 8 bytes of the buffer by 0
322 memset((theBuffer + aCurrentPos), 0, 8);
323 //Copy the length of the file to the buffer
324 memcpy((theBuffer + aCurrentPos), (aFileSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));
327 aFile->seekg(0, ios::beg);
328 aFile->read((char *)(theBuffer + aCurrentPos), aFileSize[i]);
331 aCurrentPos += aFileSize[i];
334 delete[] aFileNameSize;
337 theBufferSize = aBufferSize;
341 Converts a byte sequence <theBuffer> to files and return list of them
343 LightApp_Driver::ListOfFiles LightApp_Driver::PutStreamToFiles( const unsigned char* theBuffer,
344 const long theBufferSize, bool theNamesOnly )
346 if(theBufferSize == 0 || theBuffer == 0)
347 return ListOfFiles();
349 // Create a temporary directory for the component's data files
350 std::string aDir = GetTmpDir();
352 // Remember that the files are in a temporary location that should be deleted
353 // when a study is closed
354 SetIsTemporary( true );
356 //Get a temporary directory for saving a file
357 TCollection_AsciiString aTmpDir(const_cast<char*>(aDir.c_str()));
359 long aFileSize, aCurrentPos = 4;
360 int i, aFileNameSize, aNbFiles = 0;
362 //Copy the number of files in the stream
363 memcpy(&aNbFiles, theBuffer, sizeof(int));
365 const int n = aNbFiles + 1;
366 ListOfFiles aFiles(n);
369 for(i = 0; i < aNbFiles; i++) {
370 //Put a length of the file name to aFileNameSize
371 memcpy(&aFileNameSize, (theBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int)));
374 char *aFileName = new char[aFileNameSize];
375 //Put a file name to aFileName
376 memcpy(aFileName, (theBuffer + aCurrentPos), aFileNameSize);
377 aCurrentPos += aFileNameSize;
379 //Put a length of the file to aFileSize
381 memcpy(&aFileSize, (theBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long)));
384 TCollection_AsciiString aFullPath = aTmpDir + aFileName;
387 ofstream aFile(aFullPath.ToCString(), ios::out | ios::binary);
389 ofstream aFile(aFullPath.ToCString());
392 aFile.write((char *)(theBuffer+aCurrentPos), aFileSize);
394 aCurrentPos += aFileSize;
396 std::string aStrFileName(aFileName);
397 aFiles[i+1] = aStrFileName;
404 Remove files. First item in <theFiles> is a directory with slash at the end.
405 Other items are names of files. If <IsDirDeleted> is true,
406 then the directory is also deleted.
408 void LightApp_Driver::RemoveFiles( const ListOfFiles& theFiles, const bool IsDirDeleted)
410 int i, aLength = theFiles.size() - 1;
414 //Get a temporary directory for saved a file
415 TCollection_AsciiString aDirName(const_cast<char*>(theFiles[0].c_str()));
417 for(i = 0; i < aLength; i++) {
418 TCollection_AsciiString aFile(aDirName);
419 aFile += const_cast<char*>(theFiles[i+1].c_str());
420 OSD_Path anOSDPath(aFile);
421 OSD_File anOSDFile(anOSDPath);
422 if(!anOSDFile.Exists()) continue;
428 OSD_Path aPath(aDirName);
429 OSD_Directory aDir(aPath);
430 // san -- Using a special code block below is essential - it ensures that
431 // OSD_FileIterator instance is destroyed by the moment when
432 // OSD_Directory::Remove() is called.
433 // Otherwise, the directory remains locked (at least on Windows)
434 // by the iterator and cannot be removed.
436 OSD_FileIterator anIterator(aPath, '*');
437 if(!aDir.Exists() || anIterator.More())
445 Removes files which was created from module theModuleName if
446 <IsDirDeleted> is true tmp directory is also deleted if it is empty
448 void LightApp_Driver::RemoveTemporaryFiles( const char* theModuleName, const bool IsDirDeleted )
450 std::string aModuleName(theModuleName);
451 ListOfFiles aFiles = myMap[aModuleName];
452 // aFiles must contain temporary directory name in its first item
453 // and names of files (relatively the temporary directory) in the others
454 RemoveFiles( aFiles, IsDirDeleted );
459 Clears map of list files
461 void LightApp_Driver::ClearDriverContents()
463 std::map<std::string, ListOfFiles>::iterator it;
464 for ( it = myMap.begin(); it != myMap.end(); ++it )
466 const char* aModuleName = const_cast<char*>(it->first.c_str());
467 // If the driver contains temporary files -
468 // remove them along with the temporary directory
469 RemoveTemporaryFiles( aModuleName, IsTemporary() );
472 // Reset the "temporary" flag
473 SetIsTemporary( false );
477 \return a temp directory to store created files like "/tmp/sub_dir/"
479 std::string LightApp_Driver::GetTmpDir()
481 if ( myTmpDir.length() != 0 )
484 //Find a temporary directory to store a file
485 TCollection_AsciiString aTmpDir;
487 char *Tmp_dir = getenv("SALOME_TMP_DIR");
489 Tmp_dir = getenv ( "TEMP" );
491 Tmp_dir = getenv ( "TMP" );
494 aTmpDir = TCollection_AsciiString(Tmp_dir);
496 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
498 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
504 aTmpDir = TCollection_AsciiString("C:\\");
506 aTmpDir = TCollection_AsciiString("/tmp/");
510 srand((unsigned int)time(NULL));
511 int aRND = 999 + (int)(100000.0*rand()/(RAND_MAX+1.0)); //Get a random number to present a name of a sub directory
512 TCollection_AsciiString aSubDir(aRND);
513 if(aSubDir.Length() <= 1) aSubDir = TCollection_AsciiString("123409876");
515 aTmpDir += aSubDir; //Get RND sub directory
518 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
520 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
523 OSD_Path aPath(aTmpDir);
524 OSD_Directory aDir(aPath);
526 for(aRND = 0; aDir.Exists(); aRND++) {
527 aTmpDir.Insert((aTmpDir.Length() - 1), TCollection_AsciiString(aRND)); //Build a unique directory name
528 aPath = OSD_Path(aTmpDir);
529 aDir = OSD_Directory(aPath);
533 // Workaround for OSD_Protection bug on Windows
534 OSD_Protection aProtection(OSD_RWXD, OSD_RWXD, OSD_RWXD, OSD_RWXD);
536 OSD_Protection aProtection(OSD_RX, OSD_RWXD, OSD_RX, OSD_RX);
538 aDir.Build(aProtection);
540 myTmpDir = aTmpDir.ToCString();
542 return aTmpDir.ToCString();
546 \return the dir by the path
548 std::string LightApp_Driver::GetDirFromPath( const std::string& thePath ) {
551 OSD_Path aPath = OSD_Path(TCollection_AsciiString(const_cast<char*>(thePath.c_str())));
552 TCollection_AsciiString aDirString(aPath.Trek());
553 aDirString.ChangeAll('|','/');
554 return aDirString.ToCString();