76623f9bc893f0b0d90666935ae18ff3a2ea009e
[occt.git] / src / OSD / OSD_File.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 //------------------------------------------------------------------------
16 //                    UNIX Part
17 //------------------------------------------------------------------------
18
19 #ifndef _WIN32
20
21
22 #include <OSD_File.hxx>
23 #include <OSD_FromWhere.hxx>
24 #include <OSD_OSDError.hxx>
25 #include <OSD_Path.hxx>
26 #include <OSD_Protection.hxx>
27 #include <OSD_WhoAmI.hxx>
28 #include <Standard_PCharacter.hxx>
29 #include <Standard_ProgramError.hxx>
30 #include <TCollection_AsciiString.hxx>
31
32 const OSD_WhoAmI Iam = OSD_WFile;
33
34 #if defined (sun) || defined(SOLARIS)
35 #define POSIX
36 #else             
37 #define SYSV
38 #endif
39
40 #include <errno.h>
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include <sys/stat.h>
46
47 #define NEWLINE '\10';
48
49 // ---------------------------------------------------------------------
50 // Create an empty file object
51 // ---------------------------------------------------------------------
52
53 OSD_File::OSD_File():OSD_FileNode()
54 {
55  ImperativeFlag = Standard_False;
56  myLock         = OSD_NoLock;
57  myIO           = 0;
58  myMode         = OSD_ReadWrite;
59  myFILE         = (Standard_Address) NULL;
60  myFileChannel  = -1;
61  myFileHandle   = 0;
62 }
63
64 // ---------------------------------------------------------------------
65 // Create and initialize a file object
66 // ---------------------------------------------------------------------
67
68 OSD_File::OSD_File(const OSD_Path& Name):OSD_FileNode(Name)
69 {
70  ImperativeFlag = Standard_False;
71  myLock         = OSD_NoLock;
72  myIO           = 0;
73  myMode         = OSD_ReadWrite;
74  myFILE         = (Standard_Address) NULL;
75  myFileChannel  = -1;
76  myFileHandle   = 0;
77 }
78
79 // protect against occasional use of myFileHande in Linux code
80 #define myFileHandle myFileHandle_is_only_for_Windows
81
82 // ---------------------------------------------------------------------
83 // Build a file if it doesn't exist or create again if it already exists
84 // ---------------------------------------------------------------------
85
86 void OSD_File::Build(const OSD_OpenMode Mode,
87                      const OSD_Protection& Protect){
88  
89  Standard_Integer internal_prot;
90  Standard_Integer internal_mode = O_CREAT | O_TRUNC ;
91  TCollection_AsciiString aBuffer;
92
93  if (myPath.Name().Length()==0)
94   throw Standard_ProgramError("OSD_File::Build : no name was given");
95
96  if (myFileChannel != -1)
97   throw Standard_ProgramError("OSD_File::Build : file is already open");
98
99
100  myMode = Mode;
101
102  internal_prot = Protect.Internal();
103
104  const char* CMode = "r";
105
106  switch (Mode){
107   case OSD_ReadOnly:
108    internal_mode |= O_RDONLY;
109    CMode = "r";
110    break;
111   case OSD_WriteOnly:
112    internal_mode |= O_WRONLY;
113    CMode = "w";
114    break;
115   case OSD_ReadWrite:
116    internal_mode |= O_RDWR;
117    CMode = "w+";
118    break;
119  }
120
121  myPath.SystemName( aBuffer ); 
122  myFileChannel = open (aBuffer.ToCString(), internal_mode, internal_prot);
123  if (myFileChannel >= 0) { 
124    myFILE = fdopen (myFileChannel, CMode);
125  }
126  else
127  /* Handle OPEN errors */
128
129    myError.SetValue (errno, Iam, "Open");
130
131 }
132
133
134
135 // ---------------------------------------------------------------------
136 // Append to an existing file
137 // ---------------------------------------------------------------------
138
139 void  OSD_File::Append(const OSD_OpenMode Mode,
140                        const OSD_Protection& Protect){
141
142  Standard_Integer internal_prot;
143  Standard_Integer internal_mode = O_APPEND;;
144  TCollection_AsciiString aBuffer;
145
146  if ( OSD_File::KindOfFile ( ) == OSD_DIRECTORY ) {
147     throw Standard_ProgramError("OSD_File::Append : it is a directory");
148  } 
149  
150  if (myPath.Name().Length()==0)
151   throw Standard_ProgramError("OSD_File::Append : no name was given");
152
153  if (myFileChannel != -1)
154   throw Standard_ProgramError("OSD_File::Append : file is already open");
155
156  internal_prot = Protect.Internal();
157  myMode = Mode;
158  const char* CMode = "r";
159
160  switch (Mode){
161   case OSD_ReadOnly:
162    internal_mode |= O_RDONLY;
163    CMode = "r";
164    break;
165   case OSD_WriteOnly:
166    internal_mode |= O_WRONLY;
167    CMode = "a";
168    break;
169   case OSD_ReadWrite:
170    internal_mode |= O_RDWR;
171    CMode = "a+";
172    break;
173  }
174
175  // If file doesn't exist, creates it.
176
177  if (!Exists()) internal_mode |= O_CREAT;
178
179  myPath.SystemName ( aBuffer );
180  myFileChannel = open (aBuffer.ToCString(), internal_mode, internal_prot);
181  if (myFileChannel >= 0)
182    myFILE = fdopen (myFileChannel, CMode);
183  else
184  /* Handle OPEN errors */
185
186    myError.SetValue (errno, Iam, "Open");
187 }
188
189 // ---------------------------------------------------------------------
190 // Open a file
191 // ---------------------------------------------------------------------
192
193 void  OSD_File::Open(const OSD_OpenMode Mode,
194                      const OSD_Protection& Protect){
195
196  Standard_Integer internal_prot;
197  Standard_Integer internal_mode = 0;
198  TCollection_AsciiString aBuffer;
199
200   if ( OSD_File::KindOfFile ( ) == OSD_DIRECTORY ) { 
201     myError.SetValue (1, Iam, "Could not be open : it is a directory");
202   }
203
204  if (myPath.Name().Length()==0)
205   throw Standard_ProgramError("OSD_File::Open : no name was given");
206
207  if (myFileChannel != -1)
208   throw Standard_ProgramError("OSD_File::Open : file is already open");
209
210  internal_prot = Protect.Internal();
211  myMode = Mode;
212  const char* CMode = "r";
213
214  switch (Mode){
215   case OSD_ReadOnly:
216    internal_mode |= O_RDONLY;
217    CMode = "r";
218    break;
219   case OSD_WriteOnly:
220    internal_mode |= O_WRONLY;
221    CMode = "w";
222    break;
223   case OSD_ReadWrite:
224    internal_mode |= O_RDWR;
225    CMode = "w+";
226    break;
227  }
228
229  myPath.SystemName ( aBuffer );
230  myFileChannel = open (aBuffer.ToCString(), internal_mode, internal_prot);
231  if (myFileChannel >= 0)
232    myFILE = fdopen (myFileChannel, CMode);
233  else
234  /* Handle OPEN errors */
235
236    myError.SetValue (errno, Iam, "Open");
237 }
238
239
240
241 // ---------------------------------------------------------------------
242 // ---------------------------------------------------------------------
243 void OSD_File::BuildTemporary(){
244
245  if ( IsOpen() )
246   Close();
247
248 #if defined(vax) || defined(__vms) || defined(VAXVMS)
249  FILE *fic;
250  int dummy;
251
252  fic = tmpfile();
253  dummy = open("dummy", O_RDWR | O_CREAT);  // Open a dummy file
254  myFileChannel = dummy - 1;         // This is file channel of "fic" +1
255  close(dummy);                             // Close dummy file
256  unlink("dummy");                          // Removes dummy file
257
258 #else 
259  char name[] = "/tmp/CSFXXXXXX";
260  myFileChannel = mkstemp( name );
261
262  TCollection_AsciiString aName ( name ) ;
263  OSD_Path aPath( aName ) ;
264
265  SetPath( aPath ) ;
266
267  myFILE = fdopen( myFileChannel, "w+" ) ;
268
269 #endif
270
271  myMode = OSD_ReadWrite;
272 }
273  
274
275
276 // ---------------------------------------------------------------------
277 // Read content of a file
278 // ---------------------------------------------------------------------
279  
280 void  OSD_File::Read(TCollection_AsciiString& Buffer, 
281                      const Standard_Integer Nbyte){
282  Standard_PCharacter readbuf;
283  int status;
284
285   if ( OSD_File::KindOfFile ( ) == OSD_DIRECTORY ) { 
286     throw Standard_ProgramError("OSD_File::Read : it is a directory");
287   }
288
289  if (myFileChannel == -1)
290   throw Standard_ProgramError("OSD_File::Read : file is not open");
291
292  if (Failed()) Perror();
293
294  if (myMode == OSD_WriteOnly)
295   throw Standard_ProgramError("OSD_File::Read : file is Write only");
296
297  if (Nbyte <= 0)
298   throw Standard_ProgramError("OSD_File::Read : Nbyte is null");
299
300  TCollection_AsciiString transfert(Nbyte,' ');
301  readbuf = (Standard_PCharacter)transfert.ToCString();  
302
303  status = read (myFileChannel, readbuf, Nbyte);
304  //
305  Buffer = transfert;  // Copy transfert to Buffer
306
307  if (status == -1) myError.SetValue (errno, Iam, "Read");
308  else
309  if ( status < Nbyte ) myIO = EOF;
310 }
311
312
313 // ---------------------------------------------------------------------
314 // Read a line from a file
315 // ---------------------------------------------------------------------
316
317 void OSD_File::ReadLine(TCollection_AsciiString& Buffer, 
318                         const Standard_Integer Nbyte,
319                         Standard_Integer& NByteRead)
320 {
321   Standard_PCharacter readbuf, abuffer;
322   //
323   if (OSD_File::KindOfFile() == OSD_DIRECTORY ) { 
324     throw Standard_ProgramError("OSD_File::Read : it is a directory");
325   }
326   if (myFileChannel == -1){
327     throw Standard_ProgramError("OSD_File::ReadLine : file is not open");
328   }
329   if (Failed()) {
330     Perror();
331   }
332   if (myMode == OSD_WriteOnly) {
333     throw Standard_ProgramError("OSD_File::ReadLine : file is Write only");
334   }
335   if (Nbyte <= 0){
336     throw Standard_ProgramError("OSD_File::ReadLine : Nbyte is null");
337   }
338   //
339   TCollection_AsciiString transfert(Nbyte,' ');
340   readbuf = (Standard_PCharacter)transfert.ToCString();
341   //
342   abuffer = fgets(readbuf, Nbyte, (FILE *) myFILE);
343   //
344   if (abuffer == NULL) {
345     if (!feof((FILE *) myFILE)) {
346       myError.SetValue (errno, Iam, "ReadLine");
347       return;
348     }
349     else {
350       myIO = EOF;
351       Buffer.Clear();
352       NByteRead = 0 ;
353     }
354   }
355   else   {
356     NByteRead = (Standard_Integer)strlen(abuffer);
357     Buffer.SetValue(1,abuffer);  // Copy transfert to Buffer
358     Buffer.Trunc(NByteRead);
359   }
360 }
361 // -------------------------------------------------------------------------- 
362 // OSD::KindOfFile Retourne le type de fichier.
363 // -------------------------------------------------------------------------- 
364 OSD_KindFile OSD_File::KindOfFile ( ) const{
365 int status;
366 struct stat buffer;
367 TCollection_AsciiString FullName;
368 OSD_Path aPath;
369
370 Path(aPath);
371 aPath.SystemName (FullName);
372 status = stat (FullName.ToCString()  , &buffer );
373 if ( status == 0) {
374   if       (  S_ISDIR(buffer.st_mode)  )  { return OSD_DIRECTORY ; }
375   else if  (  S_ISREG(buffer.st_mode)  )  { return OSD_FILE      ; }
376   else if  (  S_ISLNK(buffer.st_mode)  )  { return OSD_LINK      ; }
377   else if  (  S_ISSOCK(buffer.st_mode) )  { return OSD_SOCKET    ; }
378   else                                    { return OSD_UNKNOWN   ; }
379 }
380 return OSD_UNKNOWN   ; 
381
382 }
383 // -------------------------------------------------------------------------- 
384 // Read content of a file
385 // -------------------------------------------------------------------------- 
386 void  OSD_File::Read(const Standard_Address   Buffer, 
387                      const Standard_Integer   Nbyte,
388                            Standard_Integer&  Readbyte)
389 {
390   int status;
391   
392   Readbyte = 0;
393   if ( OSD_File::KindOfFile ( ) == OSD_DIRECTORY ) { 
394     throw Standard_ProgramError("OSD_File::Read : it is a directory");
395   }
396  
397   if (myFileChannel == -1)
398     throw Standard_ProgramError("OSD_File::Read : file is not open");
399   
400   if (Failed()) Perror();
401   
402   if (myMode == OSD_WriteOnly)
403     throw Standard_ProgramError("OSD_File::Read : file is Write only");
404   
405   if (Nbyte <= 0)
406     throw Standard_ProgramError("OSD_File::Read : Nbyte is null");
407
408   if (Buffer == NULL)
409     throw Standard_ProgramError("OSD_File::Read : Buffer is null");
410   
411   status = read (myFileChannel, (char*) Buffer, Nbyte);
412   
413   if (status == -1) myError.SetValue (errno, Iam, "Read");
414   else{
415     if ( status < Nbyte ) myIO = EOF;
416     Readbyte = status;
417   }
418 }
419
420 // Write content of a file
421
422 void  OSD_File::Write(const TCollection_AsciiString &Buffer, 
423                       const Standard_Integer Nbyte){
424
425  Standard_CString writebuf;
426  int status;
427
428  if ( OSD_File::KindOfFile ( ) == OSD_DIRECTORY ) { 
429    throw Standard_ProgramError("OSD_File::Write : it is a directory");
430  }
431  
432  if (myFileChannel == -1)
433   throw Standard_ProgramError("OSD_File::Write : file is not open");
434
435  if (Failed()) Perror();
436
437  if (myMode == OSD_ReadOnly)
438   throw Standard_ProgramError("OSD_File::Write : file is Read only");
439
440  if (Nbyte <= 0)
441   throw Standard_ProgramError("OSD_File::Write : Nbyte is null");
442
443  writebuf = Buffer.ToCString();
444
445  status = write (myFileChannel, writebuf, Nbyte);
446
447  if ( status == -1) myError.SetValue (errno, Iam, "Write");
448  else
449  if ( status < Nbyte ) myIO = EOF;
450 }
451
452
453 void  OSD_File::Write(const Standard_Address   Buffer, 
454                       const Standard_Integer   Nbyte)
455 {
456
457   int status;
458   
459   if (myFileChannel == -1)
460     throw Standard_ProgramError("OSD_File::Write : file is not open");
461   
462   if (Failed()) Perror();
463   
464   if (myMode == OSD_ReadOnly)
465     throw Standard_ProgramError("OSD_File::Write : file is Read only");
466   
467   if (Nbyte <= 0)
468     throw Standard_ProgramError("OSD_File::Write : Nbyte is null");
469   
470   status = write (myFileChannel, (const char *)Buffer, Nbyte);
471   
472   if ( status == -1) myError.SetValue (errno, Iam, "Write");
473   else
474     if ( status < Nbyte ) myIO = EOF;
475 }
476
477
478
479
480
481 // Move file pointer to a specified position
482
483 void  OSD_File::Seek(const Standard_Integer Offset, 
484                      const OSD_FromWhere Whence){
485  int iwhere=0;
486
487  if (myFileChannel == -1)
488   throw Standard_ProgramError("OSD_File::Seek : file is not open");
489
490  if (Failed()) Perror();
491
492  switch (Whence){
493   case OSD_FromBeginning :
494     iwhere = SEEK_SET;
495     break;
496   case OSD_FromHere:
497     iwhere = SEEK_CUR;
498     break;
499   case OSD_FromEnd:
500     iwhere = SEEK_END;
501     break;
502   default :
503    myError.SetValue (EINVAL, Iam, "Seek");
504  }
505
506  off_t status = lseek (myFileChannel, Offset, iwhere);
507  if (status == -1) myError.SetValue (errno, Iam, "Seek");
508 }
509
510
511
512
513
514
515 // Close a file
516
517 void  OSD_File::Close(){
518  int status;
519
520  if (myFileChannel == -1)
521   throw Standard_ProgramError("OSD_File::Close : file is not open");
522
523  if (Failed()) Perror();
524
525  // note: it probably should be single call to fclose()...
526  status = close (myFileChannel);
527
528  if (status == -1) myError.SetValue (errno, Iam, "Close");
529  myFileChannel = -1;
530  if ( myFILE != NULL ) {
531    status = fclose ( (FILE*) myFILE );
532    myFILE = NULL;
533  }
534  myIO = 0;
535 }
536
537
538
539
540 // -------------------------------------------------------------------------- 
541 // Test if at end of file
542 // -------------------------------------------------------------------------- 
543
544 Standard_Boolean OSD_File::IsAtEnd(){
545  if (myFileChannel == -1)
546   throw Standard_ProgramError("OSD_File::IsAtEnd : file is not open");
547
548  if (myIO == EOF) return (Standard_True);
549  return (Standard_False);
550 }
551
552
553
554 /*void  OSD_File::Link(const TCollection_AsciiString& ToFile){
555  if (myFileChannel == -1)
556   throw Standard_ProgramError("OSD_File::Link : file is not open");
557
558  TCollection_AsciiString aBuffer;
559  myPath.SystemName ( aBuffer );
560  link ( aBuffer.ToCString(), ToFile.ToCString() );
561
562 }*/
563
564
565
566 void  OSD_File::SetLock(const OSD_LockType Lock){
567 int status;
568
569  if (myFileChannel == -1)
570   throw Standard_ProgramError("OSD_File::SetLock : file is not open");
571
572
573 #ifdef POSIX
574  int lock;
575  struct stat buf;
576
577  switch (Lock){
578   case OSD_ExclusiveLock :
579   case OSD_WriteLock     : lock = F_LOCK;
580                            break;
581   case OSD_ReadLock      : return;
582                            break;
583   default : myError.SetValue (EINVAL, Iam, "SetLock");
584             return;
585  }
586
587  if (fstat (myFileChannel, &buf) == -1) {
588   myError.SetValue (errno, Iam, "SetLock");
589   return;
590  }
591
592  status = lockf(myFileChannel, lock, buf.st_size);
593  if (status == -1) myError.SetValue (errno, Iam, "SetLock");
594  else myLock = Lock;
595
596 #else
597 #ifdef SYSV
598  struct stat  buf;
599  struct flock key;
600
601  switch (Lock){
602   case OSD_ExclusiveLock :
603   case OSD_WriteLock     : key.l_type = F_WRLCK;
604                            break;
605   case OSD_ReadLock      : key.l_type = F_RDLCK;
606                            break;
607   case OSD_NoLock : return;
608  // default : myError.SetValue (EINVAL, Iam, "SetLock");
609  }
610
611  key.l_whence = 0;
612  key.l_start = 0;
613  key.l_len = 0;
614
615  status = fcntl (myFileChannel, F_SETLKW, &key);
616  if (status == -1) myError.SetValue (errno, Iam, "SetLock");
617  else myLock = Lock;
618
619  if (Lock == OSD_ExclusiveLock){
620   fstat (myFileChannel, &buf);
621   TCollection_AsciiString aBuffer;
622   myPath.SystemName ( aBuffer );
623   chmod( aBuffer.ToCString() ,buf.st_mode | S_ISGID);
624   ImperativeFlag = Standard_True;
625  }
626
627 #else   /* BSD */
628  int lock;
629
630  switch (Lock){
631   case OSD_ExclusiveLock :
632   case OSD_WriteLock     : lock = F_WRLCK;
633                            break;
634   case OSD_ReadLock      : lock = F_RDLCK;
635                            break;
636   default : myError.SetValue (EINVAL, Iam, "SetLock");
637  }
638
639  status = flock (myFileChannel, lock);
640  if (status == -1) myError.SetValue (errno, Iam, "SetLock");
641  else myLock = Lock;
642 #endif // SysV
643 #endif // POSIX
644 }
645
646
647
648
649 // Remove a lock from a file
650
651 void  OSD_File::UnLock(){
652 int status;
653
654  if (myFileChannel == -1)
655   throw Standard_ProgramError("OSD_File::UnLock : file is not open");
656
657 #ifdef POSIX
658  struct stat buf;
659
660  if (fstat(myFileChannel, &buf) == -1) {
661   myError.SetValue(errno, Iam, "UnsetLock");
662   return;
663  }
664  
665  status = lockf(myFileChannel,F_ULOCK, buf.st_size);
666   if (status == -1) myError.SetValue (errno, Iam, "SetLock");
667
668 #else
669 #ifdef SYSV
670  struct stat  buf;
671  struct flock key;
672
673  if (ImperativeFlag){
674   fstat (myFileChannel, &buf);
675   TCollection_AsciiString aBuffer;
676   myPath.SystemName ( aBuffer );
677   chmod(aBuffer.ToCString(),buf.st_mode & ~S_ISGID);
678   ImperativeFlag = Standard_False;
679  }
680  key.l_type = F_UNLCK;
681  status = fcntl (myFileChannel, F_SETLK, &key);
682  if (status == -1) myError.SetValue (errno, Iam, "UnSetLock");
683 #else
684
685  status = flock (myFileChannel, LOCK_UN);
686  if (status == -1) myError.SetValue (errno, Iam, "UnSetLock");
687 #endif
688 #endif // POSIX
689  else myLock = OSD_NoLock;
690 }
691
692
693
694
695
696 // Return lock of a file
697
698 OSD_LockType  OSD_File::GetLock(){
699  return(myLock);
700 }
701
702
703
704
705 // -------------------------------------------------------------------------- 
706 // Return size of a file
707 // -------------------------------------------------------------------------- 
708
709 Standard_Size  OSD_File::Size(){
710  struct stat buffer;
711  int status;
712
713  if (myPath.Name().Length()==0)
714   throw Standard_ProgramError("OSD_File::Size : empty file name");
715
716  TCollection_AsciiString aBuffer;
717  myPath.SystemName ( aBuffer );
718  status = stat( aBuffer.ToCString() ,&buffer );
719  if (status == -1) {
720   myError.SetValue (errno, Iam, "Size");
721   return 0;
722  }
723
724  return (Standard_Size)buffer.st_size;
725 }
726
727 // -------------------------------------------------------------------------- 
728 // Test if a file is open
729 // -------------------------------------------------------------------------- 
730
731 Standard_Boolean OSD_File::IsOpen()const{
732  return (myFileChannel != -1);
733 }
734
735
736 Standard_Boolean OSD_File::IsLocked(){
737  return(myLock != OSD_NoLock); 
738 }
739
740 Standard_Boolean OSD_File::IsReadable()
741 {
742   TCollection_AsciiString FileName ;
743
744   myPath.SystemName(FileName) ;
745
746   if (access(FileName.ToCString(),F_OK|R_OK))
747     return Standard_False;
748   else
749     return Standard_True;
750 }
751
752 Standard_Boolean OSD_File::IsWriteable()
753 {
754   TCollection_AsciiString FileName ;
755
756   myPath.SystemName(FileName) ;
757
758   if (access(FileName.ToCString(),F_OK|R_OK|W_OK))
759     return Standard_False;
760   else
761     return Standard_True;
762 }
763
764 Standard_Boolean OSD_File::IsExecutable()
765 {
766   TCollection_AsciiString FileName ;
767
768   myPath.SystemName(FileName) ;
769
770   if (access(FileName.ToCString(),F_OK|X_OK))
771     return Standard_False;
772   else
773     return Standard_True;
774 }
775
776 int OSD_File::Capture(int theDescr) {
777   // Duplicate an old file descriptor of the given one to be able to restore output to it later.
778   int oldDescr = dup(theDescr);
779   // Redirect the output to this file
780   dup2(myFileChannel, theDescr);
781
782   // Return the old descriptor
783   return oldDescr;
784 }
785
786 void OSD_File::Rewind() { 
787     rewind((FILE*)myFILE); 
788 }
789
790 #else /* _WIN32 */
791
792 //------------------------------------------------------------------------
793 //-------------------  Windows NT sources for OSD_File -------------------
794 //------------------------------------------------------------------------
795
796 #include <windows.h>
797
798 #include <OSD_File.hxx>
799 #include <OSD_Protection.hxx>
800 #include <Standard_ProgramError.hxx>
801
802 #include <OSD_WNT_1.hxx>
803
804 #include <stdio.h>
805 #include <io.h>
806 #include <Standard_PCharacter.hxx>
807 #include <TCollection_ExtendedString.hxx>
808
809 #include <Strsafe.h>
810
811 #if defined(__CYGWIN32__) || defined(__MINGW32__)
812 #define VAC
813 #endif
814
815 #define ACE_HEADER_SIZE (  sizeof ( ACCESS_ALLOWED_ACE ) - sizeof ( DWORD )  )
816
817 #define RAISE( arg ) throw Standard_ProgramError (  ( arg )  )
818 #define TEST_RAISE( arg ) _test_raise (  myFileHandle, ( arg )  )
819
820 #define OPEN_NEW    0
821 #define OPEN_OLD    1
822 #define OPEN_APPEND 2
823
824 void                            _osd_wnt_set_error        ( OSD_Error&, OSD_WhoAmI, ... );
825 #ifndef OCCT_UWP
826 PSECURITY_DESCRIPTOR __fastcall _osd_wnt_protection_to_sd ( const OSD_Protection&, BOOL, const wchar_t* );
827 BOOL                 __fastcall _osd_wnt_sd_to_protection (
828                                  PSECURITY_DESCRIPTOR, OSD_Protection&, BOOL
829                                 );
830 static int       __fastcall _get_buffer(HANDLE, Standard_PCharacter&, DWORD, BOOL, BOOL);
831 #endif
832 static void      __fastcall _test_raise ( HANDLE, Standard_CString );
833 static Standard_Integer __fastcall _get_line (Standard_PCharacter& buffer, DWORD dwBuffSize, LONG& theSeekPos);
834 static DWORD     __fastcall _get_access_mask ( OSD_SingleProtection );
835 static DWORD     __fastcall _get_dir_access_mask ( OSD_SingleProtection prt );
836 static HANDLE    __fastcall _open_file  ( Standard_CString, OSD_OpenMode, DWORD, LPBOOL = NULL );
837
838 static OSD_SingleProtection __fastcall _get_protection     ( DWORD );
839 static OSD_SingleProtection __fastcall _get_protection_dir ( DWORD );
840
841 typedef OSD_SingleProtection ( __fastcall *GET_PROT_FUNC ) ( DWORD );
842
843 Standard_Integer __fastcall _get_file_type ( Standard_CString, HANDLE );
844
845 // ---------------------------------------------------------------------
846 // Create an empty file object
847 // ---------------------------------------------------------------------
848
849 OSD_File :: OSD_File ()
850 {
851  ImperativeFlag = Standard_False;
852  myLock         = OSD_NoLock;
853  myIO           = 0;
854  myFileChannel  = -1;
855  myFileHandle   = INVALID_HANDLE_VALUE;
856 }  // end constructor ( 1 )
857
858 // ---------------------------------------------------------------------
859 // Create and initialize a file object
860 // ---------------------------------------------------------------------
861
862 OSD_File :: OSD_File ( const OSD_Path& Name ) : OSD_FileNode ( Name )
863 {
864  ImperativeFlag = Standard_False;
865  myLock         = OSD_NoLock;
866  myIO           = 0;
867  myPath         = Name;
868  myFileChannel  = -1;
869  myFileHandle   = INVALID_HANDLE_VALUE;
870 }  // end constructor ( 2 )
871
872 // ---------------------------------------------------------------------
873 // Redirect a standard handle (fileno(stdout), fileno(stdin) or 
874 // fileno(stderr) to this OSD_File and return the copy of the original
875 // standard handle.
876 // Example:
877 //    OSD_File aTmp;
878 //    aTmp.BuildTemporary();
879 //    int stdfd = _fileno(stdout);
880 //
881 //    int oldout = aTmp.Capture(stdfd);
882 //    cout << "Some output to the file" << endl;
883 //    cout << flush;
884 //    fflush(stdout);
885 //
886 //    _dup2(oldout, stdfd); // Restore standard output
887 //    aTmp.Close();
888 // ---------------------------------------------------------------------
889 int OSD_File::Capture(int theDescr) {
890   // Get POSIX file descriptor from this file handle
891   int dFile = _open_osfhandle(reinterpret_cast<intptr_t>(myFileHandle), myMode);
892
893   if (0 > dFile)
894   {
895     _osd_wnt_set_error (  myError, OSD_WFile, myFileHandle );
896     return -1;
897   }
898
899   // Duplicate an old file descriptor of the given one to be able to restore output to it later.
900   int oldDescr = _dup(theDescr);
901   // Redirect the output to this file
902   _dup2(dFile, theDescr);
903
904   // Return the old descriptor
905   return oldDescr;
906 }
907
908 void OSD_File::Rewind() { 
909   LARGE_INTEGER aDistanceToMove;
910   aDistanceToMove.QuadPart = 0;
911   SetFilePointerEx(myFileHandle, aDistanceToMove, NULL, FILE_BEGIN);
912 }
913
914 // protect against occasional use of myFileHande in Windows code
915 #define myFileChannel myFileChannel_is_only_for_Linux
916
917 // ---------------------------------------------------------------------
918 // Build a file if it doesn't exist or create again if it already exists
919 // ---------------------------------------------------------------------
920
921 void OSD_File :: Build ( const OSD_OpenMode Mode, const OSD_Protection& Protect) {
922
923  TCollection_AsciiString fName;
924
925  if ( OSD_File::KindOfFile ( ) == OSD_DIRECTORY ) { 
926    throw Standard_ProgramError("OSD_File::Read : it is a directory");
927  }
928                                         
929  if (myFileHandle != INVALID_HANDLE_VALUE)
930
931   RAISE(  "OSD_File :: Build (): incorrect call - file already opened"  );
932
933  myMode = Mode;
934  myPath.SystemName ( fName );
935
936  if (  fName.IsEmpty ()  )
937
938   RAISE(  "OSD_File :: Build (): incorrent call - no filename given"  );
939
940  myFileHandle = _open_file ( fName.ToCString (), Mode, OPEN_NEW );
941
942  if (myFileHandle == INVALID_HANDLE_VALUE)
943
944   _osd_wnt_set_error ( myError, OSD_WFile );
945
946  else {
947 #ifndef OCCT_UWP
948   SetProtection ( Protect );
949 #else
950   (void)Protect;
951 #endif
952   myIO |= FLAG_FILE;
953
954  }  // end else
955
956 }  // end OSD_File :: Build
957
958
959
960 // ---------------------------------------------------------------------
961 // Open a file
962 // ---------------------------------------------------------------------
963
964 void OSD_File :: Open (const OSD_OpenMode Mode, const OSD_Protection& /*Protect*/)
965 {
966
967  TCollection_AsciiString fName;
968
969
970  if (myFileHandle != INVALID_HANDLE_VALUE)
971
972   RAISE(  "OSD_File :: Open (): incorrect call - file already opened"  );
973
974  myMode = Mode;
975  myPath.SystemName ( fName );
976
977  if (  fName.IsEmpty ()  )
978
979   RAISE(  "OSD_File :: Open (): incorrent call - no filename given"  );
980
981  myFileHandle = _open_file ( fName.ToCString (), Mode, OPEN_OLD );
982
983  if (myFileHandle == INVALID_HANDLE_VALUE) {
984
985    _osd_wnt_set_error ( myError, OSD_WFile );
986  }
987  else
988    {
989      myIO |= _get_file_type (  fName.ToCString (), myFileHandle  );
990    }
991 }  // end OSD_File :: Open
992
993 // ---------------------------------------------------------------------
994 // Append to an existing file
995 // ---------------------------------------------------------------------
996
997 void OSD_File :: Append ( const OSD_OpenMode Mode, const OSD_Protection& Protect) {
998
999  BOOL                    fNew = FALSE;
1000  TCollection_AsciiString fName;
1001
1002  if (myFileHandle != INVALID_HANDLE_VALUE)
1003
1004   RAISE(  "OSD_File :: Append (): incorrect call - file already opened"  );
1005
1006  myMode = Mode;
1007  myPath.SystemName ( fName );
1008
1009  if (  fName.IsEmpty ()  )
1010
1011   RAISE(  "OSD_File :: Append (): incorrent call - no filename given"  );
1012
1013  myFileHandle = _open_file ( fName.ToCString (), Mode, OPEN_APPEND, &fNew );
1014
1015  if (myFileHandle == INVALID_HANDLE_VALUE)
1016
1017   _osd_wnt_set_error ( myError, OSD_WFile );
1018
1019  else {
1020
1021   if ( !fNew ) {
1022
1023    myIO |= _get_file_type (  fName.ToCString (), myFileHandle  );
1024    Seek ( 0, OSD_FromEnd );
1025
1026   } else {
1027 #ifndef OCCT_UWP
1028     SetProtection ( Protect );
1029 #else
1030     (void)Protect;
1031 #endif
1032    myIO |= FLAG_FILE;
1033   
1034   }  // end else
1035
1036  }  // end else;
1037
1038 }  // end OSD_File :: Append
1039
1040 // ---------------------------------------------------------------------
1041 // Read content of a file
1042 // ---------------------------------------------------------------------
1043  
1044 void OSD_File :: Read (
1045                   TCollection_AsciiString& Buffer, const Standard_Integer Nbyte
1046                  ) {
1047
1048  if ( OSD_File::KindOfFile ( ) == OSD_DIRECTORY ) { 
1049 #ifdef OCCT_DEBUG
1050    cout << " OSD_File::Read : it is a directory " << endl;
1051 #endif
1052    return ;
1053 //   throw Standard_ProgramError("OSD_File::Read : it is a directory");
1054  }
1055                                         
1056  Standard_Integer NbyteRead;
1057
1058  TEST_RAISE(  "Read"  );
1059      
1060  char* buff = new Standard_Character[ Nbyte + 1 ];
1061
1062  Read ( buff, Nbyte, NbyteRead );
1063
1064  buff[ NbyteRead ] = 0;
1065
1066  if ( NbyteRead != 0 )
1067
1068   Buffer = buff;
1069
1070  else
1071
1072   Buffer.Clear ();
1073
1074  delete [] buff;
1075
1076 }  // end OSD_File :: Read
1077
1078 // ---------------------------------------------------------------------
1079 // Read a line from a file
1080 // ---------------------------------------------------------------------
1081
1082 // Modified so that we have <nl> at end of line if we have read <nl> or <cr>
1083 // in the file.
1084 // by LD 17 dec 98 for B4.4
1085
1086 void OSD_File :: ReadLine (
1087                   TCollection_AsciiString& Buffer,
1088                   const Standard_Integer NByte, Standard_Integer& NbyteRead
1089                  ) {
1090
1091  DWORD              dwBytesRead;
1092  DWORD              dwDummy;
1093  Standard_Character peekChar;
1094  Standard_PCharacter ppeekChar;
1095  Standard_PCharacter cBuffer;
1096  LONG               aSeekPos;
1097
1098  if ( OSD_File::KindOfFile ( ) == OSD_DIRECTORY ) { 
1099    throw Standard_ProgramError("OSD_File::Read : it is a directory");
1100  }
1101                                         
1102  TEST_RAISE(  "ReadLine"  );              
1103
1104  if (  myIO & FLAG_PIPE && !( myIO & FLAG_READ_PIPE )  )
1105
1106   RAISE(  "OSD_File :: ReadLine (): attempt to read from write only pipe"  );
1107
1108                                         // +----> leave space for end-of-string
1109                                         // |       plus <CR><LF> sequence      
1110                                         // |
1111
1112  ppeekChar=&peekChar;
1113  cBuffer = new Standard_Character[ NByte + 3 ];
1114
1115  if ( myIO & FLAG_FILE ) {
1116  
1117   if (!ReadFile (myFileHandle, cBuffer, NByte, &dwBytesRead, NULL)) {  // an error occured
1118
1119    _osd_wnt_set_error ( myError, OSD_WFile );   
1120    Buffer.Clear ();
1121    NbyteRead = 0;
1122    
1123   } else if ( dwBytesRead == 0 ) {  // end-of-file reached
1124    
1125    Buffer.Clear ();
1126    NbyteRead = 0;
1127    myIO |= FLAG_EOF;
1128    
1129   } else {
1130    myIO &= ~FLAG_EOF ;  // if the file increased since last read (LD)
1131    NbyteRead = _get_line (cBuffer, dwBytesRead, aSeekPos);
1132
1133    if ( NbyteRead == -1 )  // last character in the buffer is <CR> -
1134    {                       // peek next character to see if it is a <LF>
1135     if (!ReadFile (myFileHandle, ppeekChar, 1, &dwDummy, NULL)) {
1136     
1137      _osd_wnt_set_error ( myError, OSD_WFile );
1138
1139     } else if ( dwDummy != 0 ) {  // end-of-file reached ?
1140
1141       if (peekChar != '\n')  // if we did not get a <CR><LF> sequence
1142       {
1143         // adjust file position
1144         LARGE_INTEGER aDistanceToMove;
1145         aDistanceToMove.QuadPart = -1;
1146         SetFilePointerEx(myFileHandle, aDistanceToMove, NULL, FILE_CURRENT);
1147       }
1148     } else
1149      myIO |= FLAG_EOF;
1150
1151     NbyteRead = dwBytesRead;
1152
1153    } else if ( aSeekPos != 0 )
1154    {
1155      LARGE_INTEGER aDistanceToMove;
1156      aDistanceToMove.QuadPart = aSeekPos;
1157      SetFilePointerEx(myFileHandle, aDistanceToMove, NULL, FILE_CURRENT);
1158    }
1159
1160   }  // end else
1161    
1162  } else if ( myIO & FLAG_SOCKET || myIO & FLAG_PIPE || myIO & FLAG_NAMED_PIPE ) {
1163 #ifndef OCCT_UWP
1164   dwBytesRead = (DWORD)_get_buffer (myFileHandle, cBuffer, 
1165                                     (DWORD)NByte, TRUE, myIO & FLAG_SOCKET);
1166
1167   if (  ( int )dwBytesRead == -1  ) { // an error occured
1168
1169    _osd_wnt_set_error ( myError, OSD_WFile );
1170    Buffer.Clear ();
1171    NbyteRead = 0;
1172
1173   } else if ( dwBytesRead == 0 )  { // connection closed - set end-of-file flag
1174
1175    Buffer.Clear ();
1176    NbyteRead = 0;
1177    myIO |= FLAG_EOF;
1178
1179   } else {
1180
1181    NbyteRead = _get_line (cBuffer, dwBytesRead, aSeekPos);
1182
1183    if (NbyteRead == -1) // last character in the buffer is <CR> -    
1184    {                     // peek next character to see if it is a <LF>
1185     NbyteRead = dwBytesRead; // (LD) always fits this case.
1186
1187     dwDummy = _get_buffer (myFileHandle, ppeekChar, 1, TRUE, myIO & FLAG_SOCKET);
1188     if (  ( int )dwDummy == -1  ) {  // an error occured
1189    
1190      _osd_wnt_set_error ( myError, OSD_WFile );
1191
1192     } else if ( dwDummy != 0 ) {  // connection closed ?
1193
1194      if ( peekChar == '\n' )  // we got a <CR><LF> sequence
1195
1196        dwBytesRead++ ;  // (LD) we have to jump <LF>
1197     } else
1198
1199      myIO |= FLAG_EOF;
1200
1201    } else if (aSeekPos != 0)
1202    {
1203      dwBytesRead = dwBytesRead + aSeekPos;
1204    }
1205
1206    // Don't rewrite datas in cBuffer.
1207
1208    Standard_PCharacter cDummyBuffer = new Standard_Character[ NByte + 3 ];
1209
1210    // remove pending input
1211    _get_buffer (myFileHandle, cDummyBuffer, dwBytesRead, FALSE, myIO & FLAG_SOCKET);
1212    delete [] cDummyBuffer ;
1213
1214   }  // end else
1215 #endif
1216  } else
1217
1218   RAISE(  "OSD_File :: ReadLine (): incorrect call - file is a directory"  );
1219
1220  if (  !Failed () && !IsAtEnd ()  )
1221
1222   Buffer = cBuffer;
1223
1224  delete [] (Standard_PCharacter)cBuffer;
1225
1226 }  // end OSD_File :: ReadLine
1227
1228 // -------------------------------------------------------------------------- 
1229 // Read content of a file
1230 // -------------------------------------------------------------------------- 
1231
1232 void OSD_File :: Read (
1233                   const Standard_Address Buffer,
1234                   const Standard_Integer Nbyte, Standard_Integer& Readbyte
1235                  ) {
1236
1237  DWORD dwBytesRead;
1238
1239  if ( OSD_File::KindOfFile ( ) == OSD_DIRECTORY ) { 
1240    throw Standard_ProgramError("OSD_File::Read : it is a directory");
1241  }
1242                                         
1243  TEST_RAISE(  "Read"  );
1244
1245  if (  myIO & FLAG_PIPE && !( myIO & FLAG_READ_PIPE )  )
1246
1247   RAISE(  "OSD_File :: Read (): attempt to read from write only pipe"  );
1248
1249  if (!ReadFile (myFileHandle, Buffer, (DWORD)Nbyte, &dwBytesRead, NULL)) {
1250  
1251   _osd_wnt_set_error ( myError, OSD_WFile );
1252   dwBytesRead = 0;
1253  
1254  } else if ( dwBytesRead == 0 )
1255
1256   myIO |= FLAG_EOF;
1257
1258  else
1259
1260   myIO &= ~FLAG_EOF;
1261
1262  Readbyte = ( Standard_Integer )dwBytesRead;
1263
1264 }  // end OSD_File :: Read
1265
1266 void OSD_File :: Write (
1267                   const TCollection_AsciiString& Buffer,
1268                   const Standard_Integer Nbyte
1269                  ) {
1270
1271  Write (  ( Standard_Address )Buffer.ToCString (), Nbyte  );
1272
1273 }  // end OSD_File :: Write
1274
1275 // -------------------------------------------------------------------------- 
1276 // Write content of a file
1277 // -------------------------------------------------------------------------- 
1278
1279 void OSD_File :: Write (
1280                   const Standard_Address Buffer,
1281                   const Standard_Integer Nbyte
1282                  ) {
1283
1284  DWORD dwBytesWritten;
1285
1286  TEST_RAISE(  "Write"  );
1287
1288  if ( myIO & FLAG_PIPE && myIO & FLAG_READ_PIPE )
1289
1290   RAISE(  "OSD_File :: Write (): attempt to write to read only pipe"  );
1291
1292  if (!WriteFile (myFileHandle, Buffer, (DWORD)Nbyte, &dwBytesWritten, NULL) || 
1293      dwBytesWritten != (DWORD)Nbyte)
1294
1295   _osd_wnt_set_error ( myError, OSD_WFile );
1296
1297 }  // end OSD_File :: Write
1298
1299 void OSD_File :: Seek (
1300                   const Standard_Integer Offset, const OSD_FromWhere Whence
1301                  ) {
1302
1303  DWORD dwMoveMethod = 0;
1304
1305  TEST_RAISE(  "Seek"  );
1306
1307  if ( myIO & FLAG_FILE || myIO & FLAG_DIRECTORY ) {
1308
1309   switch ( Whence ) {
1310   
1311    case OSD_FromBeginning:
1312
1313     dwMoveMethod = FILE_BEGIN;
1314
1315    break;
1316
1317    case OSD_FromHere:
1318
1319     dwMoveMethod = FILE_CURRENT;
1320
1321    break;
1322
1323    case OSD_FromEnd:
1324
1325     dwMoveMethod = FILE_END;
1326
1327    break;
1328
1329    default:
1330
1331     RAISE(  "OSD_File :: Seek (): invalid parameter"  );
1332   
1333   }  // end switch
1334   LARGE_INTEGER aDistanceToMove, aNewFilePointer;
1335   aNewFilePointer.QuadPart = 0;
1336   aDistanceToMove.QuadPart = Offset;
1337
1338   if (!SetFilePointerEx(myFileHandle, aDistanceToMove, &aNewFilePointer, dwMoveMethod))
1339
1340    _osd_wnt_set_error ( myError, OSD_WFile );
1341   
1342  }  // end if
1343
1344  myIO &= ~FLAG_EOF;
1345
1346 }  // end OSD_File :: Seek
1347
1348 // -------------------------------------------------------------------------- 
1349 // Close a file
1350 // -------------------------------------------------------------------------- 
1351
1352 void OSD_File :: Close () {
1353
1354  TEST_RAISE(  "Close"  );
1355
1356  CloseHandle (myFileHandle);
1357
1358  myFileHandle = INVALID_HANDLE_VALUE;
1359  myIO          = 0;
1360
1361 }  // end OSD_File :: Close
1362
1363 // -------------------------------------------------------------------------- 
1364 // Test if at end of file
1365 // -------------------------------------------------------------------------- 
1366
1367 Standard_Boolean OSD_File :: IsAtEnd () {
1368
1369  TEST_RAISE(  "IsAtEnd"  );
1370
1371  if (myIO & FLAG_EOF)
1372    return Standard_True ;
1373  return Standard_False ;
1374
1375 }  // end OSD_File :: IsAtEnd
1376
1377 OSD_KindFile OSD_File :: KindOfFile () const {
1378
1379  OSD_KindFile     retVal;
1380  Standard_Integer flags;
1381
1382  if (myFileHandle == INVALID_HANDLE_VALUE) {
1383
1384   TCollection_AsciiString fName;
1385
1386   myPath.SystemName ( fName );
1387
1388   if (  fName.IsEmpty ()  )
1389
1390    RAISE(  "OSD_File :: KindOfFile (): incorrent call - no filename given"  );
1391
1392   flags = _get_file_type (fName.ToCString(), INVALID_HANDLE_VALUE);
1393
1394  } else
1395
1396   flags = myIO;
1397
1398  switch ( flags & FLAG_TYPE ) {
1399  
1400   case FLAG_FILE:
1401
1402    retVal = OSD_FILE;
1403
1404   break;
1405
1406   case FLAG_DIRECTORY:
1407
1408    retVal = OSD_DIRECTORY;
1409
1410   break;
1411
1412   case FLAG_SOCKET:
1413
1414    retVal = OSD_SOCKET;
1415
1416   break;
1417
1418   default:
1419
1420    retVal = OSD_UNKNOWN;
1421  
1422  }  // end switch
1423
1424  return retVal;
1425
1426 }  // end OSD_File :: KindOfFile
1427
1428 //-------------------------------------------------debutpri???980424
1429
1430 typedef struct _osd_wnt_key {
1431
1432                 HKEY   hKey;
1433                 wchar_t* keyPath;
1434
1435                } OSD_WNT_KEY;
1436
1437
1438  void OSD_File::BuildTemporary () {
1439
1440  OSD_Protection prt;
1441  wchar_t        tmpPath[ MAX_PATH ];
1442  BOOL           fOK = FALSE;
1443
1444 // Windows Registry not supported by UWP
1445 #ifndef OCCT_UWP
1446  HKEY           hKey;
1447
1448  OSD_WNT_KEY    regKey[ 2 ] = {
1449  
1450                  { HKEY_LOCAL_MACHINE,
1451                    L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"
1452                  },
1453                  { HKEY_USERS,
1454                    L".DEFAULT\\Environment"
1455                  }
1456  
1457                 };
1458  
1459  for ( int i = 0; i < 2; ++i ) {
1460
1461   if (  RegOpenKeyExW (
1462          regKey[ i ].hKey, regKey[ i ].keyPath, 0, KEY_QUERY_VALUE, &hKey
1463        ) == ERROR_SUCCESS
1464   ) {
1465   
1466    DWORD dwType;
1467    DWORD dwSize = 0;
1468
1469    if (  RegQueryValueExW (
1470           hKey, L"TEMP", NULL, &dwType, NULL, &dwSize
1471          ) == ERROR_SUCCESS
1472    ) {
1473   
1474      wchar_t* kVal = (wchar_t*)HeapAlloc (
1475                              GetProcessHeap (), HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS,
1476                              dwSize + sizeof (wchar_t)
1477                             );
1478
1479      RegQueryValueExW (  hKey, L"TEMP", NULL, &dwType, ( LPBYTE )kVal, &dwSize  );
1480
1481      if ( dwType == REG_EXPAND_SZ )
1482     
1483       ExpandEnvironmentStringsW ( kVal, tmpPath, MAX_PATH );
1484
1485      else
1486
1487        StringCchCopyW (tmpPath, _countof(tmpPath), kVal);
1488
1489     HeapFree (  GetProcessHeap (), 0, ( LPVOID )kVal  );
1490     fOK = TRUE;
1491
1492    }  // end if
1493
1494    RegCloseKey ( hKey );
1495
1496   }  // end if
1497
1498   if ( fOK ) break;
1499
1500  }  // end for
1501 #else
1502  if (GetTempPathW(_countof(tmpPath), tmpPath))
1503    fOK = TRUE;
1504 #endif
1505  if ( !fOK )       StringCchCopyW(tmpPath, _countof(tmpPath), L"./");
1506
1507  GetTempFileNameW ( tmpPath, L"CSF", 0, tmpPath );
1508
1509  if ( IsOpen() )
1510   Close();
1511
1512  char tmpPathA[MAX_PATH];
1513  WideCharToMultiByte(CP_UTF8, 0, tmpPath, -1, tmpPathA, sizeof(tmpPathA), NULL, NULL);
1514  SetPath(OSD_Path(tmpPathA));
1515
1516  Build   (  OSD_ReadWrite, prt    );
1517 }  // end OSD_File :: BuildTemporary
1518
1519 //-------------------------------------------------finpri???980424
1520
1521 #if defined(__CYGWIN32__) || defined(__MINGW32__)
1522 #define __try
1523 #define __finally
1524 #define __leave return
1525 #endif
1526
1527 void OSD_File :: SetLock ( const OSD_LockType Lock ) {
1528
1529  DWORD      dwFlags;
1530  OVERLAPPED ovlp;
1531
1532  TEST_RAISE(  "SetLock"  );
1533  
1534  ZeroMemory (  &ovlp, sizeof ( OVERLAPPED )  );
1535
1536  __try {
1537
1538   if (  ( myLock = Lock ) == OSD_NoLock  ) {
1539
1540    UnLock ();
1541    __leave;
1542
1543   } else if ( myLock == OSD_ReadLock || myLock == OSD_ExclusiveLock ) {
1544
1545    dwFlags = LOCKFILE_EXCLUSIVE_LOCK;
1546
1547   } else
1548
1549    dwFlags = 0;
1550
1551   LARGE_INTEGER aSize;
1552   aSize.QuadPart = Size();
1553   if (!LockFileEx (myFileHandle, dwFlags, 0, aSize.LowPart, aSize.HighPart, &ovlp)) {
1554
1555    _osd_wnt_set_error ( myError, OSD_WFile );
1556    __leave;
1557
1558   }  // end if
1559
1560   ImperativeFlag = Standard_True;
1561
1562  }  // end __try
1563
1564  __finally {}
1565
1566 #ifdef VAC
1567 leave: ;         // added for VisualAge
1568 #endif
1569 }  // end OSD_File :: SetLock
1570
1571 #if defined(__CYGWIN32__) || defined(__MINGW32__)
1572 #undef __try
1573 #undef __finally
1574 #undef __leave
1575 #endif
1576
1577 void OSD_File :: UnLock () {
1578
1579  TEST_RAISE(  "Unlock"  );
1580
1581  if ( ImperativeFlag ) {
1582  
1583   LARGE_INTEGER aSize;
1584   aSize.QuadPart = Size();
1585
1586   OVERLAPPED anOverlappedArea;
1587   anOverlappedArea.Offset = 0;
1588   anOverlappedArea.OffsetHigh = 0;
1589
1590   if (!UnlockFileEx(myFileHandle, 0, aSize.LowPart, aSize.HighPart,&anOverlappedArea))
1591    _osd_wnt_set_error ( myError, OSD_WFile );
1592
1593   ImperativeFlag = Standard_False;
1594  
1595  }  // end if
1596
1597 }  // end OSD_File :: UnLock
1598
1599 OSD_LockType OSD_File :: GetLock () {
1600
1601  return myLock;
1602
1603 }  // end OSD_File :: GetLock
1604
1605 Standard_Boolean OSD_File :: IsLocked () {
1606
1607  TEST_RAISE(  "IsLocked"  );
1608
1609  return ImperativeFlag;
1610
1611 }  // end OSD_File :: IsLocked
1612
1613
1614 // -------------------------------------------------------------------------- 
1615 // Return size of a file
1616 // -------------------------------------------------------------------------- 
1617
1618 Standard_Size OSD_File::Size()
1619 {
1620   TEST_RAISE("Size");
1621 #if (_WIN32_WINNT >= 0x0500)
1622   LARGE_INTEGER aSize;
1623   aSize.QuadPart = 0;
1624   if (GetFileSizeEx (myFileHandle, &aSize) == 0)
1625   {
1626     _osd_wnt_set_error (myError, OSD_WFile);
1627   }
1628   return (Standard_Size)aSize.QuadPart;
1629 #else
1630   DWORD aSize = GetFileSize (myFileHandle, NULL);
1631   if (aSize == INVALID_FILE_SIZE)
1632   {
1633     _osd_wnt_set_error (myError, OSD_WFile);
1634   }
1635   return aSize;
1636 #endif
1637 }
1638
1639 // -------------------------------------------------------------------------- 
1640 // Test if a file is open
1641 // -------------------------------------------------------------------------- 
1642
1643 Standard_Boolean OSD_File :: IsOpen () const {
1644
1645  return myFileHandle != INVALID_HANDLE_VALUE;
1646
1647 }  // end OSD_File :: IsOpen
1648
1649 #if defined(__CYGWIN32__) || defined(__MINGW32__)
1650 #define __try
1651 #define __finally
1652 #define __leave return retVal
1653 #endif
1654
1655 #ifndef OCCT_UWP
1656 PSECURITY_DESCRIPTOR __fastcall _osd_wnt_protection_to_sd (
1657                                  const OSD_Protection& prot, BOOL fDir, const wchar_t* fName
1658                                 ) {
1659
1660  int                  i, j;
1661  BOOL                 fOK      = FALSE;
1662  PACL                 pACL     = NULL;
1663  HANDLE               hProcess = NULL;
1664  PSID                 pSIDowner;
1665  PSID                 pSIDadmin;
1666  PSID                 pSIDworld;
1667  PSID                 pSIDtemp;
1668  DWORD                dwAccessAdmin;
1669  DWORD                dwAccessGroup;
1670  DWORD                dwAccessOwner;
1671  DWORD                dwAccessWorld;
1672  DWORD                dwAccessAdminDir;
1673 // DWORD                dwAccessGroupDir;
1674  DWORD                dwAccessOwnerDir;
1675 // DWORD                dwAccessWorldDir;
1676  DWORD                dwACLsize       = sizeof ( ACL );
1677  DWORD                dwIndex         = 0;
1678  PTOKEN_OWNER         pTkOwner        = NULL;
1679  PTOKEN_GROUPS        pTkGroups       = NULL;
1680  PTOKEN_PRIMARY_GROUP pTkPrimaryGroup = NULL;
1681  PSECURITY_DESCRIPTOR retVal = NULL;
1682  PSECURITY_DESCRIPTOR pfSD = NULL;
1683  BOOL                 fDummy;
1684  PFILE_ACE            pFileACE;
1685
1686  __try {
1687
1688   j = fDir ? 1 : 0;
1689
1690   if (  !OpenProcessToken (
1691           GetCurrentProcess (), TOKEN_QUERY, &hProcess
1692          )
1693   ) __leave;
1694
1695   if (   (  pTkGroups = ( PTOKEN_GROUPS )GetTokenInformationEx (
1696                                           hProcess, TokenGroups
1697                                          )
1698          ) == NULL
1699   ) __leave; 
1700   
1701   if (   (  pTkOwner = ( PTOKEN_OWNER )GetTokenInformationEx (
1702                                         hProcess, TokenOwner
1703                                        )
1704          ) == NULL
1705   ) __leave;
1706
1707   if (   (  pTkPrimaryGroup = ( PTOKEN_PRIMARY_GROUP )GetTokenInformationEx (
1708                                                        hProcess, TokenPrimaryGroup
1709                                                       )
1710          ) == NULL
1711   ) __leave;
1712
1713
1714 retry:
1715   if ( fName == NULL )
1716
1717    pSIDowner = pTkOwner -> Owner;
1718
1719   else {
1720
1721    pfSD = GetFileSecurityEx ( fName, OWNER_SECURITY_INFORMATION );
1722
1723    if (  pfSD == NULL || !GetSecurityDescriptorOwner ( pfSD, &pSIDowner, &fDummy )  ) {
1724
1725     fName = NULL;
1726     goto retry;
1727
1728    }  // end if
1729
1730   }  // end else
1731
1732   pSIDadmin = AdminSid ();
1733   pSIDworld = WorldSid ();
1734
1735   dwAccessAdmin = _get_access_mask (  prot.System ()  );
1736   dwAccessGroup = _get_access_mask (  prot.Group  ()  );
1737   dwAccessOwner = _get_access_mask (  prot.User   ()  );
1738   dwAccessWorld = _get_access_mask (  prot.World  ()  );
1739
1740   dwAccessAdminDir = _get_dir_access_mask (  prot.System ()  );
1741 //  dwAccessGroupDir = _get_dir_access_mask (  prot.Group  ()  );
1742   dwAccessOwnerDir = _get_dir_access_mask (  prot.User   ()  );
1743 //  dwAccessWorldDir = _get_dir_access_mask (  prot.World  ()  );
1744
1745   if (  dwAccessGroup != 0  ) {
1746                                              
1747    for ( i = 0; i < ( int )pTkGroups -> GroupCount; ++i ) {
1748
1749     pSIDtemp = pTkGroups -> Groups[ i ].Sid;
1750
1751     if (  !NtPredefinedSid ( pSIDtemp                                  ) &&
1752           !EqualSid        ( pSIDtemp, pSIDworld                       ) &&
1753           !EqualSid        ( pSIDtemp, pTkPrimaryGroup -> PrimaryGroup ) &&
1754            IsValidSid      ( pSIDtemp                                  )
1755     )
1756
1757      dwACLsize += ( (  GetLengthSid ( pSIDtemp ) + ACE_HEADER_SIZE  ) << j );
1758
1759    }  // end for
1760   
1761   }  // end if
1762
1763   dwACLsize += (  ( ( GetLengthSid ( pSIDowner ) + ACE_HEADER_SIZE ) << j ) +
1764                   ( ( GetLengthSid ( pSIDadmin ) + ACE_HEADER_SIZE ) << j ) +
1765                   ( ( GetLengthSid ( pSIDworld ) + ACE_HEADER_SIZE ) << j )
1766                );
1767
1768   if (   (  pACL = CreateAcl ( dwACLsize )  ) == NULL   ) __leave;
1769
1770   if ( dwAccessAdmin != 0 )
1771
1772    if (   (  pFileACE = ( PFILE_ACE )AllocAccessAllowedAce (
1773                                       dwAccessAdmin, 0,
1774                                       pSIDadmin
1775                                      )
1776            ) != NULL
1777    ) {
1778
1779     AddAce ( pACL, ACL_REVISION, dwIndex++, pFileACE, pFileACE -> header.AceSize );
1780
1781     if ( fDir ) {
1782
1783      pFileACE -> dwMask = dwAccessAdminDir;
1784      pFileACE -> header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE;
1785      AddAce ( pACL, ACL_REVISION, dwIndex++, pFileACE, pFileACE -> header.AceSize );
1786
1787     }  // end if
1788
1789     FreeAce ( pFileACE );
1790
1791    }  // end if
1792
1793   if ( dwAccessOwner != 0 )
1794
1795    if (   (  pFileACE = ( PFILE_ACE )AllocAccessAllowedAce (
1796                                       dwAccessOwner, 0, pSIDowner
1797                                      )
1798           ) != NULL
1799    ) {
1800
1801     AddAce ( pACL, ACL_REVISION, dwIndex++, pFileACE, pFileACE -> header.AceSize );
1802
1803     if ( fDir ) {
1804
1805      pFileACE -> dwMask = dwAccessOwnerDir;
1806      pFileACE -> header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE;
1807      AddAce ( pACL, ACL_REVISION, dwIndex++, pFileACE, pFileACE -> header.AceSize );
1808    
1809     }  // end if
1810
1811     FreeAce ( pFileACE );
1812
1813    }  // end if
1814
1815   if ( dwAccessWorld != 0 )
1816
1817    if (   (  pFileACE = ( PFILE_ACE )AllocAccessAllowedAce (
1818                                       dwAccessWorld, 0, pSIDworld
1819                                      )
1820           ) != NULL
1821    ) {
1822
1823     AddAce ( pACL, ACL_REVISION, dwIndex++, pFileACE, pFileACE -> header.AceSize );
1824
1825     if ( fDir ) {
1826
1827      pFileACE -> header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE;
1828      AddAce ( pACL, ACL_REVISION, dwIndex++, pFileACE, pFileACE -> header.AceSize );
1829    
1830     }  // end if
1831
1832     FreeAce ( pFileACE );
1833
1834    }  // end if
1835
1836   if ( dwAccessGroup != 0 ) {
1837
1838    for ( i = 0; i < ( int )pTkGroups -> GroupCount; ++i ) {
1839
1840     pSIDtemp = pTkGroups -> Groups[ i ].Sid;
1841
1842     if (  !NtPredefinedSid ( pSIDtemp                                  ) &&
1843           !EqualSid        ( pSIDtemp, pSIDworld                       ) &&
1844           !EqualSid        ( pSIDtemp, pTkPrimaryGroup -> PrimaryGroup ) &&
1845            IsValidSid      ( pSIDtemp                                  )
1846     ) {
1847
1848      if ( dwAccessGroup != 0 )
1849
1850       if (   (  pFileACE = ( PFILE_ACE )AllocAccessAllowedAce (
1851                                          dwAccessGroup, 0, pSIDtemp
1852                                         )
1853              ) != NULL
1854       ) {
1855
1856        AddAce ( pACL, ACL_REVISION, dwIndex++, pFileACE, pFileACE -> header.AceSize );
1857
1858       if ( fDir ) {
1859
1860        pFileACE -> header.AceFlags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE;
1861        AddAce ( pACL, ACL_REVISION, dwIndex++, pFileACE, pFileACE -> header.AceSize );
1862    
1863       }  // end if
1864
1865       FreeAce ( pFileACE );
1866
1867      }  // end if
1868
1869     }  // end if
1870
1871    }  // end for
1872
1873   }  // end if
1874
1875   if (   (  retVal = AllocSD ()  ) == NULL   ) __leave;
1876
1877   if (  !SetSecurityDescriptorDacl ( retVal, TRUE, pACL, TRUE )  ) __leave;
1878
1879   fOK = TRUE;
1880
1881  }  // end __try
1882
1883  __finally {
1884  
1885   if ( !fOK ) {
1886
1887    if ( retVal != NULL )
1888        
1889     FreeSD ( retVal );
1890
1891    else if ( pACL != NULL )
1892
1893     FreeAcl ( pACL );
1894
1895    retVal = NULL;
1896   
1897   }  // end if
1898
1899   if ( hProcess        != NULL ) CloseHandle          ( hProcess        );
1900   if ( pTkOwner        != NULL ) FreeTokenInformation ( pTkOwner        );
1901   if ( pTkGroups       != NULL ) FreeTokenInformation ( pTkGroups       );
1902   if ( pTkPrimaryGroup != NULL ) FreeTokenInformation ( pTkPrimaryGroup );
1903   if ( pfSD            != NULL ) FreeFileSecurity     ( pfSD            );
1904  
1905  }  // end __finally
1906
1907 #ifdef VAC
1908 leave: ;     // added for VisualAge
1909 #endif
1910
1911  return retVal;
1912  
1913 }  // end _osd_wnt_protection_to_sd */
1914 #endif
1915
1916 #if defined(__CYGWIN32__) || defined(__MINGW32__)
1917 #undef __try
1918 #undef __finally
1919 #undef __leave
1920 #endif
1921
1922 static void __fastcall _test_raise ( HANDLE hFile, Standard_CString str ) {
1923
1924   if (hFile == INVALID_HANDLE_VALUE) {
1925     TCollection_AsciiString buff = "OSD_File :: ";
1926     buff += str;
1927     buff += " (): wrong access";
1928
1929     throw Standard_ProgramError(buff.ToCString());
1930   }  // end if
1931
1932 }  // end _test_raise
1933
1934 // Returns number of bytes in the string (including end \n, but excluding \r);
1935 // 
1936 static Standard_Integer __fastcall _get_line (Standard_PCharacter& buffer, DWORD dwBuffSize, LONG& theSeekPos)
1937 {
1938
1939  Standard_PCharacter ptr;
1940
1941  buffer[ dwBuffSize ] = 0;
1942  ptr                  = buffer;
1943
1944  while ( *ptr != 0 ) {
1945  
1946   if (  *ptr == '\n'  )
1947   {
1948     ptr++ ;   // jump newline char.
1949     *ptr = 0 ;
1950     theSeekPos = (LONG)(ptr - buffer - dwBuffSize);
1951     return (Standard_Integer)(ptr - buffer);  
1952   }
1953   else if (  *ptr == '\r' && ptr[ 1 ] == '\n'  )
1954   {
1955     *(ptr++) = '\n' ; // Substitue carriage return by newline.
1956     *ptr = 0 ;
1957     theSeekPos = (LONG)(ptr + 1 - buffer - dwBuffSize);
1958     return (Standard_Integer)(ptr - buffer);  
1959   } 
1960   else if (  *ptr == '\r' && ptr[ 1 ] == 0  ) {
1961     *ptr = '\n' ; // Substitue carriage return by newline
1962     return -1;
1963   }
1964   ++ptr;
1965   
1966  }  // end while
1967
1968  theSeekPos = 0;
1969  return dwBuffSize;
1970 }  // end _get_line
1971
1972 #ifndef OCCT_UWP
1973 static int __fastcall _get_buffer (
1974                         HANDLE hChannel,
1975                         Standard_PCharacter& buffer, 
1976                                    DWORD dwSize,
1977                         BOOL fPeek, BOOL fSocket
1978                        ) {
1979
1980  int   retVal = -1;
1981  int   flags;
1982  DWORD dwDummy;
1983  DWORD dwBytesRead;
1984
1985  if ( fSocket ) {
1986  
1987   flags = fPeek ? MSG_PEEK : 0;
1988
1989   retVal = recv (  ( SOCKET )hChannel, buffer, ( int )dwSize, flags  );
1990
1991   if ( retVal == SOCKET_ERROR ) retVal = -1;
1992
1993  } else {
1994  
1995   if ( fPeek ) {
1996    
1997    if (  !PeekNamedPipe (
1998            hChannel, buffer, dwSize, &dwBytesRead, &dwDummy, &dwDummy
1999           ) && GetLastError () != ERROR_BROKEN_PIPE
2000    )
2001
2002     retVal = -1;
2003
2004    else
2005
2006     retVal = ( int )dwBytesRead;
2007    
2008   } else {
2009
2010    if (  !ReadFile ( hChannel, buffer, dwSize, &dwBytesRead, NULL )  )
2011        
2012     retVal = -1;
2013
2014    else
2015
2016     retVal = ( int )dwBytesRead;
2017    
2018   }  // end else
2019  
2020  }  // end else
2021
2022  return retVal;
2023
2024 }  // end _get_buffer
2025
2026
2027 static DWORD __fastcall _get_access_mask ( OSD_SingleProtection prt ) {
2028
2029  DWORD retVal = 0;
2030
2031  switch ( prt ) {
2032  
2033   case OSD_None:
2034
2035    retVal = 0;
2036
2037   break;
2038
2039   case OSD_R:
2040
2041    retVal = FILE_GENERIC_READ;
2042
2043   break;
2044
2045   case OSD_W:
2046
2047    retVal = FILE_GENERIC_WRITE;
2048
2049   break;
2050
2051   case OSD_RW:
2052
2053    retVal = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2054
2055   break;
2056
2057   case OSD_X:
2058
2059    retVal = FILE_GENERIC_EXECUTE;
2060
2061   break;
2062
2063   case OSD_RX:
2064
2065    retVal = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE;
2066
2067   break;
2068
2069   case OSD_WX:
2070
2071    retVal = FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE;
2072
2073   break;
2074
2075   case OSD_RWX:
2076
2077    retVal = FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE;
2078
2079   break;
2080
2081   case OSD_D:
2082
2083    retVal = DELETE;
2084
2085   break;
2086
2087   case OSD_RD:
2088
2089    retVal = FILE_GENERIC_READ | DELETE;
2090
2091   break;
2092
2093   case OSD_WD:
2094
2095    retVal = FILE_GENERIC_WRITE | DELETE;
2096
2097   break;
2098
2099   case OSD_RWD:
2100
2101    retVal = FILE_GENERIC_READ | FILE_GENERIC_WRITE | DELETE;
2102
2103   break;
2104
2105   case OSD_XD:
2106
2107    retVal = FILE_GENERIC_EXECUTE | DELETE;
2108
2109   break;
2110
2111   case OSD_RXD:
2112
2113    retVal = FILE_GENERIC_READ | FILE_GENERIC_EXECUTE | DELETE;
2114
2115   break;
2116
2117   case OSD_WXD:
2118
2119    retVal = FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | DELETE;
2120
2121   break;
2122
2123   case OSD_RWXD:
2124
2125    retVal = FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | DELETE;
2126
2127   break;
2128
2129   default:
2130
2131    RAISE(  "_get_access_mask (): incorrect parameter"  );
2132  
2133  }  // end switch
2134
2135  return retVal;
2136
2137 }  // end _get_access_mask
2138
2139 static DWORD __fastcall _get_dir_access_mask ( OSD_SingleProtection prt ) {
2140
2141  DWORD retVal = 0;
2142
2143  switch ( prt ) {
2144  
2145   case OSD_None:
2146
2147    retVal = 0;
2148
2149   break;
2150
2151   case OSD_R:
2152
2153    retVal = GENERIC_READ;
2154
2155   break;
2156
2157   case OSD_W:
2158
2159    retVal = GENERIC_WRITE;
2160
2161   break;
2162
2163   case OSD_RW:
2164
2165    retVal = GENERIC_READ | GENERIC_WRITE;
2166
2167   break;
2168
2169   case OSD_X:
2170
2171    retVal = GENERIC_EXECUTE;
2172
2173   break;
2174
2175   case OSD_RX:
2176
2177    retVal = GENERIC_READ | GENERIC_EXECUTE;
2178
2179   break;
2180
2181   case OSD_WX:
2182
2183    retVal = GENERIC_WRITE | GENERIC_EXECUTE;
2184
2185   break;
2186
2187   case OSD_RWX:
2188
2189    retVal = GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE;
2190
2191   break;
2192
2193   case OSD_D:
2194
2195    retVal = DELETE;
2196
2197   break;
2198
2199   case OSD_RD:
2200
2201    retVal = GENERIC_READ | DELETE;
2202
2203   break;
2204
2205   case OSD_WD:
2206
2207    retVal = GENERIC_WRITE | DELETE;
2208
2209   break;
2210
2211   case OSD_RWD:
2212
2213    retVal = GENERIC_READ | GENERIC_WRITE | DELETE;
2214
2215   break;
2216
2217   case OSD_XD:
2218
2219    retVal = GENERIC_EXECUTE | DELETE;
2220
2221   break;
2222
2223   case OSD_RXD:
2224
2225    retVal = GENERIC_READ | GENERIC_EXECUTE | DELETE;
2226
2227   break;
2228
2229   case OSD_WXD:
2230
2231    retVal = GENERIC_WRITE | GENERIC_EXECUTE | DELETE;
2232
2233   break;
2234
2235   case OSD_RWXD:
2236
2237    retVal = GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE;
2238
2239   break;
2240
2241   default:
2242
2243    RAISE(  "_get_dir_access_mask (): incorrect parameter"  );
2244  
2245  }  // end switch
2246
2247  return retVal;
2248
2249 }  // end _get_dir_access_mask
2250 #endif
2251 static HANDLE __fastcall _open_file (
2252                           Standard_CString fName,
2253                           OSD_OpenMode oMode,
2254                           DWORD dwOptions, LPBOOL fNew
2255                          ) {
2256
2257  HANDLE retVal = INVALID_HANDLE_VALUE;
2258  DWORD  dwDesiredAccess = 0;
2259  DWORD  dwCreationDistribution;
2260
2261  switch ( oMode ) {
2262   
2263   case OSD_ReadOnly:
2264
2265    dwDesiredAccess = GENERIC_READ;
2266
2267   break;
2268
2269   case OSD_WriteOnly:
2270
2271    dwDesiredAccess = GENERIC_WRITE;
2272
2273   break;
2274
2275   case OSD_ReadWrite:
2276
2277    dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
2278
2279   break;
2280
2281   default:
2282
2283    RAISE(  "_open_file (): incorrect parameter"  );
2284   
2285  }  // end switch
2286
2287  dwCreationDistribution = ( dwOptions != OPEN_NEW ) ? OPEN_EXISTING : CREATE_ALWAYS;
2288
2289  // make wide character string from UTF-8
2290  TCollection_ExtendedString fNameW(fName, Standard_True);
2291 #ifndef OCCT_UWP
2292  retVal = CreateFileW (
2293            fNameW.ToWideString(), dwDesiredAccess,
2294            FILE_SHARE_READ | FILE_SHARE_WRITE,
2295            NULL, dwCreationDistribution, FILE_ATTRIBUTE_NORMAL, NULL
2296           );
2297 #else
2298  CREATEFILE2_EXTENDED_PARAMETERS pCreateExParams = {};
2299  pCreateExParams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
2300  pCreateExParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
2301  pCreateExParams.lpSecurityAttributes = NULL;
2302  pCreateExParams.hTemplateFile = NULL;
2303  retVal = CreateFile2 (
2304            fNameW.ToWideString(), dwDesiredAccess,
2305            FILE_SHARE_READ | FILE_SHARE_WRITE,
2306            dwCreationDistribution, &pCreateExParams
2307           );
2308 #endif
2309  if ( retVal          == INVALID_HANDLE_VALUE &&
2310       dwOptions       == OPEN_APPEND          &&
2311       GetLastError () == ERROR_FILE_NOT_FOUND
2312  ) {
2313
2314  
2315   dwCreationDistribution = CREATE_ALWAYS;
2316 #ifndef OCCT_UWP
2317   retVal = CreateFileW (
2318             fNameW.ToWideString(), dwDesiredAccess,
2319             FILE_SHARE_READ | FILE_SHARE_WRITE,
2320             NULL, dwCreationDistribution, FILE_ATTRIBUTE_NORMAL, NULL
2321            );
2322 #else
2323   CREATEFILE2_EXTENDED_PARAMETERS pCreateExParams2 = {};
2324   pCreateExParams2.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
2325   pCreateExParams2.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
2326   pCreateExParams2.lpSecurityAttributes = NULL;
2327   pCreateExParams2.hTemplateFile = NULL;
2328   retVal = CreateFile2(
2329     fNameW.ToWideString(), dwDesiredAccess,
2330     FILE_SHARE_READ | FILE_SHARE_WRITE,
2331     dwCreationDistribution, &pCreateExParams2
2332   );
2333 #endif
2334
2335   *fNew = TRUE;
2336
2337  }  // end if
2338
2339  return retVal;
2340
2341 }  // end _open_file
2342
2343 Standard_Integer __fastcall _get_file_type (
2344                              Standard_CString fName, HANDLE fileHandle
2345                             ) {
2346
2347  Standard_Integer retVal = 0;
2348  int              fileType;
2349
2350  fileType = (fileHandle == INVALID_HANDLE_VALUE ? 
2351              FILE_TYPE_DISK : GetFileType (fileHandle));
2352
2353  switch ( fileType ) {
2354  
2355   case FILE_TYPE_UNKNOWN:
2356
2357    retVal = FLAG_SOCKET;
2358
2359   break;
2360
2361   case FILE_TYPE_DISK:
2362   {
2363    // make wide character string from UTF-8
2364    TCollection_ExtendedString fNameW(fName, Standard_True);
2365
2366    WIN32_FILE_ATTRIBUTE_DATA aFileInfo;
2367    if (GetFileAttributesExW (fNameW.ToWideString(), GetFileExInfoStandard, &aFileInfo))
2368
2369     retVal = aFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? FLAG_DIRECTORY : FLAG_FILE;
2370
2371    else
2372
2373     retVal = 0x80000000;
2374   }
2375   break;
2376
2377   case FILE_TYPE_CHAR:
2378
2379    retVal = FLAG_DEVICE;
2380
2381   break;
2382
2383   case FILE_TYPE_PIPE:
2384
2385    retVal = FLAG_PIPE;
2386
2387   break;
2388  
2389  }  // end switch
2390
2391  return retVal;
2392
2393 }  // end _get_file_type
2394
2395 #if defined(__CYGWIN32__) || defined(__MINGW32__)
2396 #define __try
2397 #define __finally
2398 #define __leave return retVal
2399 #endif
2400
2401 #ifndef OCCT_UWP
2402 // None of the existing security APIs are supported in a UWP applications
2403 BOOL __fastcall _osd_wnt_sd_to_protection (
2404                  PSECURITY_DESCRIPTOR pSD, OSD_Protection& prot, BOOL fDir
2405                 ) {
2406
2407  int           i;
2408  BOOL          fPresent;
2409  BOOL          fDefaulted;
2410  PACL          pACL;
2411  PSID          pSIDowner;
2412  PSID          pSIDadmin;
2413  PSID          pSIDworld;
2414  LPVOID        pACE;
2415  DWORD         dwAccessOwner = 0;
2416  DWORD         dwAccessGroup = 0;
2417  DWORD         dwAccessAdmin = 0;
2418  DWORD         dwAccessWorld = 0;
2419  BOOL          retVal = FALSE;
2420  GET_PROT_FUNC _get_prot_func = fDir ? &_get_protection_dir : &_get_protection;
2421
2422  __try {
2423
2424   if (  !GetSecurityDescriptorOwner ( pSD, &pSIDowner, &fDefaulted )  ) __leave;
2425
2426   if (  !GetSecurityDescriptorDacl ( pSD, &fPresent, &pACL, &fDefaulted ) ||
2427         !fPresent
2428   ) __leave;
2429
2430   if ( pSIDowner == NULL || pACL == NULL ) {
2431   
2432    SetLastError ( ERROR_NO_SECURITY_ON_OBJECT );
2433    __leave;
2434   
2435   }  // end if
2436  
2437   pSIDadmin = AdminSid ();
2438   pSIDworld = WorldSid ();
2439
2440   for ( i = 0; i < ( int )pACL -> AceCount; ++i ) {
2441   
2442    if (  GetAce ( pACL, i, &pACE )  ) {
2443    
2444     if (   EqualSid (  pSIDowner, GET_SID( pACE )  )   )
2445
2446      dwAccessOwner = (  ( PACE_HEADER )pACE  ) -> AceType == ACCESS_DENIED_ACE_TYPE ?
2447                      0 : *GET_MSK( pACE );
2448
2449     else if (   EqualSid (  pSIDadmin, GET_SID( pACE )  )   )
2450
2451      dwAccessAdmin = (  ( PACE_HEADER )pACE  ) -> AceType == ACCESS_DENIED_ACE_TYPE ?
2452                      0 : *GET_MSK( pACE );
2453
2454     else if (   EqualSid (  pSIDworld, GET_SID( pACE )  )   )
2455
2456      dwAccessWorld = (  ( PACE_HEADER )pACE  ) -> AceType == ACCESS_DENIED_ACE_TYPE ?
2457                      0 : *GET_MSK( pACE );
2458
2459     else
2460
2461      dwAccessGroup = (  ( PACE_HEADER )pACE  ) -> AceType == ACCESS_DENIED_ACE_TYPE ?
2462                      0 : *GET_MSK( pACE );
2463    
2464    }  // end if
2465   
2466   }  // end for
2467
2468   prot.SetValues (
2469         ( *_get_prot_func ) ( dwAccessAdmin ),
2470         ( *_get_prot_func ) ( dwAccessOwner ),
2471         ( *_get_prot_func ) ( dwAccessGroup ),
2472         ( *_get_prot_func ) ( dwAccessWorld )
2473        );
2474
2475   retVal = TRUE;
2476   
2477  }  // end __try
2478
2479  __finally {}
2480        
2481 #ifdef VAC
2482 leave: ;      // added for VisualAge
2483 #endif
2484
2485  return retVal;
2486
2487 }  // end _osd_wnt_sd_to_protection
2488 #endif
2489
2490 #if defined(__CYGWIN32__) || defined(__MINGW32__)
2491 #undef __try
2492 #undef __finally
2493 #undef __leave
2494 #endif
2495 #ifndef OCCT_UWP
2496 static OSD_SingleProtection __fastcall _get_protection ( DWORD mask ) {
2497
2498  OSD_SingleProtection retVal;
2499
2500  switch ( mask ) {
2501  
2502   case FILE_GENERIC_READ:
2503
2504    retVal = OSD_R;
2505
2506   break;
2507
2508   case FILE_GENERIC_WRITE:
2509
2510    retVal = OSD_W;
2511
2512   break;
2513
2514   case FILE_GENERIC_READ | FILE_GENERIC_WRITE:
2515
2516    retVal = OSD_RW;
2517
2518   break;
2519
2520   case FILE_GENERIC_EXECUTE:
2521
2522    retVal = OSD_X;
2523
2524   break;
2525
2526   case FILE_GENERIC_READ | FILE_GENERIC_EXECUTE:
2527
2528    retVal = OSD_RX;
2529
2530   break;
2531
2532   case FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE:
2533
2534    retVal = OSD_WX;
2535
2536   break;
2537
2538   case FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE:
2539
2540    retVal = OSD_RWX;
2541
2542   break;
2543
2544   case DELETE:
2545
2546    retVal = OSD_D;
2547
2548   break;
2549
2550   case FILE_GENERIC_READ | DELETE:
2551
2552    retVal = OSD_RD;
2553
2554   break;
2555
2556   case FILE_GENERIC_WRITE | DELETE:
2557
2558    retVal = OSD_WD;
2559
2560   break;
2561
2562   case FILE_GENERIC_READ | FILE_GENERIC_WRITE | DELETE:
2563
2564    retVal = OSD_RWD;
2565
2566   break;
2567
2568   case FILE_GENERIC_EXECUTE | DELETE:
2569
2570    retVal = OSD_XD;
2571
2572   break;
2573
2574   case FILE_GENERIC_READ | FILE_GENERIC_EXECUTE | DELETE:
2575
2576    retVal = OSD_RXD;
2577
2578   break;
2579
2580   case FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | DELETE:
2581
2582    retVal = OSD_WXD;
2583
2584   break;
2585
2586   case FILE_ALL_ACCESS:
2587   case FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | DELETE:
2588
2589    retVal = OSD_RWXD;
2590
2591   break;
2592
2593   case 0:
2594   default:
2595
2596    retVal = OSD_None;
2597  
2598  }  // end switch
2599
2600  return retVal;
2601
2602 }  // end _get_protection
2603
2604 static OSD_SingleProtection __fastcall _get_protection_dir (DWORD theMask)
2605 {
2606   switch (theMask)
2607   {
2608     case GENERIC_READ:
2609       return OSD_R;
2610     case GENERIC_WRITE:
2611       return OSD_W;
2612     case GENERIC_READ | GENERIC_WRITE:
2613       return OSD_RW;
2614     case GENERIC_EXECUTE:
2615       return OSD_X;
2616     case GENERIC_READ | GENERIC_EXECUTE:
2617       return OSD_RX;
2618     case GENERIC_WRITE | GENERIC_EXECUTE:
2619       return OSD_WX;
2620     case GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE:
2621       return OSD_RWX;
2622     case DELETE:
2623       return OSD_D;
2624     case GENERIC_READ | DELETE:
2625       return OSD_RD;
2626     case GENERIC_WRITE | DELETE:
2627       return OSD_WD;
2628     case GENERIC_READ | GENERIC_WRITE | DELETE:
2629       return OSD_RWD;
2630     case GENERIC_EXECUTE | DELETE:
2631       return OSD_XD;
2632     case GENERIC_READ | GENERIC_EXECUTE | DELETE:
2633       return OSD_RXD;
2634     case GENERIC_WRITE | GENERIC_EXECUTE | DELETE:
2635       return OSD_WXD;
2636     case FILE_ALL_ACCESS:
2637     case GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE:
2638       return OSD_RWXD;
2639     case 0:
2640       return OSD_None;
2641     default:
2642       // remote directories (on Samba server) have flags like for files
2643       return _get_protection (theMask);
2644   }
2645 }
2646 #endif
2647
2648 Standard_Boolean OSD_File::IsReadable()
2649 {
2650   TCollection_AsciiString FileName ;
2651   HANDLE Channel ;
2652
2653   myPath.SystemName(FileName) ;
2654   Channel = _open_file(FileName.ToCString(), OSD_ReadOnly, OPEN_OLD) ;
2655   if (Channel == INVALID_HANDLE_VALUE)
2656     return Standard_False ;
2657   else {
2658     CloseHandle (Channel) ;
2659     return Standard_True ;
2660   }
2661 }
2662
2663
2664 Standard_Boolean OSD_File::IsWriteable()
2665 {
2666   TCollection_AsciiString FileName ;
2667   HANDLE Channel ;
2668
2669   myPath.SystemName(FileName) ;
2670   Channel = _open_file(FileName.ToCString(), OSD_ReadWrite, OPEN_OLD) ;
2671   if (Channel == INVALID_HANDLE_VALUE)
2672     return Standard_False ;
2673   else {
2674     CloseHandle (Channel) ;
2675     return Standard_True ;
2676   }
2677 }
2678
2679 Standard_Boolean OSD_File::IsExecutable()
2680 {
2681   return IsReadable() ;
2682
2683 //  if (_access(FileName.ToCString(),0))
2684 }
2685
2686 #endif /* _WIN32 */
2687
2688 // ---------------------------------------------------------------------
2689 // Destructs a file object (unlocks and closes file if it is open)
2690 // ---------------------------------------------------------------------
2691
2692 OSD_File::~OSD_File()
2693 {
2694   if (IsOpen())
2695   {
2696     if (IsLocked())
2697       UnLock();
2698     Close();
2699   }
2700 }
2701
2702 // ---------------------------------------------------------------------
2703 // Read lines in a file while it is increasing.
2704 // Each line is terminated with a <nl>.
2705 // ---------------------------------------------------------------------
2706
2707 #include <OSD.hxx>
2708
2709 Standard_Boolean OSD_File::ReadLastLine(TCollection_AsciiString& aLine,const Standard_Integer aDelay,const Standard_Integer aNbTries)
2710 {
2711   static Standard_Integer MaxLength = 1000 ;
2712   Standard_Integer Len ;
2713   Standard_Integer Count = aNbTries ;
2714
2715   if (Count <= 0)
2716       return Standard_False ;
2717   for(;;) {
2718     ReadLine(aLine, MaxLength, Len) ;
2719     if (!aLine.IsEmpty()) 
2720       return Standard_True ;
2721     if (!--Count)
2722       return Standard_False ;
2723     OSD::SecSleep(aDelay) ;
2724   }
2725 }
2726
2727
2728 Standard_Boolean OSD_File::Edit()
2729 {
2730   cout << "Function OSD_File::Edit() not yet implemented." << endl;
2731   return Standard_False ;
2732 }
2733
2734
2735