/src/CMake/build-dir/Source/cmsys/SystemTools.hxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ |
3 | | #ifndef cmsys_SystemTools_hxx |
4 | | #define cmsys_SystemTools_hxx |
5 | | |
6 | | #include <cmsys/Configure.hxx> |
7 | | #include <cmsys/Status.hxx> |
8 | | |
9 | | #include <ctime> |
10 | | #include <iosfwd> |
11 | | #include <map> |
12 | | #include <string> |
13 | | #include <vector> |
14 | | |
15 | | #include <sys/types.h> |
16 | | // include sys/stat.h after sys/types.h |
17 | | #include <sys/stat.h> |
18 | | |
19 | | #if !defined(_WIN32) || defined(__CYGWIN__) |
20 | | # include <unistd.h> // For access permissions for use with access() |
21 | | #endif |
22 | | |
23 | | // Required for va_list |
24 | | #include <stdarg.h> |
25 | | // Required for FILE* |
26 | | #include <stdio.h> |
27 | | #if !defined(va_list) |
28 | | // Some compilers move va_list into the std namespace and there is no way to |
29 | | // tell that this has been done. Playing with things being included before or |
30 | | // after stdarg.h does not solve things because we do not have control over |
31 | | // what the user does. This hack solves this problem by moving va_list to our |
32 | | // own namespace that is local for kwsys. |
33 | | namespace std { |
34 | | } // Required for platforms that do not have std namespace |
35 | | namespace cmsys_VA_LIST { |
36 | | using namespace std; |
37 | | typedef va_list hack_va_list; |
38 | | } |
39 | | namespace cmsys { |
40 | | typedef cmsys_VA_LIST::hack_va_list va_list; |
41 | | } |
42 | | #endif // va_list |
43 | | |
44 | | namespace cmsys { |
45 | | |
46 | | class SystemToolsStatic; |
47 | | |
48 | | /** \class SystemToolsManager |
49 | | * \brief Use to make sure SystemTools is initialized before it is used |
50 | | * and is the last static object destroyed |
51 | | */ |
52 | | class cmsys_EXPORT SystemToolsManager |
53 | | { |
54 | | public: |
55 | | SystemToolsManager(); |
56 | | ~SystemToolsManager(); |
57 | | |
58 | | SystemToolsManager(SystemToolsManager const&) = delete; |
59 | | SystemToolsManager& operator=(SystemToolsManager const&) = delete; |
60 | | }; |
61 | | |
62 | | // This instance will show up in any translation unit that uses |
63 | | // SystemTools. It will make sure SystemTools is initialized |
64 | | // before it is used and is the last static object destroyed. |
65 | | static SystemToolsManager SystemToolsManagerInstance; |
66 | | |
67 | | // Flags for use with TestFileAccess. Use a typedef in case any operating |
68 | | // system in the future needs a special type. These are flags that may be |
69 | | // combined using the | operator. |
70 | | typedef int TestFilePermissions; |
71 | | #if defined(_WIN32) && !defined(__CYGWIN__) |
72 | | // On Windows (VC), no system header defines these constants... |
73 | | static TestFilePermissions const TEST_FILE_OK = 0; |
74 | | static TestFilePermissions const TEST_FILE_READ = 4; |
75 | | static TestFilePermissions const TEST_FILE_WRITE = 2; |
76 | | static TestFilePermissions const TEST_FILE_EXECUTE = 1; |
77 | | #else |
78 | | // Standard POSIX constants |
79 | | static TestFilePermissions const TEST_FILE_OK = F_OK; |
80 | | static TestFilePermissions const TEST_FILE_READ = R_OK; |
81 | | static TestFilePermissions const TEST_FILE_WRITE = W_OK; |
82 | | static TestFilePermissions const TEST_FILE_EXECUTE = X_OK; |
83 | | #endif |
84 | | |
85 | | /** \class SystemTools |
86 | | * \brief A collection of useful platform-independent system functions. |
87 | | */ |
88 | | class cmsys_EXPORT SystemTools |
89 | | { |
90 | | public: |
91 | | /** ----------------------------------------------------------------- |
92 | | * String Manipulation Routines |
93 | | * ----------------------------------------------------------------- |
94 | | */ |
95 | | |
96 | | /** |
97 | | * Replace symbols in str that are not valid in C identifiers as |
98 | | * defined by the 1999 standard, ie. anything except [A-Za-z0-9_]. |
99 | | * They are replaced with `_' and if the first character is a digit |
100 | | * then an underscore is prepended. Note that this can produce |
101 | | * identifiers that the standard reserves (_[A-Z].* and __.*). |
102 | | */ |
103 | | static std::string MakeCidentifier(std::string const& s); |
104 | | |
105 | | static std::string MakeCindentifier(std::string const& s) |
106 | 0 | { |
107 | 0 | return MakeCidentifier(s); |
108 | 0 | } |
109 | | |
110 | | /** |
111 | | * Replace replace all occurrences of the string in the source string. |
112 | | */ |
113 | | static void ReplaceString(std::string& source, char const* replace, |
114 | | char const* with); |
115 | | static void ReplaceString(std::string& source, std::string const& replace, |
116 | | std::string const& with); |
117 | | |
118 | | /** |
119 | | * Return a capitalized string (i.e the first letter is uppercased, |
120 | | * all other are lowercased). |
121 | | */ |
122 | | static std::string Capitalized(std::string const&); |
123 | | |
124 | | /** |
125 | | * Return a 'capitalized words' string (i.e the first letter of each word |
126 | | * is uppercased all other are left untouched though). |
127 | | */ |
128 | | static std::string CapitalizedWords(std::string const&); |
129 | | |
130 | | /** |
131 | | * Return a 'uncapitalized words' string (i.e the first letter of each word |
132 | | * is lowercased all other are left untouched though). |
133 | | */ |
134 | | static std::string UnCapitalizedWords(std::string const&); |
135 | | |
136 | | /** Return a lower-case string. */ |
137 | | static std::string LowerCase(std::string); |
138 | | |
139 | | /** Return an upper-case string. */ |
140 | | static std::string UpperCase(std::string); |
141 | | |
142 | | /** |
143 | | * Count char in string |
144 | | */ |
145 | | static size_t CountChar(char const* str, char c); |
146 | | |
147 | | /** |
148 | | * Remove some characters from a string. |
149 | | * Return a pointer to the new resulting string (allocated with 'new') |
150 | | */ |
151 | | static char* RemoveChars(char const* str, char const* toremove); |
152 | | |
153 | | /** |
154 | | * Remove remove all but 0->9, A->F characters from a string. |
155 | | * Return a pointer to the new resulting string (allocated with 'new') |
156 | | */ |
157 | | static char* RemoveCharsButUpperHex(char const* str); |
158 | | |
159 | | /** |
160 | | * Replace some characters by another character in a string (in-place) |
161 | | * Return a pointer to string |
162 | | */ |
163 | | static char* ReplaceChars(char* str, char const* toreplace, |
164 | | char replacement); |
165 | | |
166 | | /** |
167 | | * Returns true if str1 starts (respectively ends) with str2 |
168 | | */ |
169 | | static bool StringStartsWith(char const* str1, char const* str2); |
170 | | static bool StringStartsWith(std::string const& str1, char const* str2); |
171 | | static bool StringEndsWith(char const* str1, char const* str2); |
172 | | static bool StringEndsWith(std::string const& str1, char const* str2); |
173 | | |
174 | | /** |
175 | | * Returns a pointer to the last occurrence of str2 in str1 |
176 | | */ |
177 | | static char const* FindLastString(char const* str1, char const* str2); |
178 | | |
179 | | /** |
180 | | * Make a duplicate of the string similar to the strdup C function |
181 | | * but use new to create the 'new' string, so one can use |
182 | | * 'delete' to remove it. Returns 0 if the input is empty. |
183 | | */ |
184 | | static char* DuplicateString(char const* str); |
185 | | |
186 | | /** |
187 | | * Return the string cropped to a given length by removing chars in the |
188 | | * center of the string and replacing them with an ellipsis (...) |
189 | | */ |
190 | | static std::string CropString(std::string const&, size_t max_len); |
191 | | |
192 | | /** split a path by separator into an array of strings, default is /. |
193 | | If isPath is true then the string is treated like a path and if |
194 | | s starts with a / then the first element of the returned array will |
195 | | be /, so /foo/bar will be [/, foo, bar] |
196 | | */ |
197 | | static std::vector<std::string> SplitString(std::string const& s, |
198 | | char separator = '/', |
199 | | bool isPath = false); |
200 | | /** |
201 | | * Perform a case-independent string comparison. |
202 | | * Similar to POSIX's strcasecmp. |
203 | | */ |
204 | | static int Strucmp(char const* s1, char const* s2); |
205 | | |
206 | | /** |
207 | | * Perform a case-independent string comparison, but compares at most n |
208 | | * characters. Similar to POSIX's strncasecmp. |
209 | | */ |
210 | | static int Strnucmp(char const* s1, char const* s2, size_t n); |
211 | | |
212 | | /** |
213 | | * Split a string on its newlines into multiple lines |
214 | | * Return false only if the last line stored had no newline |
215 | | */ |
216 | | static bool Split(std::string const& s, std::vector<std::string>& l); |
217 | | static bool Split(std::string const& s, std::vector<std::string>& l, |
218 | | char separator); |
219 | | |
220 | | /** |
221 | | * Joins a vector of strings into a single string, with separator in between |
222 | | * each string. |
223 | | */ |
224 | | static std::string Join(std::vector<std::string> const& list, |
225 | | std::string const& separator); |
226 | | |
227 | | /** |
228 | | * Return string with space added between capitalized words |
229 | | * (i.e. EatMyShorts becomes Eat My Shorts ) |
230 | | * (note that IEatShorts becomes IEat Shorts) |
231 | | */ |
232 | | static std::string AddSpaceBetweenCapitalizedWords(std::string const&); |
233 | | |
234 | | /** |
235 | | * Append two or more strings and produce new one. |
236 | | * Programmer must 'delete []' the resulting string, which was allocated |
237 | | * with 'new'. |
238 | | * Return 0 if inputs are empty or there was an error |
239 | | */ |
240 | | static char* AppendStrings(char const* str1, char const* str2); |
241 | | static char* AppendStrings(char const* str1, char const* str2, |
242 | | char const* str3); |
243 | | |
244 | | /** |
245 | | * Estimate the length of the string that will be produced |
246 | | * from printing the given format string and arguments. The |
247 | | * returned length will always be at least as large as the string |
248 | | * that will result from printing. |
249 | | * WARNING: since va_arg is called to iterate of the argument list, |
250 | | * you will not be able to use this 'ap' anymore from the beginning. |
251 | | * It's up to you to call va_end though. |
252 | | */ |
253 | | static int EstimateFormatLength(char const* format, va_list ap); |
254 | | |
255 | | /** |
256 | | * Escape specific characters in 'str'. |
257 | | */ |
258 | | static std::string EscapeChars(char const* str, char const* chars_to_escape, |
259 | | char escape_char = '\\'); |
260 | | |
261 | | /** ----------------------------------------------------------------- |
262 | | * Filename Manipulation Routines |
263 | | * ----------------------------------------------------------------- |
264 | | */ |
265 | | |
266 | | /** |
267 | | * Replace Windows file system slashes with Unix-style slashes. |
268 | | */ |
269 | | static void ConvertToUnixSlashes(std::string& path); |
270 | | |
271 | | #ifdef _WIN32 |
272 | | /** Calls Encoding::ToWindowsExtendedPath. */ |
273 | | static std::wstring ConvertToWindowsExtendedPath(std::string const&); |
274 | | #endif |
275 | | |
276 | | /** |
277 | | * For windows this calls ConvertToWindowsOutputPath and for unix |
278 | | * it calls ConvertToUnixOutputPath |
279 | | */ |
280 | | static std::string ConvertToOutputPath(std::string const&); |
281 | | |
282 | | /** |
283 | | * Convert the path to a string that can be used in a unix makefile. |
284 | | * double slashes are removed, and spaces are escaped. |
285 | | */ |
286 | | static std::string ConvertToUnixOutputPath(std::string const&); |
287 | | |
288 | | /** |
289 | | * Convert the path to string that can be used in a windows project or |
290 | | * makefile. Double slashes are removed if they are not at the start of |
291 | | * the string, the slashes are converted to windows style backslashes, and |
292 | | * if there are spaces in the string it is double quoted. |
293 | | */ |
294 | | static std::string ConvertToWindowsOutputPath(std::string const&); |
295 | | |
296 | | /** |
297 | | * Return true if a path with the given name exists in the current directory. |
298 | | */ |
299 | | static bool PathExists(std::string const& path); |
300 | | |
301 | | /** |
302 | | * Return true if a file exists in the current directory. |
303 | | * If isFile = true, then make sure the file is a file and |
304 | | * not a directory. If isFile = false, then return true |
305 | | * if it is a file or a directory. Note that the file will |
306 | | * also be checked for read access. (Currently, this check |
307 | | * for read access is only done on POSIX systems.) |
308 | | */ |
309 | | static bool FileExists(char const* filename, bool isFile); |
310 | | static bool FileExists(std::string const& filename, bool isFile); |
311 | | static bool FileExists(char const* filename); |
312 | | static bool FileExists(std::string const& filename); |
313 | | |
314 | | /** |
315 | | * Test if a file exists and can be accessed with the requested |
316 | | * permissions. Symbolic links are followed. Returns true if |
317 | | * the access test was successful. |
318 | | * |
319 | | * On POSIX systems (including Cygwin), this maps to the access |
320 | | * function. On Windows systems, all existing files are |
321 | | * considered readable, and writable files are considered to |
322 | | * have the read-only file attribute cleared. |
323 | | */ |
324 | | static bool TestFileAccess(char const* filename, |
325 | | TestFilePermissions permissions); |
326 | | static bool TestFileAccess(std::string const& filename, |
327 | | TestFilePermissions permissions); |
328 | | /** |
329 | | * Cross platform wrapper for stat struct |
330 | | */ |
331 | | #if defined(_WIN32) && !defined(__CYGWIN__) |
332 | | typedef struct _stat64 Stat_t; |
333 | | #else |
334 | | typedef struct stat Stat_t; |
335 | | #endif |
336 | | |
337 | | /** |
338 | | * Cross platform wrapper for stat system call |
339 | | * |
340 | | * On Windows this may not work for paths longer than 250 characters |
341 | | * due to limitations of the underlying '_wstat64' call. |
342 | | */ |
343 | | static int Stat(char const* path, Stat_t* buf); |
344 | | static int Stat(std::string const& path, Stat_t* buf); |
345 | | |
346 | | /** |
347 | | * Return file length |
348 | | */ |
349 | | static unsigned long FileLength(std::string const& filename); |
350 | | |
351 | | /** |
352 | | Change the modification time or create a file |
353 | | */ |
354 | | static Status Touch(std::string const& filename, bool create); |
355 | | |
356 | | /** |
357 | | * Compare file modification times. |
358 | | * Return true for successful comparison and false for error. |
359 | | * When true is returned, result has -1, 0, +1 for |
360 | | * f1 older, same, or newer than f2. |
361 | | */ |
362 | | static Status FileTimeCompare(std::string const& f1, std::string const& f2, |
363 | | int* result); |
364 | | |
365 | | /** |
366 | | * Get the file extension (including ".") needed for an executable |
367 | | * on the current platform ("" for unix, ".exe" for Windows). |
368 | | */ |
369 | | static char const* GetExecutableExtension(); |
370 | | |
371 | | /** |
372 | | * Given a path on a Windows machine, return the actual case of |
373 | | * the path as it exists on disk. Path components that do not |
374 | | * exist on disk are returned unchanged. Relative paths are always |
375 | | * returned unchanged. Drive letters are always made upper case. |
376 | | * This does nothing on non-Windows systems but return the path. |
377 | | */ |
378 | | static std::string GetActualCaseForPath(std::string const& path); |
379 | | |
380 | | /** |
381 | | * Given the path to a program executable, get the directory part of |
382 | | * the path with the file stripped off. If there is no directory |
383 | | * part, the empty string is returned. |
384 | | */ |
385 | | static std::string GetProgramPath(std::string const&); |
386 | | static bool SplitProgramPath(std::string const& in_name, std::string& dir, |
387 | | std::string& file, bool errorReport = true); |
388 | | |
389 | | /** |
390 | | * Given a path to a file or directory, convert it to a full path. |
391 | | * This collapses away relative paths relative to the cwd argument |
392 | | * (which defaults to the current working directory). The full path |
393 | | * is returned. |
394 | | */ |
395 | | static std::string CollapseFullPath(std::string const& in_path); |
396 | | static std::string CollapseFullPath(std::string const& in_path, |
397 | | char const* in_base); |
398 | | static std::string CollapseFullPath(std::string const& in_path, |
399 | | std::string const& in_base); |
400 | | |
401 | | /** |
402 | | * Get the real path for a given path, removing all symlinks. In |
403 | | * the event of an error (non-existent path, permissions issue, |
404 | | * etc.) the original path is returned if errorMessage pointer is |
405 | | * nullptr. Otherwise empty string is returned and errorMessage |
406 | | * contains error description. |
407 | | */ |
408 | | static std::string GetRealPath(std::string const& path, |
409 | | std::string* errorMessage = nullptr); |
410 | | |
411 | | /** |
412 | | * Split a path name into its root component and the rest of the |
413 | | * path. The root component is one of the following: |
414 | | * "/" = UNIX full path |
415 | | * "c:/" = Windows full path (can be any drive letter) |
416 | | * "c:" = Windows drive-letter relative path (can be any drive letter) |
417 | | * "//" = Network path |
418 | | * "~/" = Home path for current user |
419 | | * "~u/" = Home path for user 'u' |
420 | | * "" = Relative path |
421 | | * |
422 | | * A pointer to the rest of the path after the root component is |
423 | | * returned. The root component is stored in the "root" string if |
424 | | * given. |
425 | | */ |
426 | | static char const* SplitPathRootComponent(std::string const& p, |
427 | | std::string* root = nullptr); |
428 | | |
429 | | /** |
430 | | * Split a path name into its basic components. The first component |
431 | | * always exists and is the root returned by SplitPathRootComponent. |
432 | | * The remaining components form the path. If there is a trailing |
433 | | * slash then the last component is the empty string. The |
434 | | * components can be recombined as "c[0]c[1]/c[2]/.../c[n]" to |
435 | | * produce the original path. Home directory references are |
436 | | * automatically expanded if expand_home_dir is true and this |
437 | | * platform supports them. |
438 | | * |
439 | | * This does *not* normalize the input path. All components are |
440 | | * preserved, including empty ones. Typically callers should use |
441 | | * this only on paths that have already been normalized. |
442 | | */ |
443 | | static void SplitPath(std::string const& p, |
444 | | std::vector<std::string>& components, |
445 | | bool expand_home_dir = true); |
446 | | |
447 | | /** |
448 | | * Join components of a path name into a single string. See |
449 | | * SplitPath for the format of the components. |
450 | | * |
451 | | * This does *not* normalize the input path. All components are |
452 | | * preserved, including empty ones. Typically callers should use |
453 | | * this only on paths that have already been normalized. |
454 | | */ |
455 | | static std::string JoinPath(std::vector<std::string> const& components); |
456 | | static std::string JoinPath(std::vector<std::string>::const_iterator first, |
457 | | std::vector<std::string>::const_iterator last); |
458 | | |
459 | | /** |
460 | | * Compare a path or components of a path. |
461 | | */ |
462 | | static bool ComparePath(std::string const& c1, std::string const& c2); |
463 | | |
464 | | /** |
465 | | * Return path of a full filename (no trailing slashes) |
466 | | */ |
467 | | static std::string GetFilenamePath(std::string const&); |
468 | | |
469 | | /** |
470 | | * Return file name of a full filename (i.e. file name without path) |
471 | | */ |
472 | | static std::string GetFilenameName(std::string const&); |
473 | | |
474 | | /** |
475 | | * Return longest file extension of a full filename (dot included) |
476 | | */ |
477 | | static std::string GetFilenameExtension(std::string const&); |
478 | | |
479 | | /** |
480 | | * Return shortest file extension of a full filename (dot included) |
481 | | */ |
482 | | static std::string GetFilenameLastExtension(std::string const& filename); |
483 | | |
484 | | /** |
485 | | * Return file name without extension of a full filename |
486 | | */ |
487 | | static std::string GetFilenameWithoutExtension(std::string const&); |
488 | | |
489 | | /** |
490 | | * Return file name without its last (shortest) extension |
491 | | */ |
492 | | static std::string GetFilenameWithoutLastExtension(std::string const&); |
493 | | |
494 | | /** |
495 | | * Return whether the path represents a full path (not relative) |
496 | | */ |
497 | | static bool FileIsFullPath(std::string const&); |
498 | | static bool FileIsFullPath(char const*); |
499 | | |
500 | | /** |
501 | | * For windows return the short path for the given path, |
502 | | * Unix just a pass through |
503 | | */ |
504 | | static Status GetShortPath(std::string const& path, std::string& result); |
505 | | |
506 | | /** |
507 | | * Read line from file. Make sure to read a full line and truncates it if |
508 | | * requested via sizeLimit. Returns true if any data were read before the |
509 | | * end-of-file was reached. If the has_newline argument is specified, it will |
510 | | * be true when the line read had a newline character. |
511 | | */ |
512 | | static bool GetLineFromStream( |
513 | | std::istream& istr, std::string& line, bool* has_newline = nullptr, |
514 | | std::string::size_type sizeLimit = std::string::npos); |
515 | | |
516 | | /** |
517 | | * Get the parent directory of the directory or file |
518 | | */ |
519 | | static std::string GetParentDirectory(std::string const& fileOrDir); |
520 | | |
521 | | /** |
522 | | * Check if the given file or directory is in subdirectory of dir |
523 | | */ |
524 | | static bool IsSubDirectory(std::string const& fileOrDir, |
525 | | std::string const& dir); |
526 | | |
527 | | /** ----------------------------------------------------------------- |
528 | | * File Manipulation Routines |
529 | | * ----------------------------------------------------------------- |
530 | | */ |
531 | | |
532 | | /** |
533 | | * Open a file considering unicode. On Windows, if 'e' is present in |
534 | | * mode it is first discarded. |
535 | | */ |
536 | | static FILE* Fopen(std::string const& file, char const* mode); |
537 | | |
538 | | /** |
539 | | * Visual C++ does not define mode_t. |
540 | | */ |
541 | | #if defined(_MSC_VER) |
542 | | typedef unsigned short mode_t; |
543 | | #endif |
544 | | |
545 | | /** |
546 | | * Make a new directory if it is not there. This function |
547 | | * can make a full path even if none of the directories existed |
548 | | * prior to calling this function. |
549 | | */ |
550 | | static Status MakeDirectory(char const* path, mode_t const* mode = nullptr); |
551 | | static Status MakeDirectory(std::string const& path, |
552 | | mode_t const* mode = nullptr); |
553 | | |
554 | | /** |
555 | | * Represent the result of a file copy operation. |
556 | | * This is the result 'Status' and, if the operation failed, |
557 | | * an indication of whether the error occurred on the source |
558 | | * or destination path. |
559 | | */ |
560 | | struct CopyStatus : public Status |
561 | | { |
562 | | enum WhichPath |
563 | | { |
564 | | NoPath, |
565 | | SourcePath, |
566 | | DestPath, |
567 | | }; |
568 | 0 | CopyStatus() = default; |
569 | | CopyStatus(Status s, WhichPath p) |
570 | 0 | : Status(s) |
571 | 0 | , Path(p) |
572 | 0 | { |
573 | 0 | } |
574 | | WhichPath Path = NoPath; |
575 | | }; |
576 | | |
577 | | /** |
578 | | * Copy the source file to the destination file only |
579 | | * if the two files differ. |
580 | | */ |
581 | | static CopyStatus CopyFileIfDifferent(std::string const& source, |
582 | | std::string const& destination); |
583 | | |
584 | | /** |
585 | | * Copy the source file to the destination file only |
586 | | * if the source file is newer than the destination file. |
587 | | */ |
588 | | static CopyStatus CopyFileIfNewer(std::string const& source, |
589 | | std::string const& destination); |
590 | | |
591 | | /** |
592 | | * Compare the contents of two files. Return true if different |
593 | | */ |
594 | | static bool FilesDiffer(std::string const& source, |
595 | | std::string const& destination); |
596 | | |
597 | | /** |
598 | | * Compare the contents of two files, ignoring line ending differences. |
599 | | * Return true if different |
600 | | */ |
601 | | static bool TextFilesDiffer(std::string const& path1, |
602 | | std::string const& path2); |
603 | | |
604 | | /** |
605 | | * Blockwise copy source to destination file |
606 | | */ |
607 | | static CopyStatus CopyFileContentBlockwise(std::string const& source, |
608 | | std::string const& destination); |
609 | | /** |
610 | | * Clone the source file to the destination file |
611 | | */ |
612 | | static CopyStatus CloneFileContent(std::string const& source, |
613 | | std::string const& destination); |
614 | | |
615 | | /** |
616 | | * Object encapsulating a unique identifier for a file |
617 | | * or directory |
618 | | */ |
619 | | #ifdef _WIN32 |
620 | | class WindowsFileId |
621 | | { |
622 | | public: |
623 | | WindowsFileId() = default; |
624 | | WindowsFileId(unsigned long volumeSerialNumber, |
625 | | unsigned long fileIndexHigh, unsigned long fileIndexLow); |
626 | | |
627 | | bool operator==(WindowsFileId const& o) const; |
628 | | bool operator!=(WindowsFileId const& o) const; |
629 | | |
630 | | private: |
631 | | unsigned long m_volumeSerialNumber; |
632 | | unsigned long m_fileIndexHigh; |
633 | | unsigned long m_fileIndexLow; |
634 | | }; |
635 | | using FileId = WindowsFileId; |
636 | | #else |
637 | | class UnixFileId |
638 | | { |
639 | | public: |
640 | | UnixFileId() = default; |
641 | | UnixFileId(dev_t volumeSerialNumber, ino_t fileSerialNumber, |
642 | | off_t fileSize); |
643 | | |
644 | | bool operator==(UnixFileId const& o) const; |
645 | | bool operator!=(UnixFileId const& o) const; |
646 | | |
647 | | private: |
648 | | dev_t m_volumeSerialNumber; |
649 | | ino_t m_fileSerialNumber; |
650 | | off_t m_fileSize; |
651 | | }; |
652 | | using FileId = UnixFileId; |
653 | | #endif |
654 | | |
655 | | /** |
656 | | * Outputs a FileId for the given file or directory. |
657 | | * Returns true on success, false on failure |
658 | | */ |
659 | | static bool GetFileId(std::string const& file, FileId& id); |
660 | | |
661 | | /** |
662 | | * Return true if the two files are the same file |
663 | | */ |
664 | | static bool SameFile(std::string const& file1, std::string const& file2); |
665 | | |
666 | | /** |
667 | | * Copy a file. |
668 | | */ |
669 | | static CopyStatus CopyFileAlways(std::string const& source, |
670 | | std::string const& destination); |
671 | | |
672 | | enum class CopyWhen |
673 | | { |
674 | | Always, |
675 | | OnlyIfDifferent, |
676 | | OnlyIfNewer, |
677 | | }; |
678 | | |
679 | | /** |
680 | | * Copy a file with specified copy behavior. |
681 | | */ |
682 | | static CopyStatus CopyAFile(std::string const& source, |
683 | | std::string const& destination, |
684 | | CopyWhen when = CopyWhen::Always); |
685 | | static CopyStatus CopyAFile(std::string const& source, |
686 | | std::string const& destination, bool always); |
687 | | |
688 | | /** |
689 | | * Copy content directory to another directory with all files and |
690 | | * subdirectories. The "when" argument controls when files are copied: |
691 | | * Always: all files are always copied. |
692 | | * OnlyIfDifferent: only files that have changed are copied. |
693 | | * OnlyIfNewer: only files that are newer than the destination are copied. |
694 | | */ |
695 | | static Status CopyADirectory(std::string const& source, |
696 | | std::string const& destination, |
697 | | CopyWhen when = CopyWhen::Always); |
698 | | static Status CopyADirectory(std::string const& source, |
699 | | std::string const& destination, bool always); |
700 | | |
701 | | /** |
702 | | * Remove a file |
703 | | */ |
704 | | static Status RemoveFile(std::string const& source); |
705 | | |
706 | | /** |
707 | | * Remove a directory |
708 | | */ |
709 | | static Status RemoveADirectory(std::string const& source); |
710 | | |
711 | | /** |
712 | | * Get the maximum full file path length |
713 | | */ |
714 | | static size_t GetMaximumFilePathLength(); |
715 | | |
716 | | /** |
717 | | * Find a file in the system PATH, with optional extra paths |
718 | | */ |
719 | | static std::string FindFile( |
720 | | std::string const& name, |
721 | | std::vector<std::string> const& path = std::vector<std::string>(), |
722 | | bool no_system_path = false); |
723 | | |
724 | | /** |
725 | | * Find a directory in the system PATH, with optional extra paths |
726 | | */ |
727 | | static std::string FindDirectory( |
728 | | std::string const& name, |
729 | | std::vector<std::string> const& path = std::vector<std::string>(), |
730 | | bool no_system_path = false); |
731 | | |
732 | | /** |
733 | | * Find an executable in the system PATH, with optional extra paths |
734 | | */ |
735 | | static std::string FindProgram( |
736 | | std::string const& name, |
737 | | std::vector<std::string> const& path = std::vector<std::string>(), |
738 | | bool no_system_path = false); |
739 | | |
740 | | /** |
741 | | * Return true if the file is a directory |
742 | | */ |
743 | | static bool FileIsDirectory(std::string const& name); |
744 | | |
745 | | /** |
746 | | * Return true if the file is an executable |
747 | | */ |
748 | | static bool FileIsExecutable(std::string const& name); |
749 | | |
750 | | #if defined(_WIN32) |
751 | | /** |
752 | | * Return true if the file with FileAttributes `attr` is a symlink |
753 | | * Only available on Windows. This avoids an expensive `GetFileAttributesW` |
754 | | * call. |
755 | | */ |
756 | | static bool FileIsSymlinkWithAttr(std::wstring const& path, |
757 | | unsigned long attr); |
758 | | #endif |
759 | | |
760 | | /** |
761 | | * Return true if the file is a symlink |
762 | | */ |
763 | | static bool FileIsSymlink(std::string const& name); |
764 | | |
765 | | /** |
766 | | * Return true if the file is a FIFO |
767 | | */ |
768 | | static bool FileIsFIFO(std::string const& name); |
769 | | |
770 | | /** |
771 | | * Return true if the file has a given signature (first set of bytes) |
772 | | */ |
773 | | static bool FileHasSignature(char const* filename, char const* signature, |
774 | | long offset = 0); |
775 | | |
776 | | /** |
777 | | * Attempt to detect and return the type of a file. |
778 | | * Up to 'length' bytes are read from the file, if more than 'percent_bin' % |
779 | | * of the bytes are non-textual elements, the file is considered binary, |
780 | | * otherwise textual. Textual elements are bytes in the ASCII [0x20, 0x7E] |
781 | | * range, but also \\n, \\r, \\t. |
782 | | * The algorithm is simplistic, and should probably check for usual file |
783 | | * extensions, 'magic' signature, unicode, etc. |
784 | | */ |
785 | | enum FileTypeEnum |
786 | | { |
787 | | FileTypeUnknown, |
788 | | FileTypeBinary, |
789 | | FileTypeText |
790 | | }; |
791 | | static SystemTools::FileTypeEnum DetectFileType(char const* filename, |
792 | | unsigned long length = 256, |
793 | | double percent_bin = 0.05); |
794 | | |
795 | | /** |
796 | | * Read the contents of a symbolic link. Returns whether reading |
797 | | * succeeded. |
798 | | */ |
799 | | static Status ReadSymlink(std::string const& newName, std::string& origName); |
800 | | |
801 | | /** |
802 | | * Try to locate the file 'filename' in the directory 'dir'. |
803 | | * If 'filename' is a fully qualified filename, the basename of the file is |
804 | | * used to check for its existence in 'dir'. |
805 | | * If 'dir' is not a directory, GetFilenamePath() is called on 'dir' to |
806 | | * get its directory first (thus, you can pass a filename as 'dir', as |
807 | | * a convenience). |
808 | | * 'filename_found' is assigned the fully qualified name/path of the file |
809 | | * if it is found (not touched otherwise). |
810 | | * If 'try_filename_dirs' is true, try to find the file using the |
811 | | * components of its path, i.e. if we are looking for c:/foo/bar/bill.txt, |
812 | | * first look for bill.txt in 'dir', then in 'dir'/bar, then in 'dir'/foo/bar |
813 | | * etc. |
814 | | * Return true if the file was found, false otherwise. |
815 | | */ |
816 | | static bool LocateFileInDir(char const* filename, char const* dir, |
817 | | std::string& filename_found, |
818 | | int try_filename_dirs = 0); |
819 | | |
820 | | /** compute the relative path from local to remote. local must |
821 | | be a directory. remote can be a file or a directory. |
822 | | Both remote and local must be full paths. Basically, if |
823 | | you are in directory local and you want to access the file in remote |
824 | | what is the relative path to do that. For example: |
825 | | /a/b/c/d to /a/b/c1/d1 -> ../../c1/d1 |
826 | | from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp |
827 | | */ |
828 | | static std::string RelativePath(std::string const& local, |
829 | | std::string const& remote); |
830 | | |
831 | | /** |
832 | | * Return file's modified time |
833 | | */ |
834 | | static long int ModifiedTime(std::string const& filename); |
835 | | |
836 | | /** |
837 | | * Return file's creation time (Win32: works only for NTFS, not FAT) |
838 | | */ |
839 | | static long int CreationTime(std::string const& filename); |
840 | | |
841 | | /** |
842 | | * Get and set permissions of the file. If honor_umask is set, the umask |
843 | | * is queried and applied to the given permissions. Returns false if |
844 | | * failure. |
845 | | * |
846 | | * WARNING: A non-thread-safe method is currently used to get the umask |
847 | | * if a honor_umask parameter is set to true. |
848 | | */ |
849 | | static Status GetPermissions(char const* file, mode_t& mode); |
850 | | static Status GetPermissions(std::string const& file, mode_t& mode); |
851 | | static Status SetPermissions(char const* file, mode_t mode, |
852 | | bool honor_umask = false); |
853 | | static Status SetPermissions(std::string const& file, mode_t mode, |
854 | | bool honor_umask = false); |
855 | | |
856 | | /** ----------------------------------------------------------------- |
857 | | * Time Manipulation Routines |
858 | | * ----------------------------------------------------------------- |
859 | | */ |
860 | | |
861 | | /** Get time as local time (thread-safe). */ |
862 | | static std::tm LocalTime(std::time_t timep); |
863 | | |
864 | | /** Get time as UTC time (thread-safe). */ |
865 | | static std::tm GMTime(std::time_t timep); |
866 | | |
867 | | /** Get current time in seconds since Posix Epoch (Jan 1, 1970). */ |
868 | | static double GetTime(); |
869 | | |
870 | | /** |
871 | | * Get current date/time |
872 | | */ |
873 | | static std::string GetCurrentDateTime(char const* format); |
874 | | |
875 | | /** ----------------------------------------------------------------- |
876 | | * Registry Manipulation Routines |
877 | | * ----------------------------------------------------------------- |
878 | | */ |
879 | | |
880 | | /** |
881 | | * Specify access to the 32-bit or 64-bit application view of |
882 | | * registry values. The default is to match the currently running |
883 | | * binary type. |
884 | | */ |
885 | | enum KeyWOW64 |
886 | | { |
887 | | KeyWOW64_Default, |
888 | | KeyWOW64_32, |
889 | | KeyWOW64_64 |
890 | | }; |
891 | | |
892 | | /** |
893 | | * Get a list of subkeys. |
894 | | */ |
895 | | static bool GetRegistrySubKeys(std::string const& key, |
896 | | std::vector<std::string>& subkeys, |
897 | | KeyWOW64 view = KeyWOW64_Default); |
898 | | |
899 | | /** |
900 | | * Read a registry value |
901 | | */ |
902 | | static bool ReadRegistryValue(std::string const& key, std::string& value, |
903 | | KeyWOW64 view = KeyWOW64_Default); |
904 | | |
905 | | /** |
906 | | * Write a registry value |
907 | | */ |
908 | | static bool WriteRegistryValue(std::string const& key, |
909 | | std::string const& value, |
910 | | KeyWOW64 view = KeyWOW64_Default); |
911 | | |
912 | | /** |
913 | | * Delete a registry value |
914 | | */ |
915 | | static bool DeleteRegistryValue(std::string const& key, |
916 | | KeyWOW64 view = KeyWOW64_Default); |
917 | | |
918 | | /** ----------------------------------------------------------------- |
919 | | * Environment Manipulation Routines |
920 | | * ----------------------------------------------------------------- |
921 | | */ |
922 | | |
923 | | /** |
924 | | * Add the paths from the environment variable PATH to the |
925 | | * string vector passed in. If env is set then the value |
926 | | * of env will be used instead of PATH. |
927 | | */ |
928 | | static void GetPath(std::vector<std::string>& path, |
929 | | char const* env = nullptr); |
930 | | |
931 | | /** |
932 | | * Read an environment variable |
933 | | */ |
934 | | static char const* GetEnv(char const* key); |
935 | | static char const* GetEnv(std::string const& key); |
936 | | static bool GetEnv(char const* key, std::string& result); |
937 | | static bool GetEnv(std::string const& key, std::string& result); |
938 | | static bool HasEnv(char const* key); |
939 | | static bool HasEnv(std::string const& key); |
940 | | |
941 | | /** Put a string into the environment |
942 | | of the form var=value */ |
943 | | static bool PutEnv(std::string const& env); |
944 | | |
945 | | /** Remove a string from the environment. |
946 | | Input is of the form "var" or "var=value" (value is ignored). */ |
947 | | static bool UnPutEnv(std::string const& env); |
948 | | |
949 | | /** |
950 | | * Get current working directory CWD |
951 | | */ |
952 | | static std::string GetCurrentWorkingDirectory(); |
953 | | |
954 | | /** |
955 | | * Change directory to the directory specified |
956 | | */ |
957 | | static Status ChangeDirectory(std::string const& dir); |
958 | | |
959 | | /** |
960 | | * Get the result of strerror(errno) |
961 | | */ |
962 | | static std::string GetLastSystemError(); |
963 | | |
964 | | /** |
965 | | * When building DEBUG with MSVC, this enables a hook that prevents |
966 | | * error dialogs from popping up if the program is being run from |
967 | | * DART. |
968 | | */ |
969 | | static void EnableMSVCDebugHook(); |
970 | | |
971 | | /** |
972 | | * Get the width of the terminal window. The code may or may not work, so |
973 | | * make sure you have some reasonable defaults prepared if the code returns |
974 | | * some bogus size. |
975 | | */ |
976 | | static int GetTerminalWidth(); |
977 | | |
978 | | /** |
979 | | * Delay the execution for a specified amount of time specified |
980 | | * in milliseconds |
981 | | */ |
982 | | static void Delay(unsigned int msec); |
983 | | |
984 | | /** |
985 | | * Get the operating system name and version |
986 | | * This is implemented for Win32 only for the moment |
987 | | */ |
988 | | static std::string GetOperatingSystemNameAndVersion(); |
989 | | |
990 | | /** ----------------------------------------------------------------- |
991 | | * URL Manipulation Routines |
992 | | * ----------------------------------------------------------------- |
993 | | */ |
994 | | |
995 | | /** |
996 | | * Parse a character string : |
997 | | * protocol://dataglom |
998 | | * and fill protocol as appropriate. |
999 | | * decode the dataglom using DecodeURL if set to true. |
1000 | | * Return false if the URL does not have the required form, true otherwise. |
1001 | | */ |
1002 | | static bool ParseURLProtocol(std::string const& URL, std::string& protocol, |
1003 | | std::string& dataglom, bool decode = false); |
1004 | | |
1005 | | /** |
1006 | | * Parse a string (a URL without protocol prefix) with the form: |
1007 | | * protocol://[[username[':'password]'@']hostname[':'dataport]]'/'[datapath] |
1008 | | * and fill protocol, username, password, hostname, dataport, and datapath |
1009 | | * when values are found. |
1010 | | * decode all string except the protocol using DecodeUrl if set to true. |
1011 | | * Return true if the string matches the format; false otherwise. |
1012 | | */ |
1013 | | static bool ParseURL(std::string const& URL, std::string& protocol, |
1014 | | std::string& username, std::string& password, |
1015 | | std::string& hostname, std::string& dataport, |
1016 | | std::string& datapath, bool decode = false); |
1017 | | |
1018 | | /** |
1019 | | * Decode the percent-encoded string from an URL or an URI |
1020 | | * into their correct char values. |
1021 | | * Does not perform any other sort of validation. |
1022 | | * Return the decoded string |
1023 | | */ |
1024 | | static std::string DecodeURL(std::string const& url); |
1025 | | |
1026 | | private: |
1027 | | static void ClassInitialize(); |
1028 | | static void ClassFinalize(); |
1029 | | |
1030 | | /** |
1031 | | * This method prevents warning on SGI |
1032 | | */ |
1033 | | SystemToolsManager* GetSystemToolsManager() |
1034 | 0 | { |
1035 | 0 | return &SystemToolsManagerInstance; |
1036 | 0 | } |
1037 | | |
1038 | | friend class SystemToolsStatic; |
1039 | | friend class SystemToolsManager; |
1040 | | }; |
1041 | | |
1042 | | } // namespace cmsys |
1043 | | |
1044 | | #endif |