1 : #ifndef __UTIL_H
2 : #define __UTIL_H
3 :
4 : #include <string>
5 : #include <list>
6 : #include <set>
7 : #include <sstream>
8 :
9 : #include <sys/types.h>
10 : #include <dirent.h>
11 : #include <unistd.h>
12 : #include <signal.h>
13 :
14 : #include <boost/format.hpp>
15 :
16 : using namespace std;
17 : using namespace boost;
18 :
19 :
20 : class Error : public exception
21 : {
22 : protected:
23 : string err;
24 : public:
25 : Error(const format & f);
26 14 : ~Error() throw () { };
27 0 : const char * what() const throw () { return err.c_str(); }
28 14 : const string & msg() const throw () { return err; }
29 : };
30 :
31 : class SysError : public Error
32 : {
33 : public:
34 : SysError(const format & f);
35 : };
36 :
37 : class UsageError : public Error
38 : {
39 : public:
40 0 : UsageError(const format & f) : Error(f) { };
41 : };
42 :
43 :
44 : typedef list<string> Strings;
45 : typedef set<string> StringSet;
46 :
47 :
48 : /* Paths are just strings. */
49 : typedef string Path;
50 : typedef list<Path> Paths;
51 : typedef set<Path> PathSet;
52 :
53 :
54 : /* The canonical system name, as returned by config.guess. */
55 : extern string thisSystem;
56 :
57 :
58 : /* Return an environment variable. */
59 : string getEnv(const string & key, const string & def = "");
60 :
61 : /* Return an absolutized path, resolving paths relative to the
62 : specified directory, or the current directory otherwise. The path
63 : is also canonicalised. */
64 : Path absPath(Path path, Path dir = "");
65 :
66 : /* Canonicalise a path by removing all `.' or `..' components and
67 : double or trailing slashes. */
68 : Path canonPath(const Path & path);
69 :
70 : /* Return the directory part of the given canonical path, i.e.,
71 : everything before the final `/'. If the path is the root or an
72 : immediate child thereof (e.g., `/foo'), this means an empty string
73 : is returned. */
74 : Path dirOf(const Path & path);
75 :
76 : /* Return the base name of the given canonical path, i.e., everything
77 : following the final `/'. */
78 : string baseNameOf(const Path & path);
79 :
80 : /* Return true iff the given path exists. */
81 : bool pathExists(const Path & path);
82 :
83 : /* Read the contents (target) of a symbolic link. The result is not
84 : in any way canonicalised. */
85 : Path readLink(const Path & path);
86 :
87 : /* Read the contents of a directory. The entries `.' and `..' are
88 : removed. */
89 : Strings readDirectory(const Path & path);
90 :
91 : /* Delete a path; i.e., in the case of a directory, it is deleted
92 : recursively. Don't use this at home, kids. */
93 : void deletePath(const Path & path);
94 :
95 : /* Make a path read-only recursively. */
96 : void makePathReadOnly(const Path & path);
97 :
98 : /* Create a temporary directory. */
99 : Path createTempDir();
100 :
101 : /* Create a file and write the given text to it. The file is written
102 : in binary mode (i.e., no end-of-line conversions). The path should
103 : not already exist. */
104 : void writeStringToFile(const Path & path, const string & s);
105 :
106 :
107 : /* Messages. */
108 :
109 :
110 : typedef enum {
111 : ltPretty, /* nice, nested output */
112 : ltEscapes, /* nesting indicated using escape codes (for log2xml) */
113 : ltFlat /* no nesting */
114 : } LogType;
115 :
116 : typedef enum {
117 : lvlError,
118 : lvlInfo,
119 : lvlTalkative,
120 : lvlChatty,
121 : lvlDebug,
122 : lvlVomit
123 : } Verbosity;
124 :
125 : extern LogType logType;
126 : extern Verbosity verbosity; /* suppress msgs > this */
127 :
128 : class Nest
129 : {
130 : private:
131 : bool nest;
132 : public:
133 : Nest();
134 : ~Nest();
135 : void open(Verbosity level, const format & f);
136 : void close();
137 : };
138 :
139 : void printMsg_(Verbosity level, const format & f);
140 :
141 : #define startNest(varName, level, f) \
142 : Nest varName; \
143 : if (level <= verbosity) { \
144 : varName.open(level, (f)); \
145 : }
146 :
147 : #define printMsg(level, f) \
148 : do { \
149 : if (level <= verbosity) { \
150 : printMsg_(level, (f)); \
151 : } \
152 : } while (0)
153 :
154 : #define debug(f) printMsg(lvlDebug, f)
155 :
156 :
157 : /* Wrappers arount read()/write() that read/write exactly the
158 : requested number of bytes. */
159 : void readFull(int fd, unsigned char * buf, size_t count);
160 : void writeFull(int fd, const unsigned char * buf, size_t count);
161 :
162 :
163 : /* Automatic cleanup of resources. */
164 :
165 : class AutoDelete
166 : {
167 : string path;
168 : bool del;
169 : public:
170 : AutoDelete(const string & p);
171 : ~AutoDelete();
172 : void cancel();
173 : };
174 :
175 :
176 : class AutoCloseFD
177 : {
178 : int fd;
179 : public:
180 : AutoCloseFD();
181 : AutoCloseFD(int fd);
182 : ~AutoCloseFD();
183 : void operator =(int fd);
184 : operator int();
185 : void close();
186 : bool isOpen();
187 : };
188 :
189 :
190 : class Pipe
191 : {
192 : public:
193 : AutoCloseFD readSide, writeSide;
194 : void create();
195 : };
196 :
197 :
198 : class AutoCloseDir
199 : {
200 : DIR * dir;
201 : public:
202 : AutoCloseDir();
203 : AutoCloseDir(DIR * dir);
204 : ~AutoCloseDir();
205 : void operator =(DIR * dir);
206 : operator DIR *();
207 : };
208 :
209 :
210 : class Pid
211 : {
212 : pid_t pid;
213 : bool separatePG;
214 : public:
215 : Pid();
216 : ~Pid();
217 : void operator =(pid_t pid);
218 : operator pid_t();
219 : void kill();
220 : int wait(bool block);
221 : void setSeparatePG(bool separatePG);
222 : };
223 :
224 :
225 : /* User interruption. */
226 :
227 : extern volatile sig_atomic_t _isInterrupted;
228 :
229 : void _interrupted();
230 :
231 : void inline checkInterrupt()
232 9331 : {
233 9331 : if (_isInterrupted) _interrupted();
234 : }
235 :
236 :
237 : /* String packing / unpacking. */
238 : string packStrings(const Strings & strings);
239 : Strings unpackStrings(const string & s);
240 :
241 :
242 : /* Convert the exit status of a child as returned by wait() into an
243 : error string. */
244 : string statusToString(int status);
245 :
246 : bool statusOk(int status);
247 :
248 :
249 : /* Parse a string into an integer. */
250 : bool string2Int(const string & s, int & n);
251 :
252 :
253 : /* !!! HACK HACK HACK - this should be in shared.hh, but it's to
254 : facilitate a quick hack - will remove this eventually (famous last
255 : words). */
256 : struct SwitchToOriginalUser
257 : {
258 : SwitchToOriginalUser();
259 : ~SwitchToOriginalUser();
260 : };
261 :
262 :
263 : #endif /* !__UTIL_H */
|