bump version
[buildroot.git] / toolchain / elf2flt / elf2flt / compress.c
blob69abc6a50162d55832a65d61a484081d01498155
1 /*
2 * Helper functions to handle compression via zlib
4 * Copyright (C) 2007-2008 Julian Brown
5 * Copyright (C) 2008 Mike Frysinger
7 * Licensed under the GPL-2 or later.
8 */
10 #include <assert.h>
11 #include <stdio.h>
12 #include <stdlib.h>
14 #include <zlib.h>
15 #include "compress.h"
17 /* Open an (uncompressed) file as a stream. Return 0 on success, 1 on
18 error.
19 NOTE: The MODE argument must remain valid for the lifetime of the stream,
20 because it is referred to by reopen_stream_compressed() if it is called.
21 String constants work fine. */
23 int
24 fopen_stream_u(stream *fp, const char *path, const char *mode)
26 fp->u.filep = fopen(path, mode);
27 fp->type = (fp->u.filep) ? UNCOMPRESSED : INVALID;
28 fp->mode = mode;
29 return (fp->u.filep) ? 0 : 1;
32 /* Read from stream. Return number of elements read. */
34 size_t
35 fread_stream(void *ptr, size_t size, size_t nmemb, stream *str)
37 size_t read;
39 switch (str->type) {
40 case UNCOMPRESSED:
41 read = fread(ptr, size, nmemb, str->u.filep);
42 break;
44 case COMPRESSED:
45 read = gzread(str->u.gzfilep, ptr, size * nmemb) / size;
46 break;
48 default:
49 abort();
52 return read;
55 /* Write to stream. Return number of elements written. */
57 size_t
58 fwrite_stream(const void *ptr, size_t size, size_t nmemb, stream *str)
60 size_t written;
62 switch (str->type) {
63 case UNCOMPRESSED:
64 written = fwrite(ptr, size, nmemb, str->u.filep);
65 break;
67 case COMPRESSED:
68 written = gzwrite(str->u.gzfilep, ptr, size * nmemb) / size;
69 break;
71 default:
72 abort();
75 return written;
78 /* Close stream. */
80 int
81 fclose_stream(stream *str)
83 switch (str->type) {
84 case UNCOMPRESSED:
85 return fclose(str->u.filep);
87 case COMPRESSED:
88 return gzclose(str->u.gzfilep);
90 default:
91 abort();
94 return 0;
97 int
98 ferror_stream(stream *str)
100 switch (str->type) {
101 case UNCOMPRESSED:
102 return ferror(str->u.filep);
104 case COMPRESSED:
106 const char *err;
107 int errno;
109 err = gzerror(str->u.gzfilep, &errno);
110 if (errno == Z_OK || errno == Z_STREAM_END)
111 return 0;
112 else if (errno == Z_ERRNO)
113 return 1;
114 else {
115 fprintf(stderr, "%s\n", err);
116 return 1;
119 break;
121 default:
122 abort();
125 return 0;
128 /* Reopen a stream at the current file position. */
130 void
131 reopen_stream_compressed(stream *str)
133 int fd;
134 long offset, roffset;
136 /* Already a compressed stream, return immediately */
137 if (str->type == COMPRESSED)
138 return;
140 if (str->type == INVALID)
141 abort();
143 fd = fileno(str->u.filep);
144 /* Get current (buffered) file position. */
145 offset = ftell(str->u.filep);
147 /* Make sure there's nothing left in buffers. */
148 fflush(str->u.filep);
150 /* Reposition underlying FD. (Might be unnecessary?) */
151 roffset = lseek(fd, offset, SEEK_SET);
153 assert(roffset == offset);
155 /* Reopen as compressed stream. */
156 str->u.gzfilep = gzdopen(fd, str->mode);
157 gzsetparams(str->u.gzfilep, 9, Z_DEFAULT_STRATEGY);
158 str->type = COMPRESSED;
161 void
162 transfer(stream *ifp, stream *ofp, int count)
164 char cmd[1024];
165 int n, num;
167 while (count == -1 || count > 0) {
168 if (count == -1 || count > sizeof(cmd))
169 num = sizeof(cmd);
170 else
171 num = count;
172 n = fread_stream(cmd, 1, num, ifp);
173 if (n == 0)
174 break;
175 if (fwrite_stream(cmd, n, 1, ofp) != 1) {
176 fprintf(stderr, "Write failed :-(\n");
177 exit(1);
179 if (count != -1)
180 count -= n;
182 if (count > 0) {
183 fprintf(stderr, "Failed to transfer %d bytes\n", count);
184 exit(1);