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 <process.h>
13 #include <sys/stat.h>
14 #include <windows.h>
15 #include <io.h>
16 #include <tchar.h>
17 #define getpid _getpid
18 #define open _open
19 #define close _close
20 #endif
21 
22 #include <fcntl.h>
23 
24 #include <cstdlib>
25 #include <cstdio>
26 #include <cstring>
27 
28 #if defined(__linux__) || \
29  defined(__FreeBSD_kernel__) || \
30  defined(__GNU__) || \
31  defined(__unix__) || \
32  defined(__CYGWIN__) || \
33  defined(__MACH__)
34 #include <unistd.h>
35 #endif
36 
39 #ifdef _WIN32
40 #define mkstemps my_mkstemps
41 int my_mkstemps(char *template_str, int suffix_len)
42 {
43  // The template should be of the form tmpXXXXXXsuffix
44 
45  std::size_t template_length=strlen(template_str);
46 
47  if(suffix_len<0)
48  return -1;
49 
50  if(static_cast<std::size_t>(suffix_len+6)>template_length)
51  return -1; // suffix too long
52 
53  char *XXXXXX_pos=
54  template_str+template_length-6-suffix_len;
55 
56  if(strncmp(XXXXXX_pos, "XXXXXX", 6)!=0)
57  return -1; // XXXXXX missing
58 
59  static const char letters_and_numbers[]=
60  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
61 
62  static long long unsigned int random_state;
63  random_state+=getpid()+123;
64 
65  for(unsigned attempt = 0; attempt < 1000; ++attempt)
66  {
67  unsigned long long number=random_state;
68 
69  for(unsigned i=0; i<6; i++)
70  {
71  XXXXXX_pos[i]=letters_and_numbers[number%62];
72  number/=62;
73  }
74 
75  int fd=open(template_str, O_RDWR|O_CREAT|O_EXCL, 0600);
76  if(fd>=0)
77  return fd; // ok
78 
79  random_state+=4321+getpid(); // avoid repeating
80  }
81 
82  template_str[0]=0;
83  return -1; // error
84 }
85 #endif
86 
87 std::string get_temporary_file(
88  const std::string &prefix,
89  const std::string &suffix)
90 {
91  #ifdef _WIN32
92  char lpTempPathBuffer[MAX_PATH];
93  DWORD dwRetVal;
94 
95  dwRetVal=
96  GetTempPathA(
97  MAX_PATH, // length of the buffer
98  lpTempPathBuffer); // buffer for path
99 
100  if(dwRetVal>MAX_PATH || (dwRetVal==0))
101  throw "GetTempPath failed"; // NOLINT(readability/throw)
102 
103  // the path returned by GetTempPath ends with a backslash
104  std::string t_template=
105  std::string(lpTempPathBuffer)+prefix+
106  std::to_string(getpid())+".XXXXXX"+suffix;
107  #else
108  std::string dir="/tmp/";
109  const char *TMPDIR_env=getenv("TMPDIR");
110  if(TMPDIR_env!=nullptr)
111  dir=TMPDIR_env;
112  if(*dir.rbegin()!='/')
113  dir+='/';
114 
115  std::string t_template=
116  dir+prefix+std::to_string(getpid())+".XXXXXX"+suffix;
117  #endif
118 
119  char *t_ptr=strdup(t_template.c_str());
120 
121  int fd=mkstemps(t_ptr, suffix.size());
122 
123  if(fd<0)
124  throw "mkstemps failed";
125 
126  close(fd);
127 
128  std::string result=std::string(t_ptr);
129  free(t_ptr);
130  return result;
131 }
132 
134 {
135  if(!name.empty())
136  std::remove(name.c_str());
137 }
std::string name
Definition: tempfile.h:51
void free(void *)
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:87
std::string to_string(const string_constraintt &expr)
Used for debug printing.