xref: /plan9-contrib/sys/src/cmd/gs/src/mkromfs.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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