Imported Upstream version 1.4.0
[platform/upstream/libzip.git] / examples / in-memory.c
1 /*
2   in-memory.c -- modify zip file in memory
3   Copyright (C) 2014-2015 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 <libzip@nih.at>
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 <errno.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/stat.h>
39
40 #include <zip.h>
41
42 static int
43 get_data(void **datap, size_t *sizep, const char *archive)
44 {
45     /* example implementation that reads data from file */
46     struct stat st;
47     FILE *fp;
48
49     if ((fp=fopen(archive, "r")) == NULL) {
50         if (errno != ENOENT) {
51             fprintf(stderr, "can't open %s: %s\n", archive, strerror(errno));
52             return -1;
53         }
54
55         *datap = NULL;
56         *sizep = 0;
57         
58         return 0;
59     }
60
61     if (fstat(fileno(fp), &st) < 0) {
62         fprintf(stderr, "can't stat %s: %s\n", archive, strerror(errno));
63         fclose(fp);
64         return -1;
65     }
66
67     if ((*datap = malloc((size_t)st.st_size)) == NULL) {
68         fprintf(stderr, "can't allocate buffer\n");
69         fclose(fp);
70         return -1;
71     }
72
73     if (fread(*datap, 1, (size_t)st.st_size, fp) < (size_t)st.st_size) {
74         fprintf(stderr, "can't read %s: %s\n", archive, strerror(errno));
75         free(*datap);
76         fclose(fp);
77         return -1;
78     }
79
80     fclose(fp);
81
82     *sizep = (size_t)st.st_size;
83     return 0;
84 }
85
86 static int
87 modify_archive(zip_t *za)
88 {
89     /* modify the archive */
90     return 0;
91 }
92
93
94 static int
95 use_data(void *data, size_t size, const char *archive)
96 {
97     /* example implementation that writes data to file */
98     FILE *fp;
99
100     if (data == NULL) {
101         if (remove(archive) < 0 && errno != ENOENT) {
102             fprintf(stderr, "can't remove %s: %s\n", archive, strerror(errno));
103             return -1;
104         }
105         return 0;
106     }
107
108     if ((fp = fopen(archive, "wb")) == NULL) {
109         fprintf(stderr, "can't open %s: %s\n", archive, strerror(errno));
110         return -1;
111     }
112     if (fwrite(data, 1, size, fp) < size) {
113         fprintf(stderr, "can't write %s: %s\n", archive, strerror(errno));
114         fclose(fp);
115         return -1;
116     }
117     if (fclose(fp) < 0) {
118         fprintf(stderr, "can't write %s: %s\n", archive, strerror(errno));
119         return -1;
120     }
121
122     return 0;
123 }
124
125
126 int
127 main(int argc, char *argv[])
128 {
129     const char *archive;
130     zip_source_t *src;
131     zip_t *za;
132     zip_error_t error;
133     void *data;
134     size_t size;
135
136     if (argc < 2) {
137         fprintf(stderr, "usage: %s archive\n", argv[0]);
138         return 1;
139     }
140     archive = argv[1];
141
142     /* get buffer with zip archive inside */
143     if (get_data(&data, &size, archive) < 0) {
144         return 1;
145     }
146
147     zip_error_init(&error);
148     /* create source from buffer */
149     if ((src = zip_source_buffer_create(data, size, 1, &error)) == NULL) {
150         fprintf(stderr, "can't create source: %s\n", zip_error_strerror(&error));
151         free(data);
152         zip_error_fini(&error);
153         return 1;
154     }
155
156     /* open zip archive from source */
157     if ((za = zip_open_from_source(src, 0, &error)) == NULL) {
158         fprintf(stderr, "can't open zip from source: %s\n", zip_error_strerror(&error));
159         zip_source_free(src);
160         zip_error_fini(&error);
161         return 1;
162     }
163     zip_error_fini(&error);
164
165     /* we'll want to read the data back after zip_close */
166     zip_source_keep(src);
167
168     /* modify archive */
169     modify_archive(za);
170
171     /* close archive */
172     if (zip_close(za) < 0) {
173         fprintf(stderr, "can't close zip archive '%s': %s\n", archive, zip_strerror(za));
174         return 1;
175     }
176
177
178     /* copy new archive to buffer */
179
180     if (zip_source_is_deleted(src)) {
181         /* new archive is empty, thus no data */
182         data = NULL;
183     }
184     else {
185         zip_stat_t zst;
186
187         if (zip_source_stat(src, &zst) < 0) {
188             fprintf(stderr, "can't stat source: %s\n", zip_error_strerror(zip_source_error(src)));
189             return 1;
190         }
191
192         size = zst.size;
193
194         if (zip_source_open(src) < 0) {
195             fprintf(stderr, "can't open source: %s\n", zip_error_strerror(zip_source_error(src)));
196             return 1;
197         }
198         if ((data = malloc(size)) == NULL) {
199             fprintf(stderr, "malloc failed: %s\n", strerror(errno));
200             zip_source_close(src);
201             return 1;
202         }
203         if ((zip_uint64_t)zip_source_read(src, data, size) < size) {
204             fprintf(stderr, "can't read data from source: %s\n", zip_error_strerror(zip_source_error(src)));
205             zip_source_close(src);
206             free(data);
207             return 1;
208         }
209         zip_source_close(src);
210     }
211
212     /* we're done with src */
213     zip_source_free(src);
214
215     /* use new data */
216     use_data(data, size, archive);
217
218     free(data);
219
220     return 0;
221 }