7d6f2a85d09612c3849c266b581b9947b8581198
   1/*
   2 * Copyright (c) 2006 Rene Scharfe
   3 */
   4#include "cache.h"
   5#include "archive.h"
   6#include "streaming.h"
   7#include "utf8.h"
   8#include "userdiff.h"
   9#include "xdiff-interface.h"
  10
  11static int zip_date;
  12static int zip_time;
  13
  14/* We only care about the "buf" part here. */
  15static struct strbuf zip_dir;
  16
  17static uintmax_t zip_offset;
  18static uint64_t zip_dir_entries;
  19
  20static unsigned int max_creator_version;
  21
  22#define ZIP_STREAM      (1 <<  3)
  23#define ZIP_UTF8        (1 << 11)
  24
  25struct zip_local_header {
  26        unsigned char magic[4];
  27        unsigned char version[2];
  28        unsigned char flags[2];
  29        unsigned char compression_method[2];
  30        unsigned char mtime[2];
  31        unsigned char mdate[2];
  32        unsigned char crc32[4];
  33        unsigned char compressed_size[4];
  34        unsigned char size[4];
  35        unsigned char filename_length[2];
  36        unsigned char extra_length[2];
  37        unsigned char _end[1];
  38};
  39
  40struct zip_data_desc {
  41        unsigned char magic[4];
  42        unsigned char crc32[4];
  43        unsigned char compressed_size[4];
  44        unsigned char size[4];
  45        unsigned char _end[1];
  46};
  47
  48struct zip_dir_trailer {
  49        unsigned char magic[4];
  50        unsigned char disk[2];
  51        unsigned char directory_start_disk[2];
  52        unsigned char entries_on_this_disk[2];
  53        unsigned char entries[2];
  54        unsigned char size[4];
  55        unsigned char offset[4];
  56        unsigned char comment_length[2];
  57        unsigned char _end[1];
  58};
  59
  60struct zip_extra_mtime {
  61        unsigned char magic[2];
  62        unsigned char extra_size[2];
  63        unsigned char flags[1];
  64        unsigned char mtime[4];
  65        unsigned char _end[1];
  66};
  67
  68struct zip64_dir_trailer {
  69        unsigned char magic[4];
  70        unsigned char record_size[8];
  71        unsigned char creator_version[2];
  72        unsigned char version[2];
  73        unsigned char disk[4];
  74        unsigned char directory_start_disk[4];
  75        unsigned char entries_on_this_disk[8];
  76        unsigned char entries[8];
  77        unsigned char size[8];
  78        unsigned char offset[8];
  79        unsigned char _end[1];
  80};
  81
  82struct zip64_dir_trailer_locator {
  83        unsigned char magic[4];
  84        unsigned char disk[4];
  85        unsigned char offset[8];
  86        unsigned char number_of_disks[4];
  87        unsigned char _end[1];
  88};
  89
  90/*
  91 * On ARM, padding is added at the end of the struct, so a simple
  92 * sizeof(struct ...) reports two bytes more than the payload size
  93 * we're interested in.
  94 */
  95#define ZIP_LOCAL_HEADER_SIZE   offsetof(struct zip_local_header, _end)
  96#define ZIP_DATA_DESC_SIZE      offsetof(struct zip_data_desc, _end)
  97#define ZIP_DIR_HEADER_SIZE     offsetof(struct zip_dir_header, _end)
  98#define ZIP_DIR_TRAILER_SIZE    offsetof(struct zip_dir_trailer, _end)
  99#define ZIP_EXTRA_MTIME_SIZE    offsetof(struct zip_extra_mtime, _end)
 100#define ZIP_EXTRA_MTIME_PAYLOAD_SIZE \
 101        (ZIP_EXTRA_MTIME_SIZE - offsetof(struct zip_extra_mtime, flags))
 102#define ZIP64_DIR_TRAILER_SIZE  offsetof(struct zip64_dir_trailer, _end)
 103#define ZIP64_DIR_TRAILER_RECORD_SIZE \
 104        (ZIP64_DIR_TRAILER_SIZE - \
 105         offsetof(struct zip64_dir_trailer, creator_version))
 106#define ZIP64_DIR_TRAILER_LOCATOR_SIZE \
 107        offsetof(struct zip64_dir_trailer_locator, _end)
 108
 109static void copy_le16(unsigned char *dest, unsigned int n)
 110{
 111        dest[0] = 0xff & n;
 112        dest[1] = 0xff & (n >> 010);
 113}
 114
 115static void copy_le32(unsigned char *dest, unsigned int n)
 116{
 117        dest[0] = 0xff & n;
 118        dest[1] = 0xff & (n >> 010);
 119        dest[2] = 0xff & (n >> 020);
 120        dest[3] = 0xff & (n >> 030);
 121}
 122
 123static void copy_le64(unsigned char *dest, uint64_t n)
 124{
 125        dest[0] = 0xff & n;
 126        dest[1] = 0xff & (n >> 010);
 127        dest[2] = 0xff & (n >> 020);
 128        dest[3] = 0xff & (n >> 030);
 129        dest[4] = 0xff & (n >> 040);
 130        dest[5] = 0xff & (n >> 050);
 131        dest[6] = 0xff & (n >> 060);
 132        dest[7] = 0xff & (n >> 070);
 133}
 134
 135static uint64_t clamp_max(uint64_t n, uint64_t max, int *clamped)
 136{
 137        if (n <= max)
 138                return n;
 139        *clamped = 1;
 140        return max;
 141}
 142
 143static void copy_le16_clamp(unsigned char *dest, uint64_t n, int *clamped)
 144{
 145        copy_le16(dest, clamp_max(n, 0xffff, clamped));
 146}
 147
 148static void copy_le32_clamp(unsigned char *dest, uint64_t n, int *clamped)
 149{
 150        copy_le32(dest, clamp_max(n, 0xffffffff, clamped));
 151}
 152
 153static int strbuf_add_le(struct strbuf *sb, size_t size, uintmax_t n)
 154{
 155        while (size-- > 0) {
 156                strbuf_addch(sb, n & 0xff);
 157                n >>= 8;
 158        }
 159        return -!!n;
 160}
 161
 162static uint32_t clamp32(uintmax_t n)
 163{
 164        const uintmax_t max = 0xffffffff;
 165        return (n < max) ? n : max;
 166}
 167
 168static void *zlib_deflate_raw(void *data, unsigned long size,
 169                              int compression_level,
 170                              unsigned long *compressed_size)
 171{
 172        git_zstream stream;
 173        unsigned long maxsize;
 174        void *buffer;
 175        int result;
 176
 177        git_deflate_init_raw(&stream, compression_level);
 178        maxsize = git_deflate_bound(&stream, size);
 179        buffer = xmalloc(maxsize);
 180
 181        stream.next_in = data;
 182        stream.avail_in = size;
 183        stream.next_out = buffer;
 184        stream.avail_out = maxsize;
 185
 186        do {
 187                result = git_deflate(&stream, Z_FINISH);
 188        } while (result == Z_OK);
 189
 190        if (result != Z_STREAM_END) {
 191                free(buffer);
 192                return NULL;
 193        }
 194
 195        git_deflate_end(&stream);
 196        *compressed_size = stream.total_out;
 197
 198        return buffer;
 199}
 200
 201static void write_zip_data_desc(unsigned long size,
 202                                unsigned long compressed_size,
 203                                unsigned long crc)
 204{
 205        struct zip_data_desc trailer;
 206
 207        copy_le32(trailer.magic, 0x08074b50);
 208        copy_le32(trailer.crc32, crc);
 209        copy_le32(trailer.compressed_size, compressed_size);
 210        copy_le32(trailer.size, size);
 211        write_or_die(1, &trailer, ZIP_DATA_DESC_SIZE);
 212}
 213
 214static void set_zip_header_data_desc(struct zip_local_header *header,
 215                                     unsigned long size,
 216                                     unsigned long compressed_size,
 217                                     unsigned long crc)
 218{
 219        copy_le32(header->crc32, crc);
 220        copy_le32(header->compressed_size, compressed_size);
 221        copy_le32(header->size, size);
 222}
 223
 224static int has_only_ascii(const char *s)
 225{
 226        for (;;) {
 227                int c = *s++;
 228                if (c == '\0')
 229                        return 1;
 230                if (!isascii(c))
 231                        return 0;
 232        }
 233}
 234
 235static int entry_is_binary(const char *path, const void *buffer, size_t size)
 236{
 237        struct userdiff_driver *driver = userdiff_find_by_path(path);
 238        if (!driver)
 239                driver = userdiff_find_by_name("default");
 240        if (driver->binary != -1)
 241                return driver->binary;
 242        return buffer_is_binary(buffer, size);
 243}
 244
 245#define STREAM_BUFFER_SIZE (1024 * 16)
 246
 247static int write_zip_entry(struct archiver_args *args,
 248                           const unsigned char *sha1,
 249                           const char *path, size_t pathlen,
 250                           unsigned int mode)
 251{
 252        struct zip_local_header header;
 253        uintmax_t offset = zip_offset;
 254        struct zip_extra_mtime extra;
 255        unsigned long attr2;
 256        unsigned long compressed_size;
 257        unsigned long crc;
 258        int method;
 259        unsigned char *out;
 260        void *deflated = NULL;
 261        void *buffer;
 262        struct git_istream *stream = NULL;
 263        unsigned long flags = 0;
 264        unsigned long size;
 265        int is_binary = -1;
 266        const char *path_without_prefix = path + args->baselen;
 267        unsigned int creator_version = 0;
 268        size_t zip_dir_extra_size = ZIP_EXTRA_MTIME_SIZE;
 269        size_t zip64_dir_extra_payload_size = 0;
 270
 271        crc = crc32(0, NULL, 0);
 272
 273        if (!has_only_ascii(path)) {
 274                if (is_utf8(path))
 275                        flags |= ZIP_UTF8;
 276                else
 277                        warning("Path is not valid UTF-8: %s", path);
 278        }
 279
 280        if (pathlen > 0xffff) {
 281                return error("path too long (%d chars, SHA1: %s): %s",
 282                                (int)pathlen, sha1_to_hex(sha1), path);
 283        }
 284
 285        if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
 286                method = 0;
 287                attr2 = 16;
 288                out = NULL;
 289                size = 0;
 290                compressed_size = 0;
 291                buffer = NULL;
 292        } else if (S_ISREG(mode) || S_ISLNK(mode)) {
 293                enum object_type type = sha1_object_info(sha1, &size);
 294
 295                method = 0;
 296                attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
 297                        (mode & 0111) ? ((mode) << 16) : 0;
 298                if (S_ISLNK(mode) || (mode & 0111))
 299                        creator_version = 0x0317;
 300                if (S_ISREG(mode) && args->compression_level != 0 && size > 0)
 301                        method = 8;
 302
 303                if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert &&
 304                    size > big_file_threshold) {
 305                        stream = open_istream(sha1, &type, &size, NULL);
 306                        if (!stream)
 307                                return error("cannot stream blob %s",
 308                                             sha1_to_hex(sha1));
 309                        flags |= ZIP_STREAM;
 310                        out = buffer = NULL;
 311                } else {
 312                        buffer = sha1_file_to_archive(args, path, sha1, mode,
 313                                                      &type, &size);
 314                        if (!buffer)
 315                                return error("cannot read %s",
 316                                             sha1_to_hex(sha1));
 317                        crc = crc32(crc, buffer, size);
 318                        is_binary = entry_is_binary(path_without_prefix,
 319                                                    buffer, size);
 320                        out = buffer;
 321                }
 322                compressed_size = (method == 0) ? size : 0;
 323        } else {
 324                return error("unsupported file mode: 0%o (SHA1: %s)", mode,
 325                                sha1_to_hex(sha1));
 326        }
 327
 328        if (creator_version > max_creator_version)
 329                max_creator_version = creator_version;
 330
 331        if (buffer && method == 8) {
 332                out = deflated = zlib_deflate_raw(buffer, size,
 333                                                  args->compression_level,
 334                                                  &compressed_size);
 335                if (!out || compressed_size >= size) {
 336                        out = buffer;
 337                        method = 0;
 338                        compressed_size = size;
 339                }
 340        }
 341
 342        copy_le16(extra.magic, 0x5455);
 343        copy_le16(extra.extra_size, ZIP_EXTRA_MTIME_PAYLOAD_SIZE);
 344        extra.flags[0] = 1;     /* just mtime */
 345        copy_le32(extra.mtime, args->time);
 346
 347        copy_le32(header.magic, 0x04034b50);
 348        copy_le16(header.version, 10);
 349        copy_le16(header.flags, flags);
 350        copy_le16(header.compression_method, method);
 351        copy_le16(header.mtime, zip_time);
 352        copy_le16(header.mdate, zip_date);
 353        set_zip_header_data_desc(&header, size, compressed_size, crc);
 354        copy_le16(header.filename_length, pathlen);
 355        copy_le16(header.extra_length, ZIP_EXTRA_MTIME_SIZE);
 356        write_or_die(1, &header, ZIP_LOCAL_HEADER_SIZE);
 357        zip_offset += ZIP_LOCAL_HEADER_SIZE;
 358        write_or_die(1, path, pathlen);
 359        zip_offset += pathlen;
 360        write_or_die(1, &extra, ZIP_EXTRA_MTIME_SIZE);
 361        zip_offset += ZIP_EXTRA_MTIME_SIZE;
 362        if (stream && method == 0) {
 363                unsigned char buf[STREAM_BUFFER_SIZE];
 364                ssize_t readlen;
 365
 366                for (;;) {
 367                        readlen = read_istream(stream, buf, sizeof(buf));
 368                        if (readlen <= 0)
 369                                break;
 370                        crc = crc32(crc, buf, readlen);
 371                        if (is_binary == -1)
 372                                is_binary = entry_is_binary(path_without_prefix,
 373                                                            buf, readlen);
 374                        write_or_die(1, buf, readlen);
 375                }
 376                close_istream(stream);
 377                if (readlen)
 378                        return readlen;
 379
 380                compressed_size = size;
 381                zip_offset += compressed_size;
 382
 383                write_zip_data_desc(size, compressed_size, crc);
 384                zip_offset += ZIP_DATA_DESC_SIZE;
 385        } else if (stream && method == 8) {
 386                unsigned char buf[STREAM_BUFFER_SIZE];
 387                ssize_t readlen;
 388                git_zstream zstream;
 389                int result;
 390                size_t out_len;
 391                unsigned char compressed[STREAM_BUFFER_SIZE * 2];
 392
 393                git_deflate_init_raw(&zstream, args->compression_level);
 394
 395                compressed_size = 0;
 396                zstream.next_out = compressed;
 397                zstream.avail_out = sizeof(compressed);
 398
 399                for (;;) {
 400                        readlen = read_istream(stream, buf, sizeof(buf));
 401                        if (readlen <= 0)
 402                                break;
 403                        crc = crc32(crc, buf, readlen);
 404                        if (is_binary == -1)
 405                                is_binary = entry_is_binary(path_without_prefix,
 406                                                            buf, readlen);
 407
 408                        zstream.next_in = buf;
 409                        zstream.avail_in = readlen;
 410                        result = git_deflate(&zstream, 0);
 411                        if (result != Z_OK)
 412                                die("deflate error (%d)", result);
 413                        out_len = zstream.next_out - compressed;
 414
 415                        if (out_len > 0) {
 416                                write_or_die(1, compressed, out_len);
 417                                compressed_size += out_len;
 418                                zstream.next_out = compressed;
 419                                zstream.avail_out = sizeof(compressed);
 420                        }
 421
 422                }
 423                close_istream(stream);
 424                if (readlen)
 425                        return readlen;
 426
 427                zstream.next_in = buf;
 428                zstream.avail_in = 0;
 429                result = git_deflate(&zstream, Z_FINISH);
 430                if (result != Z_STREAM_END)
 431                        die("deflate error (%d)", result);
 432
 433                git_deflate_end(&zstream);
 434                out_len = zstream.next_out - compressed;
 435                write_or_die(1, compressed, out_len);
 436                compressed_size += out_len;
 437                zip_offset += compressed_size;
 438
 439                write_zip_data_desc(size, compressed_size, crc);
 440                zip_offset += ZIP_DATA_DESC_SIZE;
 441        } else if (compressed_size > 0) {
 442                write_or_die(1, out, compressed_size);
 443                zip_offset += compressed_size;
 444        }
 445
 446        free(deflated);
 447        free(buffer);
 448
 449        if (offset > 0xffffffff) {
 450                zip64_dir_extra_payload_size += 8;
 451                zip_dir_extra_size += 2 + 2 + zip64_dir_extra_payload_size;
 452        }
 453
 454        strbuf_add_le(&zip_dir, 4, 0x02014b50); /* magic */
 455        strbuf_add_le(&zip_dir, 2, creator_version);
 456        strbuf_add_le(&zip_dir, 2, 10);         /* version */
 457        strbuf_add_le(&zip_dir, 2, flags);
 458        strbuf_add_le(&zip_dir, 2, method);
 459        strbuf_add_le(&zip_dir, 2, zip_time);
 460        strbuf_add_le(&zip_dir, 2, zip_date);
 461        strbuf_add_le(&zip_dir, 4, crc);
 462        strbuf_add_le(&zip_dir, 4, compressed_size);
 463        strbuf_add_le(&zip_dir, 4, size);
 464        strbuf_add_le(&zip_dir, 2, pathlen);
 465        strbuf_add_le(&zip_dir, 2, zip_dir_extra_size);
 466        strbuf_add_le(&zip_dir, 2, 0);          /* comment length */
 467        strbuf_add_le(&zip_dir, 2, 0);          /* disk */
 468        strbuf_add_le(&zip_dir, 2, !is_binary);
 469        strbuf_add_le(&zip_dir, 4, attr2);
 470        strbuf_add_le(&zip_dir, 4, clamp32(offset));
 471        strbuf_add(&zip_dir, path, pathlen);
 472        strbuf_add(&zip_dir, &extra, ZIP_EXTRA_MTIME_SIZE);
 473        if (zip64_dir_extra_payload_size) {
 474                strbuf_add_le(&zip_dir, 2, 0x0001);     /* magic */
 475                strbuf_add_le(&zip_dir, 2, zip64_dir_extra_payload_size);
 476                if (offset >= 0xffffffff)
 477                        strbuf_add_le(&zip_dir, 8, offset);
 478        }
 479        zip_dir_entries++;
 480
 481        return 0;
 482}
 483
 484static void write_zip64_trailer(void)
 485{
 486        struct zip64_dir_trailer trailer64;
 487        struct zip64_dir_trailer_locator locator64;
 488
 489        copy_le32(trailer64.magic, 0x06064b50);
 490        copy_le64(trailer64.record_size, ZIP64_DIR_TRAILER_RECORD_SIZE);
 491        copy_le16(trailer64.creator_version, max_creator_version);
 492        copy_le16(trailer64.version, 45);
 493        copy_le32(trailer64.disk, 0);
 494        copy_le32(trailer64.directory_start_disk, 0);
 495        copy_le64(trailer64.entries_on_this_disk, zip_dir_entries);
 496        copy_le64(trailer64.entries, zip_dir_entries);
 497        copy_le64(trailer64.size, zip_dir.len);
 498        copy_le64(trailer64.offset, zip_offset);
 499
 500        copy_le32(locator64.magic, 0x07064b50);
 501        copy_le32(locator64.disk, 0);
 502        copy_le64(locator64.offset, zip_offset + zip_dir.len);
 503        copy_le32(locator64.number_of_disks, 1);
 504
 505        write_or_die(1, &trailer64, ZIP64_DIR_TRAILER_SIZE);
 506        write_or_die(1, &locator64, ZIP64_DIR_TRAILER_LOCATOR_SIZE);
 507}
 508
 509static void write_zip_trailer(const unsigned char *sha1)
 510{
 511        struct zip_dir_trailer trailer;
 512        int clamped = 0;
 513
 514        copy_le32(trailer.magic, 0x06054b50);
 515        copy_le16(trailer.disk, 0);
 516        copy_le16(trailer.directory_start_disk, 0);
 517        copy_le16_clamp(trailer.entries_on_this_disk, zip_dir_entries,
 518                        &clamped);
 519        copy_le16_clamp(trailer.entries, zip_dir_entries, &clamped);
 520        copy_le32(trailer.size, zip_dir.len);
 521        copy_le32_clamp(trailer.offset, zip_offset, &clamped);
 522        copy_le16(trailer.comment_length, sha1 ? GIT_SHA1_HEXSZ : 0);
 523
 524        write_or_die(1, zip_dir.buf, zip_dir.len);
 525        if (clamped)
 526                write_zip64_trailer();
 527        write_or_die(1, &trailer, ZIP_DIR_TRAILER_SIZE);
 528        if (sha1)
 529                write_or_die(1, sha1_to_hex(sha1), GIT_SHA1_HEXSZ);
 530}
 531
 532static void dos_time(time_t *time, int *dos_date, int *dos_time)
 533{
 534        struct tm *t = localtime(time);
 535
 536        *dos_date = t->tm_mday + (t->tm_mon + 1) * 32 +
 537                    (t->tm_year + 1900 - 1980) * 512;
 538        *dos_time = t->tm_sec / 2 + t->tm_min * 32 + t->tm_hour * 2048;
 539}
 540
 541static int archive_zip_config(const char *var, const char *value, void *data)
 542{
 543        return userdiff_config(var, value);
 544}
 545
 546static int write_zip_archive(const struct archiver *ar,
 547                             struct archiver_args *args)
 548{
 549        int err;
 550
 551        git_config(archive_zip_config, NULL);
 552
 553        dos_time(&args->time, &zip_date, &zip_time);
 554
 555        strbuf_init(&zip_dir, 0);
 556
 557        err = write_archive_entries(args, write_zip_entry);
 558        if (!err)
 559                write_zip_trailer(args->commit_sha1);
 560
 561        strbuf_release(&zip_dir);
 562
 563        return err;
 564}
 565
 566static struct archiver zip_archiver = {
 567        "zip",
 568        write_zip_archive,
 569        ARCHIVER_WANT_COMPRESSION_LEVELS|ARCHIVER_REMOTE
 570};
 571
 572void init_zip_archiver(void)
 573{
 574        register_archiver(&zip_archiver);
 575}