"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 }