cprover
file_util.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: File Utilities
4 
5 Author:
6 
7 Date: January 2012
8 
9 \*******************************************************************/
10 
13 
14 #include "file_util.h"
15 
16 #include "invariant.h"
17 
18 #include <cerrno>
19 #include <cstring>
20 
21 #if defined(__linux__) || \
22  defined(__FreeBSD_kernel__) || \
23  defined(__GNU__) || \
24  defined(__unix__) || \
25  defined(__CYGWIN__) || \
26  defined(__MACH__)
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <dirent.h>
30 #include <cstdlib>
31 #include <cstdio>
32 #endif
33 
34 #ifdef _WIN32
35 #include <io.h>
36 #include <windows.h>
37 #include <direct.h>
38 #include <util/unicode.h>
39 #define chdir _chdir
40 #define popen _popen
41 #define pclose _pclose
42 #endif
43 
46 {
47  #ifndef _WIN32
48  errno=0;
49  char *wd=realpath(".", nullptr);
50  INVARIANT(
51  wd!=nullptr && errno==0,
52  std::string("realpath failed: ")+strerror(errno));
53 
54  std::string working_directory=wd;
55  free(wd);
56  #else
57  char buffer[4096];
58  DWORD retval=GetCurrentDirectory(4096, buffer);
59  CHECK_RETURN(retval>0);
60  std::string working_directory(buffer);
61  #endif
62 
63  return working_directory;
64 }
65 
67 #ifdef _WIN32
68 
69 void delete_directory_utf16(const std::wstring &path)
70 {
71  std::wstring pattern=path + L"\\*";
72  // NOLINTNEXTLINE(readability/identifiers)
73  struct _wfinddata_t info;
74  intptr_t hFile=_wfindfirst(pattern.c_str(), &info);
75  if(hFile!=-1)
76  {
77  do
78  {
79  if(wcscmp(info.name, L".")==0 || wcscmp(info.name, L"..")==0)
80  continue;
81  std::wstring sub_path=path+L"\\"+info.name;
82  if(info.attrib & _A_SUBDIR)
83  delete_directory_utf16(sub_path);
84  else
85  DeleteFileW(sub_path.c_str());
86  }
87  while(_wfindnext(hFile, &info)==0);
88  _findclose(hFile);
89  RemoveDirectoryW(path.c_str());
90  }
91 }
92 
93 #endif
94 
95 void delete_directory(const std::string &path)
96 {
97 #ifdef _WIN32
98  delete_directory_utf16(utf8_to_utf16_native_endian(path));
99 #else
100  DIR *dir=opendir(path.c_str());
101  if(dir!=nullptr)
102  {
103  struct dirent *ent;
104  while((ent=readdir(dir))!=nullptr)
105  {
106  // Needed for Alpine Linux
107  if(strcmp(ent->d_name, ".")==0 || strcmp(ent->d_name, "..")==0)
108  continue;
109 
110  std::string sub_path=path+"/"+ent->d_name;
111 
112  struct stat stbuf;
113  int result=stat(sub_path.c_str(), &stbuf);
114  if(result!=0)
115  throw std::string("Stat failed: ")+std::strerror(errno);
116 
117  if(S_ISDIR(stbuf.st_mode))
118  delete_directory(sub_path);
119  else
120  {
121  result=remove(sub_path.c_str());
122  if(result!=0)
123  throw std::string("Remove failed: ")+std::strerror(errno);
124  }
125  }
126  closedir(dir);
127  }
128  rmdir(path.c_str());
129 #endif
130 }
131 
134 std::string concat_dir_file(
135  const std::string &directory,
136  const std::string &file_name)
137 {
138  #ifdef _WIN32
139  return (file_name.size() > 1 && file_name[0] != '/' && file_name[1] == ':') ?
140  file_name : directory + "\\" + file_name;
141  #else
142  return (!file_name.empty() && file_name[0]=='/') ?
143  file_name : directory+"/"+file_name;
144  #endif
145 }
146 
147 bool is_directory(const std::string &path)
148 {
149  if(path.empty())
150  return false;
151 
152 #ifdef _WIN32
153 
154  auto attributes = ::GetFileAttributesW(widen(path).c_str());
155  if (attributes == INVALID_FILE_ATTRIBUTES)
156  return false;
157  else
158  return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
159 
160 #else
161 
162  struct stat buf;
163 
164  if(stat(path.c_str(), &buf)!=0)
165  return false;
166  else
167  return (buf.st_mode & S_IFDIR) != 0;
168 
169 #endif
170 }
std::string concat_dir_file(const std::string &directory, const std::string &file_name)
Definition: file_util.cpp:134
std::wstring widen(const char *s)
Definition: unicode.cpp:46
std::wstring utf8_to_utf16_native_endian(const std::string &in)
Convert UTF8-encoded string to UTF-16 with architecture-native endianness.
Definition: unicode.cpp:190
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:266
std::string get_current_working_directory()
Definition: file_util.cpp:45
#define INVARIANT(CONDITION, REASON)
Definition: invariant.h:204
void free(void *)
void delete_directory(const std::string &path)
deletes all files in &#39;path&#39; and then the directory itself
Definition: file_util.cpp:95
bool is_directory(const std::string &path)
Definition: file_util.cpp:147