cprover
tempfile.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening
6 
7 \*******************************************************************/
8 
9 #include "tempfile.h"
10 
11 #ifdef _WIN32
12 #include <util/pragma_push.def>
13 #ifdef _MSC_VER
14 #pragma warning(disable:4668)
15  // using #if/#elif on undefined macro
16 #pragma warning(disable : 5039)
17 // pointer or reference to potentially throwing function passed to extern C
18 #endif
19 #include <process.h>
20 #include <sys/stat.h>
21 #include <windows.h>
22 #include <io.h>
23 #include <tchar.h>
24 #define getpid _getpid
25 #define open _open
26 #define close _close
27 #include <util/pragma_pop.def>
28 #endif
29 
30 #include <fcntl.h>
31 
32 #include <cstdlib>
33 #include <cstdio>
34 #include <cstring>
35 
36 #include "exception_utils.h"
37 #include "file_util.h"
38 
39 #if defined(__linux__) || \
40  defined(__FreeBSD_kernel__) || \
41  defined(__GNU__) || \
42  defined(__unix__) || \
43  defined(__CYGWIN__) || \
44  defined(__MACH__)
45 #include <unistd.h>
46 #endif
47 
50 #ifdef _WIN32
51 #define mkstemps my_mkstemps
52 int my_mkstemps(char *template_str, int suffix_len)
53 {
54  // The template should be of the form tmpXXXXXXsuffix
55 
56  std::size_t template_length=strlen(template_str);
57 
58  if(suffix_len<0)
59  return -1;
60 
61  if(static_cast<std::size_t>(suffix_len+6)>template_length)
62  return -1; // suffix too long
63 
64  char *XXXXXX_pos=
65  template_str+template_length-6-suffix_len;
66 
67  if(strncmp(XXXXXX_pos, "XXXXXX", 6)!=0)
68  return -1; // XXXXXX missing
69 
70  static const char letters_and_numbers[]=
71  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
72 
73  static long long unsigned int random_state;
74  random_state+=getpid()+123;
75 
76  for(unsigned attempt = 0; attempt < 1000; ++attempt)
77  {
78  unsigned long long number=random_state;
79 
80  for(unsigned i=0; i<6; i++)
81  {
82  XXXXXX_pos[i]=letters_and_numbers[number%62];
83  number/=62;
84  }
85 
86  int fd=open(template_str, O_RDWR|O_CREAT|O_EXCL, 0600);
87  if(fd>=0)
88  return fd; // ok
89 
90  random_state+=4321+getpid(); // avoid repeating
91  }
92 
93  template_str[0]=0;
94  return -1; // error
95 }
96 #endif
97 
98 std::string get_temporary_file(
99  const std::string &prefix,
100  const std::string &suffix)
101 {
102  #ifdef _WIN32
103  char lpTempPathBuffer[MAX_PATH];
104  DWORD dwRetVal;
105 
106  dwRetVal=
107  GetTempPathA(
108  MAX_PATH, // length of the buffer
109  lpTempPathBuffer); // buffer for path
110 
111  if(dwRetVal>MAX_PATH || (dwRetVal==0))
112  throw system_exceptiont("Failed to get temporary directory");
113 
114  // the path returned by GetTempPath ends with a backslash
115  std::string t_template=
116  std::string(lpTempPathBuffer)+prefix+
117  std::to_string(getpid())+".XXXXXX"+suffix;
118  #else
119  std::string dir="/tmp/";
120  const char *TMPDIR_env=getenv("TMPDIR");
121  if(TMPDIR_env!=nullptr)
122  dir=TMPDIR_env;
123  if(*dir.rbegin()!='/')
124  dir+='/';
125 
126  std::string t_template=
127  dir+prefix+std::to_string(getpid())+".XXXXXX"+suffix;
128  #endif
129 
130  char *t_ptr=strdup(t_template.c_str());
131 
132  int fd=mkstemps(t_ptr, suffix.size());
133 
134  if(fd<0)
135  throw system_exceptiont("Failed to open temporary file");
136 
137  close(fd);
138 
139  std::string result=std::string(t_ptr);
140  free(t_ptr);
141  return result;
142 }
143 
145 {
146  if(!name.empty())
147  file_remove(name);
148 }
exception_utils.h
get_temporary_file
std::string get_temporary_file(const std::string &prefix, const std::string &suffix)
Substitute for mkstemps (OpenBSD standard) for Windows, where it is unavailable.
Definition: tempfile.cpp:98
tempfile.h
file_util.h
file_remove
bool file_remove(const std::string &path)
C++17 will allow us to use std::filesystem::remove.
Definition: file_util.cpp:231
to_string
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
Definition: string_constraint.cpp:55
system_exceptiont
Thrown when some external system fails unexpectedly.
Definition: exception_utils.h:61
temporary_filet::name
std::string name
Definition: tempfile.h:51
temporary_filet::~temporary_filet
~temporary_filet()
Definition: tempfile.cpp:144