2 * Licensed under a two-clause BSD-style license.
3 * See LICENSE for details.
6 #include "git-compat-util.h"
7 #include "sliding_window.h"
8 #include "line_buffer.h"
11 static int input_error(struct line_buffer
*file
)
13 if (!buffer_ferror(file
))
14 return error("delta preimage ends early");
15 return error("cannot read delta preimage: %s", strerror(errno
));
18 static int skip_or_whine(struct line_buffer
*file
, off_t gap
)
20 if (buffer_skip_bytes(file
, gap
) != gap
)
21 return input_error(file
);
25 static int read_to_fill_or_whine(struct line_buffer
*file
,
26 struct strbuf
*buf
, size_t width
)
28 buffer_read_binary(file
, buf
, width
- buf
->len
);
29 if (buf
->len
!= width
)
30 return input_error(file
);
34 static int check_overflow(off_t a
, size_t b
)
36 if (b
> maximum_signed_value_of_type(off_t
))
37 return error("unrepresentable length in delta: "
38 "%"PRIuMAX
" > OFF_MAX", (uintmax_t) b
);
39 if (signed_add_overflows(a
, (off_t
) b
))
40 return error("unrepresentable offset in delta: "
41 "%"PRIuMAX
" + %"PRIuMAX
" > OFF_MAX",
42 (uintmax_t) a
, (uintmax_t) b
);
46 int move_window(struct sliding_view
*view
, off_t off
, size_t width
)
50 assert(view
->width
<= view
->buf
.len
);
51 assert(!check_overflow(view
->off
, view
->buf
.len
));
53 if (check_overflow(off
, width
))
55 if (off
< view
->off
|| off
+ width
< view
->off
+ view
->width
)
56 return error("invalid delta: window slides left");
58 file_offset
= view
->off
+ view
->buf
.len
;
59 if (off
< file_offset
) {
60 /* Move the overlapping region into place. */
61 strbuf_remove(&view
->buf
, 0, off
- view
->off
);
63 /* Seek ahead to skip the gap. */
64 if (skip_or_whine(view
->file
, off
- file_offset
))
66 strbuf_setlen(&view
->buf
, 0);
69 if (view
->buf
.len
> width
)
71 else if (read_to_fill_or_whine(view
->file
, &view
->buf
, width
))