16 #include <sys/syscall.h>
22 extern char * * environ
;
28 BaseError::BaseError(const FormatOrString
& fs
, unsigned int status
)
35 BaseError
& BaseError::addPrefix(const FormatOrString
& fs
)
37 prefix_
= fs
.s
+ prefix_
;
42 SysError::SysError(const FormatOrString
& fs
)
43 : Error(format("%1%: %2%") % fs
.s
% strerror(errno
))
49 string
getEnv(const string
& key
, const string
& def
)
51 char * value
= getenv(key
.c_str());
52 return value
? string(value
) : def
;
56 Path
absPath(Path path
, Path dir
)
61 /* GNU (aka. GNU/Hurd) doesn't have any limitation on path
62 lengths and doesn't define `PATH_MAX'. */
63 char *buf
= getcwd(NULL
, 0);
67 if (!getcwd(buf
, sizeof(buf
)))
69 throw SysError("cannot get cwd");
75 path
= dir
+ "/" + path
;
77 return canonPath(path
);
81 Path
canonPath(const Path
& path
, bool resolveSymlinks
)
86 throw Error(format("not an absolute path: `%1%'") % path
);
88 string::const_iterator i
= path
.begin(), end
= path
.end();
91 /* Count the number of times we follow a symlink and stop at some
92 arbitrary (but high) limit to prevent infinite loops. */
93 unsigned int followCount
= 0, maxFollow
= 1024;
98 while (i
!= end
&& *i
== '/') i
++;
102 if (*i
== '.' && (i
+ 1 == end
|| i
[1] == '/'))
105 /* If `..', delete the last component. */
106 else if (*i
== '.' && i
+ 1 < end
&& i
[1] == '.' &&
107 (i
+ 2 == end
|| i
[2] == '/'))
109 if (!s
.empty()) s
.erase(s
.rfind('/'));
113 /* Normal component; copy it. */
116 while (i
!= end
&& *i
!= '/') s
+= *i
++;
118 /* If s points to a symlink, resolve it and restart (since
119 the symlink target might contain new symlinks). */
120 if (resolveSymlinks
&& isLink(s
)) {
121 if (++followCount
>= maxFollow
)
122 throw Error(format("infinite symlink recursion in path `%1%'") % path
);
123 temp
= absPath(readLink(s
), dirOf(s
))
125 i
= temp
.begin(); /* restart */
128 /* !!! potential for infinite loop */
133 return s
.empty() ? "/" : s
;
137 Path
dirOf(const Path
& path
)
139 Path::size_type pos
= path
.rfind('/');
140 if (pos
== string::npos
)
141 throw Error(format("invalid file name `%1%'") % path
);
142 return pos
== 0 ? "/" : Path(path
, 0, pos
);
146 string
baseNameOf(const Path
& path
)
148 Path::size_type pos
= path
.rfind('/');
149 if (pos
== string::npos
)
150 throw Error(format("invalid file name `%1%'") % path
);
151 return string(path
, pos
+ 1);
155 bool isInDir(const Path
& path
, const Path
& dir
)
157 return path
[0] == '/'
158 && string(path
, 0, dir
.size()) == dir
159 && path
.size() >= dir
.size() + 2
160 && path
[dir
.size()] == '/';
164 struct stat
lstat(const Path
& path
)
167 if (lstat(path
.c_str(), &st
))
168 throw SysError(format("getting status of `%1%'") % path
);
173 bool pathExists(const Path
& path
)
177 res
= lstat(path
.c_str(), &st
);
178 if (!res
) return true;
179 if (errno
!= ENOENT
&& errno
!= ENOTDIR
)
180 throw SysError(format("getting status of %1%") % path
);
185 Path
readLink(const Path
& path
)
188 struct stat st
= lstat(path
);
189 if (!S_ISLNK(st
.st_mode
))
190 throw Error(format("`%1%' is not a symlink") % path
);
191 char buf
[st
.st_size
];
192 if (readlink(path
.c_str(), buf
, st
.st_size
) != st
.st_size
)
193 throw SysError(format("reading symbolic link `%1%'") % path
);
194 return string(buf
, st
.st_size
);
198 bool isLink(const Path
& path
)
200 struct stat st
= lstat(path
);
201 return S_ISLNK(st
.st_mode
);
205 Strings
readDirectory(const Path
& path
)
209 AutoCloseDir dir
= opendir(path
.c_str());
210 if (!dir
) throw SysError(format("opening directory `%1%'") % path
);
212 struct dirent
* dirent
;
213 while (errno
= 0, dirent
= readdir(dir
)) { /* sic */
215 string name
= dirent
->d_name
;
216 if (name
== "." || name
== "..") continue;
217 names
.push_back(name
);
219 if (errno
) throw SysError(format("reading directory `%1%'") % path
);
225 string
readFile(int fd
)
228 if (fstat(fd
, &st
) == -1)
229 throw SysError("statting file");
231 unsigned char * buf
= new unsigned char[st
.st_size
];
232 AutoDeleteArray
<unsigned char> d(buf
);
233 readFull(fd
, buf
, st
.st_size
);
235 return string((char *) buf
, st
.st_size
);
239 string
readFile(const Path
& path
, bool drain
)
241 AutoCloseFD fd
= open(path
.c_str(), O_RDONLY
);
243 throw SysError(format("opening file `%1%'") % path
);
244 return drain
? drainFD(fd
) : readFile(fd
);
248 void writeFile(const Path
& path
, const string
& s
)
250 AutoCloseFD fd
= open(path
.c_str(), O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
252 throw SysError(format("opening file `%1%'") % path
);
253 writeFull(fd
, (unsigned char *) s
.data(), s
.size());
257 string
readLine(int fd
)
263 ssize_t rd
= read(fd
, &ch
, 1);
266 throw SysError("reading a line");
268 throw EndOfFile("unexpected EOF reading a line");
270 if (ch
== '\n') return s
;
277 void writeLine(int fd
, string s
)
280 writeFull(fd
, (const unsigned char *) s
.data(), s
.size());
284 static void _deletePath(const Path
& path
, unsigned long long & bytesFreed
)
288 printMsg(lvlVomit
, format("%1%") % path
);
290 struct stat st
= lstat(path
);
292 if (!S_ISDIR(st
.st_mode
) && st
.st_nlink
== 1)
293 bytesFreed
+= st
.st_blocks
* 512;
295 if (S_ISDIR(st
.st_mode
)) {
296 Strings names
= readDirectory(path
);
298 /* Make the directory writable. */
299 if (!(st
.st_mode
& S_IWUSR
)) {
300 if (chmod(path
.c_str(), st
.st_mode
| S_IWUSR
) == -1)
301 throw SysError(format("making `%1%' writable") % path
);
304 for (Strings::iterator i
= names
.begin(); i
!= names
.end(); ++i
)
305 _deletePath(path
+ "/" + *i
, bytesFreed
);
308 if (remove(path
.c_str()) == -1)
309 throw SysError(format("cannot unlink `%1%'") % path
);
313 void deletePath(const Path
& path
)
315 unsigned long long dummy
;
316 deletePath(path
, dummy
);
320 void deletePath(const Path
& path
, unsigned long long & bytesFreed
)
322 startNest(nest
, lvlDebug
,
323 format("recursively deleting path `%1%'") % path
);
325 _deletePath(path
, bytesFreed
);
329 static Path
tempName(Path tmpRoot
, const Path
& prefix
, bool includePid
,
332 tmpRoot
= canonPath(tmpRoot
.empty() ? getEnv("TMPDIR", "/tmp") : tmpRoot
, true);
334 return (format("%1%/%2%-%3%-%4%") % tmpRoot
% prefix
% getpid() % counter
++).str();
336 return (format("%1%/%2%-%3%") % tmpRoot
% prefix
% counter
++).str();
340 Path
createTempDir(const Path
& tmpRoot
, const Path
& prefix
,
341 bool includePid
, bool useGlobalCounter
, mode_t mode
)
343 static int globalCounter
= 0;
344 int localCounter
= 0;
345 int & counter(useGlobalCounter
? globalCounter
: localCounter
);
349 Path tmpDir
= tempName(tmpRoot
, prefix
, includePid
, counter
);
350 if (mkdir(tmpDir
.c_str(), mode
) == 0) {
351 /* Explicitly set the group of the directory. This is to
352 work around around problems caused by BSD's group
353 ownership semantics (directories inherit the group of
354 the parent). For instance, the group of /tmp on
355 FreeBSD is "wheel", so all directories created in /tmp
356 will be owned by "wheel"; but if the user is not in
357 "wheel", then "tar" will fail to unpack archives that
358 have the setgid bit set on directories. */
359 if (chown(tmpDir
.c_str(), (uid_t
) -1, getegid()) != 0)
360 throw SysError(format("setting group of directory `%1%'") % tmpDir
);
364 throw SysError(format("creating directory `%1%'") % tmpDir
);
369 Paths
createDirs(const Path
& path
)
372 if (path
== "/") return created
;
375 if (lstat(path
.c_str(), &st
) == -1) {
376 created
= createDirs(dirOf(path
));
377 if (mkdir(path
.c_str(), 0777) == -1 && errno
!= EEXIST
)
378 throw SysError(format("creating directory `%1%'") % path
);
380 created
.push_back(path
);
383 if (!S_ISDIR(st
.st_mode
)) throw Error(format("`%1%' is not a directory") % path
);
389 void createSymlink(const Path
& target
, const Path
& link
)
391 if (symlink(target
.c_str(), link
.c_str()))
392 throw SysError(format("creating symlink from `%1%' to `%2%'") % link
% target
);
396 LogType logType
= ltPretty
;
397 Verbosity verbosity
= lvlInfo
;
399 static int nestingLevel
= 0;
414 static string
escVerbosity(Verbosity level
)
416 return int2String((int) level
);
420 void Nest::open(Verbosity level
, const FormatOrString
& fs
)
422 if (level
<= verbosity
) {
423 if (logType
== ltEscapes
)
424 std::cerr
<< "\033[" << escVerbosity(level
) << "p"
427 printMsg_(level
, fs
);
438 if (logType
== ltEscapes
)
439 std::cerr
<< "\033[q";
445 void printMsg_(Verbosity level
, const FormatOrString
& fs
)
448 if (level
> verbosity
) return;
450 if (logType
== ltPretty
)
451 for (int i
= 0; i
< nestingLevel
; i
++)
453 else if (logType
== ltEscapes
&& level
!= lvlInfo
)
454 prefix
= "\033[" + escVerbosity(level
) + "s";
455 string s
= (format("%1%%2%\n") % prefix
% fs
.s
).str();
460 void warnOnce(bool & haveWarned
, const FormatOrString
& fs
)
463 printMsg(lvlError
, format("warning: %1%") % fs
.s
);
469 void writeToStderr(const string
& s
)
472 _writeToStderr((const unsigned char *) s
.data(), s
.size());
473 } catch (SysError
& e
) {
474 /* Ignore failing writes to stderr if we're in an exception
475 handler, otherwise throw an exception. We need to ignore
476 write errors in exception handlers to ensure that cleanup
477 code runs to completion if the other side of stderr has
478 been closed unexpectedly. */
479 if (!std::uncaught_exception()) throw;
484 static void defaultWriteToStderr(const unsigned char * buf
, size_t count
)
486 writeFull(STDERR_FILENO
, buf
, count
);
490 void (*_writeToStderr
) (const unsigned char * buf
, size_t count
) = defaultWriteToStderr
;
493 void readFull(int fd
, unsigned char * buf
, size_t count
)
497 ssize_t res
= read(fd
, (char *) buf
, count
);
499 if (errno
== EINTR
) continue;
500 throw SysError("reading from file");
502 if (res
== 0) throw EndOfFile("unexpected end-of-file");
509 void writeFull(int fd
, const unsigned char * buf
, size_t count
)
513 ssize_t res
= write(fd
, (char *) buf
, count
);
515 if (errno
== EINTR
) continue;
516 throw SysError("writing to file");
524 string
drainFD(int fd
)
527 unsigned char buffer
[4096];
530 ssize_t rd
= read(fd
, buffer
, sizeof buffer
);
533 throw SysError("reading from file");
535 else if (rd
== 0) break;
536 else result
.append((char *) buffer
, rd
);
543 //////////////////////////////////////////////////////////////////////
546 AutoDelete::AutoDelete(const string
& p
, bool recursive
) : path(p
)
549 this->recursive
= recursive
;
552 AutoDelete::~AutoDelete()
559 if (remove(path
.c_str()) == -1)
560 throw SysError(format("cannot unlink `%1%'") % path
);
568 void AutoDelete::cancel()
575 //////////////////////////////////////////////////////////////////////
578 AutoCloseFD::AutoCloseFD()
584 AutoCloseFD::AutoCloseFD(int fd
)
590 AutoCloseFD::AutoCloseFD(const AutoCloseFD
& fd
)
592 /* Copying an AutoCloseFD isn't allowed (who should get to close
593 it?). But as an edge case, allow copying of closed
594 AutoCloseFDs. This is necessary due to tiresome reasons
595 involving copy constructor use on default object values in STL
596 containers (like when you do `map[value]' where value isn't in
599 if (this->fd
!= -1) abort();
603 AutoCloseFD::~AutoCloseFD()
613 void AutoCloseFD::operator =(int fd
)
615 if (this->fd
!= fd
) close();
620 AutoCloseFD::operator int() const
626 void AutoCloseFD::close()
629 if (::close(fd
) == -1)
630 /* This should never happen. */
631 throw SysError(format("closing file descriptor %1%") % fd
);
637 bool AutoCloseFD::isOpen()
643 /* Pass responsibility for closing this fd to the caller. */
644 int AutoCloseFD::borrow()
655 if (pipe(fds
) != 0) throw SysError("creating pipe");
658 closeOnExec(readSide
);
659 closeOnExec(writeSide
);
664 //////////////////////////////////////////////////////////////////////
667 AutoCloseDir::AutoCloseDir()
673 AutoCloseDir::AutoCloseDir(DIR * dir
)
679 AutoCloseDir::~AutoCloseDir()
685 void AutoCloseDir::operator =(DIR * dir
)
691 AutoCloseDir::operator DIR *()
697 void AutoCloseDir::close()
706 //////////////////////////////////////////////////////////////////////
713 killSignal
= SIGKILL
;
723 void Pid::operator =(pid_t pid
)
725 if (this->pid
!= pid
) kill();
727 killSignal
= SIGKILL
; // reset signal to default
731 Pid::operator pid_t()
739 if (pid
== -1 || pid
== 0) return;
741 printMsg(lvlError
, format("killing process %1%") % pid
);
743 /* Send the requested signal to the child. If it has its own
744 process group, send the signal to every process in the child
745 process group (which hopefully includes *all* its children). */
746 if (::kill(separatePG
? -pid
: pid
, killSignal
) != 0)
747 printMsg(lvlError
, (SysError(format("killing process %1%") % pid
).msg()));
749 /* Wait until the child dies, disregarding the exit status. */
751 while (waitpid(pid
, &status
, 0) == -1) {
753 if (errno
!= EINTR
) {
755 (SysError(format("waiting for process %1%") % pid
).msg()));
764 int Pid::wait(bool block
)
769 int res
= waitpid(pid
, &status
, block
? 0 : WNOHANG
);
774 if (res
== 0 && !block
) return -1;
776 throw SysError("cannot get child exit status");
782 void Pid::setSeparatePG(bool separatePG
)
784 this->separatePG
= separatePG
;
788 void Pid::setKillSignal(int signal
)
790 this->killSignal
= signal
;
794 void killUser(uid_t uid
)
796 debug(format("killing all processes running under uid `%1%'") % uid
);
798 assert(uid
!= 0); /* just to be safe... */
800 /* The system call kill(-1, sig) sends the signal `sig' to all
801 users to which the current process can send signals. So we
802 fork a process, switch to uid, and send a mass kill. */
809 throw SysError("unable to fork");
814 if (setuid(uid
) == -1)
815 throw SysError("setting uid");
819 /* OSX's kill syscall takes a third parameter that, among other
820 things, determines if kill(-1, signo) affects the calling
821 process. In the OSX libc, it's set to true, which means
822 "follow POSIX", which we don't want here
824 if (syscall(SYS_kill
, -1, SIGKILL
, false) == 0) break;
826 if (kill(-1, SIGKILL
) == 0) break;
828 if (errno
== ESRCH
) break; /* no more processes */
830 throw SysError(format("cannot kill processes for uid `%1%'") % uid
);
833 } catch (std::exception
& e
) {
834 writeToStderr((format("killing processes belonging to uid `%1%': %2%\n") % uid
% e
.what()).str());
841 int status
= pid
.wait(true);
843 throw Error(format("cannot kill processes for uid `%1%': %2%") % uid
% statusToString(status
));
845 /* !!! We should really do some check to make sure that there are
846 no processes left running under `uid', but there is no portable
847 way to do so (I think). The most reliable way may be `ps -eo
848 uid | grep -q $uid'. */
852 //////////////////////////////////////////////////////////////////////
855 std::vector
<const char *> stringsToCharPtrs(const Strings
& ss
)
857 std::vector
<const char *> res
;
858 foreach (Strings::const_iterator
, i
, ss
)
859 res
.push_back(i
->c_str());
865 string
runProgram(Path program
, bool searchPath
, const Strings
& args
)
880 throw SysError("unable to fork");
884 if (dup2(pipe
.writeSide
, STDOUT_FILENO
) == -1)
885 throw SysError("dupping stdout");
888 args_
.push_front(program
);
889 auto cargs
= stringsToCharPtrs(args_
);
892 execvp(program
.c_str(), (char * *) &cargs
[0]);
894 execv(program
.c_str(), (char * *) &cargs
[0]);
895 throw SysError(format("executing `%1%'") % program
);
897 } catch (std::exception
& e
) {
898 writeToStderr("error: " + string(e
.what()) + "\n");
905 pipe
.writeSide
.close();
907 string result
= drainFD(pipe
.readSide
);
909 /* Wait for the child to finish. */
910 int status
= pid
.wait(true);
911 if (!statusOk(status
))
912 throw Error(format("program `%1%' %2%")
913 % program
% statusToString(status
));
919 void closeMostFDs(const set
<int> & exceptions
)
922 maxFD
= sysconf(_SC_OPEN_MAX
);
923 for (int fd
= 0; fd
< maxFD
; ++fd
)
924 if (fd
!= STDIN_FILENO
&& fd
!= STDOUT_FILENO
&& fd
!= STDERR_FILENO
925 && exceptions
.find(fd
) == exceptions
.end())
926 close(fd
); /* ignore result */
930 void closeOnExec(int fd
)
933 if ((prev
= fcntl(fd
, F_GETFD
, 0)) == -1 ||
934 fcntl(fd
, F_SETFD
, prev
| FD_CLOEXEC
) == -1)
935 throw SysError("setting close-on-exec flag");
940 pid_t (*maybeVfork
)() = vfork
;
942 pid_t (*maybeVfork
)() = fork
;
946 //////////////////////////////////////////////////////////////////////
949 volatile sig_atomic_t _isInterrupted
= 0;
953 /* Block user interrupts while an exception is being handled.
954 Throwing an exception while another exception is being handled
955 kills the program! */
956 if (!std::uncaught_exception()) {
958 throw Interrupted("interrupted by the user");
964 //////////////////////////////////////////////////////////////////////
967 template<class C
> C
tokenizeString(const string
& s
, const string
& separators
)
970 string::size_type pos
= s
.find_first_not_of(separators
, 0);
971 while (pos
!= string::npos
) {
972 string::size_type end
= s
.find_first_of(separators
, pos
+ 1);
973 if (end
== string::npos
) end
= s
.size();
974 string
token(s
, pos
, end
- pos
);
975 result
.insert(result
.end(), token
);
976 pos
= s
.find_first_not_of(separators
, end
);
981 template Strings
tokenizeString(const string
& s
, const string
& separators
);
982 template StringSet
tokenizeString(const string
& s
, const string
& separators
);
983 template vector
<string
> tokenizeString(const string
& s
, const string
& separators
);
986 string
concatStringsSep(const string
& sep
, const Strings
& ss
)
989 foreach (Strings::const_iterator
, i
, ss
) {
990 if (s
.size() != 0) s
+= sep
;
997 string
concatStringsSep(const string
& sep
, const StringSet
& ss
)
1000 foreach (StringSet::const_iterator
, i
, ss
) {
1001 if (s
.size() != 0) s
+= sep
;
1008 string
chomp(const string
& s
)
1010 size_t i
= s
.find_last_not_of(" \n\r\t");
1011 return i
== string::npos
? "" : string(s
, 0, i
+ 1);
1015 string
statusToString(int status
)
1017 if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
1018 if (WIFEXITED(status
))
1019 return (format("failed with exit code %1%") % WEXITSTATUS(status
)).str();
1020 else if (WIFSIGNALED(status
)) {
1021 int sig
= WTERMSIG(status
);
1023 const char * description
= strsignal(sig
);
1024 return (format("failed due to signal %1% (%2%)") % sig
% description
).str();
1026 return (format("failed due to signal %1%") % sig
).str();
1030 return "died abnormally";
1031 } else return "succeeded";
1035 bool statusOk(int status
)
1037 return WIFEXITED(status
) && WEXITSTATUS(status
) == 0;
1041 bool hasSuffix(const string
& s
, const string
& suffix
)
1043 return s
.size() >= suffix
.size() && string(s
, s
.size() - suffix
.size()) == suffix
;
1047 void expect(std::istream
& str
, const string
& s
)
1050 str
.read(s2
, s
.size());
1051 if (string(s2
, s
.size()) != s
)
1052 throw FormatError(format("expected string `%1%'") % s
);
1056 string
parseString(std::istream
& str
)
1061 while ((c
= str
.get()) != '"')
1064 if (c
== 'n') res
+= '\n';
1065 else if (c
== 'r') res
+= '\r';
1066 else if (c
== 't') res
+= '\t';
1074 bool endOfList(std::istream
& str
)
1076 if (str
.peek() == ',') {
1080 if (str
.peek() == ']') {
1088 string
decodeOctalEscaped(const string
& s
)
1091 for (string::const_iterator i
= s
.begin(); i
!= s
.end(); ) {
1092 if (*i
!= '\\') { r
+= *i
++; continue; }
1093 unsigned char c
= 0;
1095 while (i
!= s
.end() && *i
>= '0' && *i
< '8')
1096 c
= c
* 8 + (*i
++ - '0');
1103 void ignoreException()
1107 } catch (std::exception
& e
) {
1108 printMsg(lvlError
, format("error (ignored): %1%") % e
.what());