/src/CMake/Source/cmWriteFileCommand.cxx
Line | Count | Source |
1 | | /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
2 | | file LICENSE.rst or https://cmake.org/licensing for details. */ |
3 | | #include "cmWriteFileCommand.h" |
4 | | |
5 | | #include "cmsys/FStream.hxx" |
6 | | |
7 | | #include "cm_sys_stat.h" |
8 | | |
9 | | #include "cmDiagnostics.h" |
10 | | #include "cmExecutionStatus.h" |
11 | | #include "cmMakefile.h" |
12 | | #include "cmStringAlgorithms.h" |
13 | | #include "cmSystemTools.h" |
14 | | |
15 | | // cmLibraryCommand |
16 | | bool cmWriteFileCommand(std::vector<std::string> const& args, |
17 | | cmExecutionStatus& status) |
18 | 0 | { |
19 | 0 | cmMakefile& mf = status.GetMakefile(); |
20 | |
|
21 | 0 | mf.IssueDiagnostic(cmDiagnostics::CMD_DEPRECATED, |
22 | 0 | "The 'write_file' command has been superseded. " |
23 | 0 | "Use 'file(WRITE)' instead."); |
24 | |
|
25 | 0 | if (args.size() < 2) { |
26 | 0 | status.SetError("called with incorrect number of arguments"); |
27 | 0 | return false; |
28 | 0 | } |
29 | 0 | std::string message; |
30 | 0 | auto i = args.begin(); |
31 | |
|
32 | 0 | std::string const& fileName = *i; |
33 | 0 | bool overwrite = true; |
34 | 0 | i++; |
35 | |
|
36 | 0 | for (; i != args.end(); ++i) { |
37 | 0 | if (*i == "APPEND") { |
38 | 0 | overwrite = false; |
39 | 0 | } else { |
40 | 0 | message += *i; |
41 | 0 | } |
42 | 0 | } |
43 | |
|
44 | 0 | if (!mf.CanIWriteThisFile(fileName)) { |
45 | 0 | std::string e = |
46 | 0 | "attempted to write a file: " + fileName + " into a source directory."; |
47 | 0 | status.SetError(e); |
48 | 0 | cmSystemTools::SetFatalErrorOccurred(); |
49 | 0 | return false; |
50 | 0 | } |
51 | | |
52 | 0 | std::string dir = cmSystemTools::GetFilenamePath(fileName); |
53 | 0 | cmSystemTools::MakeDirectory(dir); |
54 | |
|
55 | 0 | mode_t mode = 0; |
56 | 0 | bool writable = false; |
57 | | |
58 | | // Set permissions to writable |
59 | 0 | if (cmSystemTools::GetPermissions(fileName.c_str(), mode)) { |
60 | | #if defined(_MSC_VER) || defined(__MINGW32__) |
61 | | writable = (mode & S_IWRITE) != 0; |
62 | | mode_t newMode = mode | S_IWRITE; |
63 | | #else |
64 | 0 | writable = mode & S_IWUSR; |
65 | 0 | mode_t newMode = mode | S_IWUSR | S_IWGRP; |
66 | 0 | #endif |
67 | 0 | if (!writable) { |
68 | 0 | cmSystemTools::SetPermissions(fileName.c_str(), newMode); |
69 | 0 | } |
70 | 0 | } |
71 | | // If GetPermissions fails, pretend like it is ok. File open will fail if |
72 | | // the file is not writable |
73 | 0 | cmsys::ofstream file(fileName.c_str(), |
74 | 0 | overwrite ? std::ios::out : std::ios::app); |
75 | 0 | if (!file) { |
76 | 0 | std::string error = |
77 | 0 | cmStrCat("Internal CMake error when trying to open file: ", fileName, |
78 | 0 | " for writing."); |
79 | 0 | status.SetError(error); |
80 | 0 | return false; |
81 | 0 | } |
82 | 0 | file << message << '\n'; |
83 | 0 | file.close(); |
84 | 0 | if (mode && !writable) { |
85 | 0 | cmSystemTools::SetPermissions(fileName.c_str(), mode); |
86 | 0 | } |
87 | |
|
88 | 0 | return true; |
89 | 0 | } |