4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
17 #define _BSD_SOURCE /* see readdir */
21 #include <sys/types.h>
34 #if !defined(MODE_OF_FILE_CREATION)
35 #define MODE_OF_FILE_CREATION 0640
37 #if !defined(MODE_OF_DIRECTORY_CREATION)
38 #define MODE_OF_DIRECTORY_CREATION 0750
42 int create_directory(char *file, int mode)
45 char *last = strrchr(file, '/');
48 rc = mkdir(file, mode);
52 else if (errno == ENOENT) {
53 rc = create_directory(file, mode);
55 rc = mkdir(file, mode);
59 syslog(LOG_ERR, "can't create directory %s", file);
65 int create_file(char *file, int fmode, int dmode)
67 int fd = creat(file, fmode);
68 if (fd < 0 && errno == ENOENT) {
69 if (!create_directory(file, dmode))
70 fd = creat(file, fmode);
73 syslog(LOG_ERR, "can't create file %s", file);
77 /* read (extract) 'zipfile' in current directory */
78 int zread(const char *zipfile, unsigned long long maxsize)
80 struct filedesc *fdesc;
84 unsigned int count, index;
85 struct zip_file *zfile;
86 struct zip_stat zstat;
91 /* open the zip file */
92 zip = zip_open(zipfile, ZIP_CHECKCONS, &err);
94 syslog(LOG_ERR, "Can't connect to file %s", zipfile);
98 z64 = zip_get_num_entries(zip, 0);
99 if (z64 < 0 || z64 > UINT_MAX) {
100 syslog(LOG_ERR, "too many entries in %s", zipfile);
103 count = (unsigned int)z64;
105 /* records the files */
108 for (index = 0 ; index < count ; index++) {
109 err = zip_stat_index(zip, index, ZIP_FL_ENC_GUESS, &zstat);
110 /* check the file name */
111 if (zstat.name[0] == '/') {
112 syslog(LOG_ERR, "absolute entry %s found in %s", zstat.name, zipfile);
115 len = strlen(zstat.name);
117 syslog(LOG_ERR, "empty entry found in %s", zipfile);
120 if (zstat.size == 0) {
122 if (zstat.name[len - 1] != '/') {
123 syslog(LOG_ERR, "bad directory name %s in %s", zstat.name, zipfile);
127 fdesc = file_add_directory(zstat.name);
130 if (zstat.name[len - 1] == '/') {
131 syslog(LOG_ERR, "bad file name %s in %s", zstat.name, zipfile);
137 fdesc = file_add_file(zstat.name);
141 fdesc->zindex = index;
145 if (maxsize && esize > maxsize) {
146 syslog(LOG_ERR, "extracted size %zu greater than allowed size %llu", esize, maxsize);
150 /* unpack the recorded files */
151 assert(count == file_count());
152 for (index = 0 ; index < count ; index++) {
153 fdesc = file_of_index(index);
154 assert(fdesc != NULL);
155 err = zip_stat_index(zip, fdesc->zindex, ZIP_FL_ENC_GUESS, &zstat);
156 assert(zstat.name[0] != '/');
157 if (zstat.size == 0) {
159 err = create_directory((char*)zstat.name, MODE_OF_DIRECTORY_CREATION);
160 if (err && errno != EEXIST)
164 zfile = zip_fopen_index(zip, fdesc->zindex, 0);
166 syslog(LOG_ERR, "Can't open %s in %s", zstat.name, zipfile);
169 fd = create_file((char*)zstat.name, MODE_OF_FILE_CREATION, MODE_OF_DIRECTORY_CREATION);
175 sizr = zip_fread(zfile, buffer, sizeof buffer);
177 syslog(LOG_ERR, "error while reading %s in %s", zstat.name, zipfile);
180 sizw = write(fd, buffer, sizr);
182 syslog(LOG_ERR, "error while writing %s", zstat.name);
210 static int zwr(struct zws *zws, int offset)
216 struct zip_source *zsrc;
221 dir = opendir(zws->name);
222 zws->name[offset++] = '/';
225 syslog(LOG_ERR, "opendir %.*s failed in zwr", offset, zws->name);
230 while (ent != NULL) {
231 len = strlen(ent->d_name);
232 if (ent->d_name[0] == '.' && (len == 1 ||
233 (ent->d_name[1] == '.' && len == 2)))
235 else if (offset + len >= sizeof(zws->name)) {
237 syslog(LOG_ERR, "name too long in zwr");
238 errno = ENAMETOOLONG;
241 memcpy(zws->name + offset, ent->d_name, 1+len);
242 switch (ent->d_type) {
244 z64 = zip_dir_add(zws->zip, zws->name, ZIP_FL_ENC_UTF_8);
246 syslog(LOG_ERR, "zip_dir_add of %s failed", zws->name);
250 err = zwr(zws, offset + len);
257 zsrc = zip_source_file(zws->zip, zws->name, 0, 0);
259 syslog(LOG_ERR, "zip_source_file of %s failed", zws->name);
263 z64 = zip_file_add(zws->zip, zws->name, zsrc, ZIP_FL_ENC_UTF_8);
265 syslog(LOG_ERR, "zip_file_add of %s failed", zws->name);
266 zip_source_free(zsrc);
282 /* write (pack) content of the current directory in 'zipfile' */
283 int zwrite(const char *zipfile)
288 zws.zip = zip_open(zipfile, ZIP_CREATE|ZIP_TRUNCATE, &err);
290 syslog(LOG_ERR, "Can't open %s for write", zipfile);
300 #if defined(TEST_READ)
301 int main(int ac, char **av)
303 for(av++ ; *av ; av++)
309 #if defined(TEST_WRITE)
310 int main(int ac, char **av)
312 for(av++ ; *av ; av++)