blob: 5d30cc8c895cd616e44c88f75e154344d22c249d [file] [log] [blame]
Chris Lattner7a6ff2b2003-08-01 21:16:14 +00001//===- Support/FileUtilities.cpp - File System Utilities ------------------===//
John Criswellb576c942003-10-20 19:43:21 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Chris Lattner7a6ff2b2003-08-01 21:16:14 +00009//
10// This file implements a family of utility functions which are useful for doing
11// various things with files.
12//
13//===----------------------------------------------------------------------===//
14
15#include "Support/FileUtilities.h"
Misha Brukmanda81eca2003-08-07 21:35:41 +000016#include "Config/unistd.h"
John Criswell6991a032003-09-02 20:14:57 +000017#include "Config/sys/stat.h"
18#include "Config/sys/types.h"
Chris Lattner7a6ff2b2003-08-01 21:16:14 +000019#include <fstream>
20#include <iostream>
21#include <cstdio>
22
23/// DiffFiles - Compare the two files specified, returning true if they are
24/// different or if there is a file error. If you specify a string to fill in
25/// for the error option, it will set the string to an error message if an error
26/// occurs, allowing the caller to distinguish between a failed diff and a file
27/// system error.
28///
29bool DiffFiles(const std::string &FileA, const std::string &FileB,
30 std::string *Error) {
31 std::ifstream FileAStream(FileA.c_str());
32 if (!FileAStream) {
33 if (Error) *Error = "Couldn't open file '" + FileA + "'";
34 return true;
35 }
36
37 std::ifstream FileBStream(FileB.c_str());
38 if (!FileBStream) {
39 if (Error) *Error = "Couldn't open file '" + FileB + "'";
40 return true;
41 }
42
43 // Compare the two files...
44 int C1, C2;
45 do {
46 C1 = FileAStream.get();
47 C2 = FileBStream.get();
48 if (C1 != C2) return true;
49 } while (C1 != EOF);
50
51 return false;
52}
53
54
55/// MoveFileOverIfUpdated - If the file specified by New is different than Old,
56/// or if Old does not exist, move the New file over the Old file. Otherwise,
57/// remove the New file.
58///
59void MoveFileOverIfUpdated(const std::string &New, const std::string &Old) {
60 if (DiffFiles(New, Old)) {
61 if (std::rename(New.c_str(), Old.c_str()))
62 std::cerr << "Error renaming '" << New << "' to '" << Old << "'!\n";
63 } else {
64 std::remove(New.c_str());
65 }
66}
Misha Brukman3d1b0c72003-08-07 21:28:50 +000067
68/// removeFile - Delete the specified file
69///
70void removeFile(const std::string &Filename) {
71 std::remove(Filename.c_str());
72}
73
74/// getUniqueFilename - Return a filename with the specified prefix. If the
75/// file does not exist yet, return it, otherwise add a suffix to make it
76/// unique.
77///
78std::string getUniqueFilename(const std::string &FilenameBase) {
79 if (!std::ifstream(FilenameBase.c_str()))
80 return FilenameBase; // Couldn't open the file? Use it!
81
82 // Create a pattern for mkstemp...
83 char *FNBuffer = new char[FilenameBase.size()+8];
84 strcpy(FNBuffer, FilenameBase.c_str());
85 strcpy(FNBuffer+FilenameBase.size(), "-XXXXXX");
86
87 // Agree on a temporary file name to use....
88 int TempFD;
89 if ((TempFD = mkstemp(FNBuffer)) == -1) {
90 std::cerr << "bugpoint: ERROR: Cannot create temporary file in the current "
91 << " directory!\n";
92 exit(1);
93 }
94
Misha Brukman950971d2003-09-16 15:31:46 +000095 // We don't need to hold the temp file descriptor... we will trust that no one
Misha Brukman3d1b0c72003-08-07 21:28:50 +000096 // will overwrite/delete the file while we are working on it...
97 close(TempFD);
98 std::string Result(FNBuffer);
99 delete[] FNBuffer;
100 return Result;
101}
John Criswell6991a032003-09-02 20:14:57 +0000102
103///
104/// Method: MakeFileExecutable ()
105///
106/// Description:
107/// This method makes the specified filename executable by giving it
John Criswell9adeccc2003-09-02 20:30:16 +0000108/// execute permission. It respects the umask value of the process, and it
109/// does not enable any unnecessary access bits.
John Criswell6991a032003-09-02 20:14:57 +0000110///
John Criswell9adeccc2003-09-02 20:30:16 +0000111/// Algorithm:
112/// o Get file's current permissions.
113/// o Get the process's current umask.
114/// o Take the set of all execute bits and disable those found in the umask.
115/// o Add the remaining permissions to the file's permissions.
John Criswell6991a032003-09-02 20:14:57 +0000116///
117bool
118MakeFileExecutable (const std::string & Filename)
119{
120 // Permissions masking value of the user
121 mode_t mask;
122
123 // Permissions currently enabled on the file
124 struct stat fstat;
125
126 //
127 // Grab the umask value from the operating system. We want to use it when
128 // changing the file's permissions.
129 //
130 // Note:
131 // Umask() is one of those annoying system calls. You have to call it
132 // to get the current value and then set it back.
133 //
134 mask = umask (0x777);
135 umask (mask);
136
137 //
138 // Go fetch the file's current permission bits. We want to *add* execute
139 // access to the file.
140 //
141 if ((stat (Filename.c_str(), &fstat)) == -1)
142 {
143 return false;
144 }
145
John Criswell9adeccc2003-09-02 20:30:16 +0000146 //
147 // Make the file executable...
148 //
149 if ((chmod(Filename.c_str(), (fstat.st_mode | (0111 & ~mask)))) == -1)
150 {
151 return false;
152 }
John Criswell6991a032003-09-02 20:14:57 +0000153
154 return true;
155}
156
John Criswell66622be2003-09-02 21:09:30 +0000157///
158/// Method: MakeFileReadable ()
159///
160/// Description:
161/// This method makes the specified filename readable by giving it
162/// read permission. It respects the umask value of the process, and it
163/// does not enable any unnecessary access bits.
164///
165/// Algorithm:
166/// o Get file's current permissions.
167/// o Get the process's current umask.
168/// o Take the set of all read bits and disable those found in the umask.
169/// o Add the remaining permissions to the file's permissions.
170///
171bool
172MakeFileReadable (const std::string & Filename)
173{
174 // Permissions masking value of the user
175 mode_t mask;
176
177 // Permissions currently enabled on the file
178 struct stat fstat;
179
180 //
181 // Grab the umask value from the operating system. We want to use it when
182 // changing the file's permissions.
183 //
184 // Note:
185 // Umask() is one of those annoying system calls. You have to call it
186 // to get the current value and then set it back.
187 //
188 mask = umask (0x777);
189 umask (mask);
190
191 //
192 // Go fetch the file's current permission bits. We want to *add* execute
193 // access to the file.
194 //
195 if ((stat (Filename.c_str(), &fstat)) == -1)
196 {
197 return false;
198 }
199
200 //
201 // Make the file executable...
202 //
203 if ((chmod(Filename.c_str(), (fstat.st_mode | (0444 & ~mask)))) == -1)
204 {
205 return false;
206 }
207
208 return true;
209}
210