Subversion Repositories freemyipod

Rev

Rev 447 | Details | Compare with Previous | Last modification | View Log | RSS feed

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