Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/paxlib/ico/ico.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* pax ico format
24
*/
25
26
#include <paxlib.h>
27
#include <ccode.h>
28
#include <swap.h>
29
#include <tm.h>
30
31
#define ICO_HEADER 6
32
#define ICO_DIRECTORY 16
33
34
#define ICO_MAGIC 0
35
#define ICO_TYPE 1
36
37
#define ICO_PNG_COLORS 0
38
#define ICO_PNG_PLANES 1
39
#define ICO_PNG_BPP 32
40
41
typedef struct Ico_header_s
42
{
43
uint16_t magic;
44
uint16_t type;
45
uint16_t count;
46
} Ico_header_t;
47
48
typedef struct Ico_directory_s
49
{
50
uint8_t width;
51
uint8_t height;
52
uint8_t colors;
53
uint8_t magic;
54
uint16_t panes;
55
uint16_t bpp;
56
uint32_t size;
57
uint32_t offset;
58
} Ico_directory_t;
59
60
typedef struct Ico_s
61
{
62
Sfio_t* head;
63
Sfio_t* data;
64
unsigned char* cur;
65
int mode;
66
int entries;
67
char name[32];
68
unsigned char dir[1];
69
} Ico_t;
70
71
static int
72
ico_done(Pax_t* pax, register Paxarchive_t* ap)
73
{
74
register Ico_t* ico = (Ico_t*)ap->data;
75
76
if (!ico)
77
return -1;
78
if (ico->data)
79
sfclose(ico->data);
80
if (ico->head)
81
sfclose(ico->head);
82
free(ico);
83
ap->data = 0;
84
return 0;
85
}
86
87
static int
88
ico_getprologue(Pax_t* pax, Paxformat_t* fp, register Paxarchive_t* ap, Paxfile_t* f, register unsigned char* p, size_t size)
89
{
90
register Ico_t* ico;
91
size_t m;
92
size_t n;
93
94
if (size < ICO_HEADER + ICO_DIRECTORY)
95
return 0;
96
if (swapget(3, p, 2) != ICO_MAGIC || swapget(3, p+2, 2) != ICO_TYPE || p[9] != 0 && p[9] != 255)
97
return 0;
98
if (paxseek(pax, ap, ICO_HEADER, SEEK_SET, 1) != ICO_HEADER)
99
return 0;
100
m = swapget(3, p+4, 2);
101
n = m * ICO_DIRECTORY;
102
if (!(ico = newof(0, Ico_t, 1, n - 1)))
103
return paxnospace(pax);
104
umask(ico->mode = umask(0));
105
ico->mode = X_IFREG | (0666 & ~ico->mode);
106
ico->entries = m;
107
if (paxread(pax, ap, ico->dir, n, n, 0) <= 0)
108
{
109
free(ico);
110
return 0;
111
}
112
ico->cur = ico->dir;
113
ap->data = ico;
114
return 1;
115
}
116
117
static int
118
ico_getheader(Pax_t* pax, register Paxarchive_t* ap, register Paxfile_t* f)
119
{
120
register Ico_t* ico = (Ico_t*)ap->data;
121
register unsigned char* p;
122
int width;
123
int height;
124
size_t offset;
125
size_t size;
126
127
if (ap->entry > ico->entries)
128
{
129
ap->io->eof = 1;
130
return 0;
131
}
132
p = ico->cur;
133
ico->cur += ICO_DIRECTORY;
134
width = p[0] ? p[0] : 256;
135
height = p[1] ? p[1] : 256;
136
size = swapget(3, p+8, 4);
137
offset = swapget(3, p+12, 4);
138
sfsprintf(ico->name, sizeof(ico->name), "ico-%d-c%dp%db%dw%dh%d.ico", ap->entry, p[2], (int)swapget(3, p+4, 2), (int)swapget(3, p+6, 2), width, height);
139
f->name = ico->name;
140
f->linktype = PAX_NOLINK;
141
f->linkpath = 0;
142
f->st->st_mode = ico->mode;
143
f->st->st_uid = pax->uid;
144
f->st->st_gid = pax->gid;
145
f->st->st_size = size;
146
f->st->st_mtime = time(NiL);
147
f->st->st_nlink = 1;
148
if (paxseek(pax, ap, offset, SEEK_SET, 1) != offset)
149
return -1;
150
return 1;
151
}
152
153
static int
154
ico_getdata(Pax_t* pax, register Paxarchive_t* ap, register Paxfile_t* f, int fd)
155
{
156
register Ico_t* ico = (Ico_t*)ap->data;
157
Sfio_t* sp;
158
ssize_t n;
159
size_t z;
160
unsigned char* dir;
161
unsigned char hdr[ICO_HEADER];
162
163
if (fd < 0 || !f->st->st_size)
164
return 1;
165
if (!(sp = paxpart(pax, ap, f->st->st_size)))
166
return -1;
167
swapput(3, hdr+0, 2, ICO_MAGIC);
168
swapput(3, hdr+2, 2, ICO_TYPE);
169
swapput(3, hdr+4, 2, 1);
170
sfwrite(sp, hdr, ICO_HEADER);
171
if (paxdata(pax, ap, f, fd, hdr, ICO_HEADER))
172
return -1;
173
dir = ico->cur - ICO_DIRECTORY;
174
swapput(3, dir+12, 4, ICO_HEADER + ICO_DIRECTORY);
175
if (paxdata(pax, ap, f, fd, dir, ICO_DIRECTORY))
176
return -1;
177
while ((n = sfread(sp, pax->buf, sizeof(pax->buf))) > 0)
178
if (paxdata(pax, ap, f, fd, pax->buf, n))
179
return -1;
180
if (n)
181
(*pax->errorf)(NiL, pax, 2, "%s: %s: unexpected EOF", ap->name, f->name);
182
return 1;
183
}
184
185
static int
186
ico_putprologue(Pax_t* pax, register Paxarchive_t* ap, int append)
187
{
188
register Ico_t* ico = (Ico_t*)ap->data;
189
unsigned char hdr[ICO_HEADER];
190
191
if (!ico)
192
{
193
if (!(ico = newof(0, Ico_t, 1, 0)) || !(ico->head = sfstropen()) || !(ico->data = sftmp(64 * 1024)))
194
return paxnospace(pax);
195
swapput(3, hdr+0, 2, ICO_MAGIC);
196
swapput(3, hdr+2, 2, ICO_TYPE);
197
swapput(3, hdr+4, 2, 0);
198
sfwrite(ico->head, hdr, ICO_HEADER);
199
ap->data = ico;
200
}
201
return 1;
202
}
203
204
static int
205
ico_putheader(Pax_t* pax, Paxarchive_t* ap, Paxfile_t* f)
206
{
207
return 1;
208
}
209
210
static int
211
ico_putdata(Pax_t* pax, Paxarchive_t* ap, Paxfile_t* f, int fd)
212
{
213
register Ico_t* ico = (Ico_t*)ap->data;
214
Sfio_t* sp;
215
unsigned char* p;
216
int d;
217
ssize_t n;
218
size_t z;
219
uint32_t size;
220
unsigned char dir[ICO_HEADER+ICO_DIRECTORY];
221
222
if (!(sp = sfnew(NiL, NiL, SF_UNBOUND, fd, SF_READ)))
223
return paxnospace(pax);
224
d = 1;
225
z = f->st->st_size;
226
do
227
{
228
if ((n = sizeof(pax->buf)) > z)
229
n = z;
230
if ((n = sfread(sp, pax->buf, n)) <= 0)
231
{
232
if (pax->errorf)
233
(*pax->errorf)(NiL, pax, 2, "%s: %s: read error", ap->name, f->name);
234
return -1;
235
}
236
p = (unsigned char*)pax->buf;
237
if (d)
238
{
239
if (n < ICO_HEADER + ICO_DIRECTORY)
240
{
241
if (pax->errorf)
242
(*pax->errorf)(NiL, pax, 2, "%s: %s: read error", ap->name, f->name);
243
return -1;
244
}
245
if (swapget(3, p+0, 2) == ICO_MAGIC && swapget(3, p+2, 2) == ICO_TYPE)
246
{
247
sfwrite(ico->head, p+ICO_HEADER, ICO_DIRECTORY);
248
p += ICO_HEADER + ICO_DIRECTORY;
249
n -= ICO_HEADER + ICO_DIRECTORY;
250
z -= ICO_HEADER + ICO_DIRECTORY;
251
}
252
else if (!memcmp(p, "\x89PNG\x0d\x0a\x1a\x0a", 8))
253
{
254
dir[0] = (d = swapget(0, p+16, 4)) < 256 ? d : 0;
255
dir[1] = (d = swapget(0, p+20, 4)) < 256 ? d : 0;
256
dir[2] = ICO_PNG_COLORS;
257
dir[3] = 0;
258
swapput(3, dir+4, 2, ICO_PNG_PLANES);
259
swapput(3, dir+6, 2, ICO_PNG_BPP);
260
swapput(3, dir+8, 2, f->st->st_size);
261
swapput(3, dir+12, 2, 0);
262
sfwrite(ico->head, dir, ICO_DIRECTORY);
263
}
264
else
265
{
266
if (pax->errorf)
267
(*pax->errorf)(NiL, pax, 2, "%s: %s: not an icon resource or image", ap->name, f->name);
268
return -1;
269
}
270
d = 0;
271
}
272
sfwrite(ico->data, p, n);
273
} while (z -= n);
274
if (sfclose(sp))
275
{
276
if (pax->errorf)
277
(*pax->errorf)(NiL, pax, 2, "%s: %s: write error", ap->name, f->name);
278
return -1;
279
}
280
return n;
281
}
282
283
static off_t
284
ico_putepilogue(Pax_t* pax, Paxarchive_t* ap)
285
{
286
register Ico_t* ico = (Ico_t*)ap->data;
287
register unsigned char* p;
288
unsigned char* b;
289
int i;
290
uint32_t size;
291
uint32_t offset;
292
293
b = p = (unsigned char*)sfstrbase(ico->head);
294
swapput(3, p+4, 2, ap->entry);
295
p += ICO_HEADER;
296
size = offset = ICO_HEADER + ap->entries * ICO_DIRECTORY;
297
for (i = 0; i < ap->entry; i++)
298
{
299
swapput(3, p+12, 4, offset);
300
offset += swapget(3, p+8, 4);
301
p += ICO_DIRECTORY;
302
}
303
paxwrite(pax, ap, b, size);
304
sfseek(ico->data, 0, SEEK_SET);
305
while ((i = sfread(ico->data, pax->buf, sizeof(pax->buf))) > 0)
306
paxwrite(pax, ap, pax->buf, i);
307
if (i < 0)
308
{
309
if (pax->errorf)
310
(*pax->errorf)(NiL, pax, 2, "%s: write error", ap->name);
311
return -1;
312
}
313
return 1;
314
}
315
316
Paxformat_t pax_ico_format =
317
{
318
"ico",
319
0,
320
"windows icon file",
321
0,
322
PAX_ARCHIVE|PAX_NOHARDLINKS|PAX_IN|PAX_OUT,
323
PAX_DEFBUFFER,
324
PAX_DEFBLOCKS,
325
0,
326
PAXNEXT(ico),
327
0,
328
ico_done,
329
ico_getprologue,
330
ico_getheader,
331
ico_getdata,
332
0,
333
0,
334
ico_putprologue,
335
ico_putheader,
336
ico_putdata,
337
0,
338
ico_putepilogue,
339
};
340
341
PAXLIB(ico)
342
343