Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
445 theseven 1
/*
2
 * Helper functions to handle compression via zlib
3
 *
4
 * Copyright (C) 2007-2008 Julian Brown
5
 * Copyright (C) 2008 Mike Frysinger
6
 *
7
 * Licensed under the GPL-2 or later.
8
 */
9
 
10
#include <assert.h>
11
#include <stdio.h>
12
#include <stdlib.h>
447 theseven 13
#include <string.h>
445 theseven 14
 
447 theseven 15
//#include <zlib.h>
16
#include "ucl/ucl.h"
445 theseven 17
#include "compress.h"
18
#include "stubs.h"
19
 
20
/* Open an (uncompressed) file as a stream.  Return 0 on success, 1 on
21
   error.
22
   NOTE: The MODE argument must remain valid for the lifetime of the stream,
23
   because it is referred to by reopen_stream_compressed() if it is called.
24
   String constants work fine.  */
25
 
26
int
27
fopen_stream_u(stream *fp, const char *path, const char *mode)
28
{
447 theseven 29
	fp->filep = fopen(path, mode);
30
	fp->type = (fp->filep) ? UNCOMPRESSED : INVALID;
445 theseven 31
	fp->mode = mode;
447 theseven 32
    fp->buffer = NULL;
33
    fp->bufsize = 0;
34
    fp->bufused = 0;
35
	return (fp->filep) ? 0 : 1;
445 theseven 36
}
37
 
38
/* Read from stream.  Return number of elements read.  */
39
 
40
size_t
41
fread_stream(void *ptr, size_t size, size_t nmemb, stream *str)
42
{
43
	size_t read;
44
 
45
	switch (str->type) {
46
		case UNCOMPRESSED:
447 theseven 47
		read = fread(ptr, size, nmemb, str->filep);
445 theseven 48
		break;
49
 
447 theseven 50
//		case COMPRESSED:
51
//		read = gzread(str->u.gzfilep, ptr, size * nmemb) / size;
52
//		break;
445 theseven 53
 
54
		default:
55
		abort();
56
	}
57
 
58
	return read;
59
}
60
 
61
/* Write to stream.  Return number of elements written.  */
62
 
63
size_t
64
fwrite_stream(const void *ptr, size_t size, size_t nmemb, stream *str)
65
{
66
	size_t written;
67
 
68
	switch (str->type) {
69
		case UNCOMPRESSED:
447 theseven 70
		written = fwrite(ptr, size, nmemb, str->filep);
445 theseven 71
		break;
72
 
73
		case COMPRESSED:
447 theseven 74
        if (str->bufused + size * nmemb > str->bufsize)
75
        {
76
            str->bufsize = (str->bufused + size * nmemb + 0xfff) & ~0xfff;
77
            str->buffer = (char*)realloc(str->buffer, str->bufsize);
78
        }
79
        memcpy(&str->buffer[str->bufused], ptr, size * nmemb);
80
        str->bufused += size * nmemb;
81
        written = nmemb;
82
		//written = gzwrite(str->u.gzfilep, ptr, size * nmemb) / size;
445 theseven 83
		break;
84
 
85
		default:
86
		abort();
87
	}
88
 
89
	return written;
90
}
91
 
92
/* Close stream.  */
93
 
94
int
95
fclose_stream(stream *str)
96
{
97
	switch (str->type) {
98
		case UNCOMPRESSED:
447 theseven 99
		return fclose(str->filep);
445 theseven 100
 
101
		case COMPRESSED:
447 theseven 102
        {
103
            int outsize = str->bufused + str->bufused / 8 + 256;
104
            str->buffer = (char*)realloc(str->buffer, str->bufused);
105
            char* buffer = (char*)malloc(outsize);
106
            int r = ucl_nrv2e_99_compress(str->buffer, str->bufused, buffer, &outsize, 0, 10, NULL, NULL);
107
            free(str->buffer);
108
            if (r != UCL_E_OK)
109
            {
110
                free(buffer);
111
                /* this should NEVER happen */
112
                printf("internal error - compression failed: %d\n", r);
113
                return 2;
114
            }
115
            buffer = (char*)realloc(buffer, outsize);
116
            int done = 0;
117
            while (done < outsize)
118
            {
119
                int bytes = fwrite(&buffer[done], 1, outsize - done, str->filep);
120
                if (bytes <= 0) return 3;
121
                done += bytes;
122
            }
123
            free(buffer);
124
		    return fclose(str->filep);
125
        }
126
//		return gzclose(str->u.gzfilep);
445 theseven 127
 
128
		default:
129
		abort();
130
	}
131
 
132
	return 0;
133
}
134
 
