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_errno("cannot read delta preimage");
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_offset_overflow(off_t offset
, uintmax_t len
)
36 if (len
> maximum_signed_value_of_type(off_t
))
37 return error("unrepresentable length in delta: "
38 "%"PRIuMAX
" > OFF_MAX", len
);
39 if (signed_add_overflows(offset
, (off_t
) len
))
40 return error("unrepresentable offset in delta: "
41 "%"PRIuMAX
" + %"PRIuMAX
" > OFF_MAX",
42 (uintmax_t) offset
, len
);
46 int move_window(struct sliding_view
*view
, off_t off
, size_t width
)
50 assert(view
->width
<= view
->buf
.len
);
51 assert(!check_offset_overflow(view
->off
, view
->buf
.len
));
53 if (check_offset_overflow(off
, width
))
55 if (off
< view
->off
|| off
+ width
< view
->off
+ view
->width
)
56 return error("invalid delta: window slides left");
57 if (view
->max_off
>= 0 && view
->max_off
< off
+ (off_t
) width
)
58 return error("delta preimage ends early");
60 file_offset
= view
->off
+ view
->buf
.len
;
61 if (off
< file_offset
) {
62 /* Move the overlapping region into place. */
63 strbuf_remove(&view
->buf
, 0, off
- view
->off
);
65 /* Seek ahead to skip the gap. */
66 if (skip_or_whine(view
->file
, off
- file_offset
))
68 strbuf_setlen(&view
->buf
, 0);
71 if (view
->buf
.len
> width
)
73 else if (read_to_fill_or_whine(view
->file
, &view
->buf
, width
))