Rizin
unix-like reverse engineering framework and cli tools
zip_source_file_stdio_named.c
Go to the documentation of this file.
1 /*
2  zip_source_file_stdio_named.c -- source for stdio file opened by name
3  Copyright (C) 1999-2022 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 "zipint.h"
35 
36 #include "zip_source_file.h"
37 #include "zip_source_file_stdio.h"
38 
39 #include <fcntl.h>
40 #include <stdlib.h>
41 #include <sys/stat.h>
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45 
46 #ifdef HAVE_CLONEFILE
47 #include <sys/attr.h>
48 #include <sys/clonefile.h>
49 #define CAN_CLONE
50 #endif
51 #ifdef HAVE_FICLONERANGE
52 #include <linux/fs.h>
53 #include <sys/ioctl.h>
54 #define CAN_CLONE
55 #endif
56 
57 static int create_temp_file(zip_source_file_context_t *ctx, bool create_file);
58 
61 #ifdef CAN_CLONE
62 static zip_int64_t _zip_stdio_op_create_temp_output_cloning(zip_source_file_context_t *ctx, zip_uint64_t offset);
63 #endif
67 static char *_zip_stdio_op_strdup(zip_source_file_context_t *ctx, const char *string);
69 
70 /* clang-format off */
75 #ifdef CAN_CLONE
76  _zip_stdio_op_create_temp_output_cloning,
77 #else
78  NULL,
79 #endif
89 };
90 /* clang-format on */
91 
94  if (za == NULL)
95  return NULL;
96 
98 }
99 
100 
103  if (fname == NULL || length < -1) {
105  return NULL;
106  }
107 
109 }
110 
111 
112 static zip_int64_t
114  if (fclose(ctx->fout) < 0) {
115  zip_error_set(&ctx->error, ZIP_ER_WRITE, errno);
116  return -1;
117  }
118  if (rename(ctx->tmpname, ctx->fname) < 0) {
120  return -1;
121  }
122 
123  return 0;
124 }
125 
126 
127 static zip_int64_t
129  int fd = create_temp_file(ctx, true);
130 
131  if (fd < 0) {
132  return -1;
133  }
134 
135  if ((ctx->fout = fdopen(fd, "r+b")) == NULL) {
137  close(fd);
138  (void)remove(ctx->tmpname);
139  free(ctx->tmpname);
140  ctx->tmpname = NULL;
141  return -1;
142  }
143 
144  return 0;
145 }
146 
147 #ifdef CAN_CLONE
148 static zip_int64_t
149 _zip_stdio_op_create_temp_output_cloning(zip_source_file_context_t *ctx, zip_uint64_t offset) {
150  FILE *tfp;
151 
152  if (offset > ZIP_OFF_MAX) {
154  return -1;
155  }
156 
157 #ifdef HAVE_CLONEFILE
158  /* clonefile insists on creating the file, so just create a name */
159  if (create_temp_file(ctx, false) < 0) {
160  return -1;
161  }
162 
163  if (clonefile(ctx->fname, ctx->tmpname, 0) < 0) {
165  free(ctx->tmpname);
166  ctx->tmpname = NULL;
167  return -1;
168  }
169  if ((tfp = _zip_fopen_close_on_exec(ctx->tmpname, true)) == NULL) {
171  (void)remove(ctx->tmpname);
172  free(ctx->tmpname);
173  ctx->tmpname = NULL;
174  return -1;
175  }
176 #else
177  {
178  int fd;
179  struct file_clone_range range;
180  struct stat st;
181 
182  if (fstat(fileno(ctx->f), &st) < 0) {
184  return -1;
185  }
186 
187  if ((fd = create_temp_file(ctx, true)) < 0) {
188  return -1;
189  }
190 
191  range.src_fd = fileno(ctx->f);
192  range.src_offset = 0;
193  range.src_length = ((offset + st.st_blksize - 1) / st.st_blksize) * st.st_blksize;
194  if (range.src_length > st.st_size) {
195  range.src_length = 0;
196  }
197  range.dest_offset = 0;
198  if (ioctl(fd, FICLONERANGE, &range) < 0) {
200  (void)close(fd);
201  (void)remove(ctx->tmpname);
202  free(ctx->tmpname);
203  ctx->tmpname = NULL;
204  return -1;
205  }
206 
207  if ((tfp = fdopen(fd, "r+b")) == NULL) {
209  (void)close(fd);
210  (void)remove(ctx->tmpname);
211  free(ctx->tmpname);
212  ctx->tmpname = NULL;
213  return -1;
214  }
215  }
216 #endif
217 
218  if (ftruncate(fileno(tfp), (off_t)offset) < 0) {
219  (void)fclose(tfp);
220  (void)remove(ctx->tmpname);
221  free(ctx->tmpname);
222  ctx->tmpname = NULL;
223  return -1;
224  }
225  if (fseeko(tfp, (off_t)offset, SEEK_SET) < 0) {
227  (void)fclose(tfp);
228  (void)remove(ctx->tmpname);
229  free(ctx->tmpname);
230  ctx->tmpname = NULL;
231  return -1;
232  }
233 
234  ctx->fout = tfp;
235 
236  return 0;
237 }
238 #endif
239 
240 static bool
242  if ((ctx->f = _zip_fopen_close_on_exec(ctx->fname, false)) == NULL) {
243  zip_error_set(&ctx->error, ZIP_ER_OPEN, errno);
244  return false;
245  }
246  return true;
247 }
248 
249 
250 static zip_int64_t
252  if (remove(ctx->fname) < 0) {
254  return -1;
255  }
256  return 0;
257 }
258 
259 
260 static void
262  if (ctx->fout) {
263  fclose(ctx->fout);
264  }
265  (void)remove(ctx->tmpname);
266 }
267 
268 static char *
270  return strdup(string);
271 }
272 
273 
274 static zip_int64_t
276  size_t ret;
277 
278  clearerr((FILE *)ctx->fout);
279  ret = fwrite(data, 1, len, (FILE *)ctx->fout);
280  if (ret != len || ferror((FILE *)ctx->fout)) {
281  zip_error_set(&ctx->error, ZIP_ER_WRITE, errno);
282  return -1;
283  }
284 
285  return (zip_int64_t)ret;
286 }
287 
288 
289 static int create_temp_file(zip_source_file_context_t *ctx, bool create_file) {
290  char *temp;
291  int mode;
292  struct stat st;
293  int fd;
294  char *start, *end;
295 
296  if (stat(ctx->fname, &st) == 0) {
297  mode = st.st_mode;
298  }
299  else {
300  mode = -1;
301  }
302 
303  if ((temp = (char *)malloc(strlen(ctx->fname) + 13)) == NULL) {
305  return -1;
306  }
307  sprintf(temp, "%s.XXXXXX.part", ctx->fname);
308  end = temp + strlen(temp) - 5;
309  start = end - 6;
310 
311  for (;;) {
313  char *xs = start;
314 
315  while (xs < end) {
316  char digit = value % 36;
317  if (digit < 10) {
318  *(xs++) = digit + '0';
319  }
320  else {
321  *(xs++) = digit - 10 + 'a';
322  }
323  value /= 36;
324  }
325 
326  if (create_file) {
327  if ((fd = open(temp, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, mode == -1 ? 0666 : (mode_t)mode)) >= 0) {
328  if (mode != -1) {
329  /* open() honors umask(), which we don't want in this case */
330 #ifdef HAVE_FCHMOD
331  (void)fchmod(fd, (mode_t)mode);
332 #else
333  (void)chmod(temp, (mode_t)mode);
334 #endif
335  }
336  break;
337  }
338  if (errno != EEXIST) {
340  free(temp);
341  return -1;
342  }
343  }
344  else {
345  if (stat(temp, &st) < 0) {
346  if (errno == ENOENT) {
347  break;
348  }
349  else {
351  free(temp);
352  return -1;
353  }
354  }
355  }
356  }
357 
358  ctx->tmpname = temp;
359 
360  return create_file ? fd : 0;
361 }
size_t len
Definition: 6502dis.c:15
static int value
Definition: cmd_api.c:93
#define fseeko(s, o, w)
Definition: compat.h:121
#define O_CLOEXEC
Definition: compat.h:80
#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 ftruncate
Definition: sflib.h:113
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 fchmod
Definition: sflib.h:84
static static fork const void static count close
Definition: sflib.h:33
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 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 fstat
Definition: sflib.h:107
static static sync static getppid static getegid const char static filename ioctl
Definition: sflib.h:62
static static fork const void static count static fd const char const char static newpath const char static path chmod
Definition: sflib.h:35
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 length
Definition: sflib.h:133
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
sprintf
Definition: kernel.h:365
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int)
Definition: zip_error.c:126
#define ZIP_ER_WRITE
Definition: zip.h:111
#define ZIP_ER_SEEK
Definition: zip.h:109
#define ZIP_ER_OPEN
Definition: zip.h:116
#define ZIP_ER_MEMORY
Definition: zip.h:119
#define ZIP_ER_TMPOPEN
Definition: zip.h:117
#define ZIP_ER_REMOVE
Definition: zip.h:127
#define ZIP_EXTERN
Definition: zip.h:54
#define ZIP_ER_INVAL
Definition: zip.h:123
#define ZIP_ER_RENAME
Definition: zip.h:107
void * malloc(size_t size)
Definition: malloc.c:123
static stat
Definition: sflib.h:131
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync rename
Definition: sflib.h:69
string FILE
Definition: benchmark.py:21
#define ENOENT
Definition: sftypes.h:112
#define EEXIST
Definition: sftypes.h:127
#define O_CREAT
Definition: sftypes.h:489
int mode_t
Definition: sftypes.h:42
#define O_EXCL
Definition: sftypes.h:490
int off_t
Definition: sftypes.h:41
#define E2BIG
Definition: sftypes.h:117
#define O_RDWR
Definition: sftypes.h:488
zip_error_t * error
Definition: sftypes.h:80
Definition: zip.h:284
Definition: zipint.h:278
zip_error_t error
Definition: zipint.h:281
void error(const char *msg)
Definition: untgz.c:593
static const z80_opcode fd[]
Definition: z80_tab.h:997
#define SEEK_SET
Definition: zip.c:88
zip_uint32_t zip_random_uint32(void)
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)
void _zip_stdio_op_close(zip_source_file_context_t *ctx)
zip_int64_t _zip_stdio_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len)
zip_int64_t _zip_stdio_op_tell(zip_source_file_context_t *ctx, void *f)
bool _zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st)
FILE * _zip_fopen_close_on_exec(const char *name, bool writeable)
bool _zip_stdio_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence)
static void _zip_stdio_op_rollback_write(zip_source_file_context_t *ctx)
static char * _zip_stdio_op_strdup(zip_source_file_context_t *ctx, const char *string)
ZIP_EXTERN zip_source_t * zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error)
static zip_int64_t _zip_stdio_op_commit_write(zip_source_file_context_t *ctx)
static zip_int64_t _zip_stdio_op_remove(zip_source_file_context_t *ctx)
static zip_int64_t _zip_stdio_op_create_temp_output(zip_source_file_context_t *ctx)
ZIP_EXTERN zip_source_t * zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len)
static bool _zip_stdio_op_open(zip_source_file_context_t *ctx)
static zip_int64_t _zip_stdio_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len)
static int create_temp_file(zip_source_file_context_t *ctx, bool create_file)
static zip_source_file_operations_t ops_stdio_named
uint64_t zip_uint64_t
Definition: zipconf.h:39
uint32_t zip_uint32_t
Definition: zipconf.h:37
int64_t zip_int64_t
Definition: zipconf.h:38
zip_t * za
Definition: ziptool.c:79