copy: optionally check for SIGINT regularly, and abort operation safely
This commit is contained in:
+34
-1
@@ -86,6 +86,22 @@ static int fd_is_nonblock_pipe(int fd) {
|
||||
return FLAGS_SET(flags, O_NONBLOCK) ? FD_IS_NONBLOCKING_PIPE : FD_IS_BLOCKING_PIPE;
|
||||
}
|
||||
|
||||
static int sigint_pending(void) {
|
||||
sigset_t ss;
|
||||
|
||||
assert_se(sigemptyset(&ss) >= 0);
|
||||
assert_se(sigaddset(&ss, SIGINT) >= 0);
|
||||
|
||||
if (sigtimedwait(&ss, NULL, &(struct timespec) { 0, 0 }) < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return false;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int copy_bytes_full(
|
||||
int fdf, int fdt,
|
||||
uint64_t max_bytes,
|
||||
@@ -174,6 +190,14 @@ int copy_bytes_full(
|
||||
if (max_bytes <= 0)
|
||||
return 1; /* return > 0 if we hit the max_bytes limit */
|
||||
|
||||
if (FLAGS_SET(copy_flags, COPY_SIGINT)) {
|
||||
r = sigint_pending();
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
if (max_bytes != UINT64_MAX && m > max_bytes)
|
||||
m = max_bytes;
|
||||
|
||||
@@ -559,6 +583,14 @@ static int fd_copy_directory(
|
||||
if (dot_or_dot_dot(de->d_name))
|
||||
continue;
|
||||
|
||||
if (FLAGS_SET(copy_flags, COPY_SIGINT)) {
|
||||
r = sigint_pending();
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
if (fstatat(dirfd(d), de->d_name, &buf, AT_SYMLINK_NOFOLLOW) < 0) {
|
||||
r = -errno;
|
||||
continue;
|
||||
@@ -618,9 +650,10 @@ static int fd_copy_directory(
|
||||
else
|
||||
q = -EOPNOTSUPP;
|
||||
|
||||
if (q == -EINTR) /* Propagate SIGINT up instantly */
|
||||
return q;
|
||||
if (q == -EEXIST && (copy_flags & COPY_MERGE))
|
||||
q = 0;
|
||||
|
||||
if (q < 0)
|
||||
r = q;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user