Coverage Report

Created: 2026-01-09 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/git/pkt-line.c
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
}