vul_file.cxx
Go to the documentation of this file.
1 // This is core/vul/vul_file.cxx
2 //:
3 // \file
4 // \author Andrew W. Fitzgibbon, Oxford RRG
5 // \date 02 Nov 1998
6 //
7 // \verbatim
8 // Modifications
9 // 08 Jan 2009 Peter Vanroose- simplified "delete_file_glob()" implementation
10 // \endverbatim
11 //
12 //-----------------------------------------------------------------------------
13 
14 #include <cstring>
15 #include <cctype>
16 #include <cstdlib>
17 #include "vul_file.h"
18 
19 #include <sys/stat.h>
20 #ifdef _MSC_VER
21 # include <vcl_msvc_warnings.h>
22 #endif
23 
24 #if defined(_WIN32) && !defined(__CYGWIN__)
25 #include <direct.h> // for getcwd, mkdir
26 #else
27 #include <unistd.h>
28 #endif
29 
30 #include <vul/vul_user_info.h>
31 
32 std::string vul_file::get_cwd()
33 {
34  constexpr int BIG = 65536;
35  char buf[BIG];
36  if (getcwd(buf,BIG-1))
37  return buf;
38  else
39  return "Error returned by getcwd";
40 }
41 
42 bool vul_file::change_directory(char const* dirname)
43 {
44  return 0 == chdir(dirname);
45 }
46 
47 bool vul_file::make_directory(char const* name)
48 {
49 #if defined(_WIN32) && !defined(__CYGWIN__)
50  return -1 != mkdir(name);
51 #else
52  return -1 != mkdir(name, 0755);
53 #endif
54 }
55 
56 bool vul_file::is_directory(char const* fn)
57 {
58  struct stat fs;
59  return stat(fn, &fs) == 0
60  && (fs.st_mode & S_IFMT) == S_IFDIR;
61 }
62 
63 std::time_t vul_file::time_modified(char const* filename){
64  struct stat fs;
65  if(stat(filename, &fs)!=0)
66  return std::time_t(0);
67  return fs.st_mtime;
68 }
69 
70 #if defined(_WIN32) && !defined(__CYGWIN__)
71 bool vul_file::is_drive(char const* fn)
72 {
73  // a drive string looks like "c:", "z:"
74  return fn
75  && std::isalpha(fn[0])
76  && fn[1]==':'
77  && fn[2]=='\0';
78 }
79 #endif
80 
81 //: Make a writable directory, including any necessary parents.
82 // Returns true if successful, or if the directory already exists.
83 // Implemented by calling itself recursively on the parent directory.
84 bool vul_file::make_directory_path(char const* filename)
85 {
86 #if defined(_WIN32) && !defined(__CYGWIN__)
87  if (is_directory(filename) || is_drive(filename)) return true;
88 #else
89  if (is_directory(filename)) return true;
90 #endif
91  // You can get a race condition here if there are multiple
92  // process/threads trying to make the same dir at the same time
93  // So if the make_directory fails, just check that someone else
94  // didn't make it in the intervening time.
95  return make_directory_path(dirname(filename))
96  && (make_directory(filename) || is_directory(filename));
97 }
98 
99 
100 unsigned long vul_file::size(char const* fn)
101 {
102  struct stat fs;
103  if (stat(fn, &fs) == 0)
104  return fs.st_size;
105  else
106  return 0L;
107 }
109 bool vul_file::exists(char const* fn)
110 {
111  struct stat fs;
112  std::string name(fn);
113 
114 #if defined(_WIN32) && !defined(__CYGWIN__)
115  std::string::size_type last_non_slash_index = name.find_last_not_of("\\/");
116 #else
117  std::string::size_type last_non_slash_index = name.find_last_not_of('/');
118 #endif
119  if (last_non_slash_index != std::string::npos)
120  last_non_slash_index++;
121  name = name.substr(0, last_non_slash_index);
122  return stat(name.c_str(), &fs) == 0;
123 }
125 std::string vul_file::dirname(char const* fn)
126 {
127  std::string self(fn);
128 
129 #if defined(_WIN32) && !defined(__CYGWIN__)
130  std::string::size_type slash_index = self.find_last_of("\\/");
131 #else
132  std::string::size_type slash_index = self.rfind('/');
133 #endif
134  if (slash_index == std::string::npos)
135  return ".";
136 
137 
138  return self.substr(0, slash_index);
139 }
141 std::string vul_file::extension(char const* fn)
142 {
143  std::string self(fn);
144 
145  std::string::size_type dot_index = self.rfind('.');
146  if (dot_index != std::string::npos)
147  return self.substr(dot_index, std::string::npos);
148  else
149  return std::string();
150 }
152 std::string vul_file::strip_directory(char const* fn)
153 {
154  std::string self(fn);
155 
156 #if defined(_WIN32) && !defined(__CYGWIN__)
157  std::string::size_type slash_index = self.find_last_of("\\/");
158 #else
159  std::string::size_type slash_index = self.rfind('/');
160 #endif
161  if (slash_index != std::string::npos)
162  self.erase(0, slash_index+1);
163 
164  return self;
165 }
167 std::string vul_file::strip_extension(char const* fn)
168 {
169  std::string self(fn);
170 
171  std::string::size_type dot_index = self.rfind('.');
172  if (dot_index != std::string::npos)
173  self.erase(dot_index, std::string::npos);
174 
175  return self;
176 }
178 std::string vul_file::basename(char const* fn, char const * suffix)
179 {
180  // First strip dir
181  std::string self(fn);
182 
183 #if defined(_WIN32) && !defined(__CYGWIN__)
184  std::string::size_type slash_index = self.find_last_of("\\/");
185 #else
186  std::string::size_type slash_index = self.rfind('/');
187 #endif
188 
189  if (slash_index != std::string::npos)
190  self.erase(0, slash_index+1);
191 
192  // Now strip suffix if any
193  if (suffix) {
194  int start = (int)(self.size() - std::strlen(suffix));
195  if (start >= 0)
196  if (std::string(self.begin()+start, self.end()) == suffix)
197  self.erase(start, std::string::npos);
198  }
199  return self;
200 }
201 
202 
203 #if defined(_WIN32) && !defined(__CYGWIN__)
204 //: replace instances of 'from' in 's' with 'to'
205 static unsigned replace(char from, char to, std::string &s)
206 {
207  unsigned c = 0;
208  for (unsigned i=0; i<s.size(); ++i)
209  if (s[i] == from)
210  {
211  c++;
212  s[i] = to;
213  }
214  return c;
215 }
216 #endif
217 
218 //: Delete 1 or more files using the Local OS preferred globbing.
219 // E.g. \c delete_file_glob("*"); will delete all the files in the
220 // current directory on most operating systems.
221 // Takes Posix path separators i.e. '/'
222 bool vul_file::delete_file_glob(std::string const& file_glob)
223 {
224 #if defined(_WIN32) && !defined(__CYGWIN__)
225  std::string command = file_glob;
226  replace('/', '\\', command);
227  command = "del /Q " + command;
228 #else
229  std::string command = "/bin/rm -f " + file_glob;
230 #endif
231  return std::system(command.c_str())==0;
232 }
233 
235 std::string vul_file::expand_tilde(char const* vul_filename)
236 {
237  if (!vul_filename || (std::strlen(vul_filename) == 0))
238  return "";
239 
240 #if defined(_WIN32) && !defined(__CYGWIN__)
241  // ~ meaningless on win32
242  return std::string(vul_filename);
243 #else
244 
245  if (vul_filename[0] != '~')
246  return std::string(vul_filename);
247 
248  //// ** Have a tilde, go for it
249 
250  // 1. Strip to directory only, and remove the tilde itself
251  std::string fn(vul_filename);
252  std::string dir;
253  std::string::size_type first_slash = fn.find('/');
254  if (first_slash != std::string::npos) {
255  dir = fn.substr(1, first_slash-1);
256  fn = fn.substr(first_slash, std::string::npos);
257  }
258  else {
259  dir = fn.substr(1, std::string::npos);
260  fn = "";
261  }
262  // Now, from original to (dir, vul_filename) is one of
263  // ~ "" ""
264  // ~fre "fre" ""
265  // ~/fred "" "/fred"
266  // ~user/fred "user" "/fred"
267 
268  if (dir.size() == 0) {
269  // Was just ~, use getenv(HOME)
270  char const * home_directory = getenv("HOME");
271  if (!home_directory) home_directory = "";
272  return std::string(home_directory) + fn;
273  }
274 
275  // Was ~user, Check password list for match
276  vul_user_info user(dir);
277  if (!user.ok)
278  return std::string(vul_filename);
279 
280  // Got user info
281  return user.home_directory + fn;
282 #endif
283 }
284 
285 
286 #if defined(_WIN32) && VXL_USE_WIN_WCHAR_T
287 #include <cwchar>
288 
289 std::wstring
290 vul_file::get_cwd(wchar_t* /*dummy*/)
291 {
292  constexpr int BIG = 65536;
293  wchar_t buf[BIG];
294  buf[0] = L'\0';
295  _wgetcwd(buf,BIG-1);
296  return buf;
297 }
298 
299 bool vul_file::change_directory(wchar_t const* dirname)
300 {
301  return 0 == _wchdir(dirname);
302 }
303 
304 bool vul_file::make_directory(wchar_t const* name)
305 {
306  return -1 != _wmkdir(name);
307 }
308 
309 bool vul_file::is_directory(wchar_t const* fn)
310 {
311  struct _stat fs;
312  return _wstat(fn, &fs) == 0
313  && (fs.st_mode & S_IFMT) == S_IFDIR;
314 }
315 
316 bool vul_file::is_drive(wchar_t const* fn)
317 {
318  // a drive string looks like "c:", "z:"
319  return fn
320  && iswalpha(fn[0])
321  && fn[1]==L':'
322  && fn[2]==L'\0';
323 }
324 
325 //: Make a writable directory, including any necessary parents.
326 // Returns true if successful, or if the directory already exists.
327 bool vul_file::make_directory_path(wchar_t const* filename)
328 {
329  if (is_directory(filename) || is_drive(filename)) return true;
330 
331  return make_directory_path(dirname(filename))
332  && make_directory(filename);
333 }
334 
335 bool vul_file::exists(wchar_t const* fn)
336 {
337  struct _stat fs;
338  return _wstat(fn, &fs) == 0;
339 }
340 
341 std::wstring vul_file::dirname(wchar_t const* fn)
342 {
343  std::wstring self(fn);
344 
345  std::wstring::size_type slash_index = self.find_last_of(L"\\/");
346  if (slash_index == std::wstring::npos)
347  return L".";
348 
349  return self.substr(0, slash_index);
350 }
351 
352 std::wstring vul_file::extension(wchar_t const* fn)
353 {
354  std::wstring self(fn);
355 
356  std::wstring::size_type dot_index = self.rfind(L'.');
357  if (dot_index != std::wstring::npos)
358  return self.substr(dot_index, std::wstring::npos);
359  else
360  return std::wstring();
361 }
362 
363 std::wstring vul_file::strip_directory(wchar_t const* fn)
364 {
365  std::wstring self(fn);
366 
367  std::wstring::size_type slash_index = self.find_last_of(L"\\/");
368  if (slash_index != std::wstring::npos)
369  self.erase(0, slash_index+1);
370 
371  return self;
372 }
373 
374 std::wstring vul_file::strip_extension(wchar_t const* fn)
375 {
376  std::wstring self(fn);
377 
378  std::wstring::size_type dot_index = self.rfind(L'.');
379  if (dot_index != std::wstring::npos)
380  self.erase(dot_index, std::wstring::npos);
381 
382  return self;
383 }
384 
385 std::wstring vul_file::basename(wchar_t const* fn, wchar_t const * suffix)
386 {
387  // First strip dir
388  std::wstring self(fn);
389 
390  std::wstring::size_type slash_index = self.find_last_of(L"\\/");
391 
392  if (slash_index != std::wstring::npos)
393  self.erase(0, slash_index+1);
394 
395  // Now strip suffix if any
396  if (suffix) {
397  int start = (int)self.size() - (int)wcslen(suffix);
398  if (start >= 0)
399  if (std::wstring(self.begin()+start, self.end()) == suffix)
400  self.erase(start, std::wstring::npos);
401  }
402  return self;
403 }
404 
405 #endif
Reads information about a user from the password file.
static std::string extension(char const *filename)
Return extension (including the '.
Definition: vul_file.cxx:140
static std::string basename(char const *filename, char const *suffix=nullptr)
Return basename.
Definition: vul_file.cxx:177
Reads information about a user from the password file.
Definition: vul_user_info.h:22
static bool delete_file_glob(std::string const &file_glob)
Delete 1 or more files using the Local OS preferred globbing.
Definition: vul_file.cxx:221
static bool make_directory_path(char const *filename)
Make a writable directory, including any necessary parents.
Definition: vul_file.cxx:83
A collection of miscellaneous filesystem-type utilities.
static std::string strip_directory(char const *filename)
Strips away directory of the filename.
Definition: vul_file.cxx:151
static bool change_directory(char const *dirname)
change current working directory.
Definition: vul_file.cxx:41
static std::string expand_tilde(char const *filename)
Expand any leading ~ escapes in filename.
Definition: vul_file.cxx:234
static unsigned long size(char const *filename)
Return size of vul_file.
Definition: vul_file.cxx:99
static bool is_directory(char const *filename)
Return true iff filename is a directory.
Definition: vul_file.cxx:55
static std::string get_cwd()
Return current working directory.
Definition: vul_file.cxx:31
static std::string strip_extension(char const *filename)
Strips away extension of the filename.
Definition: vul_file.cxx:166
static bool make_directory(char const *filename)
Make a writable directory.
Definition: vul_file.cxx:46
static std::time_t time_modified(char const *filename)
Definition: vul_file.cxx:62
static bool exists(char const *filename)
Return true iff filename exists. It may be any sort of file.
Definition: vul_file.cxx:108
std::string home_directory
Definition: vul_user_info.h:31
static std::string dirname(char const *filename)
Return dirname.
Definition: vul_file.cxx:124