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