Contents of /tags/mkinitrd-6_1_0/busybox/libbb/copyfd.c
Parent Directory | Revision Log
Revision 820 -
(show annotations)
(download)
Fri Apr 24 19:09:57 2009 UTC (15 years, 5 months ago) by niro
File MIME type: text/plain
File size: 2481 byte(s)
Fri Apr 24 19:09:57 2009 UTC (15 years, 5 months ago) by niro
File MIME type: text/plain
File size: 2481 byte(s)
tagged 'mkinitrd-6_1_0'
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * Utility routines. |
4 | * |
5 | * Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org> |
6 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
8 | */ |
9 | |
10 | #include "libbb.h" |
11 | |
12 | /* Used by NOFORK applets (e.g. cat) - must not use xmalloc */ |
13 | |
14 | static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size) |
15 | { |
16 | int status = -1; |
17 | off_t total = 0; |
18 | #if CONFIG_FEATURE_COPYBUF_KB <= 4 |
19 | char buffer[CONFIG_FEATURE_COPYBUF_KB * 1024]; |
20 | enum { buffer_size = sizeof(buffer) }; |
21 | #else |
22 | char *buffer; |
23 | int buffer_size; |
24 | |
25 | /* We want page-aligned buffer, just in case kernel is clever |
26 | * and can do page-aligned io more efficiently */ |
27 | buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024, |
28 | PROT_READ | PROT_WRITE, |
29 | MAP_PRIVATE | MAP_ANON, |
30 | /* ignored: */ -1, 0); |
31 | buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; |
32 | if (buffer == MAP_FAILED) { |
33 | buffer = alloca(4 * 1024); |
34 | buffer_size = 4 * 1024; |
35 | } |
36 | #endif |
37 | |
38 | if (src_fd < 0) |
39 | goto out; |
40 | |
41 | if (!size) { |
42 | size = buffer_size; |
43 | status = 1; /* copy until eof */ |
44 | } |
45 | |
46 | while (1) { |
47 | ssize_t rd; |
48 | |
49 | rd = safe_read(src_fd, buffer, size > buffer_size ? buffer_size : size); |
50 | |
51 | if (!rd) { /* eof - all done */ |
52 | status = 0; |
53 | break; |
54 | } |
55 | if (rd < 0) { |
56 | bb_perror_msg(bb_msg_read_error); |
57 | break; |
58 | } |
59 | /* dst_fd == -1 is a fake, else... */ |
60 | if (dst_fd >= 0) { |
61 | ssize_t wr = full_write(dst_fd, buffer, rd); |
62 | if (wr < rd) { |
63 | bb_perror_msg(bb_msg_write_error); |
64 | break; |
65 | } |
66 | } |
67 | total += rd; |
68 | if (status < 0) { /* if we aren't copying till EOF... */ |
69 | size -= rd; |
70 | if (!size) { |
71 | /* 'size' bytes copied - all done */ |
72 | status = 0; |
73 | break; |
74 | } |
75 | } |
76 | } |
77 | out: |
78 | |
79 | #if CONFIG_FEATURE_COPYBUF_KB > 4 |
80 | if (buffer_size != 4 * 1024) |
81 | munmap(buffer, buffer_size); |
82 | #endif |
83 | return status ? -1 : total; |
84 | } |
85 | |
86 | |
87 | #if 0 |
88 | void FAST_FUNC complain_copyfd_and_die(off_t sz) |
89 | { |
90 | if (sz != -1) |
91 | bb_error_msg_and_die("short read"); |
92 | /* if sz == -1, bb_copyfd_XX already complained */ |
93 | xfunc_die(); |
94 | } |
95 | #endif |
96 | |
97 | off_t FAST_FUNC bb_copyfd_size(int fd1, int fd2, off_t size) |
98 | { |
99 | if (size) { |
100 | return bb_full_fd_action(fd1, fd2, size); |
101 | } |
102 | return 0; |
103 | } |
104 | |
105 | void FAST_FUNC bb_copyfd_exact_size(int fd1, int fd2, off_t size) |
106 | { |
107 | off_t sz = bb_copyfd_size(fd1, fd2, size); |
108 | if (sz == size) |
109 | return; |
110 | if (sz != -1) |
111 | bb_error_msg_and_die("short read"); |
112 | /* if sz == -1, bb_copyfd_XX already complained */ |
113 | xfunc_die(); |
114 | } |
115 | |
116 | off_t FAST_FUNC bb_copyfd_eof(int fd1, int fd2) |
117 | { |
118 | return bb_full_fd_action(fd1, fd2, 0); |
119 | } |