"Fossies" - the Fresh Open Source Software Archive

Member "libzip-1.5.2/regress/ziptool_regress.c" (12 Mar 2019, 9694 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 "ziptool_regress.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.4.0_vs_1.5.0.

    1 #include "zip.h"
    2 
    3 #define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b))
    4 
    5 #define FOR_REGRESS
    6 
    7 typedef enum { SOURCE_TYPE_NONE, SOURCE_TYPE_IN_MEMORY, SOURCE_TYPE_HOLE } source_type_t;
    8 
    9 source_type_t source_type = SOURCE_TYPE_NONE;
   10 zip_uint64_t fragment_size = 0;
   11 
   12 static int add_nul(int argc, char *argv[]);
   13 static int unchange_all(int argc, char *argv[]);
   14 static int zin_close(int argc, char *argv[]);
   15 
   16 #define OPTIONS_REGRESS "F:Hm"
   17 
   18 #define USAGE_REGRESS " [-Hm] [-F fragment-size]"
   19 
   20 #define GETOPT_REGRESS                              \
   21     case 'H':                                       \
   22     source_type = SOURCE_TYPE_HOLE;             \
   23     break;                                      \
   24     case 'm':                                       \
   25     source_type = SOURCE_TYPE_IN_MEMORY;        \
   26     break;                                      \
   27     case 'F':                                       \
   28     fragment_size = strtoull(optarg, NULL, 10); \
   29     break;
   30 
   31 #define DISPATCH_REGRESS \
   32     {"add_nul", 2, "name length", "add NUL bytes", add_nul}, {"unchange_all", 0, "", "revert all changes", unchange_all}, { "zin_close", 1, "index", "close input zip_source (for internal tests)", zin_close }
   33 
   34 
   35 zip_t *ziptool_open(const char *archive, int flags, zip_error_t *error, zip_uint64_t offset, zip_uint64_t len);
   36 
   37 
   38 #include "ziptool.c"
   39 
   40 
   41 zip_source_t *memory_src = NULL;
   42 
   43 zip_source_t *source_hole_create(const char *, int flags, zip_error_t *);
   44 
   45 static zip_t *read_to_memory(const char *archive, int flags, zip_error_t *error, zip_source_t **srcp);
   46 static zip_source_t *source_nul(zip_t *za, zip_uint64_t length);
   47 
   48 
   49 static int
   50 add_nul(int argc, char *argv[]) {
   51     zip_source_t *zs;
   52     zip_uint64_t length = strtoull(argv[1], NULL, 10);
   53 
   54     if ((zs = source_nul(za, length)) == NULL) {
   55     fprintf(stderr, "can't create zip_source for length: %s\n", zip_strerror(za));
   56     return -1;
   57     }
   58 
   59     if (zip_add(za, argv[0], zs) == -1) {
   60     zip_source_free(zs);
   61     fprintf(stderr, "can't add file '%s': %s\n", argv[0], zip_strerror(za));
   62     return -1;
   63     }
   64     return 0;
   65 }
   66 
   67 static int
   68 unchange_all(int argc, char *argv[]) {
   69     if (zip_unchange_all(za) < 0) {
   70     fprintf(stderr, "can't revert changes to archive: %s\n", zip_strerror(za));
   71     return -1;
   72     }
   73     return 0;
   74 }
   75 
   76 static int
   77 zin_close(int argc, char *argv[]) {
   78     zip_uint64_t idx;
   79 
   80     idx = strtoull(argv[0], NULL, 10);
   81     if (idx >= z_in_count) {
   82     fprintf(stderr, "invalid argument '%" PRIu64 "', only %d zip sources open\n", idx, z_in_count);
   83     return -1;
   84     }
   85     if (zip_close(z_in[idx]) < 0) {
   86     fprintf(stderr, "can't close source archive: %s\n", zip_strerror(z_in[idx]));
   87     return -1;
   88     }
   89     z_in[idx] = z_in[z_in_count];
   90     z_in_count--;
   91 
   92     return 0;
   93 }
   94 
   95 
   96 static zip_t *
   97 read_hole(const char *archive, int flags, zip_error_t *error) {
   98     zip_source_t *src = NULL;
   99     zip_t *zs = NULL;
  100 
  101     if (strcmp(archive, "/dev/stdin") == 0) {
  102     zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
  103     return NULL;
  104     }
  105 
  106     if ((src = source_hole_create(archive, flags, error)) == NULL || (zs = zip_open_from_source(src, flags, error)) == NULL) {
  107     zip_source_free(src);
  108     }
  109 
  110     return zs;
  111 }
  112 
  113 
  114 static zip_t *
  115 read_to_memory(const char *archive, int flags, zip_error_t *error, zip_source_t **srcp) {
  116     zip_source_t *src;
  117     zip_t *zb;
  118     FILE *fp;
  119 
  120     if (strcmp(archive, "/dev/stdin") == 0) {
  121     zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
  122     return NULL;
  123     }
  124 
  125     if ((fp = fopen(archive, "r")) == NULL) {
  126     if (errno == ENOENT) {
  127         src = zip_source_buffer_create(NULL, 0, 0, error);
  128     }
  129     else {
  130         zip_error_set(error, ZIP_ER_OPEN, errno);
  131         return NULL;
  132     }
  133     }
  134     else {
  135     struct stat st;
  136 
  137     if (fstat(fileno(fp), &st) < 0) {
  138         fclose(fp);
  139         zip_error_set(error, ZIP_ER_OPEN, errno);
  140         return NULL;
  141     }
  142     if (fragment_size == 0) {
  143         char *buf;
  144         if ((buf = malloc((size_t)st.st_size)) == NULL) {
  145         fclose(fp);
  146         zip_error_set(error, ZIP_ER_MEMORY, 0);
  147         return NULL;
  148         }
  149         if (fread(buf, (size_t)st.st_size, 1, fp) < 1) {
  150         free(buf);
  151         fclose(fp);
  152         zip_error_set(error, ZIP_ER_READ, errno);
  153         return NULL;
  154         }
  155         src = zip_source_buffer_create(buf, (zip_uint64_t)st.st_size, 1, error);
  156         if (src == NULL) {
  157         free(buf);
  158         }
  159     }
  160     else {
  161         zip_uint64_t nfragments, i, left;
  162         zip_buffer_fragment_t *fragments;
  163 
  164         nfragments = ((size_t)st.st_size + fragment_size - 1) / fragment_size;
  165         if ((fragments = malloc(sizeof(fragments[0]) * nfragments)) == NULL) {
  166         fclose(fp);
  167         zip_error_set(error, ZIP_ER_MEMORY, 0);
  168         return NULL;
  169         }
  170         for (i = 0; i < nfragments; i++) {
  171         left = ZIP_MIN(fragment_size, (size_t)st.st_size - i * fragment_size);
  172         if ((fragments[i].data = malloc(left)) == NULL) {
  173 #ifndef __clang_analyzer__
  174                     /* fragments is initialized up to i - 1*/
  175             while (--i > 0) {
  176             free(fragments[i].data);
  177                     }
  178 #endif
  179             free(fragments);
  180             fclose(fp);
  181             zip_error_set(error, ZIP_ER_MEMORY, 0);
  182             return NULL;
  183         }
  184         fragments[i].length = left;
  185         if (fread(fragments[i].data, left, 1, fp) < 1) {
  186 #ifndef __clang_analyzer__
  187                     /* fragments is initialized up to i - 1*/
  188             while (--i > 0) {
  189             free(fragments[i].data);
  190             }
  191 #endif
  192             free(fragments);
  193             fclose(fp);
  194             zip_error_set(error, ZIP_ER_READ, errno);
  195             return NULL;
  196         }
  197         }
  198         src = zip_source_buffer_fragment_create(fragments, nfragments, 1, error);
  199         if (src == NULL) {
  200         for (i = 0; i < nfragments; i++) {
  201             free(fragments[i].data);
  202         }
  203         free(fragments);
  204         fclose(fp);
  205         return NULL;
  206         }
  207             free(fragments);
  208     }
  209     fclose(fp);
  210     }
  211     if (src == NULL) {
  212     return NULL;
  213     }
  214     zb = zip_open_from_source(src, flags, error);
  215     if (zb == NULL) {
  216     zip_source_free(src);
  217     return NULL;
  218     }
  219     zip_source_keep(src);
  220     *srcp = src;
  221     return zb;
  222 }
  223 
  224 
  225 typedef struct source_nul {
  226     zip_error_t error;
  227     zip_uint64_t length;
  228     zip_uint64_t offset;
  229 } source_nul_t;
  230 
  231 static zip_int64_t
  232 source_nul_cb(void *ud, void *data, zip_uint64_t length, zip_source_cmd_t command) {
  233     source_nul_t *ctx = (source_nul_t *)ud;
  234 
  235     switch (command) {
  236     case ZIP_SOURCE_CLOSE:
  237     return 0;
  238 
  239     case ZIP_SOURCE_ERROR:
  240     return zip_error_to_data(&ctx->error, data, length);
  241 
  242     case ZIP_SOURCE_FREE:
  243     free(ctx);
  244     return 0;
  245 
  246     case ZIP_SOURCE_OPEN:
  247     ctx->offset = 0;
  248     return 0;
  249 
  250     case ZIP_SOURCE_READ:
  251     if (length > ZIP_INT64_MAX) {
  252         zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
  253         return -1;
  254     }
  255 
  256     if (length > ctx->length - ctx->offset) {
  257         length = ctx->length - ctx->offset;
  258     }
  259 
  260     memset(data, 0, length);
  261     ctx->offset += length;
  262     return (zip_int64_t)length;
  263 
  264     case ZIP_SOURCE_STAT: {
  265     zip_stat_t *st = ZIP_SOURCE_GET_ARGS(zip_stat_t, data, length, &ctx->error);
  266 
  267     if (st == NULL) {
  268         return -1;
  269     }
  270 
  271     st->valid |= ZIP_STAT_SIZE;
  272     st->size = ctx->length;
  273 
  274     return 0;
  275     }
  276 
  277     case ZIP_SOURCE_SUPPORTS:
  278     return zip_source_make_command_bitmap(ZIP_SOURCE_CLOSE, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_STAT, -1);
  279 
  280     default:
  281     zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
  282     return -1;
  283     }
  284 }
  285 
  286 static zip_source_t *
  287 source_nul(zip_t *zs, zip_uint64_t length) {
  288     source_nul_t *ctx;
  289     zip_source_t *src;
  290 
  291     if ((ctx = (source_nul_t *)malloc(sizeof(*ctx))) == NULL) {
  292     zip_error_set(zip_get_error(zs), ZIP_ER_MEMORY, 0);
  293     return NULL;
  294     }
  295 
  296     zip_error_init(&ctx->error);
  297     ctx->length = length;
  298     ctx->offset = 0;
  299 
  300     if ((src = zip_source_function(zs, source_nul_cb, ctx)) == NULL) {
  301     free(ctx);
  302     return NULL;
  303     }
  304 
  305     return src;
  306 }
  307 
  308 
  309 static int
  310 write_memory_src_to_file(const char *archive, zip_source_t *src) {
  311     zip_stat_t zst;
  312     char *buf;
  313     FILE *fp;
  314 
  315     if (zip_source_stat(src, &zst) < 0) {
  316     fprintf(stderr, "zip_source_stat on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
  317     return -1;
  318     }
  319     if (zip_source_open(src) < 0) {
  320     if (zip_error_code_zip(zip_source_error(src)) == ZIP_ER_DELETED) {
  321         if (unlink(archive) < 0 && errno != ENOENT) {
  322         fprintf(stderr, "unlink failed: %s\n", strerror(errno));
  323         return -1;
  324         }
  325         return 0;
  326     }
  327     fprintf(stderr, "zip_source_open on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
  328     return -1;
  329     }
  330     if ((buf = malloc(zst.size)) == NULL) {
  331     fprintf(stderr, "malloc failed: %s\n", strerror(errno));
  332     zip_source_close(src);
  333     return -1;
  334     }
  335     if (zip_source_read(src, buf, zst.size) < (zip_int64_t)zst.size) {
  336     fprintf(stderr, "zip_source_read on buffer failed: %s\n", zip_error_strerror(zip_source_error(src)));
  337     zip_source_close(src);
  338     free(buf);
  339     return -1;
  340     }
  341     zip_source_close(src);
  342     if ((fp = fopen(archive, "wb")) == NULL) {
  343     fprintf(stderr, "fopen failed: %s\n", strerror(errno));
  344     free(buf);
  345     return -1;
  346     }
  347     if (fwrite(buf, zst.size, 1, fp) < 1) {
  348     fprintf(stderr, "fwrite failed: %s\n", strerror(errno));
  349     free(buf);
  350     fclose(fp);
  351     return -1;
  352     }
  353     free(buf);
  354     if (fclose(fp) != 0) {
  355     fprintf(stderr, "fclose failed: %s\n", strerror(errno));
  356     return -1;
  357     }
  358     return 0;
  359 }
  360 
  361 
  362 zip_t *
  363 ziptool_open(const char *archive, int flags, zip_error_t *error, zip_uint64_t offset, zip_uint64_t len) {
  364     switch (source_type) {
  365     case SOURCE_TYPE_NONE:
  366     za = read_from_file(archive, flags, error, offset, len);
  367     break;
  368 
  369     case SOURCE_TYPE_IN_MEMORY:
  370     za = read_to_memory(archive, flags, error, &memory_src);
  371     break;
  372 
  373     case SOURCE_TYPE_HOLE:
  374     za = read_hole(archive, flags, error);
  375     break;
  376     }
  377 
  378     return za;
  379 }
  380 
  381 
  382 int
  383 ziptool_post_close(const char *archive) {
  384     if (source_type == SOURCE_TYPE_IN_MEMORY) {
  385     if (write_memory_src_to_file(archive, memory_src) < 0) {
  386         return -1;
  387     }
  388     zip_source_free(memory_src);
  389     }
  390 
  391     return 0;
  392 }