Imported Upstream version 1.3.2
[platform/upstream/libzip.git] / src / hole.c
1 /*
2  hole.c -- convert huge files with mostly NULs to/from source_hole
3  Copyright (C) 2014-2016 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 "config.h"
35
36 #include <errno.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #endif
43
44 #ifndef HAVE_GETOPT
45 #include "getopt.h"
46 #endif
47
48 #include "zip.h"
49
50 /* public API */
51
52 zip_source_t *source_hole_create(const char *, int flags, zip_error_t *);
53
54 const char *prg;
55
56
57 static int
58 copy_source(zip_source_t *from, zip_source_t *to)
59 {
60     zip_uint8_t buf[8192];
61     zip_int64_t n;
62     
63     if (zip_source_open(from) < 0) {
64         fprintf(stderr, "%s: can't open source for reading: %s\n", prg, zip_error_strerror(zip_source_error(from)));
65         return -1;
66     }
67     
68     if (zip_source_begin_write(to) < 0) {
69         fprintf(stderr, "%s: can't open source for writing: %s\n", prg, zip_error_strerror(zip_source_error(to)));
70         zip_source_close(from);
71         return -1;
72     }
73         
74     while ((n = zip_source_read(from, buf, sizeof(buf))) > 0) {
75         if (zip_source_write(to, buf, (zip_uint64_t)n) != n) {
76             fprintf(stderr, "%s: can't write to source: %s\n", prg, zip_error_strerror(zip_source_error(to)));
77             zip_source_close(from);
78             zip_source_rollback_write(to);
79             return -1;
80         }
81     }
82     
83     if (n < 0) {
84         fprintf(stderr, "%s: can't read from source: %s\n", prg, zip_error_strerror(zip_source_error(from)));
85         zip_source_close(from);
86         zip_source_rollback_write(to);
87         return -1;
88     }
89
90     zip_source_close(from);
91     
92     if (zip_source_commit_write(to) < 0) {
93         fprintf(stderr, "%s: can't commit source: %s\n", prg, zip_error_strerror(zip_source_error(to)));
94         zip_source_rollback_write(to);
95         return -1;
96     }
97     
98     return 0;
99 }
100
101
102 static zip_source_t *
103 open_compressed(const char *fname, int flags)
104 {
105     zip_error_t error;
106     zip_source_t *src;
107     
108     zip_error_init(&error);
109     
110     if ((src = source_hole_create(fname, flags, &error)) == NULL) {
111         fprintf(stderr, "%s: can't open compressed file %s: %s\n", prg, fname, zip_error_strerror(&error));
112         zip_error_fini(&error);
113         exit(1);
114     }
115     
116     return src;
117 }
118
119
120 static zip_source_t *
121 open_file(const char *fname)
122 {
123     zip_error_t error;
124     zip_source_t *src;
125     
126     zip_error_init(&error);
127     
128     if ((src = zip_source_file_create(fname, 0, 0, &error)) == NULL) {
129         fprintf(stderr, "%s: can't open file %s: %s\n", prg, fname, zip_error_strerror(&error));
130         zip_error_fini(&error);
131         exit(1);
132     }
133     
134     return src;
135 }
136
137
138 static void
139 usage(void)
140 {
141     fprintf(stderr, "usage: %s [-du] in out\n", prg);
142     fprintf(stderr, "\nOptions:\n  -d  decompress in\n  -u  update in\n");
143     exit(1);
144 }
145
146
147 int
148 main(int argc, char **argv)
149 {
150     zip_source_t *from;
151     zip_source_t *to;
152     int c, err;
153     int compress = 1;
154     int decompress = 0;
155     
156     prg = argv[0];
157     
158     while ((c=getopt(argc, argv, "du")) != -1) {
159         switch (c) {
160             case 'd':
161                 compress = 0;
162                 decompress = 1;
163                 break;
164
165             case 'u':
166                 compress = 1;
167                 decompress = 1;
168                 break;
169
170             default:
171                 usage();
172                 break;
173         }
174     }
175     
176     if (optind+2 != argc) {
177         usage();
178     }
179     
180     if (decompress) {
181         from = open_compressed(argv[optind], 0);
182     }
183     else {
184         from = open_file(argv[optind]);
185     }
186
187     if (compress) {
188         to = open_compressed(argv[optind+1], ZIP_CREATE);
189     }
190     else {
191         to = open_file(argv[optind+1]);
192     }
193     
194     err = copy_source(from, to);
195     
196     zip_source_free(from);
197     zip_source_free(to);
198     
199     exit(err < 0 ? 1 : 0);
200 }
201