2  * Copyright (c) 2006 Rene Scharfe
 
  10 static unsigned char *zip_dir;
 
  11 static unsigned int zip_dir_size;
 
  13 static unsigned int zip_offset;
 
  14 static unsigned int zip_dir_offset;
 
  15 static unsigned int zip_dir_entries;
 
  17 #define ZIP_DIRECTORY_MIN_SIZE  (1024 * 1024)
 
  19 struct zip_local_header {
 
  20         unsigned char magic[4];
 
  21         unsigned char version[2];
 
  22         unsigned char flags[2];
 
  23         unsigned char compression_method[2];
 
  24         unsigned char mtime[2];
 
  25         unsigned char mdate[2];
 
  26         unsigned char crc32[4];
 
  27         unsigned char compressed_size[4];
 
  28         unsigned char size[4];
 
  29         unsigned char filename_length[2];
 
  30         unsigned char extra_length[2];
 
  31         unsigned char _end[1];
 
  34 struct zip_dir_header {
 
  35         unsigned char magic[4];
 
  36         unsigned char creator_version[2];
 
  37         unsigned char version[2];
 
  38         unsigned char flags[2];
 
  39         unsigned char compression_method[2];
 
  40         unsigned char mtime[2];
 
  41         unsigned char mdate[2];
 
  42         unsigned char crc32[4];
 
  43         unsigned char compressed_size[4];
 
  44         unsigned char size[4];
 
  45         unsigned char filename_length[2];
 
  46         unsigned char extra_length[2];
 
  47         unsigned char comment_length[2];
 
  48         unsigned char disk[2];
 
  49         unsigned char attr1[2];
 
  50         unsigned char attr2[4];
 
  51         unsigned char offset[4];
 
  52         unsigned char _end[1];
 
  55 struct zip_dir_trailer {
 
  56         unsigned char magic[4];
 
  57         unsigned char disk[2];
 
  58         unsigned char directory_start_disk[2];
 
  59         unsigned char entries_on_this_disk[2];
 
  60         unsigned char entries[2];
 
  61         unsigned char size[4];
 
  62         unsigned char offset[4];
 
  63         unsigned char comment_length[2];
 
  64         unsigned char _end[1];
 
  68  * On ARM, padding is added at the end of the struct, so a simple
 
  69  * sizeof(struct ...) reports two bytes more than the payload size
 
  70  * we're interested in.
 
  72 #define ZIP_LOCAL_HEADER_SIZE   offsetof(struct zip_local_header, _end)
 
  73 #define ZIP_DIR_HEADER_SIZE     offsetof(struct zip_dir_header, _end)
 
  74 #define ZIP_DIR_TRAILER_SIZE    offsetof(struct zip_dir_trailer, _end)
 
  76 static void copy_le16(unsigned char *dest, unsigned int n)
 
  79         dest[1] = 0xff & (n >> 010);
 
  82 static void copy_le32(unsigned char *dest, unsigned int n)
 
  85         dest[1] = 0xff & (n >> 010);
 
  86         dest[2] = 0xff & (n >> 020);
 
  87         dest[3] = 0xff & (n >> 030);
 
  90 static void *zlib_deflate(void *data, unsigned long size,
 
  91                 int compression_level, unsigned long *compressed_size)
 
  94         unsigned long maxsize;
 
  98         memset(&stream, 0, sizeof(stream));
 
  99         git_deflate_init(&stream, compression_level);
 
 100         maxsize = git_deflate_bound(&stream, size);
 
 101         buffer = xmalloc(maxsize);
 
 103         stream.next_in = data;
 
 104         stream.avail_in = size;
 
 105         stream.next_out = buffer;
 
 106         stream.avail_out = maxsize;
 
 109                 result = git_deflate(&stream, Z_FINISH);
 
 110         } while (result == Z_OK);
 
 112         if (result != Z_STREAM_END) {
 
 117         git_deflate_end(&stream);
 
 118         *compressed_size = stream.total_out;
 
 123 static int write_zip_entry(struct archiver_args *args,
 
 124                 const unsigned char *sha1, const char *path, size_t pathlen,
 
 125                 unsigned int mode, void *buffer, unsigned long size)
 
 127         struct zip_local_header header;
 
 128         struct zip_dir_header dirent;
 
 130         unsigned long compressed_size;
 
 131         unsigned long uncompressed_size;
 
 133         unsigned long direntsize;
 
 136         void *deflated = NULL;
 
 138         crc = crc32(0, NULL, 0);
 
 140         if (pathlen > 0xffff) {
 
 141                 return error("path too long (%d chars, SHA1: %s): %s",
 
 142                                 (int)pathlen, sha1_to_hex(sha1), path);
 
 145         if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
 
 149                 uncompressed_size = 0;
 
 151         } else if (S_ISREG(mode) || S_ISLNK(mode)) {
 
 153                 attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
 
 154                         (mode & 0111) ? ((mode) << 16) : 0;
 
 155                 if (S_ISREG(mode) && args->compression_level != 0)
 
 157                 crc = crc32(crc, buffer, size);
 
 159                 uncompressed_size = size;
 
 160                 compressed_size = size;
 
 162                 return error("unsupported file mode: 0%o (SHA1: %s)", mode,
 
 167                 deflated = zlib_deflate(buffer, size, args->compression_level,
 
 169                 if (deflated && compressed_size - 6 < size) {
 
 170                         /* ZLIB --> raw compressed data (see RFC 1950) */
 
 171                         /* CMF and FLG ... */
 
 172                         out = (unsigned char *)deflated + 2;
 
 173                         compressed_size -= 6;   /* ... and ADLER32 */
 
 176                         compressed_size = size;
 
 180         /* make sure we have enough free space in the dictionary */
 
 181         direntsize = ZIP_DIR_HEADER_SIZE + pathlen;
 
 182         while (zip_dir_size < zip_dir_offset + direntsize) {
 
 183                 zip_dir_size += ZIP_DIRECTORY_MIN_SIZE;
 
 184                 zip_dir = xrealloc(zip_dir, zip_dir_size);
 
 187         copy_le32(dirent.magic, 0x02014b50);
 
 188         copy_le16(dirent.creator_version,
 
 189                 S_ISLNK(mode) || (S_ISREG(mode) && (mode & 0111)) ? 0x0317 : 0);
 
 190         copy_le16(dirent.version, 10);
 
 191         copy_le16(dirent.flags, 0);
 
 192         copy_le16(dirent.compression_method, method);
 
 193         copy_le16(dirent.mtime, zip_time);
 
 194         copy_le16(dirent.mdate, zip_date);
 
 195         copy_le32(dirent.crc32, crc);
 
 196         copy_le32(dirent.compressed_size, compressed_size);
 
 197         copy_le32(dirent.size, uncompressed_size);
 
 198         copy_le16(dirent.filename_length, pathlen);
 
 199         copy_le16(dirent.extra_length, 0);
 
 200         copy_le16(dirent.comment_length, 0);
 
 201         copy_le16(dirent.disk, 0);
 
 202         copy_le16(dirent.attr1, 0);
 
 203         copy_le32(dirent.attr2, attr2);
 
 204         copy_le32(dirent.offset, zip_offset);
 
 205         memcpy(zip_dir + zip_dir_offset, &dirent, ZIP_DIR_HEADER_SIZE);
 
 206         zip_dir_offset += ZIP_DIR_HEADER_SIZE;
 
 207         memcpy(zip_dir + zip_dir_offset, path, pathlen);
 
 208         zip_dir_offset += pathlen;
 
 211         copy_le32(header.magic, 0x04034b50);
 
 212         copy_le16(header.version, 10);
 
 213         copy_le16(header.flags, 0);
 
 214         copy_le16(header.compression_method, method);
 
 215         copy_le16(header.mtime, zip_time);
 
 216         copy_le16(header.mdate, zip_date);
 
 217         copy_le32(header.crc32, crc);
 
 218         copy_le32(header.compressed_size, compressed_size);
 
 219         copy_le32(header.size, uncompressed_size);
 
 220         copy_le16(header.filename_length, pathlen);
 
 221         copy_le16(header.extra_length, 0);
 
 222         write_or_die(1, &header, ZIP_LOCAL_HEADER_SIZE);
 
 223         zip_offset += ZIP_LOCAL_HEADER_SIZE;
 
 224         write_or_die(1, path, pathlen);
 
 225         zip_offset += pathlen;
 
 226         if (compressed_size > 0) {
 
 227                 write_or_die(1, out, compressed_size);
 
 228                 zip_offset += compressed_size;
 
 236 static void write_zip_trailer(const unsigned char *sha1)
 
 238         struct zip_dir_trailer trailer;
 
 240         copy_le32(trailer.magic, 0x06054b50);
 
 241         copy_le16(trailer.disk, 0);
 
 242         copy_le16(trailer.directory_start_disk, 0);
 
 243         copy_le16(trailer.entries_on_this_disk, zip_dir_entries);
 
 244         copy_le16(trailer.entries, zip_dir_entries);
 
 245         copy_le32(trailer.size, zip_dir_offset);
 
 246         copy_le32(trailer.offset, zip_offset);
 
 247         copy_le16(trailer.comment_length, sha1 ? 40 : 0);
 
 249         write_or_die(1, zip_dir, zip_dir_offset);
 
 250         write_or_die(1, &trailer, ZIP_DIR_TRAILER_SIZE);
 
 252                 write_or_die(1, sha1_to_hex(sha1), 40);
 
 255 static void dos_time(time_t *time, int *dos_date, int *dos_time)
 
 257         struct tm *t = localtime(time);
 
 259         *dos_date = t->tm_mday + (t->tm_mon + 1) * 32 +
 
 260                     (t->tm_year + 1900 - 1980) * 512;
 
 261         *dos_time = t->tm_sec / 2 + t->tm_min * 32 + t->tm_hour * 2048;
 
 264 static int write_zip_archive(const struct archiver *ar,
 
 265                              struct archiver_args *args)
 
 269         dos_time(&args->time, &zip_date, &zip_time);
 
 271         zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);
 
 272         zip_dir_size = ZIP_DIRECTORY_MIN_SIZE;
 
 274         err = write_archive_entries(args, write_zip_entry);
 
 276                 write_zip_trailer(args->commit_sha1);
 
 283 static struct archiver zip_archiver = {
 
 286         ARCHIVER_WANT_COMPRESSION_LEVELS|ARCHIVER_REMOTE
 
 289 void init_zip_archiver(void)
 
 291         register_archiver(&zip_archiver);