Rizin
unix-like reverse engineering framework and cli tools
zip_source_file_common.c
Go to the documentation of this file.
1 /*
2  zip_source_file_common.c -- create data source from file
3  Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
4 
5  This file is part of libzip, a library to manipulate ZIP archives.
6  The authors can be contacted at <info@libzip.org>
7 
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions
10  are met:
11  1. Redistributions of source code must retain the above copyright
12  notice, this list of conditions and the following disclaimer.
13  2. Redistributions in binary form must reproduce the above copyright
14  notice, this list of conditions and the following disclaimer in
15  the documentation and/or other materials provided with the
16  distribution.
17  3. The names of the authors may not be used to endorse or promote
18  products derived from this software without specific prior
19  written permission.
20 
21  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include "zipint.h"
39 
40 #include "zip_source_file.h"
41 
42 static zip_int64_t read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd);
43 
44 static void
46  st->size = 0;
47  st->mtime = time(NULL);
48  st->exists = false;
49  st->regular_file = false;
50 }
51 
55  zip_source_t *zs;
57 
58  if (ops == NULL) {
60  return NULL;
61  }
62 
63  if (ops->close == NULL || ops->read == NULL || ops->seek == NULL || ops->stat == NULL) {
65  return NULL;
66  }
67 
68  if (ops->write != NULL && (ops->commit_write == NULL || ops->create_temp_output == NULL || ops->remove == NULL || ops->rollback_write == NULL || ops->tell == NULL)) {
70  return NULL;
71  }
72 
73  if (fname != NULL) {
74  if (ops->open == NULL || ops->string_duplicate == NULL) {
76  return NULL;
77  }
78  }
79  else if (file == NULL) {
81  return NULL;
82  }
83 
84  if (len < 0) {
85  len = 0;
86  }
87 
90  return NULL;
91  }
92 
95  return NULL;
96  }
97 
98  ctx->ops = ops;
99  ctx->ops_userdata = ops_userdata;
100  ctx->fname = NULL;
101  if (fname) {
102  if ((ctx->fname = ops->string_duplicate(ctx, fname)) == NULL) {
104  free(ctx);
105  return NULL;
106  }
107  }
108  ctx->f = file;
109  ctx->start = start;
110  ctx->len = (zip_uint64_t)len;
111  if (st) {
112  memcpy(&ctx->st, st, sizeof(ctx->st));
113  ctx->st.name = NULL;
114  ctx->st.valid &= ~ZIP_STAT_NAME;
115  }
116  else {
117  zip_stat_init(&ctx->st);
118  }
119 
120  if (ctx->len > 0) {
121  ctx->st.size = ctx->len;
122  ctx->st.valid |= ZIP_STAT_SIZE;
123  }
124 
125  zip_error_init(&ctx->stat_error);
126 
127  ctx->tmpname = NULL;
128  ctx->fout = NULL;
129 
131  zip_file_attributes_init(&ctx->attributes);
132 
134 
136  if (!ops->stat(ctx, &sb)) {
138  free(ctx->fname);
139  free(ctx);
140  return NULL;
141  }
142 
143  if (!sb.exists) {
144  if (ctx->fname && ctx->start == 0 && ctx->len == 0 && ops->write != NULL) {
145  ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
146  /* zip_open_from_source checks for this to detect non-existing files */
147  zip_error_set(&ctx->stat_error, ZIP_ER_READ, ENOENT);
148  }
149  else {
150  zip_error_set(&ctx->stat_error, ZIP_ER_READ, ENOENT);
151  free(ctx->fname);
152  free(ctx);
153  return NULL;
154  }
155  }
156  else {
157  if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) {
158  ctx->st.mtime = sb.mtime;
159  ctx->st.valid |= ZIP_STAT_MTIME;
160  }
161  if (sb.regular_file) {
162  ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
163 
164  if (ctx->start + ctx->len > sb.size) {
166  free(ctx->fname);
167  free(ctx);
168  return NULL;
169  }
170 
171  if (ctx->len == 0) {
172  ctx->len = sb.size - ctx->start;
173  ctx->st.size = ctx->len;
174  ctx->st.valid |= ZIP_STAT_SIZE;
175 
176  /* when using a partial file, don't allow writing */
177  if (ctx->fname && start == 0 && ops->write != NULL) {
178  ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
179  }
180  }
181  }
182 
184  }
185 
187  if (ops->create_temp_output_cloning != NULL) {
190  }
191  }
192 
194  free(ctx->fname);
195  free(ctx);
196  return NULL;
197  }
198 
199  return zs;
200 }
201 
202 
203 static zip_int64_t
206  char *buf;
207 
209  buf = (char *)data;
210 
211  switch (cmd) {
213  return 0;
214 
216  /* write support should not be set if fname is NULL */
217  if (ctx->fname == NULL) {
219  return -1;
220  }
221  return ctx->ops->create_temp_output(ctx);
222 
224  /* write support should not be set if fname is NULL */
225  if (ctx->fname == NULL) {
227  return -1;
228  }
229  return ctx->ops->create_temp_output_cloning(ctx, len);
230 
231  case ZIP_SOURCE_CLOSE:
232  if (ctx->fname) {
233  ctx->ops->close(ctx);
234  ctx->f = NULL;
235  }
236  return 0;
237 
239  zip_int64_t ret = ctx->ops->commit_write(ctx);
240  ctx->fout = NULL;
241  if (ret == 0) {
242  free(ctx->tmpname);
243  ctx->tmpname = NULL;
244  }
245  return ret;
246  }
247 
248  case ZIP_SOURCE_ERROR:
249  return zip_error_to_data(&ctx->error, data, len);
250 
251  case ZIP_SOURCE_FREE:
252  free(ctx->fname);
253  free(ctx->tmpname);
254  if (ctx->f) {
255  ctx->ops->close(ctx);
256  }
257  free(ctx);
258  return 0;
259 
261  if (len < sizeof(ctx->attributes)) {
263  return -1;
264  }
265  memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
266  return sizeof(ctx->attributes);
267 
268  case ZIP_SOURCE_OPEN:
269  if (ctx->fname) {
270  if (ctx->ops->open(ctx) == false) {
271  return -1;
272  }
273  }
274 
275  if (ctx->start > 0) { // TODO: rewind on re-open
276  if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)ctx->start, SEEK_SET) == false) {
277  /* TODO: skip by reading */
278  return -1;
279  }
280  }
281  ctx->offset = 0;
282  return 0;
283 
284  case ZIP_SOURCE_READ: {
285  zip_int64_t i;
286  zip_uint64_t n;
287 
288  if (ctx->len > 0) {
289  n = ZIP_MIN(ctx->len - ctx->offset, len);
290  }
291  else {
292  n = len;
293  }
294 
295  if ((i = ctx->ops->read(ctx, buf, n)) < 0) {
296  zip_error_set(&ctx->error, ZIP_ER_READ, errno);
297  return -1;
298  }
299  ctx->offset += (zip_uint64_t)i;
300 
301  return i;
302  }
303 
304  case ZIP_SOURCE_REMOVE:
305  return ctx->ops->remove(ctx);
306 
308  ctx->ops->rollback_write(ctx);
309  ctx->fout = NULL;
310  free(ctx->tmpname);
311  ctx->tmpname = NULL;
312  return 0;
313 
314  case ZIP_SOURCE_SEEK: {
315  zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset, ctx->len, data, len, &ctx->error);
316 
317  if (new_offset < 0) {
318  return -1;
319  }
320 
321  /* The actual offset inside the file must be representable as zip_int64_t. */
322  if (new_offset > ZIP_INT64_MAX - (zip_int64_t)ctx->start) {
324  return -1;
325  }
326 
327  ctx->offset = (zip_uint64_t)new_offset;
328 
329  if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)(ctx->offset + ctx->start), SEEK_SET) == false) {
330  return -1;
331  }
332  return 0;
333  }
334 
335  case ZIP_SOURCE_SEEK_WRITE: {
337 
339  if (args == NULL) {
340  return -1;
341  }
342 
343  if (ctx->ops->seek(ctx, ctx->fout, args->offset, args->whence) == false) {
344  return -1;
345  }
346  return 0;
347  }
348 
349  case ZIP_SOURCE_STAT: {
350  if (len < sizeof(ctx->st))
351  return -1;
352 
353  if (zip_error_code_zip(&ctx->stat_error) != 0) {
354  zip_error_set(&ctx->error, zip_error_code_zip(&ctx->stat_error), zip_error_code_system(&ctx->stat_error));
355  return -1;
356  }
357 
358  memcpy(data, &ctx->st, sizeof(ctx->st));
359  return sizeof(ctx->st);
360  }
361 
362  case ZIP_SOURCE_SUPPORTS:
363  return ctx->supports;
364 
365  case ZIP_SOURCE_TELL:
366  return (zip_int64_t)ctx->offset;
367 
369  return ctx->ops->tell(ctx, ctx->fout);
370 
371  case ZIP_SOURCE_WRITE:
372  return ctx->ops->write(ctx, data, len);
373 
374  default:
376  return -1;
377  }
378 }
size_t len
Definition: 6502dis.c:15
static struct @29 ops[]
lzma_index ** i
Definition: index.h:629
static SblHeader sb
Definition: bin_mbn.c:26
#define EOVERFLOW
Definition: compat.h:75
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
Definition: sflib.h:79
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
#define ZIP_ER_INTERNAL
Definition: zip.h:125
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int)
Definition: zip_error.c:126
#define ZIP_STAT_NAME
Definition: zip.h:290
#define ZIP_ER_SEEK
Definition: zip.h:109
#define ZIP_SOURCE_SUPPORTS_SEEKABLE
Definition: zip.h:256
#define ZIP_SOURCE_SUPPORTS_READABLE
Definition: zip.h:249
ZIP_EXTERN void zip_file_attributes_init(zip_file_attributes_t *_Nonnull)
#define ZIP_SOURCE_SUPPORTS_WRITABLE
Definition: zip.h:261
#define ZIP_ER_MEMORY
Definition: zip.h:119
#define ZIP_STAT_SIZE
Definition: zip.h:292
ZIP_EXTERN int zip_error_code_system(const zip_error_t *_Nonnull)
Definition: zip_error.c:40
ZIP_EXTERN zip_int64_t zip_source_seek_compute_offset(zip_uint64_t, zip_uint64_t, void *_Nonnull, zip_uint64_t, zip_error_t *_Nullable)
ZIP_EXTERN void zip_stat_init(zip_stat_t *_Nonnull)
Definition: zip_stat_init.c:40
ZIP_EXTERN void zip_error_init(zip_error_t *_Nonnull)
Definition: zip_error.c:59
enum zip_source_cmd zip_source_cmd_t
Definition: zip.h:241
#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd)
Definition: zip.h:243
@ ZIP_SOURCE_CLOSE
Definition: zip.h:222
@ ZIP_SOURCE_READ
Definition: zip.h:221
@ ZIP_SOURCE_GET_FILE_ATTRIBUTES
Definition: zip.h:239
@ ZIP_SOURCE_FREE
Definition: zip.h:225
@ ZIP_SOURCE_ACCEPT_EMPTY
Definition: zip.h:238
@ ZIP_SOURCE_BEGIN_WRITE_CLONING
Definition: zip.h:237
@ ZIP_SOURCE_SEEK
Definition: zip.h:226
@ ZIP_SOURCE_SEEK_WRITE
Definition: zip.h:232
@ ZIP_SOURCE_SUPPORTS
Definition: zip.h:234
@ ZIP_SOURCE_STAT
Definition: zip.h:223
@ ZIP_SOURCE_TELL
Definition: zip.h:227
@ ZIP_SOURCE_OPEN
Definition: zip.h:220
@ ZIP_SOURCE_REMOVE
Definition: zip.h:235
@ ZIP_SOURCE_ROLLBACK_WRITE
Definition: zip.h:230
@ ZIP_SOURCE_TELL_WRITE
Definition: zip.h:233
@ ZIP_SOURCE_BEGIN_WRITE
Definition: zip.h:228
@ ZIP_SOURCE_WRITE
Definition: zip.h:231
@ ZIP_SOURCE_ERROR
Definition: zip.h:224
@ ZIP_SOURCE_COMMIT_WRITE
Definition: zip.h:229
ZIP_EXTERN zip_source_t *_Nullable zip_source_function_create(zip_source_callback _Nonnull, void *_Nullable, zip_error_t *_Nullable)
#define ZIP_ER_INVAL
Definition: zip.h:123
ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t,...)
#define ZIP_STAT_MTIME
Definition: zip.h:294
ZIP_EXTERN int zip_error_code_zip(const zip_error_t *_Nonnull)
Definition: zip_error.c:46
#define ZIP_ER_OPNOTSUPP
Definition: zip.h:133
ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *_Nonnull, void *_Nonnull, zip_uint64_t)
Definition: zip_error.c:141
#define ZIP_ER_READ
Definition: zip.h:110
#define ZIP_SOURCE_GET_ARGS(type, data, len, error)
Definition: zip.h:279
void * malloc(size_t size)
Definition: malloc.c:123
static static fork const void static count static fd const char const char static newpath char char char static envp time
Definition: sflib.h:42
int args
Definition: mipsasm.c:18
int n
Definition: mipsasm.c:19
#define ENOENT
Definition: sftypes.h:112
zip_error_t * error
Definition: gzappend.c:170
Definition: dis.h:43
Definition: zip.h:284
Definition: zip.h:300
void error(const char *msg)
Definition: untgz.c:593
static int file
Definition: z80asm.c:58
#define SEEK_SET
Definition: zip.c:88
void _zip_error_copy(zip_error_t *dst, const zip_error_t *src)
Definition: zip_error.c:102
static zip_int64_t read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
zip_source_t * zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_source_file_operations_t *ops, void *ops_userdata, zip_error_t *error)
static void zip_source_file_stat_init(zip_source_file_stat_t *st)
uint64_t zip_uint64_t
Definition: zipconf.h:39
#define ZIP_INT64_MAX
Definition: zipconf.h:54
int64_t zip_int64_t
Definition: zipconf.h:38
#define ZIP_MIN(a, b)
Definition: zipint.h:473