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 | |
7033c769 LC |
97 | returns the number of bytes and blocks freed, and 'linkThreshold' denotes |
98 | the number of links under which a file is accounted for in 'bytesFreed'. */ | |
36457566 LC |
99 | void deletePath(const Path & path); |
100 | ||
7033c769 LC |
101 | void deletePath(const Path & path, unsigned long long & bytesFreed, |
102 | size_t linkThreshold = 1); | |
36457566 LC |
103 | |
104 | /* Create a temporary directory. */ | |
105 | Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix", | |
106 | bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755); | |
107 | ||
108 | /* Create a directory and all its parents, if necessary. Returns the | |
109 | list of created directories, in order of creation. */ | |
110 | Paths createDirs(const Path & path); | |
111 | ||
112 | /* Create a symlink. */ | |
113 | void createSymlink(const Path & target, const Path & link); | |
114 | ||
115 | ||
116 | template<class T, class A> | |
117 | T singleton(const A & a) | |
118 | { | |
119 | T t; | |
120 | t.insert(a); | |
121 | return t; | |
122 | } | |
123 | ||
124 | ||
125 | /* Messages. */ | |
126 | ||
127 | ||
128 | typedef enum { | |
129 | ltPretty, /* nice, nested output */ | |
130 | ltEscapes, /* nesting indicated using escape codes (for log2xml) */ | |
131 | ltFlat /* no nesting */ | |
132 | } LogType; | |
133 | ||
134 | extern LogType logType; | |
135 | extern Verbosity verbosity; /* suppress msgs > this */ | |
136 | ||
137 | class Nest | |
138 | { | |
139 | private: | |
140 | bool nest; | |
141 | public: | |
142 | Nest(); | |
143 | ~Nest(); | |
144 | void open(Verbosity level, const FormatOrString & fs); | |
145 | void close(); | |
146 | }; | |
147 | ||
148 | void printMsg_(Verbosity level, const FormatOrString & fs); | |
149 | ||
150 | #define startNest(varName, level, f) \ | |
151 | Nest varName; \ | |
152 | if (level <= verbosity) { \ | |
153 | varName.open(level, (f)); \ | |
154 | } | |
155 | ||
156 | #define printMsg(level, f) \ | |
157 | do { \ | |
14fb686a ED |
158 | if (level <= nix::verbosity) { \ |
159 | nix::printMsg_(level, (f)); \ | |
36457566 LC |
160 | } \ |
161 | } while (0) | |
162 | ||
163 | #define debug(f) printMsg(lvlDebug, f) | |
164 | ||
165 | void warnOnce(bool & haveWarned, const FormatOrString & fs); | |
166 | ||
167 | void writeToStderr(const string & s); | |
168 | ||
169 | extern void (*_writeToStderr) (const unsigned char * buf, size_t count); | |
170 | ||
171 | ||
172 | /* Wrappers arount read()/write() that read/write exactly the | |
173 | requested number of bytes. */ | |
174 | void readFull(int fd, unsigned char * buf, size_t count); | |
175 | void writeFull(int fd, const unsigned char * buf, size_t count); | |
54c260e6 | 176 | void writeFull(int fd, const string & s); |
36457566 LC |
177 | |
178 | MakeError(EndOfFile, Error) | |
179 | ||
180 | ||
181 | /* Read a file descriptor until EOF occurs. */ | |
182 | string drainFD(int fd); | |
183 | ||
184 | ||
185 | ||
186 | /* Automatic cleanup of resources. */ | |
187 | ||
188 | ||
189 | template <class T> | |
190 | struct AutoDeleteArray | |
191 | { | |
192 | T * p; | |
193 | AutoDeleteArray(T * p) : p(p) { } | |
194 | ~AutoDeleteArray() | |
195 | { | |
196 | delete [] p; | |
197 | } | |
198 | }; | |
199 | ||
200 | ||
201 | class AutoDelete | |
202 | { | |
203 | Path path; | |
204 | bool del; | |
205 | bool recursive; | |
206 | public: | |
207 | AutoDelete(const Path & p, bool recursive = true); | |
208 | ~AutoDelete(); | |
209 | void cancel(); | |
210 | }; | |
211 | ||
212 | ||
213 | class AutoCloseFD | |
214 | { | |
215 | int fd; | |
216 | public: | |
217 | AutoCloseFD(); | |
218 | AutoCloseFD(int fd); | |
219 | AutoCloseFD(const AutoCloseFD & fd); | |
220 | ~AutoCloseFD(); | |
221 | void operator =(int fd); | |
222 | operator int() const; | |
223 | void close(); | |
224 | bool isOpen(); | |
225 | int borrow(); | |
226 | }; | |
227 | ||
228 | ||
229 | class Pipe | |
230 | { | |
231 | public: | |
232 | AutoCloseFD readSide, writeSide; | |
233 | void create(); | |
234 | }; | |
235 | ||
236 | ||
237 | class AutoCloseDir | |
238 | { | |
239 | DIR * dir; | |
240 | public: | |
241 | AutoCloseDir(); | |
242 | AutoCloseDir(DIR * dir); | |
243 | ~AutoCloseDir(); | |
244 | void operator =(DIR * dir); | |
245 | operator DIR *(); | |
246 | void close(); | |
247 | }; | |
248 | ||
249 | ||
250 | class Pid | |
251 | { | |
252 | pid_t pid; | |
253 | bool separatePG; | |
254 | int killSignal; | |
255 | public: | |
256 | Pid(); | |
2bb04905 | 257 | Pid(pid_t pid); |
36457566 LC |
258 | ~Pid(); |
259 | void operator =(pid_t pid); | |
260 | operator pid_t(); | |
2bb04905 | 261 | void kill(bool quiet = false); |
36457566 LC |
262 | int wait(bool block); |
263 | void setSeparatePG(bool separatePG); | |
264 | void setKillSignal(int signal); | |
265 | }; | |
266 | ||
267 | ||
268 | /* Kill all processes running under the specified uid by sending them | |
269 | a SIGKILL. */ | |
270 | void killUser(uid_t uid); | |
271 | ||
272 | ||
2bb04905 LC |
273 | /* Fork a process that runs the given function, and return the child |
274 | pid to the caller. */ | |
275 | pid_t startProcess(std::function<void()> fun, bool dieWithParent = true, | |
276 | const string & errorPrefix = "error: ", bool runExitHandlers = false); | |
277 | ||
278 | ||
36457566 LC |
279 | /* Run a program and return its stdout in a string (i.e., like the |
280 | shell backtick operator). */ | |
281 | string runProgram(Path program, bool searchPath = false, | |
282 | const Strings & args = Strings()); | |
283 | ||
2bb04905 LC |
284 | MakeError(ExecError, Error) |
285 | ||
54c260e6 LC |
286 | /* Convert a list of strings to a null-terminated vector of char |
287 | *'s. The result must not be accessed beyond the lifetime of the | |
288 | list of strings. */ | |
322eeb87 | 289 | std::vector<char *> stringsToCharPtrs(const Strings & ss); |
54c260e6 | 290 | |
36457566 LC |
291 | /* Close all file descriptors except stdin, stdout, stderr, and those |
292 | listed in the given set. Good practice in child processes. */ | |
293 | void closeMostFDs(const set<int> & exceptions); | |
294 | ||
295 | /* Set the close-on-exec flag for the given file descriptor. */ | |
296 | void closeOnExec(int fd); | |
297 | ||
36457566 LC |
298 | |
299 | /* User interruption. */ | |
300 | ||
301 | extern volatile sig_atomic_t _isInterrupted; | |
302 | ||
303 | void _interrupted(); | |
304 | ||
305 | void inline checkInterrupt() | |
306 | { | |
307 | if (_isInterrupted) _interrupted(); | |
308 | } | |
309 | ||
310 | MakeError(Interrupted, BaseError) | |
311 | ||
312 | ||
313 | /* String tokenizer. */ | |
314 | template<class C> C tokenizeString(const string & s, const string & separators = " \t\n\r"); | |
315 | ||
316 | ||
317 | /* Concatenate the given strings with a separator between the | |
318 | elements. */ | |
319 | string concatStringsSep(const string & sep, const Strings & ss); | |
320 | string concatStringsSep(const string & sep, const StringSet & ss); | |
321 | ||
322 | ||
323 | /* Remove trailing whitespace from a string. */ | |
324 | string chomp(const string & s); | |
325 | ||
326 | ||
327 | /* Convert the exit status of a child as returned by wait() into an | |
328 | error string. */ | |
329 | string statusToString(int status); | |
330 | ||
331 | bool statusOk(int status); | |
332 | ||
333 | ||
334 | /* Parse a string into an integer. */ | |
335 | template<class N> bool string2Int(const string & s, N & n) | |
336 | { | |
337 | std::istringstream str(s); | |
338 | str >> n; | |
339 | return str && str.get() == EOF; | |
340 | } | |
341 | ||
36457566 LC |
342 | |
343 | /* Return true iff `s' ends in `suffix'. */ | |
344 | bool hasSuffix(const string & s, const string & suffix); | |
345 | ||
346 | ||
347 | /* Read string `s' from stream `str'. */ | |
348 | void expect(std::istream & str, const string & s); | |
349 | ||
15ddeff5 LC |
350 | MakeError(FormatError, Error) |
351 | ||
36457566 LC |
352 | |
353 | /* Read a C-style string from stream `str'. */ | |
354 | string parseString(std::istream & str); | |
355 | ||
356 | ||
357 | /* Utility function used to parse legacy ATerms. */ | |
358 | bool endOfList(std::istream & str); | |
359 | ||
360 | ||
36457566 LC |
361 | /* Exception handling in destructors: print an error message, then |
362 | ignore the exception. */ | |
363 | void ignoreException(); | |
364 | ||
365 | ||
366 | } |