/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 | | */ |
203 | | static int Strucmp(char const* s1, char const* s2); |
204 | | |
205 | | /** |
206 | | * Split a string on its newlines into multiple lines |
207 | | * Return false only if the last line stored had no newline |
208 | | */ |
209 | | static bool Split(std::string const& s, std::vector<std::string>& l); |
210 | | static bool Split(std::string const& s, std::vector<std::string>& l, |
211 | | char separator); |
212 | | |
213 | | /** |
214 | | * Joins a vector of strings into a single string, with separator in between |
215 | | * each string. |
216 | | */ |
217 | | static std::string Join(std::vector<std::string> const& list, |
218 | | std::string const& separator); |
219 | | |
220 | | /** |
221 | | * Return string with space added between capitalized words |
222 | | * (i.e. EatMyShorts becomes Eat My Shorts ) |
223 | | * (note that IEatShorts becomes IEat Shorts) |
224 | | */ |
225 | | static std::string AddSpaceBetweenCapitalizedWords(std::string const&); |
226 | | |
227 | | /** |
228 | | * Append two or more strings and produce new one. |
229 | | * Programmer must 'delete []' the resulting string, which was allocated |
230 | | * with 'new'. |
231 | | * Return 0 if inputs are empty or there was an error |
232 | | */ |
233 | | static char* AppendStrings(char const* str1, char const* str2); |
234 | | static char* AppendStrings(char const* str1, char const* str2, |
235 | | char const* str3); |
236 | | |
237 | | /** |
238 | | * Estimate the length of the string that will be produced |
239 | | * from printing the given format string and arguments. The |
240 | | * returned length will always be at least as large as the string |
241 | | * that will result from printing. |
242 | | * WARNING: since va_arg is called to iterate of the argument list, |
243 | | * you will not be able to use this 'ap' anymore from the beginning. |
244 | | * It's up to you to call va_end though. |
245 | | */ |
246 | | static int EstimateFormatLength(char const* format, va_list ap); |
247 | | |
248 | | /** |
249 | | * Escape specific characters in 'str'. |
250 | | */ |
251 | | static std::string EscapeChars(char const* str, char const* chars_to_escape, |
252 | | char escape_char = '\\'); |
253 | | |
254 | | /** ----------------------------------------------------------------- |
255 | | * Filename Manipulation Routines |
256 | | * ----------------------------------------------------------------- |
257 | | */ |
258 | | |
259 | | /** |
260 | | * Replace Windows file system slashes with Unix-style slashes. |
261 | | */ |
262 | | static void ConvertToUnixSlashes(std::string& path); |
263 | | |
264 | | #ifdef _WIN32 |
265 | | /** Calls Encoding::ToWindowsExtendedPath. */ |
266 | | static std::wstring ConvertToWindowsExtendedPath(std::string const&); |
267 | | #endif |
268 | | |
269 | | /** |
270 | | * For windows this calls ConvertToWindowsOutputPath and for unix |
271 | | * it calls ConvertToUnixOutputPath |
272 | | */ |
273 | | static std::string ConvertToOutputPath(std::string const&); |
274 | | |
275 | | /** |
276 | | * Convert the path to a string that can be used in a unix makefile. |
277 | | * double slashes are removed, and spaces are escaped. |
278 | | */ |
279 | | static std::string ConvertToUnixOutputPath(std::string const&); |
280 | | |
281 | | /** |
282 | | * Convert the path to string that can be used in a windows project or |
283 | | * makefile. Double slashes are removed if they are not at the start of |
284 | | * the string, the slashes are converted to windows style backslashes, and |
285 | | * if there are spaces in the string it is double quoted. |
286 | | */ |
287 | | static std::string ConvertToWindowsOutputPath(std::string const&); |
288 | | |
289 | | /** |
290 | | * Return true if a path with the given name exists in the current directory. |
291 | | */ |
292 | | static bool PathExists(std::string const& path); |
293 | | |
294 | | /** |
295 | | * Return true if a file exists in the current directory. |
296 | | * If isFile = true, then make sure the file is a file and |
297 | | * not a directory. If isFile = false, then return true |
298 | | * if it is a file or a directory. Note that the file will |
299 | | * also be checked for read access. (Currently, this check |
300 | | * for read access is only done on POSIX systems.) |
301 | | */ |
302 | | static bool FileExists(char const* filename, bool isFile); |
303 | | static bool FileExists(std::string const& filename, bool isFile); |
304 | | static bool FileExists(char const* filename); |
305 | | static bool FileExists(std::string const& filename); |
306 | | |
307 | | /** |
308 | | * Test if a file exists and can be accessed with the requested |
309 | | * permissions. Symbolic links are followed. Returns true if |
310 | | * the access test was successful. |
311 | | * |
312 | | * On POSIX systems (including Cygwin), this maps to the access |
313 | | * function. On Windows systems, all existing files are |
314 | | * considered readable, and writable files are considered to |
315 | | * have the read-only file attribute cleared. |
316 | | */ |
317 | | static bool TestFileAccess(char const* filename, |
318 | | TestFilePermissions permissions); |
319 | | static bool TestFileAccess(std::string const& filename, |
320 | | TestFilePermissions permissions); |
321 | | /** |
322 | | * Cross platform wrapper for stat struct |
323 | | */ |
324 | | #if defined(_WIN32) && !defined(__CYGWIN__) |
325 | | typedef struct _stat64 Stat_t; |
326 | | #else |
327 | | typedef struct stat Stat_t; |
328 | | #endif |
329 | | |
330 | | /** |
331 | | * Cross platform wrapper for stat system call |
332 | | * |
333 | | * On Windows this may not work for paths longer than 250 characters |
334 | | * due to limitations of the underlying '_wstat64' call. |
335 | | */ |
336 | | static int Stat(char const* path, Stat_t* buf); |
337 | | static int Stat(std::string const& path, Stat_t* buf); |
338 | | |
339 | | /** |
340 | | * Return file length |
341 | | */ |
342 | | static unsigned long FileLength(std::string const& filename); |
343 | | |
344 | | /** |
345 | | Change the modification time or create a file |
346 | | */ |
347 | | static Status Touch(std::string const& filename, bool create); |
348 | | |
349 | | /** |
350 | | * Compare file modification times. |
351 | | * Return true for successful comparison and false for error. |
352 | | * When true is returned, result has -1, 0, +1 for |
353 | | * f1 older, same, or newer than f2. |
354 | | */ |
355 | | static Status FileTimeCompare(std::string const& f1, std::string const& f2, |
356 | | int* result); |
357 | | |
358 | | /** |
359 | | * Get the file extension (including ".") needed for an executable |
360 | | * on the current platform ("" for unix, ".exe" for Windows). |
361 | | */ |
362 | | static char const* GetExecutableExtension(); |
363 | | |
364 | | /** |
365 | | * Given a path on a Windows machine, return the actual case of |
366 | | * the path as it exists on disk. Path components that do not |
367 | | * exist on disk are returned unchanged. Relative paths are always |
368 | | * returned unchanged. Drive letters are always made upper case. |
369 | | * This does nothing on non-Windows systems but return the path. |
370 | | */ |
371 | | static std::string GetActualCaseForPath(std::string const& path); |
372 | | |
373 | | /** |
374 | | * Given the path to a program executable, get the directory part of |
375 | | * the path with the file stripped off. If there is no directory |
376 | | * part, the empty string is returned. |
377 | | */ |
378 | | static std::string GetProgramPath(std::string const&); |
379 | | static bool SplitProgramPath(std::string const& in_name, std::string& dir, |
380 | | std::string& file, bool errorReport = true); |
381 | | |
382 | | /** |
383 | | * Given a path to a file or directory, convert it to a full path. |
384 | | * This collapses away relative paths relative to the cwd argument |
385 | | * (which defaults to the current working directory). The full path |
386 | | * is returned. |
387 | | */ |
388 | | static std::string CollapseFullPath(std::string const& in_path); |
389 | | static std::string CollapseFullPath(std::string const& in_path, |
390 | | char const* in_base); |
391 | | static std::string CollapseFullPath(std::string const& in_path, |
392 | | std::string const& in_base); |
393 | | |
394 | | /** |
395 | | * Get the real path for a given path, removing all symlinks. In |
396 | | * the event of an error (non-existent path, permissions issue, |
397 | | * etc.) the original path is returned if errorMessage pointer is |
398 | | * nullptr. Otherwise empty string is returned and errorMessage |
399 | | * contains error description. |
400 | | */ |
401 | | static std::string GetRealPath(std::string const& path, |
402 | | std::string* errorMessage = nullptr); |
403 | | |
404 | | /** |
405 | | * Split a path name into its root component and the rest of the |
406 | | * path. The root component is one of the following: |
407 | | * "/" = UNIX full path |
408 | | * "c:/" = Windows full path (can be any drive letter) |
409 | | * "c:" = Windows drive-letter relative path (can be any drive letter) |
410 | | * "//" = Network path |
411 | | * "~/" = Home path for current user |
412 | | * "~u/" = Home path for user 'u' |
413 | | * "" = Relative path |
414 | | * |
415 | | * A pointer to the rest of the path after the root component is |
416 | | * returned. The root component is stored in the "root" string if |
417 | | * given. |
418 | | */ |
419 | | static char const* SplitPathRootComponent(std::string const& p, |
420 | | std::string* root = nullptr); |
421 | | |
422 | | /** |
423 | | * Split a path name into its basic components. The first component |
424 | | * always exists and is the root returned by SplitPathRootComponent. |
425 | | * The remaining components form the path. If there is a trailing |
426 | | * slash then the last component is the empty string. The |
427 | | * components can be recombined as "c[0]c[1]/c[2]/.../c[n]" to |
428 | | * produce the original path. Home directory references are |
429 | | * automatically expanded if expand_home_dir is true and this |
430 | | * platform supports them. |
431 | | * |
432 | | * This does *not* normalize the input path. All components are |
433 | | * preserved, including empty ones. Typically callers should use |
434 | | * this only on paths that have already been normalized. |
435 | | */ |
436 | | static void SplitPath(std::string const& p, |
437 | | std::vector<std::string>& components, |
438 | | bool expand_home_dir = true); |
439 | | |
440 | | /** |
441 | | * Join components of a path name into a single string. See |
442 | | * SplitPath for the format of the components. |
443 | | * |
444 | | * This does *not* normalize the input path. All components are |
445 | | * preserved, including empty ones. Typically callers should use |
446 | | * this only on paths that have already been normalized. |
447 | | */ |
448 | | static std::string JoinPath(std::vector<std::string> const& components); |
449 | | static std::string JoinPath(std::vector<std::string>::const_iterator first, |
450 | | std::vector<std::string>::const_iterator last); |
451 | | |
452 | | /** |
453 | | * Compare a path or components of a path. |
454 | | */ |
455 | | static bool ComparePath(std::string const& c1, std::string const& c2); |
456 | | |
457 | | /** |
458 | | * Return path of a full filename (no trailing slashes) |
459 | | */ |
460 | | static std::string GetFilenamePath(std::string const&); |
461 | | |
462 | | /** |
463 | | * Return file name of a full filename (i.e. file name without path) |
464 | | */ |
465 | | static std::string GetFilenameName(std::string const&); |
466 | | |
467 | | /** |
468 | | * Return longest file extension of a full filename (dot included) |
469 | | */ |
470 | | static std::string GetFilenameExtension(std::string const&); |
471 | | |
472 | | /** |
473 | | * Return shortest file extension of a full filename (dot included) |
474 | | */ |
475 | | static std::string GetFilenameLastExtension(std::string const& filename); |
476 | | |
477 | | /** |
478 | | * Return file name without extension of a full filename |
479 | | */ |
480 | | static std::string GetFilenameWithoutExtension(std::string const&); |
481 | | |
482 | | /** |
483 | | * Return file name without its last (shortest) extension |
484 | | */ |
485 | | static std::string GetFilenameWithoutLastExtension(std::string const&); |
486 | | |
487 | | /** |
488 | | * Return whether the path represents a full path (not relative) |
489 | | */ |
490 | | static bool FileIsFullPath(std::string const&); |
491 | | static bool FileIsFullPath(char const*); |
492 | | |
493 | | /** |
494 | | * For windows return the short path for the given path, |
495 | | * Unix just a pass through |
496 | | */ |
497 | | static Status GetShortPath(std::string const& path, std::string& result); |
498 | | |
499 | | /** |
500 | | * Read line from file. Make sure to read a full line and truncates it if |
501 | | * requested via sizeLimit. Returns true if any data were read before the |
502 | | * end-of-file was reached. If the has_newline argument is specified, it will |
503 | | * be true when the line read had a newline character. |
504 | | */ |
505 | | static bool GetLineFromStream( |
506 | | std::istream& istr, std::string& line, bool* has_newline = nullptr, |
507 | | std::string::size_type sizeLimit = std::string::npos); |
508 | | |
509 | | /** |
510 | | * Get the parent directory of the directory or file |
511 | | */ |
512 | | static std::string GetParentDirectory(std::string const& fileOrDir); |
513 | | |
514 | | /** |
515 | | * Check if the given file or directory is in subdirectory of dir |
516 | | */ |
517 | | static bool IsSubDirectory(std::string const& fileOrDir, |
518 | | std::string const& dir); |
519 | | |
520 | | /** ----------------------------------------------------------------- |
521 | | * File Manipulation Routines |
522 | | * ----------------------------------------------------------------- |
523 | | */ |
524 | | |
525 | | /** |
526 | | * Open a file considering unicode. On Windows, if 'e' is present in |
527 | | * mode it is first discarded. |
528 | | */ |
529 | | static FILE* Fopen(std::string const& file, char const* mode); |
530 | | |
531 | | /** |
532 | | * Visual C++ does not define mode_t. |
533 | | */ |
534 | | #if defined(_MSC_VER) |
535 | | typedef unsigned short mode_t; |
536 | | #endif |
537 | | |
538 | | /** |
539 | | * Make a new directory if it is not there. This function |
540 | | * can make a full path even if none of the directories existed |
541 | | * prior to calling this function. |
542 | | */ |
543 | | static Status MakeDirectory(char const* path, mode_t const* mode = nullptr); |
544 | | static Status MakeDirectory(std::string const& path, |
545 | | mode_t const* mode = nullptr); |
546 | | |
547 | | /** |
548 | | * Represent the result of a file copy operation. |
549 | | * This is the result 'Status' and, if the operation failed, |
550 | | * an indication of whether the error occurred on the source |
551 | | * or destination path. |
552 | | */ |
553 | | struct CopyStatus : public Status |
554 | | { |
555 | | enum WhichPath |
556 | | { |
557 | | NoPath, |
558 | | SourcePath, |
559 | | DestPath, |
560 | | }; |
561 | 0 | CopyStatus() = default; |
562 | | CopyStatus(Status s, WhichPath p) |
563 | 0 | : Status(s) |
564 | 0 | , Path(p) |
565 | 0 | { |
566 | 0 | } |
567 | | WhichPath Path = NoPath; |
568 | | }; |
569 | | |
570 | | /** |
571 | | * Copy the source file to the destination file only |
572 | | * if the two files differ. |
573 | | */ |
574 | | static CopyStatus CopyFileIfDifferent(std::string const& source, |
575 | | std::string const& destination); |
576 | | |
577 | | /** |
578 | | * Copy the source file to the destination file only |
579 | | * if the source file is newer than the destination file. |
580 | | */ |
581 | | static CopyStatus CopyFileIfNewer(std::string const& source, |
582 | | std::string const& destination); |
583 | | |
584 | | /** |
585 | | * Compare the contents of two files. Return true if different |
586 | | */ |
587 | | static bool FilesDiffer(std::string const& source, |
588 | | std::string const& destination); |
589 | | |
590 | | /** |
591 | | * Compare the contents of two files, ignoring line ending differences. |
592 | | * Return true if different |
593 | | */ |
594 | | static bool TextFilesDiffer(std::string const& path1, |
595 | | std::string const& path2); |
596 | | |
597 | | /** |
598 | | * Blockwise copy source to destination file |
599 | | */ |
600 | | static CopyStatus CopyFileContentBlockwise(std::string const& source, |
601 | | std::string const& destination); |
602 | | /** |
603 | | * Clone the source file to the destination file |
604 | | */ |
605 | | static CopyStatus CloneFileContent(std::string const& source, |
606 | | std::string const& destination); |
607 | | |
608 | | /** |
609 | | * Object encapsulating a unique identifier for a file |
610 | | * or directory |
611 | | */ |
612 | | #ifdef _WIN32 |
613 | | class WindowsFileId |
614 | | { |
615 | | public: |
616 | | WindowsFileId() = default; |
617 | | WindowsFileId(unsigned long volumeSerialNumber, |
618 | | unsigned long fileIndexHigh, unsigned long fileIndexLow); |
619 | | |
620 | | bool operator==(WindowsFileId const& o) const; |
621 | | bool operator!=(WindowsFileId const& o) const; |
622 | | |
623 | | private: |
624 | | unsigned long m_volumeSerialNumber; |
625 | | unsigned long m_fileIndexHigh; |
626 | | unsigned long m_fileIndexLow; |
627 | | }; |
628 | | using FileId = WindowsFileId; |
629 | | #else |
630 | | class UnixFileId |
631 | | { |
632 | | public: |
633 | | UnixFileId() = default; |
634 | | UnixFileId(dev_t volumeSerialNumber, ino_t fileSerialNumber, |
635 | | off_t fileSize); |
636 | | |
637 | | bool operator==(UnixFileId const& o) const; |
638 | | bool operator!=(UnixFileId const& o) const; |
639 | | |
640 | | private: |
641 | | dev_t m_volumeSerialNumber; |
642 | | ino_t m_fileSerialNumber; |
643 | | off_t m_fileSize; |
644 | | }; |
645 | | using FileId = UnixFileId; |
646 | | #endif |
647 | | |
648 | | /** |
649 | | * Outputs a FileId for the given file or directory. |
650 | | * Returns true on success, false on failure |
651 | | */ |
652 | | static bool GetFileId(std::string const& file, FileId& id); |
653 | | |
654 | | /** |
655 | | * Return true if the two files are the same file |
656 | | */ |
657 | | static bool SameFile(std::string const& file1, std::string const& file2); |
658 | | |
659 | | /** |
660 | | * Copy a file. |
661 | | */ |
662 | | static CopyStatus CopyFileAlways(std::string const& source, |
663 | | std::string const& destination); |
664 | | |
665 | | enum class CopyWhen |
666 | | { |
667 | | Always, |
668 | | OnlyIfDifferent, |
669 | | OnlyIfNewer, |
670 | | }; |
671 | | |
672 | | /** |
673 | | * Copy a file with specified copy behavior. |
674 | | */ |
675 | | static CopyStatus CopyAFile(std::string const& source, |
676 | | std::string const& destination, |
677 | | CopyWhen when = CopyWhen::Always); |
678 | | static CopyStatus CopyAFile(std::string const& source, |
679 | | std::string const& destination, bool always); |
680 | | |
681 | | /** |
682 | | * Copy content directory to another directory with all files and |
683 | | * subdirectories. The "when" argument controls when files are copied: |
684 | | * Always: all files are always copied. |
685 | | * OnlyIfDifferent: only files that have changed are copied. |
686 | | * OnlyIfNewer: only files that are newer than the destination are copied. |
687 | | */ |
688 | | static Status CopyADirectory(std::string const& source, |
689 | | std::string const& destination, |
690 | | CopyWhen when = CopyWhen::Always); |
691 | | static Status CopyADirectory(std::string const& source, |
692 | | std::string const& destination, bool always); |
693 | | |
694 | | /** |
695 | | * Remove a file |
696 | | */ |
697 | | static Status RemoveFile(std::string const& source); |
698 | | |
699 | | /** |
700 | | * Remove a directory |
701 | | */ |
702 | | static Status RemoveADirectory(std::string const& source); |
703 | | |
704 | | /** |
705 | | * Get the maximum full file path length |
706 | | */ |
707 | | static size_t GetMaximumFilePathLength(); |
708 | | |
709 | | /** |
710 | | * Find a file in the system PATH, with optional extra paths |
711 | | */ |
712 | | static std::string FindFile( |
713 | | std::string const& name, |
714 | | std::vector<std::string> const& path = std::vector<std::string>(), |
715 | | bool no_system_path = false); |
716 | | |
717 | | /** |
718 | | * Find a directory in the system PATH, with optional extra paths |
719 | | */ |
720 | | static std::string FindDirectory( |
721 | | std::string const& name, |
722 | | std::vector<std::string> const& path = std::vector<std::string>(), |
723 | | bool no_system_path = false); |
724 | | |
725 | | /** |
726 | | * Find an executable in the system PATH, with optional extra paths |
727 | | */ |
728 | | static std::string FindProgram( |
729 | | std::string const& name, |
730 | | std::vector<std::string> const& path = std::vector<std::string>(), |
731 | | bool no_system_path = false); |
732 | | |
733 | | /** |
734 | | * Return true if the file is a directory |
735 | | */ |
736 | | static bool FileIsDirectory(std::string const& name); |
737 | | |
738 | | /** |
739 | | * Return true if the file is an executable |
740 | | */ |
741 | | static bool FileIsExecutable(std::string const& name); |
742 | | |
743 | | #if defined(_WIN32) |
744 | | /** |
745 | | * Return true if the file with FileAttributes `attr` is a symlink |
746 | | * Only available on Windows. This avoids an expensive `GetFileAttributesW` |
747 | | * call. |
748 | | */ |
749 | | static bool FileIsSymlinkWithAttr(std::wstring const& path, |
750 | | unsigned long attr); |
751 | | #endif |
752 | | |
753 | | /** |
754 | | * Return true if the file is a symlink |
755 | | */ |
756 | | static bool FileIsSymlink(std::string const& name); |
757 | | |
758 | | /** |
759 | | * Return true if the file is a FIFO |
760 | | */ |
761 | | static bool FileIsFIFO(std::string const& name); |
762 | | |
763 | | /** |
764 | | * Return true if the file has a given signature (first set of bytes) |
765 | | */ |
766 | | static bool FileHasSignature(char const* filename, char const* signature, |
767 | | long offset = 0); |
768 | | |
769 | | /** |
770 | | * Attempt to detect and return the type of a file. |
771 | | * Up to 'length' bytes are read from the file, if more than 'percent_bin' % |
772 | | * of the bytes are non-textual elements, the file is considered binary, |
773 | | * otherwise textual. Textual elements are bytes in the ASCII [0x20, 0x7E] |
774 | | * range, but also \\n, \\r, \\t. |
775 | | * The algorithm is simplistic, and should probably check for usual file |
776 | | * extensions, 'magic' signature, unicode, etc. |
777 | | */ |
778 | | enum FileTypeEnum |
779 | | { |
780 | | FileTypeUnknown, |
781 | | FileTypeBinary, |
782 | | FileTypeText |
783 | | }; |
784 | | static SystemTools::FileTypeEnum DetectFileType(char const* filename, |
785 | | unsigned long length = 256, |
786 | | double percent_bin = 0.05); |
787 | | |
788 | | /** |
789 | | * Create a symbolic link if the platform supports it. Returns whether |
790 | | * creation succeeded. |
791 | | */ |
792 | | static Status CreateSymlink(std::string const& origName, |
793 | | std::string const& newName); |
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 |