Line | Count | Source (jump to first uncovered line) |
1 | | #include "git-compat-util.h" |
2 | | #include "copy.h" |
3 | | #include "pkt-line.h" |
4 | | #include "gettext.h" |
5 | | #include "hex.h" |
6 | | #include "run-command.h" |
7 | | #include "sideband.h" |
8 | | #include "trace.h" |
9 | | #include "write-or-die.h" |
10 | | |
11 | | char packet_buffer[LARGE_PACKET_MAX]; |
12 | | static const char *packet_trace_prefix = "git"; |
13 | | static struct trace_key trace_packet = TRACE_KEY_INIT(PACKET); |
14 | | static struct trace_key trace_pack = TRACE_KEY_INIT(PACKFILE); |
15 | | |
16 | | void packet_trace_identity(const char *prog) |
17 | 0 | { |
18 | 0 | packet_trace_prefix = xstrdup(prog); |
19 | 0 | } |
20 | | |
21 | | static const char *get_trace_prefix(void) |
22 | 0 | { |
23 | 0 | return in_async() ? "sideband" : packet_trace_prefix; |
24 | 0 | } |
25 | | |
26 | | static int packet_trace_pack(const char *buf, unsigned int len, int sideband) |
27 | 0 | { |
28 | 0 | if (!sideband) { |
29 | 0 | trace_verbatim(&trace_pack, buf, len); |
30 | 0 | return 1; |
31 | 0 | } else if (len && *buf == '\1') { |
32 | 0 | trace_verbatim(&trace_pack, buf + 1, len - 1); |
33 | 0 | return 1; |
34 | 0 | } else { |
35 | | /* it's another non-pack sideband */ |
36 | 0 | return 0; |
37 | 0 | } |
38 | 0 | } |
39 | | |
40 | | static void packet_trace(const char *buf, unsigned int len, int write) |
41 | 0 | { |
42 | 0 | int i; |
43 | 0 | struct strbuf out; |
44 | 0 | static int in_pack, sideband; |
45 | |
|
46 | 0 | if (!trace_want(&trace_packet) && !trace_want(&trace_pack)) |
47 | 0 | return; |
48 | | |
49 | 0 | if (in_pack) { |
50 | 0 | if (packet_trace_pack(buf, len, sideband)) |
51 | 0 | return; |
52 | 0 | } else if (starts_with(buf, "PACK") || starts_with(buf, "\1PACK")) { |
53 | 0 | in_pack = 1; |
54 | 0 | sideband = *buf == '\1'; |
55 | 0 | packet_trace_pack(buf, len, sideband); |
56 | | |
57 | | /* |
58 | | * Make a note in the human-readable trace that the pack data |
59 | | * started. |
60 | | */ |
61 | 0 | buf = "PACK ..."; |
62 | 0 | len = strlen(buf); |
63 | 0 | } |
64 | | |
65 | 0 | if (!trace_want(&trace_packet)) |
66 | 0 | return; |
67 | | |
68 | | /* +32 is just a guess for header + quoting */ |
69 | 0 | strbuf_init(&out, len+32); |
70 | |
|
71 | 0 | strbuf_addf(&out, "packet: %12s%c ", |
72 | 0 | get_trace_prefix(), write ? '>' : '<'); |
73 | | |
74 | | /* XXX we should really handle printable utf8 */ |
75 | 0 | for (i = 0; i < len; i++) { |
76 | | /* suppress newlines */ |
77 | 0 | if (buf[i] == '\n') |
78 | 0 | continue; |
79 | 0 | if (buf[i] >= 0x20 && buf[i] <= 0x7e) |
80 | 0 | strbuf_addch(&out, buf[i]); |
81 | 0 | else |
82 | 0 | strbuf_addf(&out, "\\%o", buf[i]); |
83 | 0 | } |
84 | |
|
85 | 0 | strbuf_addch(&out, '\n'); |
86 | 0 | trace_strbuf(&trace_packet, &out); |
87 | 0 | strbuf_release(&out); |
88 | 0 | } |
89 | | |
90 | | /* |
91 | | * If we buffered things up above (we don't, but we should), |
92 | | * we'd flush it here |
93 | | */ |
94 | | void packet_flush(int fd) |
95 | 0 | { |
96 | 0 | packet_trace("0000", 4, 1); |
97 | 0 | if (write_in_full(fd, "0000", 4) < 0) |
98 | 0 | die_errno(_("unable to write flush packet")); |
99 | 0 | } |
100 | | |
101 | | void packet_delim(int fd) |
102 | 0 | { |
103 | 0 | packet_trace("0001", 4, 1); |
104 | 0 | if (write_in_full(fd, "0001", 4) < 0) |
105 | 0 | die_errno(_("unable to write delim packet")); |
106 | 0 | } |
107 | | |
108 | | void packet_response_end(int fd) |
109 | 0 | { |
110 | 0 | packet_trace("0002", 4, 1); |
111 | 0 | if (write_in_full(fd, "0002", 4) < 0) |
112 | 0 | die_errno(_("unable to write response end packet")); |
113 | 0 | } |
114 | | |
115 | | int packet_flush_gently(int fd) |
116 | 0 | { |
117 | 0 | packet_trace("0000", 4, 1); |
118 | 0 | if (write_in_full(fd, "0000", 4) < 0) |
119 | 0 | return error(_("flush packet write failed")); |
120 | 0 | return 0; |
121 | 0 | } |
122 | | |
123 | | void packet_buf_flush(struct strbuf *buf) |
124 | 0 | { |
125 | 0 | packet_trace("0000", 4, 1); |
126 | 0 | strbuf_add(buf, "0000", 4); |
127 | 0 | } |
128 | | |
129 | | void packet_buf_delim(struct strbuf *buf) |
130 | 0 | { |
131 | 0 | packet_trace("0001", 4, 1); |
132 | 0 | strbuf_add(buf, "0001", 4); |
133 | 0 | } |
134 | | |
135 | | void set_packet_header(char *buf, int size) |
136 | 0 | { |
137 | 0 | static char hexchar[] = "0123456789abcdef"; |
138 | |
|
139 | 0 | #define hex(a) (hexchar[(a) & 15]) |
140 | 0 | buf[0] = hex(size >> 12); |
141 | 0 | buf[1] = hex(size >> 8); |
142 | 0 | buf[2] = hex(size >> 4); |
143 | 0 | buf[3] = hex(size); |
144 | 0 | #undef hex |
145 | 0 | } |
146 | | |
147 | | static void format_packet(struct strbuf *out, const char *prefix, |
148 | | const char *fmt, va_list args) |
149 | 0 | { |
150 | 0 | size_t orig_len, n; |
151 | |
|
152 | 0 | orig_len = out->len; |
153 | 0 | strbuf_addstr(out, "0000"); |
154 | 0 | strbuf_addstr(out, prefix); |
155 | 0 | strbuf_vaddf(out, fmt, args); |
156 | 0 | n = out->len - orig_len; |
157 | |
|
158 | 0 | if (n > LARGE_PACKET_MAX) |
159 | 0 | die(_("protocol error: impossibly long line")); |
160 | | |
161 | 0 | set_packet_header(&out->buf[orig_len], n); |
162 | 0 | packet_trace(out->buf + orig_len + 4, n - 4, 1); |
163 | 0 | } |
164 | | |
165 | | static int packet_write_fmt_1(int fd, int gently, const char *prefix, |
166 | | const char *fmt, va_list args) |
167 | 0 | { |
168 | 0 | static struct strbuf buf = STRBUF_INIT; |
169 | |
|
170 | 0 | strbuf_reset(&buf); |
171 | 0 | format_packet(&buf, prefix, fmt, args); |
172 | 0 | if (write_in_full(fd, buf.buf, buf.len) < 0) { |
173 | 0 | if (!gently) { |
174 | 0 | check_pipe(errno); |
175 | 0 | die_errno(_("packet write with format failed")); |
176 | 0 | } |
177 | 0 | return error(_("packet write with format failed")); |
178 | 0 | } |
179 | | |
180 | 0 | return 0; |
181 | 0 | } |
182 | | |
183 | | void packet_write_fmt(int fd, const char *fmt, ...) |
184 | 0 | { |
185 | 0 | va_list args; |
186 | |
|
187 | 0 | va_start(args, fmt); |
188 | 0 | packet_write_fmt_1(fd, 0, "", fmt, args); |
189 | 0 | va_end(args); |
190 | 0 | } |
191 | | |
192 | | int packet_write_fmt_gently(int fd, const char *fmt, ...) |
193 | 0 | { |
194 | 0 | int status; |
195 | 0 | va_list args; |
196 | |
|
197 | 0 | va_start(args, fmt); |
198 | 0 | status = packet_write_fmt_1(fd, 1, "", fmt, args); |
199 | 0 | va_end(args); |
200 | 0 | return status; |
201 | 0 | } |
202 | | |
203 | | static int do_packet_write(const int fd_out, const char *buf, size_t size, |
204 | | struct strbuf *err) |
205 | 0 | { |
206 | 0 | char header[4]; |
207 | 0 | size_t packet_size; |
208 | |
|
209 | 0 | if (size > LARGE_PACKET_DATA_MAX) { |
210 | 0 | strbuf_addstr(err, _("packet write failed - data exceeds max packet size")); |
211 | 0 | return -1; |
212 | 0 | } |
213 | | |
214 | 0 | packet_trace(buf, size, 1); |
215 | 0 | packet_size = size + 4; |
216 | |
|
217 | 0 | set_packet_header(header, packet_size); |
218 | | |
219 | | /* |
220 | | * Write the header and the buffer in 2 parts so that we do |
221 | | * not need to allocate a buffer or rely on a static buffer. |
222 | | * This also avoids putting a large buffer on the stack which |
223 | | * might have multi-threading issues. |
224 | | */ |
225 | |
|
226 | 0 | if (write_in_full(fd_out, header, 4) < 0 || |
227 | 0 | write_in_full(fd_out, buf, size) < 0) { |
228 | 0 | strbuf_addf(err, _("packet write failed: %s"), strerror(errno)); |
229 | 0 | return -1; |
230 | 0 | } |
231 | 0 | return 0; |
232 | 0 | } |
233 | | |
234 | | static int packet_write_gently(const int fd_out, const char *buf, size_t size) |
235 | 0 | { |
236 | 0 | struct strbuf err = STRBUF_INIT; |
237 | 0 | if (do_packet_write(fd_out, buf, size, &err)) { |
238 | 0 | error("%s", err.buf); |
239 | 0 | strbuf_release(&err); |
240 | 0 | return -1; |
241 | 0 | } |
242 | 0 | return 0; |
243 | 0 | } |
244 | | |
245 | | void packet_write(int fd_out, const char *buf, size_t size) |
246 | 0 | { |
247 | 0 | struct strbuf err = STRBUF_INIT; |
248 | 0 | if (do_packet_write(fd_out, buf, size, &err)) |
249 | 0 | die("%s", err.buf); |
250 | 0 | } |
251 | | |
252 | | void packet_fwrite(FILE *f, const char *buf, size_t size) |
253 | 0 | { |
254 | 0 | size_t packet_size; |
255 | 0 | char header[4]; |
256 | |
|
257 | 0 | if (size > LARGE_PACKET_DATA_MAX) |
258 | 0 | die(_("packet write failed - data exceeds max packet size")); |
259 | | |
260 | 0 | packet_trace(buf, size, 1); |
261 | 0 | packet_size = size + 4; |
262 | |
|
263 | 0 | set_packet_header(header, packet_size); |
264 | 0 | fwrite_or_die(f, header, 4); |
265 | 0 | fwrite_or_die(f, buf, size); |
266 | 0 | } |
267 | | |
268 | | void packet_fwrite_fmt(FILE *fh, const char *fmt, ...) |
269 | 0 | { |
270 | 0 | static struct strbuf buf = STRBUF_INIT; |
271 | 0 | va_list args; |
272 | |
|
273 | 0 | strbuf_reset(&buf); |
274 | |
|
275 | 0 | va_start(args, fmt); |
276 | 0 | format_packet(&buf, "", fmt, args); |
277 | 0 | va_end(args); |
278 | |
|
279 | 0 | fwrite_or_die(fh, buf.buf, buf.len); |
280 | 0 | } |
281 | | |
282 | | void packet_fflush(FILE *f) |
283 | 0 | { |
284 | 0 | packet_trace("0000", 4, 1); |
285 | 0 | fwrite_or_die(f, "0000", 4); |
286 | 0 | fflush_or_die(f); |
287 | 0 | } |
288 | | |
289 | | void packet_buf_write(struct strbuf *buf, const char *fmt, ...) |
290 | 0 | { |
291 | 0 | va_list args; |
292 | |
|
293 | 0 | va_start(args, fmt); |
294 | 0 | format_packet(buf, "", fmt, args); |
295 | 0 | va_end(args); |
296 | 0 | } |
297 | | |
298 | | int write_packetized_from_fd_no_flush(int fd_in, int fd_out) |
299 | 0 | { |
300 | 0 | char *buf = xmalloc(LARGE_PACKET_DATA_MAX); |
301 | 0 | int err = 0; |
302 | 0 | ssize_t bytes_to_write; |
303 | |
|
304 | 0 | while (!err) { |
305 | 0 | bytes_to_write = xread(fd_in, buf, LARGE_PACKET_DATA_MAX); |
306 | 0 | if (bytes_to_write < 0) { |
307 | 0 | free(buf); |
308 | 0 | return COPY_READ_ERROR; |
309 | 0 | } |
310 | 0 | if (bytes_to_write == 0) |
311 | 0 | break; |
312 | 0 | err = packet_write_gently(fd_out, buf, bytes_to_write); |
313 | 0 | } |
314 | 0 | free(buf); |
315 | 0 | return err; |
316 | 0 | } |
317 | | |
318 | | int write_packetized_from_buf_no_flush_count(const char *src_in, size_t len, |
319 | | int fd_out, int *packet_counter) |
320 | 0 | { |
321 | 0 | int err = 0; |
322 | 0 | size_t bytes_written = 0; |
323 | 0 | size_t bytes_to_write; |
324 | |
|
325 | 0 | while (!err) { |
326 | 0 | if ((len - bytes_written) > LARGE_PACKET_DATA_MAX) |
327 | 0 | bytes_to_write = LARGE_PACKET_DATA_MAX; |
328 | 0 | else |
329 | 0 | bytes_to_write = len - bytes_written; |
330 | 0 | if (bytes_to_write == 0) |
331 | 0 | break; |
332 | 0 | err = packet_write_gently(fd_out, src_in + bytes_written, bytes_to_write); |
333 | 0 | bytes_written += bytes_to_write; |
334 | 0 | if (packet_counter) |
335 | 0 | (*packet_counter)++; |
336 | 0 | } |
337 | 0 | return err; |
338 | 0 | } |
339 | | |
340 | | static int get_packet_data(int fd, char **src_buf, size_t *src_size, |
341 | | void *dst, unsigned size, int options) |
342 | 0 | { |
343 | 0 | ssize_t ret; |
344 | |
|
345 | 0 | if (fd >= 0 && src_buf && *src_buf) |
346 | 0 | BUG("multiple sources given to packet_read"); |
347 | | |
348 | | /* Read up to "size" bytes from our source, whatever it is. */ |
349 | 0 | if (src_buf && *src_buf) { |
350 | 0 | ret = size < *src_size ? size : *src_size; |
351 | 0 | memcpy(dst, *src_buf, ret); |
352 | 0 | *src_buf += ret; |
353 | 0 | *src_size -= ret; |
354 | 0 | } else { |
355 | 0 | ret = read_in_full(fd, dst, size); |
356 | 0 | if (ret < 0) { |
357 | 0 | if (options & PACKET_READ_GENTLE_ON_READ_ERROR) |
358 | 0 | return error_errno(_("read error")); |
359 | 0 | die_errno(_("read error")); |
360 | 0 | } |
361 | 0 | } |
362 | | |
363 | | /* And complain if we didn't get enough bytes to satisfy the read. */ |
364 | 0 | if (ret != size) { |
365 | 0 | if (options & PACKET_READ_GENTLE_ON_EOF) |
366 | 0 | return -1; |
367 | | |
368 | 0 | if (options & PACKET_READ_GENTLE_ON_READ_ERROR) |
369 | 0 | return error(_("the remote end hung up unexpectedly")); |
370 | 0 | die(_("the remote end hung up unexpectedly")); |
371 | 0 | } |
372 | | |
373 | 0 | return ret; |
374 | 0 | } |
375 | | |
376 | | int packet_length(const char lenbuf_hex[4], size_t size) |
377 | 0 | { |
378 | 0 | if (size < 4) |
379 | 0 | BUG("buffer too small"); |
380 | 0 | return hexval(lenbuf_hex[0]) << 12 | |
381 | 0 | hexval(lenbuf_hex[1]) << 8 | |
382 | 0 | hexval(lenbuf_hex[2]) << 4 | |
383 | 0 | hexval(lenbuf_hex[3]); |
384 | 0 | } |
385 | | |
386 | | static char *find_packfile_uri_path(const char *buffer) |
387 | 0 | { |
388 | 0 | const char *URI_MARK = "://"; |
389 | 0 | char *path; |
390 | 0 | int len; |
391 | | |
392 | | /* First char is sideband mark */ |
393 | 0 | buffer += 1; |
394 | |
|
395 | 0 | len = strspn(buffer, "0123456789abcdefABCDEF"); |
396 | | /* size of SHA1 and SHA256 hash */ |
397 | 0 | if (!(len == 40 || len == 64) || buffer[len] != ' ') |
398 | 0 | return NULL; /* required "<hash>SP" not seen */ |
399 | | |
400 | 0 | path = strstr(buffer + len + 1, URI_MARK); |
401 | 0 | if (!path) |
402 | 0 | return NULL; |
403 | | |
404 | 0 | path = strchr(path + strlen(URI_MARK), '/'); |
405 | 0 | if (!path || !*(path + 1)) |
406 | 0 | return NULL; |
407 | | |
408 | | /* position after '/' */ |
409 | 0 | return ++path; |
410 | 0 | } |
411 | | |
412 | | enum packet_read_status packet_read_with_status(int fd, char **src_buffer, |
413 | | size_t *src_len, char *buffer, |
414 | | unsigned size, int *pktlen, |
415 | | int options) |
416 | 0 | { |
417 | 0 | int len; |
418 | 0 | char linelen[4]; |
419 | 0 | char *uri_path_start; |
420 | |
|
421 | 0 | if (get_packet_data(fd, src_buffer, src_len, linelen, 4, options) < 0) { |
422 | 0 | *pktlen = -1; |
423 | 0 | return PACKET_READ_EOF; |
424 | 0 | } |
425 | | |
426 | 0 | len = packet_length(linelen, sizeof(linelen)); |
427 | |
|
428 | 0 | if (len < 0) { |
429 | 0 | if (options & PACKET_READ_GENTLE_ON_READ_ERROR) |
430 | 0 | return error(_("protocol error: bad line length " |
431 | 0 | "character: %.4s"), linelen); |
432 | 0 | die(_("protocol error: bad line length character: %.4s"), linelen); |
433 | 0 | } else if (!len) { |
434 | 0 | packet_trace("0000", 4, 0); |
435 | 0 | *pktlen = 0; |
436 | 0 | return PACKET_READ_FLUSH; |
437 | 0 | } else if (len == 1) { |
438 | 0 | packet_trace("0001", 4, 0); |
439 | 0 | *pktlen = 0; |
440 | 0 | return PACKET_READ_DELIM; |
441 | 0 | } else if (len == 2) { |
442 | 0 | packet_trace("0002", 4, 0); |
443 | 0 | *pktlen = 0; |
444 | 0 | return PACKET_READ_RESPONSE_END; |
445 | 0 | } else if (len < 4) { |
446 | 0 | if (options & PACKET_READ_GENTLE_ON_READ_ERROR) |
447 | 0 | return error(_("protocol error: bad line length %d"), |
448 | 0 | len); |
449 | 0 | die(_("protocol error: bad line length %d"), len); |
450 | 0 | } |
451 | | |
452 | 0 | len -= 4; |
453 | 0 | if ((unsigned)len >= size) { |
454 | 0 | if (options & PACKET_READ_GENTLE_ON_READ_ERROR) |
455 | 0 | return error(_("protocol error: bad line length %d"), |
456 | 0 | len); |
457 | 0 | die(_("protocol error: bad line length %d"), len); |
458 | 0 | } |
459 | | |
460 | 0 | if (get_packet_data(fd, src_buffer, src_len, buffer, len, options) < 0) { |
461 | 0 | *pktlen = -1; |
462 | 0 | return PACKET_READ_EOF; |
463 | 0 | } |
464 | | |
465 | 0 | if ((options & PACKET_READ_CHOMP_NEWLINE) && |
466 | 0 | len && buffer[len-1] == '\n') { |
467 | 0 | if (options & PACKET_READ_USE_SIDEBAND) { |
468 | 0 | int band = *buffer & 0xff; |
469 | 0 | switch (band) { |
470 | 0 | case 1: |
471 | | /* Chomp newline for payload */ |
472 | 0 | len--; |
473 | 0 | break; |
474 | 0 | case 2: |
475 | 0 | case 3: |
476 | | /* |
477 | | * Do not chomp newline for progress and error |
478 | | * message. |
479 | | */ |
480 | 0 | break; |
481 | 0 | default: |
482 | | /* |
483 | | * Bad sideband, let's leave it to |
484 | | * demultiplex_sideband() to catch this error. |
485 | | */ |
486 | 0 | break; |
487 | 0 | } |
488 | 0 | } else { |
489 | 0 | len--; |
490 | 0 | } |
491 | 0 | } |
492 | | |
493 | 0 | buffer[len] = 0; |
494 | 0 | if (options & PACKET_READ_REDACT_URI_PATH && |
495 | 0 | (uri_path_start = find_packfile_uri_path(buffer))) { |
496 | 0 | const char *redacted = "<redacted>"; |
497 | 0 | struct strbuf tracebuf = STRBUF_INIT; |
498 | 0 | strbuf_insert(&tracebuf, 0, buffer, len); |
499 | 0 | strbuf_splice(&tracebuf, uri_path_start - buffer, |
500 | 0 | strlen(uri_path_start), redacted, strlen(redacted)); |
501 | 0 | packet_trace(tracebuf.buf, tracebuf.len, 0); |
502 | 0 | strbuf_release(&tracebuf); |
503 | 0 | } else { |
504 | 0 | packet_trace(buffer, len, 0); |
505 | 0 | } |
506 | |
|
507 | 0 | if ((options & PACKET_READ_DIE_ON_ERR_PACKET) && |
508 | 0 | starts_with(buffer, "ERR ")) |
509 | 0 | die(_("remote error: %s"), buffer + 4); |
510 | | |
511 | 0 | *pktlen = len; |
512 | 0 | return PACKET_READ_NORMAL; |
513 | 0 | } |
514 | | |
515 | | int packet_read(int fd, char *buffer, unsigned size, int options) |
516 | 0 | { |
517 | 0 | int pktlen = -1; |
518 | |
|
519 | 0 | packet_read_with_status(fd, NULL, NULL, buffer, size, &pktlen, |
520 | 0 | options); |
521 | |
|
522 | 0 | return pktlen; |
523 | 0 | } |
524 | | |
525 | | char *packet_read_line(int fd, int *dst_len) |
526 | 0 | { |
527 | 0 | int len = packet_read(fd, packet_buffer, sizeof(packet_buffer), |
528 | 0 | PACKET_READ_CHOMP_NEWLINE); |
529 | 0 | if (dst_len) |
530 | 0 | *dst_len = len; |
531 | 0 | return (len > 0) ? packet_buffer : NULL; |
532 | 0 | } |
533 | | |
534 | | int packet_read_line_gently(int fd, int *dst_len, char **dst_line) |
535 | 0 | { |
536 | 0 | int len = packet_read(fd, packet_buffer, sizeof(packet_buffer), |
537 | 0 | PACKET_READ_CHOMP_NEWLINE|PACKET_READ_GENTLE_ON_EOF); |
538 | 0 | if (dst_len) |
539 | 0 | *dst_len = len; |
540 | 0 | if (dst_line) |
541 | 0 | *dst_line = (len > 0) ? packet_buffer : NULL; |
542 | 0 | return len; |
543 | 0 | } |
544 | | |
545 | | ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out, int options) |
546 | 0 | { |
547 | 0 | int packet_len; |
548 | |
|
549 | 0 | size_t orig_len = sb_out->len; |
550 | 0 | size_t orig_alloc = sb_out->alloc; |
551 | |
|
552 | 0 | for (;;) { |
553 | 0 | strbuf_grow(sb_out, LARGE_PACKET_DATA_MAX); |
554 | 0 | packet_len = packet_read(fd_in, |
555 | | /* strbuf_grow() above always allocates one extra byte to |
556 | | * store a '\0' at the end of the string. packet_read() |
557 | | * writes a '\0' extra byte at the end, too. Let it know |
558 | | * that there is already room for the extra byte. |
559 | | */ |
560 | 0 | sb_out->buf + sb_out->len, LARGE_PACKET_DATA_MAX+1, |
561 | 0 | options); |
562 | 0 | if (packet_len <= 0) |
563 | 0 | break; |
564 | 0 | sb_out->len += packet_len; |
565 | 0 | } |
566 | |
|
567 | 0 | if (packet_len < 0) { |
568 | 0 | if (orig_alloc == 0) |
569 | 0 | strbuf_release(sb_out); |
570 | 0 | else |
571 | 0 | strbuf_setlen(sb_out, orig_len); |
572 | 0 | return packet_len; |
573 | 0 | } |
574 | 0 | return sb_out->len - orig_len; |
575 | 0 | } |
576 | | |
577 | | int recv_sideband(const char *me, int in_stream, int out) |
578 | 0 | { |
579 | 0 | char buf[LARGE_PACKET_MAX + 1]; |
580 | 0 | int len; |
581 | 0 | struct strbuf scratch = STRBUF_INIT; |
582 | 0 | enum sideband_type sideband_type; |
583 | |
|
584 | 0 | while (1) { |
585 | 0 | int status = packet_read_with_status(in_stream, NULL, NULL, |
586 | 0 | buf, LARGE_PACKET_MAX, |
587 | 0 | &len, |
588 | 0 | PACKET_READ_GENTLE_ON_EOF); |
589 | 0 | if (!demultiplex_sideband(me, status, buf, len, 0, &scratch, |
590 | 0 | &sideband_type)) |
591 | 0 | continue; |
592 | 0 | switch (sideband_type) { |
593 | 0 | case SIDEBAND_PRIMARY: |
594 | 0 | write_or_die(out, buf + 1, len - 1); |
595 | 0 | break; |
596 | 0 | default: /* errors: message already written */ |
597 | 0 | if (scratch.len > 0) |
598 | 0 | BUG("unhandled incomplete sideband: '%s'", |
599 | 0 | scratch.buf); |
600 | 0 | return sideband_type; |
601 | 0 | } |
602 | 0 | } |
603 | 0 | } |
604 | | |
605 | | /* Packet Reader Functions */ |
606 | | void packet_reader_init(struct packet_reader *reader, int fd, |
607 | | char *src_buffer, size_t src_len, |
608 | | int options) |
609 | 0 | { |
610 | 0 | memset(reader, 0, sizeof(*reader)); |
611 | |
|
612 | 0 | reader->fd = fd; |
613 | 0 | reader->src_buffer = src_buffer; |
614 | 0 | reader->src_len = src_len; |
615 | 0 | reader->buffer = packet_buffer; |
616 | 0 | reader->buffer_size = sizeof(packet_buffer); |
617 | 0 | reader->options = options; |
618 | 0 | reader->me = "git"; |
619 | 0 | reader->hash_algo = &hash_algos[GIT_HASH_SHA1]; |
620 | 0 | strbuf_init(&reader->scratch, 0); |
621 | 0 | } |
622 | | |
623 | | enum packet_read_status packet_reader_read(struct packet_reader *reader) |
624 | 0 | { |
625 | 0 | if (reader->line_peeked) { |
626 | 0 | reader->line_peeked = 0; |
627 | 0 | return reader->status; |
628 | 0 | } |
629 | | |
630 | 0 | if (reader->use_sideband) |
631 | 0 | reader->options |= PACKET_READ_USE_SIDEBAND; |
632 | | |
633 | | /* |
634 | | * Consume all progress packets until a primary payload packet is |
635 | | * received |
636 | | */ |
637 | 0 | while (1) { |
638 | 0 | enum sideband_type sideband_type; |
639 | 0 | reader->status = packet_read_with_status(reader->fd, |
640 | 0 | &reader->src_buffer, |
641 | 0 | &reader->src_len, |
642 | 0 | reader->buffer, |
643 | 0 | reader->buffer_size, |
644 | 0 | &reader->pktlen, |
645 | 0 | reader->options); |
646 | 0 | if (!reader->use_sideband) |
647 | 0 | break; |
648 | 0 | if (demultiplex_sideband(reader->me, reader->status, |
649 | 0 | reader->buffer, reader->pktlen, 1, |
650 | 0 | &reader->scratch, &sideband_type)) |
651 | 0 | break; |
652 | 0 | } |
653 | |
|
654 | 0 | if (reader->status == PACKET_READ_NORMAL) |
655 | | /* Skip the sideband designator if sideband is used */ |
656 | 0 | reader->line = reader->use_sideband ? |
657 | 0 | reader->buffer + 1 : reader->buffer; |
658 | 0 | else |
659 | 0 | reader->line = NULL; |
660 | |
|
661 | 0 | return reader->status; |
662 | 0 | } |
663 | | |
664 | | enum packet_read_status packet_reader_peek(struct packet_reader *reader) |
665 | 0 | { |
666 | | /* Only allow peeking a single line */ |
667 | 0 | if (reader->line_peeked) |
668 | 0 | return reader->status; |
669 | | |
670 | | /* Peek a line by reading it and setting peeked flag */ |
671 | 0 | packet_reader_read(reader); |
672 | 0 | reader->line_peeked = 1; |
673 | 0 | return reader->status; |
674 | 0 | } |
675 | | |
676 | | void packet_writer_init(struct packet_writer *writer, int dest_fd) |
677 | 0 | { |
678 | 0 | writer->dest_fd = dest_fd; |
679 | 0 | writer->use_sideband = 0; |
680 | 0 | } |
681 | | |
682 | | void packet_writer_write(struct packet_writer *writer, const char *fmt, ...) |
683 | 0 | { |
684 | 0 | va_list args; |
685 | |
|
686 | 0 | va_start(args, fmt); |
687 | 0 | packet_write_fmt_1(writer->dest_fd, 0, |
688 | 0 | writer->use_sideband ? "\001" : "", fmt, args); |
689 | 0 | va_end(args); |
690 | 0 | } |
691 | | |
692 | | void packet_writer_error(struct packet_writer *writer, const char *fmt, ...) |
693 | 0 | { |
694 | 0 | va_list args; |
695 | |
|
696 | 0 | va_start(args, fmt); |
697 | 0 | packet_write_fmt_1(writer->dest_fd, 0, |
698 | 0 | writer->use_sideband ? "\003" : "ERR ", fmt, args); |
699 | 0 | va_end(args); |
700 | 0 | } |
701 | | |
702 | | void packet_writer_delim(struct packet_writer *writer) |
703 | 0 | { |
704 | 0 | packet_delim(writer->dest_fd); |
705 | 0 | } |
706 | | |
707 | | void packet_writer_flush(struct packet_writer *writer) |
708 | 0 | { |
709 | 0 | packet_flush(writer->dest_fd); |
710 | 0 | } |