]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/plr/lib/libuu/uu.c
update
[l4.git] / l4 / pkg / plr / lib / libuu / uu.c
1 /**
2  * \file   ferret/examples/merge_mon/uu.c
3  * \brief  UUencoding functions, mostly from jdb
4  *
5  * \date   14/12/2005
6  * \author Martin Pohlack  <mp26@os.inf.tu-dresden.de>
7  */
8 /*
9  * (c) 2005-2009 Technische Universität Dresden
10  * This file is part of TUD:OS and distributed under the terms of the
11  * GNU General Public License 2.
12  * Please see the COPYING-GPL-2 file for details.
13  */
14
15 /* ENC is the basic 1 character encoding function to make a char printing */
16 #define ENC(c) ((c) ? ((c) & 077) + ' ': '`')
17
18 #include <assert.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <sys/types.h>
22
23 #include <zlib.h>
24
25 #include <l4/plr/uu.h>
26
27 #define MIN(a, b) ((a)<(b)?(a):(b))
28
29 #define LINE_IN 45
30
31 static z_stream strm;
32
33 /* Init. zlib data structures, available input data and start address
34  */
35 static void init_z(size_t len, const void *start)
36 {
37     int ret;
38     strm.zalloc = Z_NULL;
39     strm.zfree = Z_NULL;
40     strm.opaque = Z_NULL;
41     ret = deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, 15 + 16, 9,
42                        Z_DEFAULT_STRATEGY);
43     assert(ret == Z_OK);
44
45     strm.avail_in = len;
46     strm.next_in  = (void *)start;  // oh why ...
47 }
48
49 static int get_next_chunk(void *dest, ssize_t n, int flush)
50 {
51     int ret;
52
53     strm.avail_out = n;
54     strm.next_out = dest;
55     ret = deflate(&strm, flush);
56     assert(ret != Z_STREAM_ERROR);
57     return n - strm.avail_out;
58 }
59
60 static void update_in_data(const unsigned char * buf, size_t * len)
61 {
62     if (strm.avail_in == 0 && *len != 0)
63     {
64         strm.avail_in = *len;
65         strm.next_in  = (void *)buf;  // oh why ...
66         *len = 0;
67     }
68 }
69
70 void uu_dumpz(const char * filename, const unsigned char * s_buf, size_t len)
71 {
72     unsigned int ch;
73     int n, ret;
74     const unsigned char *p_buf;
75     int out_i;
76     static unsigned char in[LINE_IN + 3];  // some spare zeros for uuencode
77     static unsigned char out[70];
78     int flush = Z_NO_FLUSH;
79
80     init_z(len, s_buf);
81
82     // uuencode header
83     printf("begin 644 %s.gz\n", filename);
84
85     while (1)
86     {
87         // get next line of data
88         n = get_next_chunk(in, LINE_IN, flush);
89         if (n < LINE_IN && flush == Z_NO_FLUSH)
90         {
91             flush = Z_FINISH;  // time to clean up now
92             n += get_next_chunk(in + n, LINE_IN - n, flush);
93         }
94         else if (n == 0 && flush == Z_FINISH)
95             break;  // no more data available, leave loop
96         memset(in + n, 0, sizeof(in) - n);
97
98         // fill output buffer
99         out_i = 0;
100         // line length prefix
101         ch = ENC(n);
102         out[out_i++] = ch;
103         for (p_buf = in; n > 0; n -= 3, p_buf += 3)
104         {
105             ch = *p_buf >> 2;
106             ch = ENC(ch);
107             out[out_i++] = ch;
108             ch = ((*p_buf << 4) & 060) | ((p_buf[1] >> 4) & 017);
109             ch = ENC(ch);
110             out[out_i++] = ch;
111             ch = ((p_buf[1] << 2) & 074) | ((p_buf[2] >> 6) & 03);
112             ch = ENC(ch);
113             out[out_i++] = ch;
114             ch = p_buf[2] & 077;
115             ch = ENC(ch);
116             out[out_i++] = ch;
117         }
118         // skip this newline for log output
119         //out[out_i++] = '\n';
120         out[out_i] = '\0';
121         puts((char const*)out);  // write it
122     }
123
124     ret = deflateEnd(&strm);
125     assert(ret == Z_OK);
126
127     // uuencode footer
128     printf("`\nend\n");
129 }
130
131 /* Also works in ring buffers with wrap-around
132  */
133 void uu_dumpz_ringbuffer(const char * filename,
134                          const void * _buffer, size_t buffer_len,
135                          unsigned start_offset, size_t transfer_size)
136 {
137     int ret;
138     unsigned char * buffer = (unsigned char *)_buffer;
139     static unsigned char in[LINE_IN + 3];  // some spare zeros for uuencode
140     static unsigned char out[70];
141     int flush = Z_NO_FLUSH;
142     size_t first_len = MIN(transfer_size, buffer_len - start_offset);
143
144     assert((unsigned)start_offset < buffer_len);
145     assert(transfer_size <= buffer_len);
146
147     // init. zlib stream for first chunk
148     init_z(first_len, buffer + start_offset);
149     transfer_size -= first_len;
150
151     // uuencode header
152     printf("begin 644 %s.gz\n", filename);
153
154     while (1)
155     {
156         int out_i, n;
157         unsigned int ch;
158         const unsigned char * p_buf;
159
160         // get next line of data
161         n = get_next_chunk(in, LINE_IN, flush);
162         update_in_data(buffer, &transfer_size);
163         if (n < LINE_IN && flush == Z_NO_FLUSH)
164         {
165             flush = Z_FINISH;  // time to clean up now
166             n += get_next_chunk(in + n, LINE_IN - n, flush);
167             update_in_data(buffer, &transfer_size);
168         }
169         else if (n == 0 && flush == Z_FINISH)
170             break;  // no more data available, leave loop
171         memset(in + n, 0, sizeof(in) - n);
172
173         // fill output buffer
174         out_i = 0;
175         // line length prefix
176         ch = ENC(n);
177         out[out_i++] = ch;
178         for (p_buf = in; n > 0; n -= 3, p_buf += 3)
179         {
180             ch = *p_buf >> 2;
181             ch = ENC(ch);
182             out[out_i++] = ch;
183             ch = ((*p_buf << 4) & 060) | ((p_buf[1] >> 4) & 017);
184             ch = ENC(ch);
185             out[out_i++] = ch;
186             ch = ((p_buf[1] << 2) & 074) | ((p_buf[2] >> 6) & 03);
187             ch = ENC(ch);
188             out[out_i++] = ch;
189             ch = p_buf[2] & 077;
190             ch = ENC(ch);
191             out[out_i++] = ch;
192         }
193         // skip this newline for log output
194         //out[out_i++] = '\n';
195         out[out_i] = '\0';
196         puts((char const *)out);  // write it
197     }
198
199     ret = deflateEnd(&strm);
200     assert(ret == Z_OK);
201
202     // uuencode footer
203     printf("`\nend\n");
204 }
205
206 #if 0
207 void uu_dump(const char * filename, const buf_t * buf)
208 {
209     unsigned int ch;
210     int n;
211     const unsigned char *p_buf;
212     unsigned char *s_buf = buf->start;
213     int out_i;
214     static unsigned char in[48];
215     static unsigned char out[70];
216     size_t len = buf->write_pos - buf->start;
217
218     // debug
219     //printf("%hhx %hhx %hhx %hhx\n", ENC(8), ENC(64), ENC(4), ENC(2));
220
221     // uuencode header
222     printf("begin 644 %s\n", filename);
223
224     while (len > 0)
225     {
226         // get next line of data
227         if (len >= LINE_IN)
228         {
229             n = LINE_IN;
230         }
231         else
232         {
233             n = len;
234         }
235         memcpy(in, s_buf, n);
236         memset(in + n, 0, sizeof(in) - n);
237         len -= n;
238         s_buf += n;
239
240         // fill output buffer
241         out_i = 0;
242         // line length prefix
243         ch = ENC(n);
244         out[out_i++] = ch;
245         for (p_buf = in; n > 0; n -= 3, p_buf += 3)
246         {
247             ch = *p_buf >> 2;
248             ch = ENC(ch);
249             out[out_i++] = ch;
250             ch = ((*p_buf << 4) & 060) | ((p_buf[1] >> 4) & 017);
251             ch = ENC(ch);
252             out[out_i++] = ch;
253             ch = ((p_buf[1] << 2) & 074) | ((p_buf[2] >> 6) & 03);
254             ch = ENC(ch);
255             out[out_i++] = ch;
256             ch = p_buf[2] & 077;
257             ch = ENC(ch);
258             out[out_i++] = ch;
259         }
260         // skip this newline for log output
261         //out[out_i++] = '\n';
262         out[out_i] = '\0';
263
264         // write it
265         puts(out);
266     }
267
268     // uuencode footer
269     printf("`\nend\n");
270 }
271 #endif