"Fossies" - the Fresh Open Source Software Archive

Member "libzip-1.5.2/src/zipmerge.c" (12 Mar 2019, 7668 Bytes) of package /linux/misc/libzip-1.5.2.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "zipmerge.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.5.1_vs_1.5.2.

    1 /*
    2   zipmerge.c -- merge zip archives
    3   Copyright (C) 2004-2018 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 
   35 #include <ctype.h>
   36 #include <errno.h>
   37 #include <stdio.h>
   38 #include <stdlib.h>
   39 #include <string.h>
   40 
   41 #include "config.h"
   42 
   43 #ifdef HAVE_UNISTD_H
   44 #include <unistd.h>
   45 #endif
   46 
   47 #ifndef HAVE_GETOPT
   48 #include "getopt.h"
   49 #endif
   50 
   51 #include "compat.h"
   52 #include "zip.h"
   53 
   54 char *progname;
   55 
   56 #define PROGRAM "zipmerge"
   57 
   58 #define USAGE "usage: %s [-DhIiSsV] target-zip zip...\n"
   59 
   60 char help_head[] = PROGRAM " (" PACKAGE ") by Dieter Baron and Thomas Klausner\n\n";
   61 
   62 char help[] = "\n\
   63   -h       display this help message\n\
   64   -V       display version number\n\
   65   -D       ignore directory component in file names\n\
   66   -I       ignore case in file names\n\
   67   -i       ask before overwriting files\n\
   68   -S       don't overwrite identical files\n\
   69   -s       overwrite identical files without asking\n\
   70 \n\
   71 Report bugs to <libzip@nih.at>.\n";
   72 
   73 char version_string[] = PROGRAM " (" PACKAGE " " VERSION ")\n\
   74 Copyright (C) 2004-2018 Dieter Baron and Thomas Klausner\n\
   75 " PACKAGE " comes with ABSOLUTELY NO WARRANTY, to the extent permitted by law.\n";
   76 
   77 #define OPTIONS "hVDiIsS"
   78 
   79 #define CONFIRM_ALL_YES 0x001
   80 #define CONFIRM_ALL_NO 0x002
   81 #define CONFIRM_SAME_YES 0x010
   82 #define CONFIRM_SAME_NO 0x020
   83 
   84 int confirm;
   85 zip_flags_t name_flags;
   86 
   87 static int confirm_replace(zip_t *, const char *, zip_uint64_t, zip_t *, const char *, zip_uint64_t);
   88 static zip_t *merge_zip(zip_t *, const char *, const char *);
   89 
   90 
   91 int
   92 main(int argc, char *argv[]) {
   93     zip_t *za;
   94     zip_t **zs;
   95     int c, err;
   96     unsigned int i, n;
   97     char *tname;
   98 
   99     progname = argv[0];
  100 
  101     confirm = CONFIRM_ALL_YES;
  102     name_flags = 0;
  103 
  104     while ((c = getopt(argc, argv, OPTIONS)) != -1) {
  105     switch (c) {
  106     case 'D':
  107         name_flags |= ZIP_FL_NODIR;
  108         break;
  109     case 'i':
  110         confirm &= ~CONFIRM_ALL_YES;
  111         break;
  112     case 'I':
  113         name_flags |= ZIP_FL_NOCASE;
  114         break;
  115     case 's':
  116         confirm &= ~CONFIRM_SAME_NO;
  117         confirm |= CONFIRM_SAME_YES;
  118         break;
  119     case 'S':
  120         confirm &= ~CONFIRM_SAME_YES;
  121         confirm |= CONFIRM_SAME_NO;
  122         break;
  123 
  124     case 'h':
  125         fputs(help_head, stdout);
  126         printf(USAGE, progname);
  127         fputs(help, stdout);
  128         exit(0);
  129     case 'V':
  130         fputs(version_string, stdout);
  131         exit(0);
  132 
  133     default:
  134         fprintf(stderr, USAGE, progname);
  135         exit(2);
  136     }
  137     }
  138 
  139     if (argc < optind + 2) {
  140     fprintf(stderr, USAGE, progname);
  141     exit(2);
  142     }
  143 
  144     tname = argv[optind++];
  145     argv += optind;
  146 
  147     n = (unsigned int)(argc - optind);
  148     if ((zs = (zip_t **)malloc(sizeof(zs[0]) * n)) == NULL) {
  149     fprintf(stderr, "%s: out of memory\n", progname);
  150     exit(1);
  151     }
  152 
  153     if ((za = zip_open(tname, ZIP_CREATE, &err)) == NULL) {
  154     zip_error_t error;
  155     zip_error_init_with_code(&error, err);
  156     fprintf(stderr, "%s: can't open zip archive '%s': %s\n", progname, tname, zip_error_strerror(&error));
  157     zip_error_fini(&error);
  158     exit(1);
  159     }
  160 
  161     for (i = 0; i < n; i++) {
  162     if ((zs[i] = merge_zip(za, tname, argv[i])) == NULL)
  163         exit(1);
  164     }
  165 
  166     if (zip_close(za) < 0) {
  167     fprintf(stderr, "%s: cannot write zip archive '%s': %s\n", progname, tname, zip_strerror(za));
  168     exit(1);
  169     }
  170 
  171     for (i = 0; i < n; i++)
  172     zip_close(zs[i]);
  173 
  174     exit(0);
  175 }
  176 
  177 
  178 static int
  179 confirm_replace(zip_t *za, const char *tname, zip_uint64_t it, zip_t *zs, const char *sname, zip_uint64_t is) {
  180     char line[1024];
  181     struct zip_stat st, ss;
  182 
  183     if (confirm & CONFIRM_ALL_YES)
  184     return 1;
  185     else if (confirm & CONFIRM_ALL_NO)
  186     return 0;
  187 
  188     if (zip_stat_index(za, it, ZIP_FL_UNCHANGED, &st) < 0) {
  189     fprintf(stderr, "%s: cannot stat file %" PRIu64 " in '%s': %s\n", progname, it, tname, zip_strerror(za));
  190     return -1;
  191     }
  192     if (zip_stat_index(zs, is, 0, &ss) < 0) {
  193     fprintf(stderr, "%s: cannot stat file %" PRIu64 " in '%s': %s\n", progname, is, sname, zip_strerror(zs));
  194     return -1;
  195     }
  196 
  197     if (st.size == ss.size && st.crc == ss.crc) {
  198     if (confirm & CONFIRM_SAME_YES)
  199         return 1;
  200     else if (confirm & CONFIRM_SAME_NO)
  201         return 0;
  202     }
  203 
  204     printf("replace '%s' (%" PRIu64 " / %08x) in `%s'\n"
  205        "   with '%s' (%" PRIu64 " / %08x) from `%s'? ",
  206        st.name, st.size, st.crc, tname, ss.name, ss.size, ss.crc, sname);
  207     fflush(stdout);
  208 
  209     if (fgets(line, sizeof(line), stdin) == NULL) {
  210     fprintf(stderr, "%s: read error from stdin: %s\n", progname, strerror(errno));
  211     return -1;
  212     }
  213 
  214     if (tolower((unsigned char)line[0]) == 'y')
  215     return 1;
  216 
  217     return 0;
  218 }
  219 
  220 
  221 static zip_t *
  222 merge_zip(zip_t *za, const char *tname, const char *sname) {
  223     zip_t *zs;
  224     zip_source_t *source;
  225     zip_int64_t ret, idx;
  226     zip_uint64_t i;
  227     int err;
  228     const char *fname;
  229 
  230     if ((zs = zip_open(sname, 0, &err)) == NULL) {
  231     zip_error_t error;
  232     zip_error_init_with_code(&error, err);
  233     fprintf(stderr, "%s: can't open zip archive '%s': %s\n", progname, sname, zip_error_strerror(&error));
  234     zip_error_fini(&error);
  235     return NULL;
  236     }
  237 
  238     ret = zip_get_num_entries(zs, 0);
  239     if (ret < 0) {
  240     fprintf(stderr, "%s: cannot get number of entries for '%s': %s\n", progname, sname, zip_strerror(za));
  241     return NULL;
  242     }
  243     for (i = 0; i < (zip_uint64_t)ret; i++) {
  244     fname = zip_get_name(zs, i, 0);
  245 
  246     if ((idx = zip_name_locate(za, fname, name_flags)) >= 0) {
  247         switch (confirm_replace(za, tname, (zip_uint64_t)idx, zs, sname, i)) {
  248         case 0:
  249         break;
  250 
  251         case 1:
  252         if ((source = zip_source_zip(za, zs, i, 0, 0, 0)) == NULL || zip_replace(za, (zip_uint64_t)idx, source) < 0) {
  253             zip_source_free(source);
  254             fprintf(stderr, "%s: cannot replace '%s' in `%s': %s\n", progname, fname, tname, zip_strerror(za));
  255             zip_close(zs);
  256             return NULL;
  257         }
  258         break;
  259 
  260         case -1:
  261         zip_close(zs);
  262         return NULL;
  263 
  264         default:
  265         fprintf(stderr,
  266             "%s: internal error: "
  267             "unexpected return code from confirm (%d)\n",
  268             progname, err);
  269         zip_close(zs);
  270         return NULL;
  271         }
  272     }
  273     else {
  274         if ((source = zip_source_zip(za, zs, i, 0, 0, 0)) == NULL || zip_add(za, fname, source) < 0) {
  275         zip_source_free(source);
  276         fprintf(stderr, "%s: cannot add '%s' to `%s': %s\n", progname, fname, tname, zip_strerror(za));
  277         zip_close(zs);
  278         return NULL;
  279         }
  280     }
  281     }
  282 
  283     return zs;
  284 }