2 * Copyright (c) 2019 Stefan Sperling <stsp@openbsd.org>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 #include "got_error.h"
26 #include "got_object.h"
29 #include "got_lib_deflate.h"
32 #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
35 const struct got_error
*
36 got_deflate_init(struct got_deflate_buf
*zb
, uint8_t *outbuf
, size_t bufsize
)
38 const struct got_error
*err
= NULL
;
41 memset(&zb
->z
, 0, sizeof(zb
->z
));
43 zb
->z
.zalloc
= Z_NULL
;
45 zerr
= deflateInit(&zb
->z
, Z_DEFAULT_COMPRESSION
);
48 return got_error_from_errno("deflateInit");
49 if (zerr
== Z_MEM_ERROR
) {
51 return got_error_from_errno("deflateInit");
53 return got_error(GOT_ERR_COMPRESSION
);
56 zb
->inlen
= zb
->outlen
= bufsize
;
58 zb
->inbuf
= calloc(1, zb
->inlen
);
59 if (zb
->inbuf
== NULL
) {
60 err
= got_error_from_errno("calloc");
66 zb
->outbuf
= calloc(1, zb
->outlen
);
67 if (zb
->outbuf
== NULL
) {
68 err
= got_error_from_errno("calloc");
71 zb
->flags
|= GOT_DEFLATE_F_OWN_OUTBUF
;
81 csum_output(struct got_deflate_checksum
*csum
, const uint8_t *buf
, size_t len
)
84 *csum
->output_crc
= crc32(*csum
->output_crc
, buf
, len
);
86 if (csum
->output_sha1
)
87 SHA1Update(csum
->output_sha1
, buf
, len
);
90 const struct got_error
*
91 got_deflate_read(struct got_deflate_buf
*zb
, FILE *f
, size_t *outlenp
)
93 size_t last_total_out
= zb
->z
.total_out
;
97 z
->next_out
= zb
->outbuf
;
98 z
->avail_out
= zb
->outlen
;
102 if (z
->avail_in
== 0) {
103 size_t n
= fread(zb
->inbuf
, 1, zb
->inlen
, f
);
106 return got_ferror(f
, GOT_ERR_IO
);
108 ret
= deflate(z
, Z_FINISH
);
111 z
->next_in
= zb
->inbuf
;
114 ret
= deflate(z
, Z_NO_FLUSH
);
115 } while (ret
== Z_OK
&& z
->avail_out
> 0);
118 zb
->flags
|= GOT_DEFLATE_F_HAVE_MORE
;
120 if (ret
!= Z_STREAM_END
)
121 return got_error(GOT_ERR_COMPRESSION
);
122 zb
->flags
&= ~GOT_DEFLATE_F_HAVE_MORE
;
125 *outlenp
= z
->total_out
- last_total_out
;
130 got_deflate_end(struct got_deflate_buf
*zb
)
133 if (zb
->flags
& GOT_DEFLATE_F_OWN_OUTBUF
)
138 const struct got_error
*
139 got_deflate_to_file(size_t *outlen
, FILE *infile
, FILE *outfile
,
140 struct got_deflate_checksum
*csum
)
142 const struct got_error
*err
;
144 struct got_deflate_buf zb
;
146 err
= got_deflate_init(&zb
, NULL
, GOT_DEFLATE_BUFSIZE
);
153 err
= got_deflate_read(&zb
, infile
, &avail
);
158 n
= fwrite(zb
.outbuf
, avail
, 1, outfile
);
160 err
= got_ferror(outfile
, GOT_ERR_IO
);
164 csum_output(csum
, zb
.outbuf
, avail
);
167 } while (zb
.flags
& GOT_DEFLATE_F_HAVE_MORE
);
170 got_deflate_end(&zb
);