cprover
Loading...
Searching...
No Matches
file_util.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: File Utilities
4
5Author:
6
7Date: 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#pragma warning(disable : 5039)
40// pointer or reference to potentially throwing function passed to extern C
41#endif
42#include <io.h>
43#include <windows.h>
44#include <direct.h>
45#include <util/unicode.h>
46#define chdir _chdir
47#include <util/pragma_pop.def>
48#endif
49
52{
53#ifndef _WIN32
54 errno=0;
55 char *wd=realpath(".", nullptr);
56
57 if(wd == nullptr)
59 std::string("realpath failed: ") + std::strerror(errno));
60
61 std::string working_directory=wd;
62 free(wd);
63#else
64 TCHAR buffer[4096];
65 DWORD retval=GetCurrentDirectory(4096, buffer);
66 if(retval == 0)
67 throw system_exceptiont("failed to get current directory of process");
68
69# ifdef UNICODE
70 std::string working_directory(narrow(buffer));
71# else
72 std::string working_directory(buffer);
73# endif
74
75#endif
76
77 return working_directory;
78}
79
82void set_current_path(const std::string &path)
83{
84 if(chdir(path.c_str()) != 0)
86 std::string("chdir failed: ") + std::strerror(errno));
87}
88
90#ifdef _WIN32
91
92void delete_directory_utf16(const std::wstring &path)
93{
94 std::wstring pattern=path + L"\\*";
95 // NOLINTNEXTLINE(readability/identifiers)
96 struct _wfinddata_t info;
98 if(hFile!=-1)
99 {
100 do
101 {
102 if(wcscmp(info.name, L".")==0 || wcscmp(info.name, L"..")==0)
103 continue;
104 std::wstring sub_path=path+L"\\"+info.name;
105 if(info.attrib & _A_SUBDIR)
107 else
108 DeleteFileW(sub_path.c_str());
109 }
110 while(_wfindnext(hFile, &info)==0);
112 RemoveDirectoryW(path.c_str());
113 }
114}
115
116#endif
117
118void delete_directory(const std::string &path)
119{
120#ifdef _WIN32
122#else
123 DIR *dir=opendir(path.c_str());
124 if(dir!=nullptr)
125 {
126 struct dirent *ent;
127 while((ent=readdir(dir))!=nullptr)
128 {
129 // Needed for Alpine Linux
130 if(strcmp(ent->d_name, ".")==0 || strcmp(ent->d_name, "..")==0)
131 continue;
132
133 std::string sub_path=path+"/"+ent->d_name;
134
135 struct stat stbuf;
136 int result=stat(sub_path.c_str(), &stbuf);
137 if(result!=0)
138 throw system_exceptiont(
139 std::string("Stat failed: ") + std::strerror(errno));
140
141 if(S_ISDIR(stbuf.st_mode))
143 else
144 {
145 result=remove(sub_path.c_str());
146 if(result!=0)
147 throw system_exceptiont(
148 std::string("Remove failed: ") + std::strerror(errno));
149 }
150 }
151 closedir(dir);
152 }
153 rmdir(path.c_str());
154#endif
155}
156
159std::string concat_dir_file(
160 const std::string &directory,
161 const std::string &file_name)
162{
163#ifdef _WIN32
164 if(
165 file_name.size() > 1 && file_name[0] != '/' && file_name[0] != '\\' &&
166 file_name[1] == ':')
167 {
168 return file_name;
169 }
170 else if(
171 !directory.empty() && (directory.back() == '/' || directory.back() == '\\'))
172 {
173 return directory + file_name;
174 }
175 else
176 return directory + '\\' + file_name;
177#else
178 if(!file_name.empty() && file_name[0] == '/')
179 return file_name;
180 else if(!directory.empty() && directory.back() == '/')
181 return directory + file_name;
182 else
183 return directory + '/' + file_name;
184#endif
185}
186
187bool is_directory(const std::string &path)
188{
189 if(path.empty())
190 return false;
191
192#ifdef _WIN32
193
194 auto attributes = ::GetFileAttributesW(widen(path).c_str());
195 if (attributes == INVALID_FILE_ATTRIBUTES)
196 return false;
197 else
198 return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
199
200#else
201
202 struct stat buf;
203
204 if(stat(path.c_str(), &buf)!=0)
205 return false;
206 else
207 return (buf.st_mode & S_IFDIR) != 0;
208
209#endif
210}
211
212bool create_directory(const std::string &path)
213{
214#ifdef _WIN32
215 return _mkdir(path.c_str()) == 0;
216#else
217 // the umask matches what std::filesystem::create_directory does
218 return mkdir(path.c_str(), 0777) == 0;
219#endif
220}
221
222bool file_exists(const std::string &path)
223{
224#ifdef _WIN32
225 return _waccess(utf8_to_utf16_native_endian(path).c_str(), 0) == 0;
226#else
227 return access(path.c_str(), F_OK) == 0;
228#endif
229}
230
231bool file_remove(const std::string &path)
232{
233#ifdef _WIN32
234 return _wunlink(utf8_to_utf16_native_endian(path).c_str()) == 0;
235#else
236 return unlink(path.c_str()) == 0;
237#endif
238}
239
240void file_rename(const std::string &old_path, const std::string &new_path)
241{
242#ifdef _WIN32
244 {
245 // rename() only renames directories, but does not move them.
246 // MoveFile is not atomic.
247 auto MoveFile_result =
248 MoveFileW(widen(old_path).c_str(), widen(new_path).c_str());
249
250 if(MoveFile_result == 0)
251 throw system_exceptiont("MoveFileW failed");
252 }
253 else
254 {
255 // C++17 requires this to be atomic.
256 // MoveFile, MoveFileEx() or rename() do not guarantee this.
257 // Any existing file at new_path is to be overwritten.
258 // rename() does not do so on Windows.
260 widen(old_path).c_str(),
261 widen(new_path).c_str(),
263
264 if(MoveFileEx_result == 0)
265 throw system_exceptiont("MoveFileExW failed");
266 }
267#else
268 int rename_result = rename(old_path.c_str(), new_path.c_str());
269
270 if(rename_result != 0)
271 throw system_exceptiont(
272 std::string("rename failed: ") + std::strerror(errno));
273#endif
274}
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:563
ait()
Definition ai.h:566
Thrown when some external system fails unexpectedly.
void set_current_path(const std::string &path)
Set working directory.
Definition file_util.cpp:82
std::string get_current_working_directory()
Definition file_util.cpp:51
bool file_exists(const std::string &path)
Check whether file with given path exists.
bool is_directory(const std::string &path)
void delete_directory(const std::string &path)
deletes all files in 'path' and then the directory itself
bool file_remove(const std::string &path)
C++17 will allow us to use std::filesystem::remove.
bool create_directory(const std::string &path)
Create a directory with given path C++17 will allow us to use std::filesystem::create_directory.
void file_rename(const std::string &old_path, const std::string &new_path)
Rename a file.
std::string concat_dir_file(const std::string &directory, const std::string &file_name)
output_type narrow(input_type input)
Run-time checked narrowing cast.
Definition narrow.h:34
std::wstring widen(const char *s)
Definition unicode.cpp:49
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:192