4 author: José Bollo <jose.bollo@iot.bzh>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
19 #define _BSD_SOURCE /* see readdir */
22 #include <sys/types.h>
32 #include "wgtpkg-files.h"
33 #include "wgtpkg-workdir.h"
34 #include "wgtpkg-zip.h"
36 #define MODE_OF_FILE_CREATION 0640
37 #define MODE_OF_DIRECTORY_CREATION 0750
39 #if !defined(USE_LIBZIP)
43 /***********************************************************
45 ***********************************************************/
50 static int is_valid_filename(const char *filename)
56 c = (unsigned char)filename[index];
59 || ((lastsp = (c == 0x20)) && index == 0)
60 || c == 0x7f || c == 0x3c || c == 0x3e
61 || c == 0x3a || c == 0x22
62 || c == 0x5c || c == 0x7c || c == 0x3f
63 || c == 0x2a || c == 0x5e || c == 0x60
64 || c == 0x7b || c == 0x7d || c == 0x21)
66 c = (unsigned char)filename[++index];
71 static int create_directory(char *file, int mode)
74 char *last = strrchr(file, '/');
77 rc = mkdirat(workdirfd, file, mode);
81 else if (errno == ENOENT) {
82 rc = create_directory(file, mode);
84 rc = mkdirat(workdirfd, file, mode);
88 ERROR("can't create directory %s", file);
94 static int create_file(char *file, int fmode, int dmode)
96 int fd = openat(workdirfd, file, O_CREAT|O_WRONLY|O_TRUNC, fmode);
97 if (fd < 0 && errno == ENOENT) {
98 if (!create_directory(file, dmode))
99 fd = openat(workdirfd, file, O_CREAT|O_WRONLY|O_TRUNC, fmode);
102 ERROR("can't create file %s", file);
106 /* read (extract) 'zipfile' in current directory */
107 int zread(const char *zipfile, unsigned long long maxsize)
109 struct filedesc *fdesc;
113 unsigned int count, index;
114 struct zip_file *zfile;
115 struct zip_stat zstat;
120 /* open the zip file */
121 zip = zip_open(zipfile, ZIP_CHECKCONS, &err);
123 ERROR("Can't connect to file %s", zipfile);
127 z64 = zip_get_num_entries(zip, 0);
128 if (z64 < 0 || z64 > UINT_MAX) {
129 ERROR("too many entries in %s", zipfile);
132 count = (unsigned int)z64;
134 /* records the files */
137 for (index = 0 ; index < count ; index++) {
138 err = zip_stat_index(zip, index, ZIP_FL_ENC_GUESS, &zstat);
139 /* check the file name */
140 if (!is_valid_filename(zstat.name)) {
141 ERROR("invalid entry %s found in %s", zstat.name, zipfile);
144 if (zstat.name[0] == '/') {
145 ERROR("absolute entry %s found in %s", zstat.name, zipfile);
148 len = strlen(zstat.name);
150 ERROR("empty entry found in %s", zipfile);
153 if (zstat.size == 0) {
155 if (zstat.name[len - 1] != '/') {
156 ERROR("bad directory name %s in %s", zstat.name, zipfile);
160 fdesc = file_add_directory(zstat.name);
163 if (zstat.name[len - 1] == '/') {
164 ERROR("bad file name %s in %s", zstat.name, zipfile);
170 fdesc = file_add_file(zstat.name);
174 fdesc->zindex = index;
178 if (maxsize && esize > maxsize) {
179 ERROR("extracted size %zu greater than allowed size %llu", esize, maxsize);
183 /* unpack the recorded files */
184 assert(count == file_count());
185 for (index = 0 ; index < count ; index++) {
186 fdesc = file_of_index(index);
187 assert(fdesc != NULL);
188 err = zip_stat_index(zip, fdesc->zindex, ZIP_FL_ENC_GUESS, &zstat);
189 assert(zstat.name[0] != '/');
190 if (zstat.size == 0) {
192 err = create_directory((char*)zstat.name, MODE_OF_DIRECTORY_CREATION);
193 if (err && errno != EEXIST)
197 zfile = zip_fopen_index(zip, fdesc->zindex, 0);
199 ERROR("Can't open %s in %s", zstat.name, zipfile);
202 fd = create_file((char*)zstat.name, MODE_OF_FILE_CREATION, MODE_OF_DIRECTORY_CREATION);
208 sizr = zip_fread(zfile, buffer, sizeof buffer);
210 ERROR("error while reading %s in %s", zstat.name, zipfile);
213 sizw = write(fd, buffer, sizr);
215 ERROR("error while writing %s", zstat.name);
243 static int zwr(struct zws *zws, int offset)
249 struct zip_source *zsrc;
252 fd = openat(workdirfd, offset ? zws->name : ".", O_DIRECTORY|O_RDONLY);
254 ERROR("opendir %.*s failed in zwr", offset, zws->name);
260 ERROR("opendir %.*s failed in zwr", offset, zws->name);
265 zws->name[offset++] = '/';
268 while (ent != NULL) {
269 len = strlen(ent->d_name);
270 if (ent->d_name[0] == '.' && (len == 1 ||
271 (ent->d_name[1] == '.' && len == 2)))
273 else if (offset + len >= sizeof(zws->name)) {
274 ERROR("name too long in zwr");
275 errno = ENAMETOOLONG;
278 memcpy(zws->name + offset, ent->d_name, 1+len);
279 if (!is_valid_filename(ent->d_name)) {
280 ERROR("invalid name %s", zws->name);
283 switch (ent->d_type) {
285 z64 = zip_dir_add(zws->zip, zws->name, ZIP_FL_ENC_UTF_8);
287 ERROR("zip_dir_add of %s failed", zws->name);
290 err = zwr(zws, offset + len);
295 fd = openat(workdirfd, zws->name, O_RDONLY);
297 ERROR("openat of %s failed", zws->name);
300 fp = fdopen(fd, "r");
302 ERROR("fdopen of %s failed", zws->name);
306 zsrc = zip_source_filep(zws->zip, fp, 0, 0);
308 ERROR("zip_source_file of %s failed", zws->name);
312 z64 = zip_file_add(zws->zip, zws->name, zsrc, ZIP_FL_ENC_UTF_8);
314 ERROR("zip_file_add of %s failed", zws->name);
315 zip_source_free(zsrc);
333 /* write (pack) content of the current directory in 'zipfile' */
334 int zwrite(const char *zipfile)
339 zws.zip = zip_open(zipfile, ZIP_CREATE|ZIP_TRUNCATE, &err);
341 ERROR("Can't open %s for write", zipfile);
350 /***********************************************************
351 * NOT USING LIBZIP: FORKING
352 ***********************************************************/
355 #include <sys/wait.h>
357 extern char **environ;
359 static int zrun(const char *path, const char *args[])
367 ERROR("error while forking in zrun: %m");
371 rc = execve(realpath(path, NULL), (char * const*)args, environ);
372 ERROR("can't execute %s in zrun: %m", args[0]);
376 /* wait termination of the child */
377 rc = waitid(P_PID, (id_t)rc, &si, WEXITED);
379 ERROR("unexpected wait status in zrun of %s: %m", args[0]);
380 else if (si.si_code != CLD_EXITED)
381 ERROR("unexpected termination status of %s in zrun", args[0]);
382 else if (si.si_status != 0)
383 ERROR("child for %s terminated with error code %d in zwrite", args[0], si.si_status);
389 /* read (extract) 'zipfile' in current directory */
390 int zread(const char *zipfile, unsigned long long maxsize)
403 rc = zrun(PATH_TO_UNZIP, args);
409 /* write (pack) content of the current directory in 'zipfile' */
410 int zwrite(const char *zipfile)
421 return zrun(PATH_TO_ZIP, args);
425 /***********************************************************
427 ***********************************************************/
429 #if defined(TEST_READ)
430 int main(int ac, char **av)
432 for(av++ ; *av ; av++)
438 #if defined(TEST_WRITE)
439 int main(int ac, char **av)
441 for(av++ ; *av ; av++)