pkt-line.con commit Merge branch 'jn/warn-on-inaccessible-loosen' (4f43e97)
   1#include "cache.h"
   2#include "pkt-line.h"
   3
   4static const char *packet_trace_prefix = "git";
   5static const char trace_key[] = "GIT_TRACE_PACKET";
   6
   7void packet_trace_identity(const char *prog)
   8{
   9        packet_trace_prefix = xstrdup(prog);
  10}
  11
  12static void packet_trace(const char *buf, unsigned int len, int write)
  13{
  14        int i;
  15        struct strbuf out;
  16
  17        if (!trace_want(trace_key))
  18                return;
  19
  20        /* +32 is just a guess for header + quoting */
  21        strbuf_init(&out, len+32);
  22
  23        strbuf_addf(&out, "packet: %12s%c ",
  24                    packet_trace_prefix, write ? '>' : '<');
  25
  26        if ((len >= 4 && !prefixcmp(buf, "PACK")) ||
  27            (len >= 5 && !prefixcmp(buf+1, "PACK"))) {
  28                strbuf_addstr(&out, "PACK ...");
  29                unsetenv(trace_key);
  30        }
  31        else {
  32                /* XXX we should really handle printable utf8 */
  33                for (i = 0; i < len; i++) {
  34                        /* suppress newlines */
  35                        if (buf[i] == '\n')
  36                                continue;
  37                        if (buf[i] >= 0x20 && buf[i] <= 0x7e)
  38                                strbuf_addch(&out, buf[i]);
  39                        else
  40                                strbuf_addf(&out, "\\%o", buf[i]);
  41                }
  42        }
  43
  44        strbuf_addch(&out, '\n');
  45        trace_strbuf(trace_key, &out);
  46        strbuf_release(&out);
  47}
  48
  49/*
  50 * Write a packetized stream, where each line is preceded by
  51 * its length (including the header) as a 4-byte hex number.
  52 * A length of 'zero' means end of stream (and a length of 1-3
  53 * would be an error).
  54 *
  55 * This is all pretty stupid, but we use this packetized line
  56 * format to make a streaming format possible without ever
  57 * over-running the read buffers. That way we'll never read
  58 * into what might be the pack data (which should go to another
  59 * process entirely).
  60 *
  61 * The writing side could use stdio, but since the reading
  62 * side can't, we stay with pure read/write interfaces.
  63 */
  64ssize_t safe_write(int fd, const void *buf, ssize_t n)
  65{
  66        ssize_t nn = n;
  67        while (n) {
  68                int ret = xwrite(fd, buf, n);
  69                if (ret > 0) {
  70                        buf = (char *) buf + ret;
  71                        n -= ret;
  72                        continue;
  73                }
  74                if (!ret)
  75                        die("write error (disk full?)");
  76                die_errno("write error");
  77        }
  78        return nn;
  79}
  80
  81/*
  82 * If we buffered things up above (we don't, but we should),
  83 * we'd flush it here
  84 */
  85void packet_flush(int fd)
  86{
  87        packet_trace("0000", 4, 1);
  88        safe_write(fd, "0000", 4);
  89}
  90
  91void packet_buf_flush(struct strbuf *buf)
  92{
  93        packet_trace("0000", 4, 1);
  94        strbuf_add(buf, "0000", 4);
  95}
  96
  97#define hex(a) (hexchar[(a) & 15])
  98static char buffer[1000];
  99static unsigned format_packet(const char *fmt, va_list args)
 100{
 101        static char hexchar[] = "0123456789abcdef";
 102        unsigned n;
 103
 104        n = vsnprintf(buffer + 4, sizeof(buffer) - 4, fmt, args);
 105        if (n >= sizeof(buffer)-4)
 106                die("protocol error: impossibly long line");
 107        n += 4;
 108        buffer[0] = hex(n >> 12);
 109        buffer[1] = hex(n >> 8);
 110        buffer[2] = hex(n >> 4);
 111        buffer[3] = hex(n);
 112        packet_trace(buffer+4, n-4, 1);
 113        return n;
 114}
 115
 116void packet_write(int fd, const char *fmt, ...)
 117{
 118        va_list args;
 119        unsigned n;
 120
 121        va_start(args, fmt);
 122        n = format_packet(fmt, args);
 123        va_end(args);
 124        safe_write(fd, buffer, n);
 125}
 126
 127void packet_buf_write(struct strbuf *buf, const char *fmt, ...)
 128{
 129        va_list args;
 130        unsigned n;
 131
 132        va_start(args, fmt);
 133        n = format_packet(fmt, args);
 134        va_end(args);
 135        strbuf_add(buf, buffer, n);
 136}
 137
 138static int safe_read(int fd, void *buffer, unsigned size, int return_line_fail)
 139{
 140        ssize_t ret = read_in_full(fd, buffer, size);
 141        if (ret < 0)
 142                die_errno("read error");
 143        else if (ret < size) {
 144                if (return_line_fail)
 145                        return -1;
 146
 147                die("The remote end hung up unexpectedly");
 148        }
 149
 150        return ret;
 151}
 152
 153static int packet_length(const char *linelen)
 154{
 155        int n;
 156        int len = 0;
 157
 158        for (n = 0; n < 4; n++) {
 159                unsigned char c = linelen[n];
 160                len <<= 4;
 161                if (c >= '0' && c <= '9') {
 162                        len += c - '0';
 163                        continue;
 164                }
 165                if (c >= 'a' && c <= 'f') {
 166                        len += c - 'a' + 10;
 167                        continue;
 168                }
 169                if (c >= 'A' && c <= 'F') {
 170                        len += c - 'A' + 10;
 171                        continue;
 172                }
 173                return -1;
 174        }
 175        return len;
 176}
 177
 178static int packet_read_internal(int fd, char *buffer, unsigned size, int return_line_fail)
 179{
 180        int len, ret;
 181        char linelen[4];
 182
 183        ret = safe_read(fd, linelen, 4, return_line_fail);
 184        if (return_line_fail && ret < 0)
 185                return ret;
 186        len = packet_length(linelen);
 187        if (len < 0)
 188                die("protocol error: bad line length character: %.4s", linelen);
 189        if (!len) {
 190                packet_trace("0000", 4, 0);
 191                return 0;
 192        }
 193        len -= 4;
 194        if (len >= size)
 195                die("protocol error: bad line length %d", len);
 196        ret = safe_read(fd, buffer, len, return_line_fail);
 197        if (return_line_fail && ret < 0)
 198                return ret;
 199        buffer[len] = 0;
 200        packet_trace(buffer, len, 0);
 201        return len;
 202}
 203
 204int packet_read(int fd, char *buffer, unsigned size)
 205{
 206        return packet_read_internal(fd, buffer, size, 1);
 207}
 208
 209int packet_read_line(int fd, char *buffer, unsigned size)
 210{
 211        return packet_read_internal(fd, buffer, size, 0);
 212}
 213
 214int packet_get_line(struct strbuf *out,
 215        char **src_buf, size_t *src_len)
 216{
 217        int len;
 218
 219        if (*src_len < 4)
 220                return -1;
 221        len = packet_length(*src_buf);
 222        if (len < 0)
 223                return -1;
 224        if (!len) {
 225                *src_buf += 4;
 226                *src_len -= 4;
 227                packet_trace("0000", 4, 0);
 228                return 0;
 229        }
 230        if (*src_len < len)
 231                return -2;
 232
 233        *src_buf += 4;
 234        *src_len -= 4;
 235        len -= 4;
 236
 237        strbuf_add(out, *src_buf, len);
 238        *src_buf += len;
 239        *src_len -= len;
 240        packet_trace(out->buf, out->len, 0);
 241        return len;
 242}