This source file includes following definitions.
- zip_source_crc
- crc_read
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <limits.h>
38
39 #include "zipint.h"
40
41 struct crc_context {
42 int validate;
43 int crc_complete;
44 zip_error_t error;
45 zip_uint64_t size;
46 zip_uint64_t position;
47 zip_uint64_t crc_position;
48 zip_uint32_t crc;
49 };
50
51 static zip_int64_t crc_read(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
52
53
54 zip_source_t *
55 zip_source_crc(zip_t *za, zip_source_t *src, int validate)
56 {
57 struct crc_context *ctx;
58
59 if (src == NULL) {
60 zip_error_set(&za->error, ZIP_ER_INVAL, 0);
61 return NULL;
62 }
63
64 if ((ctx=(struct crc_context *)malloc(sizeof(*ctx))) == NULL) {
65 zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
66 return NULL;
67 }
68
69 zip_error_init(&ctx->error);
70 ctx->validate = validate;
71 ctx->crc_complete = 0;
72 ctx->crc_position = 0;
73 ctx->crc = (zip_uint32_t)crc32(0, NULL, 0);
74 ctx->size = 0;
75
76 return zip_source_layered(za, src, crc_read, ctx);
77 }
78
79
80 static zip_int64_t
81 crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
82 {
83 struct crc_context *ctx;
84 zip_int64_t n;
85
86 ctx = (struct crc_context *)_ctx;
87
88 switch (cmd) {
89 case ZIP_SOURCE_OPEN:
90 ctx->position = 0;
91 return 0;
92
93 case ZIP_SOURCE_READ:
94 if ((n = zip_source_read(src, data, len)) < 0) {
95 _zip_error_set_from_source(&ctx->error, src);
96 return -1;
97 }
98
99 if (n == 0) {
100 if (ctx->crc_position == ctx->position) {
101 ctx->crc_complete = 1;
102 ctx->size = ctx->position;
103
104 if (ctx->validate) {
105 struct zip_stat st;
106
107 if (zip_source_stat(src, &st) < 0) {
108 _zip_error_set_from_source(&ctx->error, src);
109 return -1;
110 }
111
112 if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
113 zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
114 return -1;
115 }
116 if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
117 zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
118 return -1;
119 }
120 }
121 }
122 }
123 else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) {
124 zip_uint64_t i, nn;
125
126 for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) {
127 nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n-i);
128
129 ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data+i, (uInt)nn);
130 ctx->crc_position += nn;
131 }
132 }
133 ctx->position += (zip_uint64_t)n;
134 return n;
135
136 case ZIP_SOURCE_CLOSE:
137 return 0;
138
139 case ZIP_SOURCE_STAT:
140 {
141 zip_stat_t *st;
142
143 st = (zip_stat_t *)data;
144
145 if (ctx->crc_complete) {
146
147
148 st->size = ctx->size;
149 st->crc = ctx->crc;
150 st->comp_size = ctx->size;
151 st->comp_method = ZIP_CM_STORE;
152 st->encryption_method = ZIP_EM_NONE;
153 st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD;;
154 }
155 return 0;
156 }
157
158 case ZIP_SOURCE_ERROR:
159 return zip_error_to_data(&ctx->error, data, len);
160
161 case ZIP_SOURCE_FREE:
162 free(ctx);
163 return 0;
164
165 case ZIP_SOURCE_SUPPORTS:
166 {
167 zip_int64_t mask = zip_source_supports(src);
168
169 if (mask < 0) {
170 _zip_error_set_from_source(&ctx->error, src);
171 return -1;
172 }
173
174 return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1);
175 }
176
177 case ZIP_SOURCE_SEEK:
178 {
179 zip_int64_t new_position;
180 zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
181
182 if (args == NULL) {
183 return -1;
184 }
185 if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) {
186 _zip_error_set_from_source(&ctx->error, src);
187 return -1;
188 }
189
190 ctx->position = (zip_uint64_t)new_position;
191
192 return 0;
193 }
194
195 case ZIP_SOURCE_TELL:
196 return (zip_int64_t)ctx->position;
197
198 default:
199 zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
200 return -1;
201 }
202 }