aboutsummaryrefslogtreecommitdiff
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 90a039164..2b8fb2f10 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 28e276a32..5c8b7279c 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 5d27ac1bd..34fff003b 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 */