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