pkt-line: drop safe_write function
[git] / pkt-line.c
1 #include "cache.h"
2 #include "pkt-line.h"
3
4 static const char *packet_trace_prefix = "git";
5 static const char trace_key[] = "GIT_TRACE_PACKET";
6
7 void packet_trace_identity(const char *prog)
8 {
9         packet_trace_prefix = xstrdup(prog);
10 }
11
12 static 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  * If we buffered things up above (we don't, but we should),
51  * we'd flush it here
52  */
53 void packet_flush(int fd)
54 {
55         packet_trace("0000", 4, 1);
56         write_or_die(fd, "0000", 4);
57 }
58
59 void packet_buf_flush(struct strbuf *buf)
60 {
61         packet_trace("0000", 4, 1);
62         strbuf_add(buf, "0000", 4);
63 }
64
65 #define hex(a) (hexchar[(a) & 15])
66 static char buffer[1000];
67 static unsigned format_packet(const char *fmt, va_list args)
68 {
69         static char hexchar[] = "0123456789abcdef";
70         unsigned n;
71
72         n = vsnprintf(buffer + 4, sizeof(buffer) - 4, fmt, args);
73         if (n >= sizeof(buffer)-4)
74                 die("protocol error: impossibly long line");
75         n += 4;
76         buffer[0] = hex(n >> 12);
77         buffer[1] = hex(n >> 8);
78         buffer[2] = hex(n >> 4);
79         buffer[3] = hex(n);
80         packet_trace(buffer+4, n-4, 1);
81         return n;
82 }
83
84 void packet_write(int fd, const char *fmt, ...)
85 {
86         va_list args;
87         unsigned n;
88
89         va_start(args, fmt);
90         n = format_packet(fmt, args);
91         va_end(args);
92         write_or_die(fd, buffer, n);
93 }
94
95 void packet_buf_write(struct strbuf *buf, const char *fmt, ...)
96 {
97         va_list args;
98         unsigned n;
99
100         va_start(args, fmt);
101         n = format_packet(fmt, args);
102         va_end(args);
103         strbuf_add(buf, buffer, n);
104 }
105
106 static int safe_read(int fd, void *buffer, unsigned size, int return_line_fail)
107 {
108         ssize_t ret = read_in_full(fd, buffer, size);
109         if (ret < 0)
110                 die_errno("read error");
111         else if (ret < size) {
112                 if (return_line_fail)
113                         return -1;
114
115                 die("The remote end hung up unexpectedly");
116         }
117
118         return ret;
119 }
120
121 static int packet_length(const char *linelen)
122 {
123         int n;
124         int len = 0;
125
126         for (n = 0; n < 4; n++) {
127                 unsigned char c = linelen[n];
128                 len <<= 4;
129                 if (c >= '0' && c <= '9') {
130                         len += c - '0';
131                         continue;
132                 }
133                 if (c >= 'a' && c <= 'f') {
134                         len += c - 'a' + 10;
135                         continue;
136                 }
137                 if (c >= 'A' && c <= 'F') {
138                         len += c - 'A' + 10;
139                         continue;
140                 }
141                 return -1;
142         }
143         return len;
144 }
145
146 static int packet_read_internal(int fd, char *buffer, unsigned size, int return_line_fail)
147 {
148         int len, ret;
149         char linelen[4];
150
151         ret = safe_read(fd, linelen, 4, return_line_fail);
152         if (return_line_fail && ret < 0)
153                 return ret;
154         len = packet_length(linelen);
155         if (len < 0)
156                 die("protocol error: bad line length character: %.4s", linelen);
157         if (!len) {
158                 packet_trace("0000", 4, 0);
159                 return 0;
160         }
161         len -= 4;
162         if (len >= size)
163                 die("protocol error: bad line length %d", len);
164         ret = safe_read(fd, buffer, len, return_line_fail);
165         if (return_line_fail && ret < 0)
166                 return ret;
167         buffer[len] = 0;
168         packet_trace(buffer, len, 0);
169         return len;
170 }
171
172 int packet_read(int fd, char *buffer, unsigned size)
173 {
174         return packet_read_internal(fd, buffer, size, 1);
175 }
176
177 int packet_read_line(int fd, char *buffer, unsigned size)
178 {
179         return packet_read_internal(fd, buffer, size, 0);
180 }
181
182 int packet_get_line(struct strbuf *out,
183         char **src_buf, size_t *src_len)
184 {
185         int len;
186
187         if (*src_len < 4)
188                 return -1;
189         len = packet_length(*src_buf);
190         if (len < 0)
191                 return -1;
192         if (!len) {
193                 *src_buf += 4;
194                 *src_len -= 4;
195                 packet_trace("0000", 4, 0);
196                 return 0;
197         }
198         if (*src_len < len)
199                 return -2;
200
201         *src_buf += 4;
202         *src_len -= 4;
203         len -= 4;
204
205         strbuf_add(out, *src_buf, len);
206         *src_buf += len;
207         *src_len -= len;
208         packet_trace(out->buf, out->len, 0);
209         return len;
210 }