"Fossies" - the Fresh Open Source Software Archive

Member "zsync-0.6.2/makegz.c" (16 Sep 2010, 5256 Bytes) of package /linux/privat/old/zsync-0.6.2.tar.gz:


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 "makegz.c" see the Fossies "Dox" file reference documentation.

    1 
    2 /*
    3  *   zsync - client side rsync over http
    4  *   Copyright (C) 2004,2005,2007,2009 Colin Phipps <cph@moria.org.uk>
    5  *
    6  *   This program is free software; you can redistribute it and/or modify
    7  *   it under the terms of the Artistic License v2 (see the accompanying
    8  *   file COPYING for the full license terms), or, at your option, any later
    9  *   version of the same license.
   10  *
   11  *   This program is distributed in the hope that it will be useful,
   12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  *   COPYING file for details.
   15  */
   16 
   17 #include "zsglobal.h"
   18 
   19 #include <stdio.h>
   20 #include <unistd.h>
   21 #include <stdlib.h>
   22 
   23 #include "zlib/zlib.h"
   24 
   25 #include <sys/types.h>
   26 #include <sys/stat.h>
   27 
   28 #ifdef WITH_DMALLOC
   29 # include <dmalloc.h>
   30 #endif
   31 
   32 /* fputlong(filehandle, long)
   33  * Writes a 32bit int as raw bytes in little-endian to the given filehandle.
   34  * Returns 0 if successful; otherwise ferror(filehandle) to see the error */
   35 static int fputlong(FILE * f, unsigned long x) {
   36     int n;
   37     for (n = 0; n < 4; n++) {
   38         if (fputc((int)(x & 0xff), f) == EOF)
   39             return -1;
   40         x >>= 8;
   41     }
   42     return 0;
   43 }
   44 
   45 /* time = get_mtime(filehandle)
   46  * Get the mtime of a file from an open filehandle; or 0 if unavailable */
   47 time_t get_mtime(FILE * f) {
   48     struct stat s;
   49 
   50     if (fstat(fileno(f), &s) == 0)
   51         return s.st_mtime;
   52     else
   53         return 0;
   54 }
   55 
   56 /* filehandle = optimal_gzip(filehandle, out_filename_str, blocksize)
   57  * Constructs a compressed version of the data in the file referenced by the
   58  * supplied filehandle; this is saved in a file with the filename supplied as
   59  * the second parameter. The compressed version is optimised for the zsync
   60  * algorithm with the supplied blocksize. The function returns a handle to the
   61  * compressed file (opened for r+w but rewound to the start of the file,
   62  * ready for reading.
   63  */
   64 
   65 /* Algorithm: simple really. We construct a gzip (have to write header with
   66  * mtime, footer with length and crc; we do a standard zlib compress on the
   67  * content _except_ that we supply one block (of the size that zsync will be
   68  * using) and a Z_PARTIAL_FLUSH at the end of each one, so zlib breaks the
   69  * compression runs at exactly the places zsync will start/stop retrieving data.
   70  */
   71 FILE *optimal_gzip(FILE * ffin, const char *fout, size_t blocksize) {
   72     time_t mtime = get_mtime(ffin);
   73 
   74     /* Open output file (for writing, but also reading so we can return the
   75      * handle for reading by the caller. */
   76     FILE *ffout = fopen(fout, "wb+");
   77     if (!ffout) {
   78         perror("open");
   79         return NULL;
   80     }
   81 
   82     /* Write gzip header */
   83     if (fwrite("\x1f\x8b\x08\x00", 4, 1, ffout) != 1) {
   84         perror("write");
   85         return NULL;
   86     }
   87     if (fputlong(ffout, mtime) == -1) {
   88         perror("write");
   89         return NULL;
   90     }
   91     if (fwrite("\x00\x03", 2, 1, ffout) != 1) {
   92         perror("write");
   93         return NULL;
   94     }
   95 
   96     {   /* Now write compressed content */
   97         z_stream zs;
   98         unsigned char *inbuf = malloc(blocksize);
   99         unsigned char *outbuf = malloc(blocksize + 500);
  100         int err, r;
  101         unsigned long crc = crc32(0L, Z_NULL, 0);
  102 
  103         /* Set up zlib object */
  104         zs.zalloc = Z_NULL;
  105         zs.zfree = Z_NULL;
  106         zs.opaque = NULL;
  107         zs.total_in = 0;
  108         zs.total_out = 0;
  109 
  110         /* windowBits is passed < 0 to suppress zlib header */
  111         err = deflateInit2(&zs, 9,
  112                            Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
  113 
  114         /* Until end of file or error */
  115         for (r = 1; r > 0;) {
  116             r = fread(inbuf, 1, blocksize, ffin);
  117             if (r < 0)
  118                 break;
  119 
  120             /* Maintain running crc (for footer) */
  121             crc = crc32(crc, inbuf, r);
  122 
  123             /* Set up compressor for this block */
  124             zs.next_in = inbuf;
  125             zs.avail_in = r;
  126             zs.next_out = outbuf;
  127             zs.avail_out = blocksize + 500;
  128 
  129             /* Compress with partial flush at the end of this block 
  130              * unless EOF, in which case finish */
  131             err = deflate(&zs, r ? Z_PARTIAL_FLUSH : Z_FINISH);
  132             switch (err) {
  133             case Z_STREAM_END:
  134             case Z_OK:
  135                 {
  136                     size_t w = zs.next_out - outbuf;
  137 
  138                     if (w != fwrite(outbuf, 1, w, ffout)) {
  139                         perror("write");
  140                         r = -1;
  141                     }
  142                 }
  143                 break;
  144             default:
  145                 fprintf(stderr, "zlib error: %s (%d)\n", zs.msg, err);
  146                 r = -1;
  147             }
  148         }
  149 
  150         /* Write gzip footer */
  151         if (fputlong(ffout, crc) == -1) {
  152             perror("write");
  153             return NULL;
  154         }
  155         if (fputlong(ffout, zs.total_in) == -1) {
  156             perror("write");
  157             return NULL;
  158         }
  159 
  160         /* Clean up */
  161         fflush(ffout);
  162         free(outbuf);
  163         free(inbuf);
  164         if (fclose(ffin) != 0 || r != 0) {
  165             fclose(ffout);
  166             return NULL;
  167         }
  168     }
  169 
  170     /* Return rewound handle on the compressed data to the caller */
  171     rewind(ffout);
  172     return ffout;
  173 }