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 "exception_utils.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 <util/pragma_push.def>
36 #ifdef _MSC_VER
37 #pragma warning(disable:4668)
38  // using #if/#elif on undefined macro
39 #endif
40 #include <io.h>
41 #include <windows.h>
42 #include <direct.h>
43 #include <util/unicode.h>
44 #include <util/pragma_pop.def>
45 #endif
46 
49 {
50  #ifndef _WIN32
51  errno=0;
52  char *wd=realpath(".", nullptr);
53 
54  if(wd == nullptr || errno != 0)
55  throw system_exceptiont(
56  std::string("realpath failed: ") + std::strerror(errno));
57 
58  std::string working_directory=wd;
59  free(wd);
60  #else
61  char buffer[4096];
62  DWORD retval=GetCurrentDirectory(4096, buffer);
63  if(retval == 0)
64  throw system_exceptiont("failed to get current directory of process");
65  std::string working_directory(buffer);
66  #endif
67 
68  return working_directory;
69 }
70 
72 #ifdef _WIN32
73 
74 void delete_directory_utf16(const std::wstring &path)
75 {
76  std::wstring pattern=path + L"\\*";
77  // NOLINTNEXTLINE(readability/identifiers)
78  struct _wfinddata_t info;
79  intptr_t hFile=_wfindfirst(pattern.c_str(), &info);
80  if(hFile!=-1)
81  {
82  do
83  {
84  if(wcscmp(info.name, L".")==0 || wcscmp(info.name, L"..")==0)
85  continue;
86  std::wstring sub_path=path+L"\\"+info.name;
87  if(info.attrib & _A_SUBDIR)
88  delete_directory_utf16(sub_path);
89  else
90  DeleteFileW(sub_path.c_str());
91  }
92  while(_wfindnext(hFile, &info)==0);
93  _findclose(hFile);
94  RemoveDirectoryW(path.c_str());
95  }
96 }
97 
98 #endif
99 
100 void delete_directory(const std::string &path)
101 {
102 #ifdef _WIN32
103  delete_directory_utf16(utf8_to_utf16_native_endian(path));
104 #else
105  DIR *dir=opendir(path.c_str());
106  if(dir!=nullptr)
107  {
108  struct dirent *ent;
109  while((ent=readdir(dir))!=nullptr)
110  {
111  // Needed for Alpine Linux
112  if(strcmp(ent->d_name, ".")==0 || strcmp(ent->d_name, "..")==0)
113  continue;
114 
115  std::string sub_path=path+"/"+ent->d_name;
116 
117  struct stat stbuf;
118  int result=stat(sub_path.c_str(), &stbuf);
119  if(result!=0)
120  throw system_exceptiont(
121  std::string("Stat failed: ") + std::strerror(errno));
122 
123  if(S_ISDIR(stbuf.st_mode))
124  delete_directory(sub_path);
125  else
126  {
127  result=remove(sub_path.c_str());
128  if(result!=0)
129  throw system_exceptiont(
130  std::string("Remove failed: ") + std::strerror(errno));
131  }
132  }
133  closedir(dir);
134  }
135  rmdir(path.c_str());
136 #endif
137 }
138 
141 std::string concat_dir_file(
142  const std::string &directory,
143  const std::string &file_name)
144 {
145  #ifdef _WIN32
146  return (file_name.size() > 1 && file_name[0] != '/' && file_name[1] == ':') ?
147  file_name : directory + "\\" + file_name;
148  #else
149  return (!file_name.empty() && file_name[0]=='/') ?
150  file_name : directory+"/"+file_name;
151  #endif
152 }
153 
154 bool is_directory(const std::string &path)
155 {
156  if(path.empty())
157  return false;
158 
159 #ifdef _WIN32
160 
161  auto attributes = ::GetFileAttributesW(widen(path).c_str());
162  if (attributes == INVALID_FILE_ATTRIBUTES)
163  return false;
164  else
165  return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
166 
167 #else
168 
169  struct stat buf;
170 
171  if(stat(path.c_str(), &buf)!=0)
172  return false;
173  else
174  return (buf.st_mode & S_IFDIR) != 0;
175 
176 #endif
177 }
std::string concat_dir_file(const std::string &directory, const std::string &file_name)
Definition: file_util.cpp:141
std::wstring widen(const char *s)
Definition: unicode.cpp:52
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:196
std::string get_current_working_directory()
Definition: file_util.cpp:48
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:100
Thrown when some external system fails unexpectedly.
bool is_directory(const std::string &path)
Definition: file_util.cpp:154