diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-08-02 19:45:31 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-08-02 19:45:31 +0200 |
commit | dc9495df03f411d67eb46002670ffea12bdd32ba (patch) | |
tree | c0d8f4c7a2482f6564252638d2d5f3b1f05aacb2 /miscutils/rx.c | |
parent | 80a3418b8c96300826842f109cd297280d3fbe05 (diff) | |
download | busybox-w32-dc9495df03f411d67eb46002670ffea12bdd32ba.tar.gz busybox-w32-dc9495df03f411d67eb46002670ffea12bdd32ba.tar.bz2 busybox-w32-dc9495df03f411d67eb46002670ffea12bdd32ba.zip |
rx: strip padding from last block. closes bug 501.
function old new delta
rx_main 876 974 +98
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils/rx.c')
-rw-r--r-- | miscutils/rx.c | 102 |
1 files changed, 59 insertions, 43 deletions
diff --git a/miscutils/rx.c b/miscutils/rx.c index 94eb4522d..3a8b6a8fe 100644 --- a/miscutils/rx.c +++ b/miscutils/rx.c | |||
@@ -1,15 +1,12 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
2 | /*------------------------------------------------------------------------- | 2 | /* |
3 | * Filename: xmodem.c | ||
4 | * Copyright: Copyright (C) 2001, Hewlett-Packard Company | 3 | * Copyright: Copyright (C) 2001, Hewlett-Packard Company |
5 | * Author: Christopher Hoover <ch@hpl.hp.com> | 4 | * Author: Christopher Hoover <ch@hpl.hp.com> |
6 | * Description: xmodem functionality for uploading of kernels | 5 | * Description: xmodem functionality for uploading of kernels |
7 | * and the like | 6 | * and the like |
8 | * Created at: Thu Dec 20 01:58:08 PST 2001 | 7 | * Created at: Thu Dec 20 01:58:08 PST 2001 |
9 | *-----------------------------------------------------------------------*/ | 8 | * |
10 | /* | 9 | * xmodem functionality for uploading of kernels and the like |
11 | * xmodem.c: xmodem functionality for uploading of kernels and | ||
12 | * the like | ||
13 | * | 10 | * |
14 | * Copyright (C) 2001 Hewlett-Packard Laboratories | 11 | * Copyright (C) 2001 Hewlett-Packard Laboratories |
15 | * | 12 | * |
@@ -26,6 +23,7 @@ | |||
26 | #define ACK 0x06 | 23 | #define ACK 0x06 |
27 | #define NAK 0x15 | 24 | #define NAK 0x15 |
28 | #define BS 0x08 | 25 | #define BS 0x08 |
26 | #define PAD 0x1A | ||
29 | 27 | ||
30 | /* | 28 | /* |
31 | Cf: | 29 | Cf: |
@@ -44,69 +42,93 @@ Cf: | |||
44 | 42 | ||
45 | static int read_byte(unsigned timeout) | 43 | static int read_byte(unsigned timeout) |
46 | { | 44 | { |
47 | char buf[1]; | 45 | unsigned char buf; |
48 | int n; | 46 | int n; |
49 | 47 | ||
50 | alarm(timeout); | 48 | alarm(timeout); |
51 | /* NOT safe_read! We want ALRM to interrupt us */ | 49 | /* NOT safe_read! We want ALRM to interrupt us */ |
52 | n = read(read_fd, buf, 1); | 50 | n = read(read_fd, &buf, 1); |
53 | alarm(0); | 51 | alarm(0); |
54 | if (n == 1) | 52 | if (n == 1) |
55 | return (unsigned char)buf[0]; | 53 | return buf; |
56 | return -1; | 54 | return -1; |
57 | } | 55 | } |
58 | 56 | ||
59 | static int receive(/*int read_fd, */int file_fd) | 57 | static int receive(/*int read_fd, */int file_fd) |
60 | { | 58 | { |
61 | unsigned char blockBuf[1024]; | 59 | unsigned char blockBuf[1024]; |
60 | unsigned blockLength = 0; | ||
62 | unsigned errors = 0; | 61 | unsigned errors = 0; |
63 | unsigned wantBlockNo = 1; | 62 | unsigned wantBlockNo = 1; |
64 | unsigned length = 0; | 63 | unsigned length = 0; |
65 | int do_crc = 1; | 64 | int do_crc = 1; |
66 | char nak = 'C'; | 65 | char reply_char; |
67 | unsigned timeout = TIMEOUT_LONG; | 66 | unsigned timeout = TIMEOUT_LONG; |
68 | 67 | ||
69 | /* Flush pending input */ | 68 | /* Flush pending input */ |
70 | tcflush(read_fd, TCIFLUSH); | 69 | tcflush(read_fd, TCIFLUSH); |
71 | 70 | ||
72 | /* Ask for CRC; if we get errors, we will go with checksum */ | 71 | /* Ask for CRC; if we get errors, we will go with checksum */ |
73 | full_write(write_fd, &nak, 1); | 72 | reply_char = 'C'; |
73 | full_write(write_fd, &reply_char, 1); | ||
74 | 74 | ||
75 | for (;;) { | 75 | for (;;) { |
76 | int blockBegin; | 76 | int blockBegin; |
77 | int blockNo, blockNoOnesCompl; | 77 | int blockNo, blockNoOnesCompl; |
78 | int blockLength; | 78 | int cksum_or_crc; |
79 | int cksum_crc; /* cksum OR crc */ | ||
80 | int expected; | 79 | int expected; |
81 | int i,j; | 80 | int i, j; |
82 | 81 | ||
83 | blockBegin = read_byte(timeout); | 82 | blockBegin = read_byte(timeout); |
84 | if (blockBegin < 0) | 83 | if (blockBegin < 0) |
85 | goto timeout; | 84 | goto timeout; |
86 | 85 | ||
86 | /* If last block, remove padding */ | ||
87 | if (blockBegin == EOT) { | ||
88 | /* Data blocks can be padded with ^Z characters */ | ||
89 | /* This code tries to detect and remove them */ | ||
90 | if (blockLength >= 3 | ||
91 | && blockBuf[blockLength - 1] == PAD | ||
92 | && blockBuf[blockLength - 2] == PAD | ||
93 | && blockBuf[blockLength - 3] == PAD | ||
94 | ) { | ||
95 | while (blockLength | ||
96 | && blockBuf[blockLength - 1] == PAD | ||
97 | ) { | ||
98 | blockLength--; | ||
99 | } | ||
100 | } | ||
101 | } | ||
102 | /* Write previously received block */ | ||
103 | if (blockLength) { | ||
104 | errno = 0; | ||
105 | if (full_write(file_fd, blockBuf, blockLength) != blockLength) { | ||
106 | bb_perror_msg("can't write to file"); | ||
107 | goto fatal; | ||
108 | } | ||
109 | } | ||
110 | |||
87 | timeout = TIMEOUT; | 111 | timeout = TIMEOUT; |
88 | nak = NAK; | 112 | reply_char = NAK; |
89 | 113 | ||
90 | switch (blockBegin) { | 114 | switch (blockBegin) { |
91 | case SOH: | 115 | case SOH: |
92 | case STX: | 116 | case STX: |
93 | break; | 117 | break; |
94 | |||
95 | case EOT: | 118 | case EOT: |
96 | nak = ACK; | 119 | reply_char = ACK; |
97 | full_write(write_fd, &nak, 1); | 120 | full_write(write_fd, &reply_char, 1); |
98 | return length; | 121 | return length; |
99 | |||
100 | default: | 122 | default: |
101 | goto error; | 123 | goto error; |
102 | } | 124 | } |
103 | 125 | ||
104 | /* block no */ | 126 | /* Block no */ |
105 | blockNo = read_byte(TIMEOUT); | 127 | blockNo = read_byte(TIMEOUT); |
106 | if (blockNo < 0) | 128 | if (blockNo < 0) |
107 | goto timeout; | 129 | goto timeout; |
108 | 130 | ||
109 | /* block no one's compliment */ | 131 | /* Block no, in one's complement form */ |
110 | blockNoOnesCompl = read_byte(TIMEOUT); | 132 | blockNoOnesCompl = read_byte(TIMEOUT); |
111 | if (blockNoOnesCompl < 0) | 133 | if (blockNoOnesCompl < 0) |
112 | goto timeout; | 134 | goto timeout; |
@@ -126,15 +148,15 @@ static int receive(/*int read_fd, */int file_fd) | |||
126 | } | 148 | } |
127 | 149 | ||
128 | if (do_crc) { | 150 | if (do_crc) { |
129 | cksum_crc = read_byte(TIMEOUT); | 151 | cksum_or_crc = read_byte(TIMEOUT); |
130 | if (cksum_crc < 0) | 152 | if (cksum_or_crc < 0) |
131 | goto timeout; | 153 | goto timeout; |
132 | cksum_crc = (cksum_crc << 8) | read_byte(TIMEOUT); | 154 | cksum_or_crc = (cksum_or_crc << 8) | read_byte(TIMEOUT); |
133 | if (cksum_crc < 0) | 155 | if (cksum_or_crc < 0) |
134 | goto timeout; | 156 | goto timeout; |
135 | } else { | 157 | } else { |
136 | cksum_crc = read_byte(TIMEOUT); | 158 | cksum_or_crc = read_byte(TIMEOUT); |
137 | if (cksum_crc < 0) | 159 | if (cksum_or_crc < 0) |
138 | goto timeout; | 160 | goto timeout; |
139 | } | 161 | } |
140 | 162 | ||
@@ -155,9 +177,9 @@ static int receive(/*int read_fd, */int file_fd) | |||
155 | expected = expected ^ blockBuf[i] << 8; | 177 | expected = expected ^ blockBuf[i] << 8; |
156 | for (j = 0; j < 8; j++) { | 178 | for (j = 0; j < 8; j++) { |
157 | if (expected & 0x8000) | 179 | if (expected & 0x8000) |
158 | expected = expected << 1 ^ 0x1021; | 180 | expected = (expected << 1) ^ 0x1021; |
159 | else | 181 | else |
160 | expected = expected << 1; | 182 | expected = (expected << 1); |
161 | } | 183 | } |
162 | } | 184 | } |
163 | expected &= 0xffff; | 185 | expected &= 0xffff; |
@@ -166,25 +188,19 @@ static int receive(/*int read_fd, */int file_fd) | |||
166 | expected += blockBuf[i]; | 188 | expected += blockBuf[i]; |
167 | expected &= 0xff; | 189 | expected &= 0xff; |
168 | } | 190 | } |
169 | if (cksum_crc != expected) { | 191 | if (cksum_or_crc != expected) { |
170 | bb_error_msg(do_crc ? "crc error, expected 0x%04x, got 0x%04x" | 192 | bb_error_msg(do_crc ? "crc error, expected 0x%04x, got 0x%04x" |
171 | : "checksum error, expected 0x%02x, got 0x%02x", | 193 | : "checksum error, expected 0x%02x, got 0x%02x", |
172 | expected, cksum_crc); | 194 | expected, cksum_or_crc); |
173 | goto error; | 195 | goto error; |
174 | } | 196 | } |
175 | 197 | ||
176 | wantBlockNo++; | 198 | wantBlockNo++; |
177 | length += blockLength; | 199 | length += blockLength; |
178 | |||
179 | errno = 0; | ||
180 | if (full_write(file_fd, blockBuf, blockLength) != blockLength) { | ||
181 | bb_perror_msg("can't write to file"); | ||
182 | goto fatal; | ||
183 | } | ||
184 | next: | 200 | next: |
185 | errors = 0; | 201 | errors = 0; |
186 | nak = ACK; | 202 | reply_char = ACK; |
187 | full_write(write_fd, &nak, 1); | 203 | full_write(write_fd, &reply_char, 1); |
188 | continue; | 204 | continue; |
189 | error: | 205 | error: |
190 | timeout: | 206 | timeout: |
@@ -192,9 +208,9 @@ static int receive(/*int read_fd, */int file_fd) | |||
192 | if (errors == MAXERRORS) { | 208 | if (errors == MAXERRORS) { |
193 | /* Abort */ | 209 | /* Abort */ |
194 | 210 | ||
195 | /* if were asking for crc, try again w/o crc */ | 211 | /* If were asking for crc, try again w/o crc */ |
196 | if (nak == 'C') { | 212 | if (reply_char == 'C') { |
197 | nak = NAK; | 213 | reply_char = NAK; |
198 | errors = 0; | 214 | errors = 0; |
199 | do_crc = 0; | 215 | do_crc = 0; |
200 | goto timeout; | 216 | goto timeout; |
@@ -209,7 +225,7 @@ static int receive(/*int read_fd, */int file_fd) | |||
209 | /* Flush pending input */ | 225 | /* Flush pending input */ |
210 | tcflush(read_fd, TCIFLUSH); | 226 | tcflush(read_fd, TCIFLUSH); |
211 | 227 | ||
212 | full_write(write_fd, &nak, 1); | 228 | full_write(write_fd, &reply_char, 1); |
213 | } /* for (;;) */ | 229 | } /* for (;;) */ |
214 | } | 230 | } |
215 | 231 | ||