1*593dc095SDavid du Colombier /* Copyright (C) 2005 artofcode LLC. All rights reserved.
2*593dc095SDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
5*593dc095SDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
9*593dc095SDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15*593dc095SDavid du Colombier */
16*593dc095SDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: mkromfs.c,v 1.2 2005/09/16 03:59:44 ray Exp $ */
18*593dc095SDavid du Colombier /* Generate source data for the %rom% IODevice */
19*593dc095SDavid du Colombier
20*593dc095SDavid du Colombier /*
21*593dc095SDavid du Colombier * For reasons of convenience and footprint reduction, the various postscript
22*593dc095SDavid du Colombier * source files, resources and fonts required by Ghostscript can be compiled
23*593dc095SDavid du Colombier * into the executable.
24*593dc095SDavid du Colombier *
25*593dc095SDavid du Colombier * This file takes a set of directories, and creates a compressed filesystem
26*593dc095SDavid du Colombier * image that can be compiled into the executable as static data and accessed
27*593dc095SDavid du Colombier * through the %rom% iodevice prefix
28*593dc095SDavid du Colombier */
29*593dc095SDavid du Colombier
30*593dc095SDavid du Colombier #include "stdpre.h"
31*593dc095SDavid du Colombier #include <stdio.h>
32*593dc095SDavid du Colombier #include <stdlib.h>
33*593dc095SDavid du Colombier #include <string.h>
34*593dc095SDavid du Colombier
35*593dc095SDavid du Colombier #include <zlib.h>
36*593dc095SDavid du Colombier
37*593dc095SDavid du Colombier #define ROMFS_BLOCKSIZE 4096
38*593dc095SDavid du Colombier #define ROMFS_CBUFSIZE ((int)((ROMFS_BLOCKSIZE) * 1.001) + 12)
39*593dc095SDavid du Colombier
40*593dc095SDavid du Colombier typedef struct romfs_inode_s {
41*593dc095SDavid du Colombier char *name;
42*593dc095SDavid du Colombier struct romfs_inode_s *next, *child;
43*593dc095SDavid du Colombier unsigned int blocks;
44*593dc095SDavid du Colombier unsigned long length;
45*593dc095SDavid du Colombier unsigned long offset;
46*593dc095SDavid du Colombier unsigned long data_size;
47*593dc095SDavid du Colombier unsigned char **data;
48*593dc095SDavid du Colombier unsigned int *data_lengths;
49*593dc095SDavid du Colombier } romfs_inode;
50*593dc095SDavid du Colombier
put_int32(unsigned char * p,const unsigned int q)51*593dc095SDavid du Colombier static int put_int32(unsigned char *p, const unsigned int q)
52*593dc095SDavid du Colombier {
53*593dc095SDavid du Colombier *p++ = (q >> 24) & 0xFF;
54*593dc095SDavid du Colombier *p++ = (q >> 16) & 0xFF;
55*593dc095SDavid du Colombier *p++ = (q >> 8) & 0xFF;
56*593dc095SDavid du Colombier *p++ = (q >> 0) & 0xFF;
57*593dc095SDavid du Colombier
58*593dc095SDavid du Colombier return 4;
59*593dc095SDavid du Colombier }
60*593dc095SDavid du Colombier
61*593dc095SDavid du Colombier /* clear the internal memory of an inode */
inode_clear(romfs_inode * node)62*593dc095SDavid du Colombier void inode_clear(romfs_inode* node)
63*593dc095SDavid du Colombier {
64*593dc095SDavid du Colombier int i;
65*593dc095SDavid du Colombier
66*593dc095SDavid du Colombier if (node) {
67*593dc095SDavid du Colombier if (node->data) {
68*593dc095SDavid du Colombier for (i = 0; i < node->blocks; i++) {
69*593dc095SDavid du Colombier if (node->data[i]) free(node->data[i]);
70*593dc095SDavid du Colombier }
71*593dc095SDavid du Colombier free(node->data);
72*593dc095SDavid du Colombier }
73*593dc095SDavid du Colombier if (node->data_lengths) free(node->data_lengths);
74*593dc095SDavid du Colombier if (node->name) free(node->name);
75*593dc095SDavid du Colombier }
76*593dc095SDavid du Colombier }
77*593dc095SDavid du Colombier
78*593dc095SDavid du Colombier /* write out and inode and its file data */
79*593dc095SDavid du Colombier int
inode_write(FILE * out,romfs_inode * node)80*593dc095SDavid du Colombier inode_write(FILE *out, romfs_inode *node)
81*593dc095SDavid du Colombier {
82*593dc095SDavid du Colombier int i, offset = 0;
83*593dc095SDavid du Colombier unsigned char buf[64];
84*593dc095SDavid du Colombier unsigned char *p = buf;
85*593dc095SDavid du Colombier
86*593dc095SDavid du Colombier /* 4 byte offset to next inode */
87*593dc095SDavid du Colombier p += put_int32(p, node->offset);
88*593dc095SDavid du Colombier /* 4 byte file length */
89*593dc095SDavid du Colombier p += put_int32(p, node->length);
90*593dc095SDavid du Colombier /* 4 byte path length */
91*593dc095SDavid du Colombier p += put_int32(p, strlen(node->name));
92*593dc095SDavid du Colombier
93*593dc095SDavid du Colombier printf("writing node '%s'...\n", node->name);
94*593dc095SDavid du Colombier printf(" offset %ld\n", node->offset);
95*593dc095SDavid du Colombier printf(" length %ld\n", node->length);
96*593dc095SDavid du Colombier printf(" path length %ld\n", strlen(node->name));
97*593dc095SDavid du Colombier
98*593dc095SDavid du Colombier printf(" %d compressed blocks comprising %ld bytes\n", node->blocks, node->data_size);
99*593dc095SDavid du Colombier
100*593dc095SDavid du Colombier /* write header */
101*593dc095SDavid du Colombier offset += fwrite(buf, 3, 4, out);
102*593dc095SDavid du Colombier /* write path */
103*593dc095SDavid du Colombier offset += fwrite(node->name, 1, strlen(node->name), out);
104*593dc095SDavid du Colombier /* write block sizes */
105*593dc095SDavid du Colombier offset += fwrite(node->data_lengths, node->blocks, sizeof(*node->data_lengths), out);
106*593dc095SDavid du Colombier /* write out compressed data */
107*593dc095SDavid du Colombier for (i = 0; i < node->blocks; i++)
108*593dc095SDavid du Colombier offset += fwrite(node->data[i], 1, node->data_lengths[i], out);
109*593dc095SDavid du Colombier
110*593dc095SDavid du Colombier printf(" wrote %d bytes in all\n", offset);
111*593dc095SDavid du Colombier return offset;
112*593dc095SDavid du Colombier }
113*593dc095SDavid du Colombier
114*593dc095SDavid du Colombier
115*593dc095SDavid du Colombier int
main(int argc,char * argv[])116*593dc095SDavid du Colombier main(int argc, char *argv[])
117*593dc095SDavid du Colombier {
118*593dc095SDavid du Colombier int i, ret, block;
119*593dc095SDavid du Colombier romfs_inode *node;
120*593dc095SDavid du Colombier unsigned char *ubuf, *cbuf;
121*593dc095SDavid du Colombier unsigned long ulen, clen;
122*593dc095SDavid du Colombier unsigned long offset = 0;
123*593dc095SDavid du Colombier FILE *in, *out;
124*593dc095SDavid du Colombier
125*593dc095SDavid du Colombier ubuf = malloc(ROMFS_BLOCKSIZE);
126*593dc095SDavid du Colombier cbuf = malloc(ROMFS_CBUFSIZE);
127*593dc095SDavid du Colombier
128*593dc095SDavid du Colombier printf("compressing with %d byte blocksize (zlib output buffer %d bytes)\n",
129*593dc095SDavid du Colombier ROMFS_BLOCKSIZE, ROMFS_CBUFSIZE);
130*593dc095SDavid du Colombier
131*593dc095SDavid du Colombier out = fopen("gsromfs", "wb");
132*593dc095SDavid du Colombier
133*593dc095SDavid du Colombier /* for each path on the commandline, attach an inode */
134*593dc095SDavid du Colombier for (i = 1; i < argc; i++) {
135*593dc095SDavid du Colombier node = calloc(1, sizeof(romfs_inode));
136*593dc095SDavid du Colombier /* get info for this file */
137*593dc095SDavid du Colombier node->name = strdup(argv[i]);
138*593dc095SDavid du Colombier in = fopen(node->name, "rb");
139*593dc095SDavid du Colombier fseek(in, 0, SEEK_END);
140*593dc095SDavid du Colombier node->length = ftell(in);
141*593dc095SDavid du Colombier node->blocks = (node->length - 1) / ROMFS_BLOCKSIZE + 1;
142*593dc095SDavid du Colombier node->data_lengths = calloc(node->blocks, sizeof(unsigned int));
143*593dc095SDavid du Colombier node->data = calloc(node->blocks, sizeof(unsigned char *));
144*593dc095SDavid du Colombier /* compress data here */
145*593dc095SDavid du Colombier fclose(in);
146*593dc095SDavid du Colombier in = fopen(node->name, "rb");
147*593dc095SDavid du Colombier block = 0;
148*593dc095SDavid du Colombier while (!feof(in)) {
149*593dc095SDavid du Colombier ulen = fread(ubuf, 1, ROMFS_BLOCKSIZE, in);
150*593dc095SDavid du Colombier if (!ulen) break;
151*593dc095SDavid du Colombier clen = ROMFS_CBUFSIZE;
152*593dc095SDavid du Colombier ret = compress(cbuf, &clen, ubuf, ulen);
153*593dc095SDavid du Colombier if (ret != Z_OK) {
154*593dc095SDavid du Colombier printf("error compressing data block!\n");
155*593dc095SDavid du Colombier }
156*593dc095SDavid du Colombier node->data_lengths[block] = clen;
157*593dc095SDavid du Colombier node->data[block] = malloc(clen);
158*593dc095SDavid du Colombier memcpy(node->data[block], cbuf, clen);
159*593dc095SDavid du Colombier block++;
160*593dc095SDavid du Colombier node->data_size += clen;
161*593dc095SDavid du Colombier }
162*593dc095SDavid du Colombier fclose(in);
163*593dc095SDavid du Colombier node->offset = 12 + 4 * node->blocks + node->data_size + strlen(node->name);
164*593dc095SDavid du Colombier printf("inode %d (%ld/%ld bytes) '%s'\t%ld%%\n",
165*593dc095SDavid du Colombier i, node->data_size, node->length, node->name, 100*node->data_size/node->length);
166*593dc095SDavid du Colombier /* write out data for this file */
167*593dc095SDavid du Colombier inode_write(out, node);
168*593dc095SDavid du Colombier /* clean up */
169*593dc095SDavid du Colombier inode_clear(node);
170*593dc095SDavid du Colombier free(node);
171*593dc095SDavid du Colombier }
172*593dc095SDavid du Colombier
173*593dc095SDavid du Colombier free(ubuf);
174*593dc095SDavid du Colombier
175*593dc095SDavid du Colombier fclose(out);
176*593dc095SDavid du Colombier
177*593dc095SDavid du Colombier return 0;
178*593dc095SDavid du Colombier }
179*593dc095SDavid du Colombier
180*593dc095SDavid du Colombier
181