about summary refs log tree commit diff
path: root/src/libutil
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/archive.cc6
-rw-r--r--src/libutil/util.cc17
-rw-r--r--src/libutil/util.hh13
3 files changed, 36 insertions, 0 deletions
diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc
index 90a039164b58..2b8fb2f10adb 100644
--- a/src/libutil/archive.cc
+++ b/src/libutil/archive.cc
@@ -83,6 +83,7 @@ static void dumpContents(const Path & path, unsigned int size,
     unsigned int total = 0;
     ssize_t n;
     while ((n = read(fd, buf, sizeof(buf)))) {
+        checkInterrupt();
         if (n == -1) throw SysError("reading file " + path);
         total += n;
         sink(buf, n);
@@ -200,6 +201,8 @@ static void restoreEntry(const Path & path, RestoreSource & source)
     if (s != "(") throw badArchive("expected open tag");
 
     while (1) {
+        checkInterrupt();
+
         s = readString(source);
 
         if (s == ")") {
@@ -224,6 +227,7 @@ static void restoreContents(int fd, const Path & path, RestoreSource & source)
     unsigned char buf[65536];
 
     while (left) {
+        checkInterrupt();
         unsigned int n = sizeof(buf);
         if (n > left) n = left;
         source(buf, n);
@@ -247,6 +251,8 @@ static void restore(const Path & path, RestoreSource & source)
     AutoCloseFD fd;
 
     while (1) {
+        checkInterrupt();
+
         s = readString(source);
 
         if (s == ")") {
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 28e276a329b3..5c8b7279c42d 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -132,6 +132,7 @@ Strings readDirectory(const Path & path)
 
     struct dirent * dirent;
     while (errno = 0, dirent = readdir(dir)) { /* sic */
+        checkInterrupt();
         string name = dirent->d_name;
         if (name == "." || name == "..") continue;
         names.push_back(name);
@@ -144,6 +145,8 @@ Strings readDirectory(const Path & path)
 
 void deletePath(const Path & path)
 {
+    checkInterrupt();
+
     printMsg(lvlVomit, format("deleting path `%1%'") % path);
 
     struct stat st;
@@ -170,6 +173,8 @@ void deletePath(const Path & path)
 
 void makePathReadOnly(const Path & path)
 {
+    checkInterrupt();
+
     struct stat st;
     if (lstat(path.c_str(), &st))
 	throw SysError(format("getting attributes of path `%1%'") % path);
@@ -199,6 +204,7 @@ static Path tempName()
 Path createTempDir()
 {
     while (1) {
+        checkInterrupt();
 	Path tmpDir = tempName();
 	if (mkdir(tmpDir.c_str(), 0777) == 0) return tmpDir;
 	if (errno != EEXIST)
@@ -246,6 +252,7 @@ void Nest::open(Verbosity level, const format & f)
 
 void printMsg_(Verbosity level, const format & f)
 {
+    checkInterrupt();
     if (level > verbosity) return;
     string spaces;
     for (int i = 0; i < nestingLevel; i++)
@@ -257,6 +264,7 @@ void printMsg_(Verbosity level, const format & f)
 void readFull(int fd, unsigned char * buf, size_t count)
 {
     while (count) {
+        checkInterrupt();
         ssize_t res = read(fd, (char *) buf, count);
         if (res == -1) throw SysError("reading from file");
         if (res == 0) throw Error("unexpected end-of-file");
@@ -269,6 +277,7 @@ void readFull(int fd, unsigned char * buf, size_t count)
 void writeFull(int fd, const unsigned char * buf, size_t count)
 {
     while (count) {
+        checkInterrupt();
         ssize_t res = write(fd, (char *) buf, count);
         if (res == -1) throw SysError("writing to file");
         count -= res;
@@ -344,3 +353,11 @@ AutoCloseDir::operator DIR *()
     return dir;
 }
 
+
+volatile sig_atomic_t _isInterrupted = 0;
+
+void _interrupted()
+{
+    _isInterrupted = 0;
+    throw Error("interrupted by the user");
+}
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 5d27ac1bddb4..34fff003b88f 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -9,6 +9,7 @@
 #include <sys/types.h>
 #include <dirent.h>
 #include <unistd.h>
+#include <signal.h>
 
 #include <boost/format.hpp>
 
@@ -179,4 +180,16 @@ public:
 };
 
 
+/* User interruption. */
+
+extern volatile sig_atomic_t _isInterrupted;
+
+void _interrupted();
+
+void inline checkInterrupt()
+{
+    if (_isInterrupted) _interrupted();
+}
+
+
 #endif /* !__UTIL_H */