135
int
136
ferror_stream(stream *str)
137
{
138
	switch (str->type) {
139
		case UNCOMPRESSED:
447 theseven 140
		return ferror(str->filep);
445 theseven 141
 
142
		case COMPRESSED:
447 theseven 143
		return ferror(str->filep);
144
//		{
145
//			const char *err;
146
//			int errno;
147
//
148
//			err = gzerror(str->u.gzfilep, &errno);
149
//			if (errno == Z_OK || errno == Z_STREAM_END)
150
//				return 0;
151
//			else if (errno == Z_ERRNO)
152
//				return 1;
153
//			else {
154
//				fprintf(stderr, "%s\n", err);
155
//				return 1;
156
//			}
157
//		}
158
//		break;
445 theseven 159
 
160
		default:
161
		abort();
162
	}
163
 
164
	return 0;
165
}
166
 
167
int
168
fseek_stream(stream *str, long offset, int whence)
169
{
170
	switch (str->type) {
171
		case UNCOMPRESSED:
447 theseven 172
		return fseek(str->filep, offset, whence);
445 theseven 173
 
447 theseven 174
//		case COMPRESSED:
175
//		return gzseek(str->u.gzfilep, offset, whence);
445 theseven 176
 
177
		default:
178
		abort();
179
	}
180
}
181
 
182
/* Reopen a stream at the current file position.  */
183
 
184
void
185
reopen_stream_compressed(stream *str)
186
{
187
	int fd;
188
	long offset, roffset;
189
 
190
	/* Already a compressed stream, return immediately  */
191
	if (str->type == COMPRESSED)
192
		return;
193
 
194
	if (str->type == INVALID)
195
		abort();
196
 
447 theseven 197
	fd = fileno(str->filep);
445 theseven 198
	/* Get current (buffered) file position.  */
447 theseven 199
	offset = ftell(str->filep);
445 theseven 200
 
201
	/* Make sure there's nothing left in buffers.  */
447 theseven 202
	fflush(str->filep);
445 theseven 203
 
204
	/* Reposition underlying FD.  (Might be unnecessary?)  */
205
	roffset = lseek(fd, offset, SEEK_SET);
206
 
207
	assert(roffset == offset);
208
 
209
	/* Reopen as compressed stream.  */
447 theseven 210
	//str->u.gzfilep = gzdopen(fd, str->mode);
211
	//gzsetparams(str->u.gzfilep, 9, Z_DEFAULT_STRATEGY);
445 theseven 212
	str->type = COMPRESSED;
213
}
214
 
215
void
216
transfer(stream *ifp, stream *ofp, int count)
217
{
218
	char cmd[1024];
219
	int n, num;
220
 
221
	while (count == -1 || count > 0) {
222
		if (count == -1 || count > sizeof(cmd))
223
			num = sizeof(cmd);
224
		else
225
			num = count;
226
		n = fread_stream(cmd, 1, num, ifp);
227
		if (n == 0)
228
			break;
229
		if (fwrite_stream(cmd, n, 1, ofp) != 1)
230
			fatal_perror("Write failed :-(\n");
231
		if (count != -1)
232
			count -= n;
233
	}
234
	if (count > 0)
235
		fatal("Failed to transfer %d bytes\n", count);
236
}