about summary refs log tree commit diff
path: root/src/libutil/util.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/util.cc')
-rw-r--r--src/libutil/util.cc22
1 files changed, 14 insertions, 8 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index def0525abc18..55d490992108 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -209,7 +209,7 @@ Path readLink(const Path & path)
     else if (rlsize > st.st_size)
         throw Error(format("symbolic link ‘%1%’ size overflow %2% > %3%")
             % path % rlsize % st.st_size);
-    return string(buf, st.st_size);
+    return string(buf, rlsize);
 }
 
 
@@ -320,9 +320,11 @@ static void _deletePath(const Path & path, unsigned long long & bytesFreed)
 {
     checkInterrupt();
 
-    printMsg(lvlVomit, format("%1%") % path);
-
-    struct stat st = lstat(path);
+    struct stat st;
+    if (lstat(path.c_str(), &st) == -1) {
+        if (errno == ENOENT) return;
+        throw SysError(format("getting status of ‘%1%’") % path);
+    }
 
     if (!S_ISDIR(st.st_mode) && st.st_nlink == 1)
         bytesFreed += st.st_blocks * 512;
@@ -338,8 +340,10 @@ static void _deletePath(const Path & path, unsigned long long & bytesFreed)
             _deletePath(path + "/" + i.name, bytesFreed);
     }
 
-    if (remove(path.c_str()) == -1)
+    if (remove(path.c_str()) == -1) {
+        if (errno == ENOENT) return;
         throw SysError(format("cannot unlink ‘%1%’") % path);
+    }
 }
 
 
@@ -544,7 +548,7 @@ void writeToStderr(const string & s)
 }
 
 
-void (*_writeToStderr) (const unsigned char * buf, size_t count) = 0;
+std::function<void(const unsigned char * buf, size_t count)> _writeToStderr;
 
 
 void readFull(int fd, unsigned char * buf, size_t count)
@@ -1058,13 +1062,15 @@ void restoreSIGPIPE()
 
 volatile sig_atomic_t _isInterrupted = 0;
 
+thread_local bool interruptThrown = false;
+
 void _interrupted()
 {
     /* Block user interrupts while an exception is being handled.
        Throwing an exception while another exception is being handled
        kills the program! */
-    if (!std::uncaught_exception()) {
-        _isInterrupted = 0;
+    if (!interruptThrown && !std::uncaught_exception()) {
+        interruptThrown = true;
         throw Interrupted("interrupted by the user");
     }
 }