/
write_or_die.c
57 lines (50 loc) · 1.27 KB
/
write_or_die.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include "write_or_die.h"
/**
* copy_between_fd is laid on top of write_in_full and read_with_timeout,
* it returns total number byte that written, returned value is not equal
* to expected_size to indicate an error. And it uses report_fd to report
* progress, if invoke with report_fd == -1 then it report nothing.
*/
size_t copy_between_fd(int from, int to, int report_fd, off_t expected_size, int die_on_error){
char buf[BUFSIZ];
off_t total = 0;
ssize_t nr;
FILE *fp = NULL;
if (report_fd != -1){
fp = fdopen(report_fd, "w");
if (fp == NULL)
error("report_fd can be open with fdopen");
setbuf(fp, NULL);
}
for (;;){
nr = read_with_timeout(from, buf, BUFSIZ, TIMEOUT);
if (nr == 0)
break;
if (nr < 0){
if (die_on_error)
fatal("timeout when reading");
else
break;
}
if (write_in_full(to, buf, nr) < 0){
if (die_on_error)
fatal("write error");
else
break;
}
total += nr;
/* FIXME we should not report that frequently */
if (fp != NULL)
fprintf(fp, "\rtransported %.2f%%", (total/(double)expected_size)*100);
}
if (fp != NULL)
fputc('\n', fp);
return total;
}
void write_or_die(int fd, void *buf, size_t count){
if (write_in_full(fd, buf, count) < 0){
if (errno == EPIPE)
exit(0);
fatal("write error");
}
}