Skip to content

Commit e832f43

Browse files
committed
vcs-svn: add binary-safe read function
buffer_read_string works well for non line-oriented input except for one problem: it does not tell the caller how many bytes were actually written. This means that unless one is very careful about checking for errors (and eof) the calling program cannot tell the difference between the string "foo" followed by an early end of file and the string "foo\0bar\0baz". So introduce a variant that reports the length, too, a thinner wrapper around strbuf_fread. Its result is written to a strbuf so the caller does not need to keep track of the number of bytes read. Signed-off-by: Jonathan Nieder <[email protected]>
1 parent d280f68 commit e832f43

File tree

4 files changed

+35
-0
lines changed

4 files changed

+35
-0
lines changed

t/t0081-line-buffer.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,15 @@ test_expect_success 'skip, copy null byte' '
151151
test_cmp expect actual
152152
'
153153

154+
test_expect_success 'read null byte' '
155+
echo ">QhelloQ" | q_to_nul >expect &&
156+
q_to_nul <<-\EOF | test-line-buffer >actual &&
157+
binary 8
158+
QhelloQ
159+
EOF
160+
test_cmp expect actual
161+
'
162+
154163
test_expect_success 'long reads are truncated' '
155164
echo foo >expect &&
156165
test-line-buffer <<-\EOF >actual &&
@@ -171,4 +180,13 @@ test_expect_success 'long copies are truncated' '
171180
test_cmp expect actual
172181
'
173182

183+
test_expect_success 'long binary reads are truncated' '
184+
echo ">foo" >expect &&
185+
test-line-buffer <<-\EOF >actual &&
186+
binary 5
187+
foo
188+
EOF
189+
test_cmp expect actual
190+
'
191+
174192
test_done

test-line-buffer.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
#include "git-compat-util.h"
6+
#include "strbuf.h"
67
#include "vcs-svn/line_buffer.h"
78

89
static uint32_t strtouint32(const char *s)
@@ -17,6 +18,15 @@ static uint32_t strtouint32(const char *s)
1718
static void handle_command(const char *command, const char *arg, struct line_buffer *buf)
1819
{
1920
switch (*command) {
21+
case 'b':
22+
if (!prefixcmp(command, "binary ")) {
23+
struct strbuf sb = STRBUF_INIT;
24+
strbuf_addch(&sb, '>');
25+
buffer_read_binary(buf, &sb, strtouint32(arg));
26+
fwrite(sb.buf, 1, sb.len, stdout);
27+
strbuf_release(&sb);
28+
return;
29+
}
2030
case 'c':
2131
if (!prefixcmp(command, "copy ")) {
2232
buffer_copy_bytes(buf, strtouint32(arg));

vcs-svn/line_buffer.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ char *buffer_read_string(struct line_buffer *buf, uint32_t len)
5656
return ferror(buf->infile) ? NULL : buf->blob_buffer.buf;
5757
}
5858

59+
void buffer_read_binary(struct line_buffer *buf,
60+
struct strbuf *sb, uint32_t size)
61+
{
62+
strbuf_fread(sb, size, buf->infile);
63+
}
64+
5965
void buffer_copy_bytes(struct line_buffer *buf, uint32_t len)
6066
{
6167
char byte_buffer[COPY_BUFFER_LEN];

vcs-svn/line_buffer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ int buffer_init(struct line_buffer *buf, const char *filename);
1616
int buffer_deinit(struct line_buffer *buf);
1717
char *buffer_read_line(struct line_buffer *buf);
1818
char *buffer_read_string(struct line_buffer *buf, uint32_t len);
19+
void buffer_read_binary(struct line_buffer *buf, struct strbuf *sb, uint32_t len);
1920
void buffer_copy_bytes(struct line_buffer *buf, uint32_t len);
2021
void buffer_skip_bytes(struct line_buffer *buf, uint32_t len);
2122
void buffer_reset(struct line_buffer *buf);

0 commit comments

Comments
 (0)