1 // Copyright (C) 2007-2023 CEA, EDF, 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>
45 LightApp_Driver::LightApp_Driver()
51 LightApp_Driver::~LightApp_Driver()
56 Save in file 'theFileName' datas from this driver
58 bool LightApp_Driver::SaveDatasInFile( const char* theFileName, bool isMultiFile )
61 std::map<std::string, ListOfFiles>::const_iterator it;
62 for (it = myMap.begin(); it != myMap.end(); ++it)
65 unsigned char** aBuffer = new unsigned char*[aNbModules];
66 long* aBufferSize = new long[aNbModules];
67 char** aModuleName = new char*[aNbModules];
69 if(aBuffer == NULL || aBufferSize == NULL || aModuleName == NULL)
72 int aFileBufferSize = 4; //4 bytes for a number of the modules that will be written to the stream;
74 for (it = myMap.begin(); it != myMap.end(); ++it) {
75 aModuleName[i] = const_cast<char*>(it->first.c_str());//(it->first);
76 aFileBufferSize += 4; //Add 4 bytes: a length of the module name
77 aFileBufferSize += (int)strlen(aModuleName[i])+1; //!< TODO: conversion from size_t to int
78 std::string aName(aModuleName[i]);
79 PutFilesToStream(aName, aBuffer[i], aBufferSize[i], isMultiFile);
80 aFileBufferSize += 8; //Add 8 bytes: a length of the buffer
81 aFileBufferSize += aBufferSize[i];
86 unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];
87 if(aFileBuffer == NULL)
90 myTmpDir = QDir::toNativeSeparators( QFileInfo( theFileName ).absolutePath() + "/" ).toUtf8().constData() ;
94 //Initialize 4 bytes of the buffer by 0
95 memset(aFileBuffer, 0, 4);
96 //Copy the number of modules that will be written to the stream
97 memcpy(aFileBuffer, &aNbModules, ((sizeof(int) > 4) ? 4 : sizeof(int)));
100 int aBufferNameSize = 0;
101 for (i = 0; i < n; i++) {
102 aBufferNameSize = (int)strlen(aModuleName[i])+1; //!< TODO: conversion from size_t to int
103 //Initialize 4 bytes of the buffer by 0
104 memset((aFileBuffer + aCurrentPos), 0, 4);
105 //Copy the length of the module name to the buffer
106 memcpy((aFileBuffer + aCurrentPos), &aBufferNameSize, ((sizeof(int) > 4) ? 4 : sizeof(int)));
108 //Copy the module name to the buffer
109 memcpy((aFileBuffer + aCurrentPos), aModuleName[i], aBufferNameSize);
110 aCurrentPos += aBufferNameSize;
112 //Initialize 8 bytes of the buffer by 0
113 memset((aFileBuffer + aCurrentPos), 0, 8);
114 //Copy the length of the module buffer to the buffer
115 memcpy((aFileBuffer + aCurrentPos), (aBufferSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));
117 //Copy the module buffer to the buffer
118 memcpy((aFileBuffer + aCurrentPos), aBuffer[i], aBufferSize[i]);
119 aCurrentPos += aBufferSize[i];
123 ofstream aFile(theFileName, ios::out | ios::binary);
125 ofstream aFile(theFileName);
127 aFile.write((char*)aFileBuffer, aFileBufferSize);
131 delete[] aBufferSize;
132 delete[] aModuleName;
133 delete[] aFileBuffer;
139 Filling current driver from file 'theFileName'
141 bool LightApp_Driver::ReadDatasFromFile( const char* theFileName, bool isMultiFile )
144 ifstream aFile(theFileName, ios::binary);
146 ifstream aFile(theFileName);
149 myTmpDir = QDir::toNativeSeparators( QFileInfo( theFileName ).absolutePath() + "/" ).toUtf8().constData() ;
151 aFile.seekg(0, ios::end);
152 int aFileBufferSize = aFile.tellg();
153 unsigned char* aFileBuffer = new unsigned char[aFileBufferSize];
154 aFile.seekg(0, ios::beg);
155 aFile.read((char*)aFileBuffer, aFileBufferSize);
159 //Copy the number of files in the stream
160 memcpy(&aNbModules, aFileBuffer, sizeof(int));
161 long aCurrentPos = 4;
164 for (int i = 0; i < aNbModules; i++) {
165 //Put a length of the module name to aModuleNameSize
166 memcpy(&aModuleNameSize, (aFileBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int)));
169 char *aModuleName = new char[aModuleNameSize];
170 //Put a module name to aModuleName
171 memcpy(aModuleName, (aFileBuffer + aCurrentPos), aModuleNameSize);
172 aCurrentPos += aModuleNameSize;
174 //Put a length of the file buffer to aBufferSize
176 memcpy(&aBufferSize, (aFileBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long)));
178 unsigned char *aBuffer = new unsigned char[aBufferSize];
180 //Put a buffer for current module to aBuffer
181 memcpy(aBuffer, (aFileBuffer + aCurrentPos), aBufferSize);
182 aCurrentPos += aBufferSize;
184 // Put buffer to aListOfFiles and set to myMap
185 ListOfFiles aListOfFiles = PutStreamToFiles(aBuffer, aBufferSize, isMultiFile);
186 SetListOfFiles(aModuleName, aListOfFiles);
188 delete[] aModuleName;
192 delete[] aFileBuffer;
198 \return temp directory for path 'theURL'
200 std::string LightApp_Driver::GetTmpDir (const char* theURL, const bool isMultiFile)
202 std::string anURLDir = GetDirFromPath(theURL);
203 std::string aTmpDir = isMultiFile ? anURLDir : GetTmpDir();
209 \return list of files for module with name 'theModuleName'
211 LightApp_Driver::ListOfFiles LightApp_Driver::GetListOfFiles( const char* theModuleName )
213 ListOfFiles aListOfFiles;
215 std::string aName(theModuleName);
216 if (myMap.count(aName))
217 aListOfFiles = myMap[aName];
223 Sets list of files for module with name 'theModuleName'
225 void LightApp_Driver::SetListOfFiles( const char* theModuleName, const ListOfFiles theListOfFiles )
227 std::string aName (theModuleName);
228 myMap[aName] = theListOfFiles;
232 Converts files which was created from module <theModuleName> into a byte sequence unsigned char
234 void LightApp_Driver::PutFilesToStream( const std::string& theModuleName, unsigned char*& theBuffer,
235 long& theBufferSize, bool theNamesOnly )
237 ListOfFiles aFiles = myMap[theModuleName];
238 // aFiles must contain temporary directory name in its first item
239 // and names of files (relatively the temporary directory) in the others
241 int i, aLength = (int)aFiles.size() - 1; //!< TODO: conversion size_t to int
244 theBuffer = new unsigned char[theBufferSize];
247 //Get a temporary directory for saved a file
248 TCollection_AsciiString aTmpDir(const_cast<char*>(aFiles[0].c_str()));
250 long aBufferSize = 0;
253 int* aFileNameSize= new int[aLength];
254 long* aFileSize= new long[aLength];
256 //Determine the required size of the buffer
257 TCollection_AsciiString aFileName;
258 for (i = 0; i < aLength; i++) {
259 char* aFName = const_cast<char*>(aFiles[i+1].c_str());
261 //Check if the file exists
262 if (!theNamesOnly) { // mpv 15.01.2003: if only file names must be stroed, then size of files is zero
263 TCollection_AsciiString aFullPath = aTmpDir + aFileName;
264 OSD_Path anOSDPath(aFullPath);
265 OSD_File anOSDFile(anOSDPath);
266 if(!anOSDFile.Exists()) continue;
268 ifstream aFile(aFullPath.ToCString(), ios::binary);
270 ifstream aFile(aFullPath.ToCString());
272 aFile.seekg(0, ios::end);
273 aFileSize[i] = aFile.tellg();
274 aBufferSize += aFileSize[i]; //Add a space to store the file
276 aFileNameSize[i] = (int)strlen(aFName) + 1; //!< TODO: conversion from size_t to int
277 aBufferSize += aFileNameSize[i]; //Add a space to store the file name
278 aBufferSize += (theNamesOnly)?4:12; //Add 4 bytes: a length of the file name,
279 // 8 bytes: length of the file itself
283 aBufferSize += 4; //4 bytes for a number of the files that will be written to the stream;
284 theBuffer = new unsigned char[aBufferSize];
285 if(theBuffer == NULL) {
290 //Initialize 4 bytes of the buffer by 0
291 memset(theBuffer, 0, 4);
292 //Copy the number of files that will be written to the stream
293 memcpy(theBuffer, &aNbFiles, ((sizeof(int) > 4) ? 4 : sizeof(int)));
297 for(i = 0; i < aLength; i++) {
299 if (!theNamesOnly) { // mpv 15.01.2003: we don't open any file if theNamesOnly = true
300 TCollection_AsciiString aName(const_cast<char*>(aFiles[i+1].c_str()));
301 TCollection_AsciiString aFullPath = aTmpDir + aName;
302 OSD_Path anOSDPath(aFullPath);
303 OSD_File anOSDFile(anOSDPath);
304 if(!anOSDFile.Exists()) continue;
306 aFile = new ifstream(aFullPath.ToCString(), ios::binary);
308 aFile = new ifstream(aFullPath.ToCString());
311 //Initialize 4 bytes of the buffer by 0
312 memset((theBuffer + aCurrentPos), 0, 4);
313 //Copy the length of the file name to the buffer
314 memcpy((theBuffer + aCurrentPos), (aFileNameSize + i), ((sizeof(int) > 4) ? 4 : sizeof(int)));
317 //Copy the file name to the buffer
318 char* aFName = const_cast<char*>(aFiles[i+1].c_str());
319 memcpy((theBuffer + aCurrentPos), aFName, aFileNameSize[i]);
320 aCurrentPos += aFileNameSize[i];
322 if (!theNamesOnly) { // mpv 15.01.2003: we don't copy file content to the buffer if !theNamesOnly
323 //Initialize 8 bytes of the buffer by 0
324 memset((theBuffer + aCurrentPos), 0, 8);
325 //Copy the length of the file to the buffer
326 memcpy((theBuffer + aCurrentPos), (aFileSize + i), ((sizeof(long) > 8) ? 8 : sizeof(long)));
329 aFile->seekg(0, ios::beg);
330 aFile->read((char *)(theBuffer + aCurrentPos), aFileSize[i]);
333 aCurrentPos += aFileSize[i];
336 delete[] aFileNameSize;
339 theBufferSize = aBufferSize;
343 Converts a byte sequence <theBuffer> to files and return list of them
345 LightApp_Driver::ListOfFiles LightApp_Driver::PutStreamToFiles( const unsigned char* theBuffer,
346 const long theBufferSize, bool theNamesOnly )
348 if(theBufferSize == 0 || theBuffer == 0)
349 return ListOfFiles();
351 // Create a temporary directory for the component's data files
352 std::string aDir = GetTmpDir();
354 // Remember that the files are in a temporary location that should be deleted
355 // when a study is closed
356 SetIsTemporary( true );
358 //Get a temporary directory for saving a file
359 TCollection_AsciiString aTmpDir(const_cast<char*>(aDir.c_str()));
361 long aFileSize, aCurrentPos = 4;
362 int i, aFileNameSize, aNbFiles = 0;
364 //Copy the number of files in the stream
365 memcpy(&aNbFiles, theBuffer, sizeof(int));
367 const int n = aNbFiles + 1;
368 ListOfFiles aFiles(n);
371 for(i = 0; i < aNbFiles; i++) {
372 //Put a length of the file name to aFileNameSize
373 memcpy(&aFileNameSize, (theBuffer + aCurrentPos), ((sizeof(int) > 4) ? 4 : sizeof(int)));
376 char *aFileName = new char[aFileNameSize];
377 //Put a file name to aFileName
378 memcpy(aFileName, (theBuffer + aCurrentPos), aFileNameSize);
379 aCurrentPos += aFileNameSize;
381 //Put a length of the file to aFileSize
383 memcpy(&aFileSize, (theBuffer + aCurrentPos), ((sizeof(long) > 8) ? 8 : sizeof(long)));
386 TCollection_AsciiString aFullPath = aTmpDir + aFileName;
389 ofstream aFile(aFullPath.ToCString(), ios::out | ios::binary);
391 ofstream aFile(aFullPath.ToCString());
394 aFile.write((char *)(theBuffer+aCurrentPos), aFileSize);
396 aCurrentPos += aFileSize;
398 std::string aStrFileName(aFileName);
399 aFiles[i+1] = aStrFileName;
406 Remove files. First item in <theFiles> is a directory with slash at the end.
407 Other items are names of files. If <IsDirDeleted> is true,
408 then the directory is also deleted.
410 void LightApp_Driver::RemoveFiles( const ListOfFiles& theFiles, const bool IsDirDeleted)
412 int i, aLength = (int)theFiles.size() - 1; //!< TODO: conversion size_t to int
416 //Get a temporary directory for saved a file
417 TCollection_AsciiString aDirName(const_cast<char*>(theFiles[0].c_str()));
419 for(i = 0; i < aLength; i++) {
420 TCollection_AsciiString aFile(aDirName);
421 aFile += const_cast<char*>(theFiles[i+1].c_str());
422 OSD_Path anOSDPath(aFile);
423 OSD_File anOSDFile(anOSDPath);
424 if(!anOSDFile.Exists()) continue;
430 OSD_Path aPath(aDirName);
431 OSD_Directory aDir(aPath);
432 // san -- Using a special code block below is essential - it ensures that
433 // OSD_FileIterator instance is destroyed by the moment when
434 // OSD_Directory::Remove() is called.
435 // Otherwise, the directory remains locked (at least on Windows)
436 // by the iterator and cannot be removed.
438 OSD_FileIterator anIterator(aPath, '*');
439 if(!aDir.Exists() || anIterator.More())
447 Removes files which was created from module theModuleName if
448 <IsDirDeleted> is true tmp directory is also deleted if it is empty
450 void LightApp_Driver::RemoveTemporaryFiles( const char* theModuleName, const bool IsDirDeleted )
452 std::string aModuleName(theModuleName);
453 ListOfFiles aFiles = myMap[aModuleName];
454 // aFiles must contain temporary directory name in its first item
455 // and names of files (relatively the temporary directory) in the others
456 RemoveFiles( aFiles, IsDirDeleted );
461 Clears map of list files
463 void LightApp_Driver::ClearDriverContents()
465 std::map<std::string, ListOfFiles>::iterator it;
466 for ( it = myMap.begin(); it != myMap.end(); ++it )
468 const char* aModuleName = const_cast<char*>(it->first.c_str());
469 // If the driver contains temporary files -
470 // remove them along with the temporary directory
471 RemoveTemporaryFiles( aModuleName, IsTemporary() );
474 // Reset the "temporary" flag
475 SetIsTemporary( false );
479 \return a temp directory to store created files like "/tmp/sub_dir/"
481 std::string LightApp_Driver::GetTmpDir()
483 if ( myTmpDir.length() != 0 )
486 //Find a temporary directory to store a file
487 TCollection_AsciiString aTmpDir;
489 char *Tmp_dir = getenv("SALOME_TMP_DIR");
491 Tmp_dir = getenv ( "TEMP" );
493 Tmp_dir = getenv ( "TMP" );
496 aTmpDir = TCollection_AsciiString(Tmp_dir);
498 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
500 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
506 aTmpDir = TCollection_AsciiString("C:\\");
508 aTmpDir = TCollection_AsciiString("/tmp/");
512 srand((unsigned int)time(NULL));
513 int aRND = 999 + (int)(100000.0*rand()/(RAND_MAX+1.0)); //Get a random number to present a name of a sub directory
514 TCollection_AsciiString aSubDir(aRND);
515 if(aSubDir.Length() <= 1) aSubDir = TCollection_AsciiString("123409876");
517 aTmpDir += aSubDir; //Get RND sub directory
520 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
522 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
525 OSD_Path aPath(aTmpDir);
526 OSD_Directory aDir(aPath);
528 for(aRND = 0; aDir.Exists(); aRND++) {
529 aTmpDir.Insert((aTmpDir.Length() - 1), TCollection_AsciiString(aRND)); //Build a unique directory name
530 aPath = OSD_Path(aTmpDir);
531 aDir = OSD_Directory(aPath);
535 // Workaround for OSD_Protection bug on Windows
536 OSD_Protection aProtection(OSD_RWXD, OSD_RWXD, OSD_RWXD, OSD_RWXD);
538 OSD_Protection aProtection(OSD_RX, OSD_RWXD, OSD_RX, OSD_RX);
540 aDir.Build(aProtection);
542 myTmpDir = aTmpDir.ToCString();
544 return aTmpDir.ToCString();
548 \return the dir by the path
550 std::string LightApp_Driver::GetDirFromPath( const std::string& thePath ) {
553 OSD_Path aPath = OSD_Path(TCollection_AsciiString(const_cast<char*>(thePath.c_str())));
554 TCollection_AsciiString aDirString(aPath.Trek());
555 aDirString.ChangeAll('|','/');
556 return aDirString.ToCString();