Use select() in dd(1)
Avoid blocking in a call to splice() when no input is available. We can now break out of dd using ^C even if the input is coming from /dev/stdin. Use tabs instead of spaces.
This commit is contained in:
parent
c94dfdc99d
commit
0ca8e52bc1
94
dd.c
94
dd.c
|
@ -17,6 +17,8 @@
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/vfs.h>
|
#include <sys/vfs.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -135,48 +137,60 @@ prepare_copy(struct dd_config *ddc, int *ifd, int *ofd)
|
||||||
static int
|
static int
|
||||||
copy_splice(struct dd_config *ddc)
|
copy_splice(struct dd_config *ddc)
|
||||||
{
|
{
|
||||||
int ifd, ofd, p[2] = {-1, -1};
|
int ifd, ofd, p[2] = {-1, -1};
|
||||||
ssize_t r = 0;
|
ssize_t r = 0;
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
if (prepare_copy(ddc, &ifd, &ofd) < 0)
|
fd_set rfd, wfd;
|
||||||
return -1;
|
|
||||||
if (pipe(p) < 0) {
|
if (prepare_copy(ddc, &ifd, &ofd) < 0)
|
||||||
ddc->saved_errno = errno;
|
return -1;
|
||||||
close(ifd); close(ofd);
|
if (pipe(p) < 0) {
|
||||||
close(p[0]); close(p[1]);
|
ddc->saved_errno = errno;
|
||||||
return -1;
|
close(ifd); close(ofd);
|
||||||
}
|
close(p[0]); close(p[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
#ifdef F_SETPIPE_SZ
|
#ifdef F_SETPIPE_SZ
|
||||||
for (n = 29; n >= 20; --n) {
|
for (n = 29; n >= 20; --n) {
|
||||||
if (fcntl(p[0], F_SETPIPE_SZ, 1<<n) != -1)
|
if (fcntl(p[0], F_SETPIPE_SZ, 1<<n) != -1)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
n = ddc->bs;
|
n = ddc->bs;
|
||||||
for (;ddc->b_out != ddc->count && !sigint;) {
|
for (;ddc->b_out != ddc->count && !sigint;) {
|
||||||
if (n > ddc->count - ddc->b_out)
|
if (n > ddc->count - ddc->b_out)
|
||||||
n = ddc->count - ddc->b_out;
|
n = ddc->count - ddc->b_out;
|
||||||
r = splice(ifd, NULL, p[1], NULL, n, SPLICE_F_MORE);
|
FD_ZERO(&rfd);
|
||||||
if (r <= 0) {
|
FD_ZERO(&wfd);
|
||||||
ddc->saved_errno = errno;
|
FD_SET(ifd, &rfd);
|
||||||
break;
|
FD_SET(ofd, &wfd);
|
||||||
}
|
if (select(ifd > ofd ? ifd + 1 : ofd + 1, &rfd, &wfd, NULL, NULL) < 0) {
|
||||||
++ddc->rec_in;
|
ddc->saved_errno = errno;
|
||||||
r = splice(p[0], NULL, ofd, NULL, r, SPLICE_F_MORE);
|
break;
|
||||||
if (r <= 0) {
|
}
|
||||||
ddc->saved_errno = errno;
|
if (FD_ISSET(ifd, &rfd) == 1 && FD_ISSET(ofd, &wfd) == 1) {
|
||||||
break;
|
r = splice(ifd, NULL, p[1], NULL, n, SPLICE_F_MORE);
|
||||||
}
|
if (r <= 0) {
|
||||||
ddc->b_out += r;
|
ddc->saved_errno = errno;
|
||||||
++ddc->rec_out;
|
break;
|
||||||
}
|
}
|
||||||
close(ifd);
|
++ddc->rec_in;
|
||||||
close(ofd);
|
r = splice(p[0], NULL, ofd, NULL, r, SPLICE_F_MORE);
|
||||||
close(p[0]);
|
if (r <= 0) {
|
||||||
close(p[1]);
|
ddc->saved_errno = errno;
|
||||||
if (r < 0)
|
break;
|
||||||
return -1;
|
}
|
||||||
return 0;
|
ddc->b_out += r;
|
||||||
|
++ddc->rec_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(ifd);
|
||||||
|
close(ofd);
|
||||||
|
close(p[0]);
|
||||||
|
close(p[1]);
|
||||||
|
if (r < 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Reference in New Issue
Block a user