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