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