0024132: Test execution fails due to permission rights issues
authorkgv <kgv@opencascade.com>
Thu, 5 Sep 2013 09:11:45 +0000 (13:11 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 5 Sep 2013 09:13:10 +0000 (13:13 +0400)
Generation of temporary files used for capturing DRAW command output on Windows is improved to use directory specified by environment variable TMP or TEMP (instead of root directory which can be write-protected)

src/Draw/Draw_Interpretor.cxx

index 41fa96e..5409852 100755 (executable)
@@ -29,6 +29,7 @@
 
 #include <TCollection_AsciiString.hxx>
 #include <TCollection_ExtendedString.hxx>
+#include <OSD_Process.hxx>
 #include <OSD_Path.hxx>
 #include <OSD.hxx>
 
@@ -120,15 +121,26 @@ namespace {
     cout << flush;
   }
 
-  FILE* capture_start (int std_fd, int *save_fd)
+  FILE* capture_start (int std_fd, int *save_fd, char*& tmp_name)
   {
-    (*save_fd) = 0;
+    *save_fd = 0;
 
     // open temporary files
-    FILE * aTmpFile = tmpfile();
-    int fd_tmp = fileno(aTmpFile);
-
-    if (fd_tmp <0) 
+  #if defined(_WIN32)
+    // use _tempnam() to decrease chances of failure (tmpfile() creates 
+    // file in root folder and will fail if it is write protected), see #24132
+    static const char* tmpdir = getenv("TEMP");
+    static char prefix[256] = ""; // prefix for temporary files, initialize once per process using pid
+    if (prefix[0] == '\0')
+      sprintf (prefix, "drawtmp%d_", (int)OSD_Process().ProcessId());
+    tmp_name = _tempnam (tmpdir, prefix);
+    FILE* aTmpFile = (tmp_name != NULL ? fopen (tmp_name, "w+b") : tmpfile());
+  #else
+    tmp_name = NULL;
+    FILE* aTmpFile = tmpfile();
+  #endif
+    int fd_tmp = (aTmpFile != NULL ? fileno (aTmpFile) : -1);
+    if (fd_tmp < 0)
     {
       cerr << "Error: cannot create temporary file for capturing console output" << endl;
       fclose (aTmpFile);
@@ -141,8 +153,11 @@ namespace {
     return aTmpFile;
   }
 
-  void capture_end (FILE* tmp_file, int std_fd, int save_fd, Standard_OStream &log, Standard_Boolean doEcho)
+  void capture_end (FILE* tmp_file, int std_fd, int save_fd, char* tmp_name, Standard_OStream &log, Standard_Boolean doEcho)
   {
+    if (! tmp_file)
+      return;
+
     // restore normal descriptors of console stream
     dup2 (save_fd, std_fd);
     close(save_fd);
@@ -160,6 +175,10 @@ namespace {
 
     // close temporary file
     fclose (tmp_file);
+
+    // remove temporary file if this is not done by the system
+    if (tmp_name)
+      remove (tmp_name);
   }
 };
 
@@ -193,14 +212,15 @@ static Standard_Integer CommandCmd
   flush_standard_streams();
 
   // capture cout and cerr to log
+  char *err_name = NULL, *out_name = NULL;
   FILE * aFile_err = NULL;
   FILE * aFile_out = NULL;
   int fd_err_save = 0;
   int fd_out_save = 0;
   if (doLog)
   {
-    aFile_out = capture_start (STDOUT_FILENO, &fd_out_save);
-    aFile_err = capture_start (STDERR_FILENO, &fd_err_save);
+    aFile_out = capture_start (STDOUT_FILENO, &fd_out_save, out_name);
+    aFile_err = capture_start (STDERR_FILENO, &fd_err_save, err_name);
   }
 
   // run command
@@ -258,8 +278,8 @@ static Standard_Integer CommandCmd
   // end capturing cout and cerr 
   if (doLog) 
   {
-    capture_end (aFile_err, STDERR_FILENO, fd_err_save, di.Log(), doEcho);
-    capture_end (aFile_out, STDOUT_FILENO, fd_out_save, di.Log(), doEcho);
+    capture_end (aFile_err, STDERR_FILENO, fd_err_save, err_name, di.Log(), doEcho);
+    capture_end (aFile_out, STDOUT_FILENO, fd_out_save, out_name, di.Log(), doEcho);
   }
 
   // log command result