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,
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;
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;
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;
}
COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */
COPY_MERGE_EMPTY = 1 << 4, /* Merge an existing, empty directory with our new tree to copy */
COPY_CRTIME = 1 << 5, /* Generate a user.crtime_usec xattr off the source crtime if there is one, on copying */
+ COPY_SIGINT = 1 << 6, /* Check for SIGINT regularly and return EINTR if seen (caller needs to block SIGINT) */
} CopyFlags;
typedef int (*copy_progress_bytes_t)(uint64_t n_bytes, void *userdata);