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