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