projects/guix·blob java-team · refs

403 lines · 10.4 KiB

1#pragma once
2
3#include "types.hh"
4
5#include <sstream>
6#include <string_view>
7
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <dirent.h>
11#include <unistd.h>
12#include <signal.h>
13#include <map>
14#include <functional>
15
16#include <cstdio>
17
18
19namespace nix {
20
21
22/* Return an environment variable. */
23string getEnv(const string & key, const string & def = "");
24
25/* Find the absolute filename corresponding to PROGRAM, searching PATH if
26 PROGRAM is a relative filename. If PROGRAM is an absolute filename for a
27 file that doesn't exist, or it can't be found in PATH, then return the
28 empty string. */
29string findProgram(const string & program);
30
31/* Return an absolutized path, resolving paths relative to the
32 specified directory, or the current directory otherwise. The path
33 is also canonicalised. */
34Path absPath(Path path, Path dir = "");
35
36/* Canonicalise a path by removing all `.' or `..' components and
37 double or trailing slashes. Optionally resolves all symlink
38 components such that each component of the resulting path is *not*
39 a symbolic link. */
40Path canonPath(const Path & path, bool resolveSymlinks = false);
41
42/* Return the directory part of the given canonical path, i.e.,
43 everything before the final `/'. If the path is the root or an
44 immediate child thereof (e.g., `/foo'), this means an empty string
45 is returned. */
46Path dirOf(const Path & path);
47
48/* Return the base name of the given canonical path, i.e., everything
49 following the final `/'. */
50string baseNameOf(const Path & path);
51
52/* Check whether a given path is a descendant of the given
53 directory. */
54bool isInDir(const Path & path, const Path & dir);
55
56/* Get status of `path'. */
57struct stat lstat(const Path & path);
58
59/* Return true iff the given path exists. */
60bool pathExists(const Path & path);
61
62/* Read the contents (target) of a symbolic link. The result is not
63 in any way canonicalised. */
64Path readLink(const Path & path);
65
66bool isLink(const Path & path);
67
68/* Return true if the file at PATH is a regular, non-executable file. */
69bool isPlainFile(const Path & path);
70
71/* Read the contents of a directory. The entries `.' and `..' are
72 removed. */
73struct DirEntry
74{
75 string name;
76 ino_t ino;
77 unsigned char type; // one of DT_*
78 DirEntry(const string & name, ino_t ino, unsigned char type)
79 : name(name), ino(ino), type(type) { }
80};
81
82typedef vector<DirEntry> DirEntries;
83
84DirEntries readDirectory(const Path & path);
85
86unsigned char getFileType(const Path & path);
87
88/* Read the contents of a file into a string. */
89string readFile(int fd);
90string readFile(const Path & path, bool drain = false);
91
92/* Write a string to a file. */
93void writeFile(const Path & path, const string & s);
94
95/* Read a line from a file descriptor. */
96string readLine(int fd);
97
98/* Write a line to a file descriptor. */
99void writeLine(int fd, string s);
100
101/* Delete a path; i.e., in the case of a directory, it is deleted
102 recursively. Don't use this at home, kids. The second variant
103 returns the number of bytes and blocks freed, and 'linkThreshold' denotes
104 the number of links under which a file is accounted for in 'bytesFreed'.
105
106 Note that if a directory is unreadable, chmod will be invoked on it to make
107 it u+rwx. On non-linux systems with no equivalent to
108 /proc/sys/fs/protected_hardlinks, a TOCTTOU race may allow the directory to
109 be replaced with a hardlink to an important file, making that file's
110 permissions overly-strict.
111 */
112void deletePath(const Path & path);
113
114void deletePath(const Path & path, unsigned long long & bytesFreed,
115 size_t linkThreshold = 1);
116
117/* Copy SOURCE to DESTINATION, recursively, preserving ownership. Throw if
118 SOURCE contains a file that is not a regular file, symlink, or directory.
119 When DELETESOURCE is true, delete source files once they have been
120 copied. */
121void copyFileRecursively(const Path &source, const Path &destination,
122 bool deleteSource = false);
123
124/* Create a temporary directory. */
125Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
126 bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755);
127
128/* Create a directory and all its parents, if necessary. Returns the
129 list of created directories, in order of creation. */
130Paths createDirs(const Path & path);
131
132/* Create a symlink. */
133void createSymlink(const Path & target, const Path & link);
134
135
136/* Messages. */
137
138
139typedef enum {
140 ltPretty, /* nice, nested output */
141 ltEscapes, /* nesting indicated using escape codes (for log2xml) */
142 ltFlat /* no nesting */
143} LogType;
144
145inline LogType logType {ltPretty};
146inline Verbosity verbosity {lvlInfo}; /* suppress msgs > this */
147
148class Nest
149{
150private:
151 bool nest;
152public:
153 Nest();
154 ~Nest();
155 void open(Verbosity level, std::string_view fs);
156 void close();
157};
158
159void printMsg_(Verbosity level, std::string_view fs);
160
161#define startNest(varName, level, f) \
162 Nest varName; \
163 if (level <= verbosity) { \
164 varName.open(level, (f)); \
165 }
166
167#define printMsg(level, f) \
168 do { \
169 if (level <= nix::verbosity) { \
170 nix::printMsg_(level, (f)); \
171 } \
172 } while (0)
173
174#define debug(f) printMsg(lvlDebug, f)
175
176void warnOnce(bool & haveWarned, std::string_view fs);
177
178void writeToStderr(const string & s);
179
180inline void (*_writeToStderr) (const unsigned char * buf, size_t count) = 0;
181
182
183/* Wrappers around read()/write() that read/write exactly the
184 requested number of bytes. */
185void readFull(int fd, unsigned char * buf, size_t count);
186void writeFull(int fd, const unsigned char * buf, size_t count);
187void writeFull(int fd, const string & s);
188
189MakeError(EndOfFile, Error)
190
191
192/* Read a file descriptor until EOF occurs. */
193string drainFD(int fd);
194
195void waitForMessage(int fd, const string & message);
196
197
198
199/* Automatic cleanup of resources. */
200
201
202class AutoDelete
203{
204 Path path;
205 bool del;
206 bool recursive;
207public:
208 AutoDelete(const Path & p, bool recursive = true);
209 ~AutoDelete();
210 void cancel();
211};
212
213
214class AutoCloseFD
215{
216 int fd;
217public:
218 AutoCloseFD();
219 AutoCloseFD(int fd);
220 AutoCloseFD(const AutoCloseFD & fd);
221 ~AutoCloseFD();
222 void operator =(int fd);
223 operator int() const;
224 void close();
225 bool isOpen();
226 int borrow();
227};
228
229/* Send and receive an FD on a unix-domain socket, along with a single null
230 byte of regular data. */
231void sendFD(int sock, int fd);
232int receiveFD(int sock);
233
234class Pipe
235{
236public:
237 AutoCloseFD readSide, writeSide;
238 void create();
239};
240
241
242class AutoCloseDir
243{
244 DIR * dir;
245public:
246 AutoCloseDir();
247 AutoCloseDir(DIR * dir);
248 ~AutoCloseDir();
249 void operator =(DIR * dir);
250 operator DIR *();
251 void close();
252};
253
254
255class Pid
256{
257 pid_t pid;
258 bool separatePG;
259 int killSignal;
260public:
261 Pid();
262 Pid(pid_t pid);
263 ~Pid();
264 void operator =(pid_t pid);
265 operator pid_t();
266 void kill(bool quiet = false);
267 int wait(bool block);
268 void setSeparatePG(bool separatePG);
269 void setKillSignal(int signal);
270};
271
272/* An "agent" is a helper program that runs in the background and that we talk
273 to over pipes, such as the "guix offload" program. */
274struct Agent
275{
276 /* Pipes for talking to the agent. */
277 Pipe toAgent;
278
279 /* Pipe for the agent's standard output/error. */
280 Pipe fromAgent;
281
282 /* Pipe for build standard output/error--e.g., for build processes started
283 by "guix offload". */
284 Pipe builderOut;
285
286 /* The process ID of the agent. */
287 Pid pid;
288
289 /* The command and arguments passed to the agent along with a list of
290 environment variable name/value pairs. */
291 Agent(const string &command, const Strings &args,
292 const std::map<string, string> &env = std::map<string, string>());
293
294 ~Agent();
295};
296
297
298/* Kill all processes running under the specified uid by sending them
299 a SIGKILL. */
300void killUser(uid_t uid);
301
302
303/* Fork a process that runs the given function, and return the child
304 pid to the caller. */
305pid_t startProcess(std::function<void()> fun, bool dieWithParent = true,
306 const string & errorPrefix = "error: ", bool runExitHandlers = false);
307
308
309/* Run a program and return its stdout in a string (i.e., like the
310 shell backtick operator). */
311string runProgram(Path program, bool searchPath = false,
312 const Strings & args = Strings());
313
314MakeError(ExecError, Error)
315
316/* Convert a list of strings to a null-terminated vector of char
317 *'s. The result must not be accessed beyond the lifetime of the
318 list of strings. */
319std::vector<char *> stringsToCharPtrs(const Strings & ss);
320
321/* Close all file descriptors except stdin, stdout, stderr, and those
322 listed in the given set. Good practice in child processes. */
323void closeMostFDs(const set<int> & exceptions);
324
325/* Set the close-on-exec flag for the given file descriptor. */
326void closeOnExec(int fd);
327
328/* Clear the close-on-exec flag for the given file descriptor. */
329void keepOnExec(int fd);
330
331/* Common initialisation performed in child processes. */
332void commonChildInit(Pipe & logPipe);
333
334/* User interruption. */
335
336inline volatile sig_atomic_t _isInterrupted = 0;
337
338void _interrupted();
339
340void inline checkInterrupt()
341{
342 if (_isInterrupted) _interrupted();
343}
344
345MakeError(Interrupted, BaseError)
346
347
348/* String tokenizer. */
349template<class C> C tokenizeString(const string & s, const string & separators = " \t\n\r");
350
351
352/* Concatenate the given strings with a separator between the
353 elements. */
354string concatStringsSep(const string & sep, const Strings & ss);
355string concatStringsSep(const string & sep, const StringSet & ss);
356
357
358/* Remove trailing whitespace from a string. */
359string chomp(const string & s);
360
361
362/* Convert the exit status of a child as returned by wait() into an
363 error string. */
364string statusToString(int status);
365
366bool statusOk(int status);
367
368
369/* Parse a string into an integer. */
370template<class N> bool string2Int(const string & s, N & n)
371{
372 std::istringstream str(s);
373 str >> n;
374 return str && str.get() == EOF;
375}
376
377
378/* Read string `s' from stream `str'. */
379void expect(std::istream & str, std::string_view s);
380
381MakeError(FormatError, Error)
382
383
384/* Read a C-style string from stream `str'. */
385string parseString(std::istream & str);
386
387
388/* Utility function used to parse legacy ATerms. */
389bool endOfList(std::istream & str);
390
391
392/* Escape a string that contains octal-encoded escape codes such as
393 used in /etc/fstab and /proc/mounts (e.g. "foo\040bar" decodes to
394 "foo bar"). */
395string decodeOctalEscaped(const string & s);
396
397
398/* Exception handling in destructors: print an error message, then
399 ignore the exception. */
400void ignoreException();
401
402
403}