19 #include <sys/syscall.h>
23 #include <sys/prctl.h>
27 extern char * * environ
;
33 BaseError::BaseError(const FormatOrString
& fs
, unsigned int status
)
40 BaseError
& BaseError::addPrefix(const FormatOrString
& fs
)
42 prefix_
= fs
.s
+ prefix_
;
47 SysError::SysError(const FormatOrString
& fs
)
48 : Error(format("%1%: %2%") % fs
.s
% strerror(errno
))
54 string
getEnv(const string
& key
, const string
& def
)
56 char * value
= getenv(key
.c_str());
57 return value
? string(value
) : def
;
61 Path
absPath(Path path
, Path dir
)
66 /* GNU (aka. GNU/Hurd) doesn't have any limitation on path
67 lengths and doesn't define `PATH_MAX'. */
68 char *buf
= getcwd(NULL
, 0);
72 if (!getcwd(buf
, sizeof(buf
)))
74 throw SysError("cannot get cwd");
80 path
= dir
+ "/" + path
;
82 return canonPath(path
);
86 Path
canonPath(const Path
& path
, bool resolveSymlinks
)
91 throw Error(format("not an absolute path: `%1%'") % path
);
93 string::const_iterator i
= path
.begin(), end
= path
.end();
96 /* Count the number of times we follow a symlink and stop at some
97 arbitrary (but high) limit to prevent infinite loops. */
98 unsigned int followCount
= 0, maxFollow
= 1024;
103 while (i
!= end
&& *i
== '/') i
++;
107 if (*i
== '.' && (i
+ 1 == end
|| i
[1] == '/'))
110 /* If `..', delete the last component. */
111 else if (*i
== '.' && i
+ 1 < end
&& i
[1] == '.' &&
112 (i
+ 2 == end
|| i
[2] == '/'))
114 if (!s
.empty()) s
.erase(s
.rfind('/'));
118 /* Normal component; copy it. */
121 while (i
!= end
&& *i
!= '/') s
+= *i
++;
123 /* If s points to a symlink, resolve it and restart (since
124 the symlink target might contain new symlinks). */
125 if (resolveSymlinks
&& isLink(s
)) {
126 if (++followCount
>= maxFollow
)
127 throw Error(format("infinite symlink recursion in path `%1%'") % path
);
128 temp
= absPath(readLink(s
), dirOf(s
))
130 i
= temp
.begin(); /* restart */
137 return s
.empty() ? "/" : s
;
141 Path
dirOf(const Path
& path
)
143 Path::size_type pos
= path
.rfind('/');
144 if (pos
== string::npos
)
145 throw Error(format("invalid file name `%1%'") % path
);
146 return pos
== 0 ? "/" : Path(path
, 0, pos
);
150 string
baseNameOf(const Path
& path
)
152 Path::size_type pos
= path
.rfind('/');
153 if (pos
== string::npos
)
154 throw Error(format("invalid file name `%1%'") % path
);
155 return string(path
, pos
+ 1);
159 bool isInDir(const Path
& path
, const Path
& dir
)
161 return path
[0] == '/'
162 && string(path
, 0, dir
.size()) == dir
163 && path
.size() >= dir
.size() + 2
164 && path
[dir
.size()] == '/';
168 struct stat
lstat(const Path
& path
)
171 if (lstat(path
.c_str(), &st
))
172 throw SysError(format("getting status of `%1%'") % path
);
177 bool pathExists(const Path
& path
)
181 res
= lstat(path
.c_str(), &st
);
182 if (!res
) return true;
183 if (errno
!= ENOENT
&& errno
!= ENOTDIR
)
184 throw SysError(format("getting status of %1%") % path
);
189 Path
readLink(const Path
& path
)
192 struct stat st
= lstat(path
);
193 if (!S_ISLNK(st
.st_mode
))
194 throw Error(format("`%1%' is not a symlink") % path
);
195 char buf
[st
.st_size
];
196 ssize_t rlsize
= readlink(path
.c_str(), buf
, st
.st_size
);
198 throw SysError(format("reading symbolic link '%1%'") % path
);
199 else if (rlsize
> st
.st_size
)
200 throw Error(format("symbolic link ‘%1%’ size overflow %2% > %3%")
201 % path
% rlsize
% st
.st_size
);
202 return string(buf
, st
.st_size
);
206 bool isLink(const Path
& path
)
208 struct stat st
= lstat(path
);
209 return S_ISLNK(st
.st_mode
);
213 DirEntries
readDirectory(const Path
& path
)
218 AutoCloseDir dir
= opendir(path
.c_str());
219 if (!dir
) throw SysError(format("opening directory `%1%'") % path
);
221 struct dirent
* dirent
;
222 while (errno
= 0, dirent
= readdir(dir
)) { /* sic */
224 string name
= dirent
->d_name
;
225 if (name
== "." || name
== "..") continue;
226 entries
.emplace_back(name
, dirent
->d_ino
, dirent
->d_type
);
228 if (errno
) throw SysError(format("reading directory `%1%'") % path
);
234 unsigned char getFileType(const Path
& path
)
236 struct stat st
= lstat(path
);
237 if (S_ISDIR(st
.st_mode
)) return DT_DIR
;
238 if (S_ISLNK(st
.st_mode
)) return DT_LNK
;
239 if (S_ISREG(st
.st_mode
)) return DT_REG
;
244 string
readFile(int fd
)
247 if (fstat(fd
, &st
) == -1)
248 throw SysError("statting file");
250 unsigned char * buf
= new unsigned char[st
.st_size
];
251 AutoDeleteArray
<unsigned char> d(buf
);
252 readFull(fd
, buf
, st
.st_size
);
254 return string((char *) buf
, st
.st_size
);
258 string
readFile(const Path
& path
, bool drain
)
260 AutoCloseFD fd
= open(path
.c_str(), O_RDONLY
);
262 throw SysError(format("opening file `%1%'") % path
);
263 return drain
? drainFD(fd
) : readFile(fd
);
267 void writeFile(const Path
& path
, const string
& s
)
269 AutoCloseFD fd
= open(path
.c_str(), O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
271 throw SysError(format("opening file '%1%'") % path
);
276 string
readLine(int fd
)
282 ssize_t rd
= read(fd
, &ch
, 1);
285 throw SysError("reading a line");
287 throw EndOfFile("unexpected EOF reading a line");
289 if (ch
== '\n') return s
;
296 void writeLine(int fd
, string s
)
303 static void _deletePath(const Path
& path
, unsigned long long & bytesFreed
)
307 printMsg(lvlVomit
, format("%1%") % path
);
309 struct stat st
= lstat(path
);
311 if (!S_ISDIR(st
.st_mode
) && st
.st_nlink
== 1)
312 bytesFreed
+= st
.st_size
;
314 if (S_ISDIR(st
.st_mode
)) {
315 /* Make the directory writable. */
316 if (!(st
.st_mode
& S_IWUSR
)) {
317 if (chmod(path
.c_str(), st
.st_mode
| S_IWUSR
) == -1)
318 throw SysError(format("making `%1%' writable") % path
);
321 for (auto & i
: readDirectory(path
))
322 _deletePath(path
+ "/" + i
.name
, bytesFreed
);
325 if (remove(path
.c_str()) == -1)
326 throw SysError(format("cannot unlink `%1%'") % path
);
330 void deletePath(const Path
& path
)
332 unsigned long long dummy
;
333 deletePath(path
, dummy
);
337 void deletePath(const Path
& path
, unsigned long long & bytesFreed
)
339 startNest(nest
, lvlDebug
,
340 format("recursively deleting path `%1%'") % path
);
342 _deletePath(path
, bytesFreed
);
346 static Path
tempName(Path tmpRoot
, const Path
& prefix
, bool includePid
,
349 tmpRoot
= canonPath(tmpRoot
.empty() ? getEnv("TMPDIR", "/tmp") : tmpRoot
, true);
351 return (format("%1%/%2%-%3%-%4%") % tmpRoot
% prefix
% getpid() % counter
++).str();
353 return (format("%1%/%2%-%3%") % tmpRoot
% prefix
% counter
++).str();
357 Path
createTempDir(const Path
& tmpRoot
, const Path
& prefix
,
358 bool includePid
, bool useGlobalCounter
, mode_t mode
)
360 static int globalCounter
= 0;
361 int localCounter
= 0;
362 int & counter(useGlobalCounter
? globalCounter
: localCounter
);
366 Path tmpDir
= tempName(tmpRoot
, prefix
, includePid
, counter
);
367 if (mkdir(tmpDir
.c_str(), mode
) == 0) {
368 /* Explicitly set the group of the directory. This is to
369 work around around problems caused by BSD's group
370 ownership semantics (directories inherit the group of
371 the parent). For instance, the group of /tmp on
372 FreeBSD is "wheel", so all directories created in /tmp
373 will be owned by "wheel"; but if the user is not in
374 "wheel", then "tar" will fail to unpack archives that
375 have the setgid bit set on directories. */
376 if (chown(tmpDir
.c_str(), (uid_t
) -1, getegid()) != 0)
377 throw SysError(format("setting group of directory `%1%'") % tmpDir
);
381 throw SysError(format("creating directory `%1%'") % tmpDir
);
386 Paths
createDirs(const Path
& path
)
389 if (path
== "/") return created
;
392 if (lstat(path
.c_str(), &st
) == -1) {
393 created
= createDirs(dirOf(path
));
394 if (mkdir(path
.c_str(), 0777) == -1 && errno
!= EEXIST
)
395 throw SysError(format("creating directory `%1%'") % path
);
397 created
.push_back(path
);
400 if (S_ISLNK(st
.st_mode
) && stat(path
.c_str(), &st
) == -1)
401 throw SysError(format("statting symlink `%1%'") % path
);
403 if (!S_ISDIR(st
.st_mode
)) throw Error(format("`%1%' is not a directory") % path
);
409 void createSymlink(const Path
& target
, const Path
& link
)
411 if (symlink(target
.c_str(), link
.c_str()))
412 throw SysError(format("creating symlink from `%1%' to `%2%'") % link
% target
);
416 LogType logType
= ltPretty
;
417 Verbosity verbosity
= lvlInfo
;
419 static int nestingLevel
= 0;
434 static string
escVerbosity(Verbosity level
)
436 return std::to_string((int) level
);
440 void Nest::open(Verbosity level
, const FormatOrString
& fs
)
442 if (level
<= verbosity
) {
443 if (logType
== ltEscapes
)
444 std::cerr
<< "\033[" << escVerbosity(level
) << "p"
447 printMsg_(level
, fs
);
458 if (logType
== ltEscapes
)
459 std::cerr
<< "\033[q";
465 void printMsg_(Verbosity level
, const FormatOrString
& fs
)
468 if (level
> verbosity
) return;
470 if (logType
== ltPretty
)
471 for (int i
= 0; i
< nestingLevel
; i
++)
473 else if (logType
== ltEscapes
&& level
!= lvlInfo
)
474 prefix
= "\033[" + escVerbosity(level
) + "s";
475 string s
= (format("%1%%2%\n") % prefix
% fs
.s
).str();
480 void warnOnce(bool & haveWarned
, const FormatOrString
& fs
)
483 printMsg(lvlError
, format("warning: %1%") % fs
.s
);
489 void writeToStderr(const string
& s
)
493 _writeToStderr((const unsigned char *) s
.data(), s
.size());
495 writeFull(STDERR_FILENO
, s
);
496 } catch (SysError
& e
) {
497 /* Ignore failing writes to stderr if we're in an exception
498 handler, otherwise throw an exception. We need to ignore
499 write errors in exception handlers to ensure that cleanup
500 code runs to completion if the other side of stderr has
501 been closed unexpectedly. */
502 if (!std::uncaught_exception()) throw;
507 void (*_writeToStderr
) (const unsigned char * buf
, size_t count
) = 0;
510 void readFull(int fd
, unsigned char * buf
, size_t count
)
514 ssize_t res
= read(fd
, (char *) buf
, count
);
516 if (errno
== EINTR
) continue;
517 throw SysError("reading from file");
519 if (res
== 0) throw EndOfFile("unexpected end-of-file");
526 void writeFull(int fd
, const unsigned char * buf
, size_t count
)
530 ssize_t res
= write(fd
, (char *) buf
, count
);
532 if (errno
== EINTR
) continue;
533 throw SysError("writing to file");
541 void writeFull(int fd
, const string
& s
)
543 writeFull(fd
, (const unsigned char *) s
.data(), s
.size());
547 string
drainFD(int fd
)
550 unsigned char buffer
[4096];
553 ssize_t rd
= read(fd
, buffer
, sizeof buffer
);
556 throw SysError("reading from file");
558 else if (rd
== 0) break;
559 else result
.append((char *) buffer
, rd
);
566 //////////////////////////////////////////////////////////////////////
569 AutoDelete::AutoDelete(const string
& p
, bool recursive
) : path(p
)
572 this->recursive
= recursive
;
575 AutoDelete::~AutoDelete()
582 if (remove(path
.c_str()) == -1)
583 throw SysError(format("cannot unlink `%1%'") % path
);
591 void AutoDelete::cancel()
598 //////////////////////////////////////////////////////////////////////
601 AutoCloseFD::AutoCloseFD()
607 AutoCloseFD::AutoCloseFD(int fd
)
613 AutoCloseFD::AutoCloseFD(const AutoCloseFD
& fd
)
615 /* Copying an AutoCloseFD isn't allowed (who should get to close
616 it?). But as an edge case, allow copying of closed
617 AutoCloseFDs. This is necessary due to tiresome reasons
618 involving copy constructor use on default object values in STL
619 containers (like when you do `map[value]' where value isn't in
622 if (this->fd
!= -1) abort();
626 AutoCloseFD::~AutoCloseFD()
636 void AutoCloseFD::operator =(int fd
)
638 if (this->fd
!= fd
) close();
643 AutoCloseFD::operator int() const
649 void AutoCloseFD::close()
652 if (::close(fd
) == -1)
653 /* This should never happen. */
654 throw SysError(format("closing file descriptor %1%") % fd
);
660 bool AutoCloseFD::isOpen()
666 /* Pass responsibility for closing this fd to the caller. */
667 int AutoCloseFD::borrow()
678 if (pipe(fds
) != 0) throw SysError("creating pipe");
681 closeOnExec(readSide
);
682 closeOnExec(writeSide
);
687 //////////////////////////////////////////////////////////////////////
690 AutoCloseDir::AutoCloseDir()
696 AutoCloseDir::AutoCloseDir(DIR * dir
)
702 AutoCloseDir::~AutoCloseDir()
708 void AutoCloseDir::operator =(DIR * dir
)
714 AutoCloseDir::operator DIR *()
720 void AutoCloseDir::close()
729 //////////////////////////////////////////////////////////////////////
733 : pid(-1), separatePG(false), killSignal(SIGKILL
)
739 : pid(pid
), separatePG(false), killSignal(SIGKILL
)
750 void Pid::operator =(pid_t pid
)
752 if (this->pid
!= pid
) kill();
754 killSignal
= SIGKILL
; // reset signal to default
758 Pid::operator pid_t()
764 void Pid::kill(bool quiet
)
766 if (pid
== -1 || pid
== 0) return;
769 printMsg(lvlError
, format("killing process %1%") % pid
);
771 /* Send the requested signal to the child. If it has its own
772 process group, send the signal to every process in the child
773 process group (which hopefully includes *all* its children). */
774 if (::kill(separatePG
? -pid
: pid
, killSignal
) != 0)
775 printMsg(lvlError
, (SysError(format("killing process %1%") % pid
).msg()));
777 /* Wait until the child dies, disregarding the exit status. */
779 while (waitpid(pid
, &status
, 0) == -1) {
781 if (errno
!= EINTR
) {
783 (SysError(format("waiting for process %1%") % pid
).msg()));
792 int Pid::wait(bool block
)
797 int res
= waitpid(pid
, &status
, block
? 0 : WNOHANG
);
802 if (res
== 0 && !block
) return -1;
804 throw SysError("cannot get child exit status");
810 void Pid::setSeparatePG(bool separatePG
)
812 this->separatePG
= separatePG
;
816 void Pid::setKillSignal(int signal
)
818 this->killSignal
= signal
;
822 void killUser(uid_t uid
)
824 debug(format("killing all processes running under uid `%1%'") % uid
);
826 assert(uid
!= 0); /* just to be safe... */
828 /* The system call kill(-1, sig) sends the signal `sig' to all
829 users to which the current process can send signals. So we
830 fork a process, switch to uid, and send a mass kill. */
832 Pid pid
= startProcess([&]() {
834 if (setuid(uid
) == -1)
835 throw SysError("setting uid");
839 /* OSX's kill syscall takes a third parameter that, among
840 other things, determines if kill(-1, signo) affects the
841 calling process. In the OSX libc, it's set to true,
842 which means "follow POSIX", which we don't want here
844 if (syscall(SYS_kill
, -1, SIGKILL
, false) == 0) break;
846 if (kill(-1, SIGKILL
) == 0) break;
848 if (errno
== ESRCH
) break; /* no more processes */
850 throw SysError(format("cannot kill processes for uid `%1%'") % uid
);
856 int status
= pid
.wait(true);
858 throw Error(format("cannot kill processes for uid `%1%': %2%") % uid
% statusToString(status
));
860 /* !!! We should really do some check to make sure that there are
861 no processes left running under `uid', but there is no portable
862 way to do so (I think). The most reliable way may be `ps -eo
863 uid | grep -q $uid'. */
867 //////////////////////////////////////////////////////////////////////
870 pid_t
startProcess(std::function
<void()> fun
,
871 bool dieWithParent
, const string
& errorPrefix
, bool runExitHandlers
)
874 if (pid
== -1) throw SysError("unable to fork");
880 if (dieWithParent
&& prctl(PR_SET_PDEATHSIG
, SIGKILL
) == -1)
881 throw SysError("setting death signal");
885 } catch (std::exception
& e
) {
887 std::cerr
<< errorPrefix
<< e
.what() << "\n";
900 std::vector
<char *> stringsToCharPtrs(const Strings
& ss
)
902 std::vector
<char *> res
;
903 for (auto & s
: ss
) res
.push_back((char *) s
.c_str());
909 string
runProgram(Path program
, bool searchPath
, const Strings
& args
)
918 Pid pid
= startProcess([&]() {
919 if (dup2(pipe
.writeSide
, STDOUT_FILENO
) == -1)
920 throw SysError("dupping stdout");
923 args_
.push_front(program
);
926 execvp(program
.c_str(), stringsToCharPtrs(args_
).data());
928 execv(program
.c_str(), stringsToCharPtrs(args_
).data());
930 throw SysError(format("executing `%1%'") % program
);
933 pipe
.writeSide
.close();
935 string result
= drainFD(pipe
.readSide
);
937 /* Wait for the child to finish. */
938 int status
= pid
.wait(true);
939 if (!statusOk(status
))
940 throw ExecError(format("program `%1%' %2%")
941 % program
% statusToString(status
));
947 void closeMostFDs(const set
<int> & exceptions
)
950 maxFD
= sysconf(_SC_OPEN_MAX
);
951 for (int fd
= 0; fd
< maxFD
; ++fd
)
952 if (fd
!= STDIN_FILENO
&& fd
!= STDOUT_FILENO
&& fd
!= STDERR_FILENO
953 && exceptions
.find(fd
) == exceptions
.end())
954 close(fd
); /* ignore result */
958 void closeOnExec(int fd
)
961 if ((prev
= fcntl(fd
, F_GETFD
, 0)) == -1 ||
962 fcntl(fd
, F_SETFD
, prev
| FD_CLOEXEC
) == -1)
963 throw SysError("setting close-on-exec flag");
967 //////////////////////////////////////////////////////////////////////
970 volatile sig_atomic_t _isInterrupted
= 0;
974 /* Block user interrupts while an exception is being handled.
975 Throwing an exception while another exception is being handled
976 kills the program! */
977 if (!std::uncaught_exception()) {
979 throw Interrupted("interrupted by the user");
985 //////////////////////////////////////////////////////////////////////
988 template<class C
> C
tokenizeString(const string
& s
, const string
& separators
)
991 string::size_type pos
= s
.find_first_not_of(separators
, 0);
992 while (pos
!= string::npos
) {
993 string::size_type end
= s
.find_first_of(separators
, pos
+ 1);
994 if (end
== string::npos
) end
= s
.size();
995 string
token(s
, pos
, end
- pos
);
996 result
.insert(result
.end(), token
);
997 pos
= s
.find_first_not_of(separators
, end
);
1002 template Strings
tokenizeString(const string
& s
, const string
& separators
);
1003 template StringSet
tokenizeString(const string
& s
, const string
& separators
);
1004 template vector
<string
> tokenizeString(const string
& s
, const string
& separators
);
1007 string
concatStringsSep(const string
& sep
, const Strings
& ss
)
1010 foreach (Strings::const_iterator
, i
, ss
) {
1011 if (s
.size() != 0) s
+= sep
;
1018 string
concatStringsSep(const string
& sep
, const StringSet
& ss
)
1021 foreach (StringSet::const_iterator
, i
, ss
) {
1022 if (s
.size() != 0) s
+= sep
;
1029 string
chomp(const string
& s
)
1031 size_t i
= s
.find_last_not_of(" \n\r\t");
1032 return i
== string::npos
? "" : string(s
, 0, i
+ 1);
1036 string
statusToString(int status
)
1038 if (!WIFEXITED(status
) || WEXITSTATUS(status
) != 0) {
1039 if (WIFEXITED(status
))
1040 return (format("failed with exit code %1%") % WEXITSTATUS(status
)).str();
1041 else if (WIFSIGNALED(status
)) {
1042 int sig
= WTERMSIG(status
);
1044 const char * description
= strsignal(sig
);
1045 return (format("failed due to signal %1% (%2%)") % sig
% description
).str();
1047 return (format("failed due to signal %1%") % sig
).str();
1051 return "died abnormally";
1052 } else return "succeeded";
1056 bool statusOk(int status
)
1058 return WIFEXITED(status
) && WEXITSTATUS(status
) == 0;
1062 bool hasSuffix(const string
& s
, const string
& suffix
)
1064 return s
.size() >= suffix
.size() && string(s
, s
.size() - suffix
.size()) == suffix
;
1068 void expect(std::istream
& str
, const string
& s
)
1071 str
.read(s2
, s
.size());
1072 if (string(s2
, s
.size()) != s
)
1073 throw FormatError(format("expected string `%1%'") % s
);
1077 string
parseString(std::istream
& str
)
1082 while ((c
= str
.get()) != '"')
1085 if (c
== 'n') res
+= '\n';
1086 else if (c
== 'r') res
+= '\r';
1087 else if (c
== 't') res
+= '\t';
1095 bool endOfList(std::istream
& str
)
1097 if (str
.peek() == ',') {
1101 if (str
.peek() == ']') {
1109 void ignoreException()
1113 } catch (std::exception
& e
) {
1114 printMsg(lvlError
, format("error (ignored): %1%") % e
.what());