blob: a1c3abe7fbec8bc48d00912ceec6a201570b091e [file] [log] [blame]
H. Peter Anvinc8578ce2009-06-28 17:33:50 -07001/* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2009 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * ----------------------------------------------------------------------- */
33
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000034/* rdflib - manipulate RDOFF library files (.rdl) */
35
H. Peter Anvin41bf8002002-04-30 20:58:18 +000036/*
37 * an rdoff library is simply a sequence of RDOFF object files, each
38 * preceded by the name of the module, an ASCII string of up to 255
Keith Kaniosa6dfa782007-04-13 16:47:53 +000039 * characters, terminated by a zero.
H. Peter Anvin27cf5032002-05-04 05:42:30 +000040 *
41 * When a library is being created, special signature block is placed
42 * in the beginning of the file. It is a string 'RDLIB' followed by a
Keith Kaniosb7a89542007-04-12 02:40:54 +000043 * version number, then int32_t content size and a int32_t time stamp.
H. Peter Anvin27cf5032002-05-04 05:42:30 +000044 * The module name of the signature block is '.sig'.
45 *
H. Peter Anvin41bf8002002-04-30 20:58:18 +000046 *
H. Peter Anvin225c5922002-04-30 21:06:16 +000047 * There may be an optional directory placed on the end of the file.
48 * The format of the directory will be 'RDLDD' followed by a version
49 * number, followed by the length of the directory, and then the
50 * directory, the format of which has not yet been designed.
H. Peter Anvin70653092007-10-19 14:42:29 -070051 * The module name of the directory must be '.dir'.
H. Peter Anvin41bf8002002-04-30 20:58:18 +000052 *
H. Peter Anvin27cf5032002-05-04 05:42:30 +000053 * All module names beginning with '.' are reserved for possible future
54 * extensions. The linker ignores all such modules, assuming they have
H. Peter Anvin038d8612007-04-12 16:54:50 +000055 * the format of a six uint8_t type & version identifier followed by int32_t
H. Peter Anvin27cf5032002-05-04 05:42:30 +000056 * content size, followed by data.
H. Peter Anvin41bf8002002-04-30 20:58:18 +000057 */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000058
H. Peter Anvinfe501952007-10-02 21:53:51 -070059#include "compiler.h"
60
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000061#include <stdio.h>
H. Peter Anvinfa969e52002-12-05 19:33:20 +000062#include <stdlib.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000063#include <errno.h>
64#include <string.h>
H. Peter Anvin27cf5032002-05-04 05:42:30 +000065#include <time.h>
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000066
67/* functions supported:
H. Peter Anvin225c5922002-04-30 21:06:16 +000068 * create a library (no extra operands required)
69 * add a module from a library (requires filename and name to give mod.)
70 * replace a module in a library (requires given name and filename)
71 * delete a module from a library (requires given name)
72 * extract a module from the library (requires given name and filename)
73 * list modules
74 */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000075
H. Peter Anvin038d8612007-04-12 16:54:50 +000076const char *usage =
H. Peter Anvine2c80182005-01-15 22:15:51 +000077 "usage:\n"
78 " rdflib x libname [extra operands]\n\n"
79 " where x is one of:\n"
80 " c - create library\n"
81 " a - add module (operands = filename module-name)\n"
82 " x - extract (module-name filename)\n"
83 " r - replace (module-name filename)\n"
84 " d - delete (module-name)\n" " t - list\n";
85
H. Peter Anvin27cf5032002-05-04 05:42:30 +000086/* Library signature */
Keith Kaniosa6dfa782007-04-13 16:47:53 +000087const char *rdl_signature = "RDLIB2", *sig_modname = ".sig";
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000088
Keith Kanios82e15cd2007-04-12 16:23:11 +000089char **_argv;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000090
H. Peter Anvine2c80182005-01-15 22:15:51 +000091#define _ENDIANNESS 0 /* 0 for little, 1 for big */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000092
Keith Kaniosb7a89542007-04-12 02:40:54 +000093static void int32_ttolocal(int32_t *l)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000094{
95#if _ENDIANNESS
Keith Kaniosb7a89542007-04-12 02:40:54 +000096 uint8_t t;
97 uint8_t *p = (uint8_t *)l;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +000098
99 t = p[0];
100 p[0] = p[3];
101 p[3] = t;
102 t = p[1];
103 p[1] = p[2];
104 p[2] = p[1];
Keith Kanios47776ac2007-04-14 01:24:14 +0000105#else
106 (void)l; /* placate optimizers */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000107#endif
108}
109
H. Peter Anvin48166382014-11-25 12:34:03 -0800110static char copybytes(FILE * fp, FILE * fp2, int n)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000111{
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000112 int i, t = 0;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000113
H. Peter Anvine2c80182005-01-15 22:15:51 +0000114 for (i = 0; i < n; i++) {
115 t = fgetc(fp);
116 if (t == EOF) {
117 fprintf(stderr, "rdflib: premature end of file in '%s'\n",
118 _argv[2]);
119 exit(1);
120 }
121 if (fp2)
122 if (fputc(t, fp2) == EOF) {
123 fprintf(stderr, "rdflib: write error\n");
124 exit(1);
125 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000126 }
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000127 return (char)t; /* return last char read */
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000128}
129
H. Peter Anvin48166382014-11-25 12:34:03 -0800130static int32_t copyint32_t(FILE * fp, FILE * fp2)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000131{
Keith Kaniosb7a89542007-04-12 02:40:54 +0000132 int32_t l;
H. Peter Anvine2c80182005-01-15 22:15:51 +0000133 int i, t;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000134 uint8_t *p = (uint8_t *)&l;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000135
H. Peter Anvine2c80182005-01-15 22:15:51 +0000136 for (i = 0; i < 4; i++) { /* skip magic no */
137 t = fgetc(fp);
138 if (t == EOF) {
139 fprintf(stderr, "rdflib: premature end of file in '%s'\n",
140 _argv[2]);
141 exit(1);
142 }
143 if (fp2)
144 if (fputc(t, fp2) == EOF) {
145 fprintf(stderr, "rdflib: write error\n");
146 exit(1);
147 }
148 *p++ = t;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000149 }
Keith Kaniosb7a89542007-04-12 02:40:54 +0000150 int32_ttolocal(&l);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000151 return l;
152}
153
Keith Kanios82e15cd2007-04-12 16:23:11 +0000154int main(int argc, char **argv)
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000155{
H. Peter Anvin27cf5032002-05-04 05:42:30 +0000156 FILE *fp, *fp2 = NULL, *fptmp;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000157 char *p, buf[256], c;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000158 int i;
Keith Kaniosb7a89542007-04-12 02:40:54 +0000159 int32_t l;
H. Peter Anvin27cf5032002-05-04 05:42:30 +0000160 time_t t;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000161 char rdbuf[10];
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000162
163 _argv = argv;
164
H. Peter Anvine2c80182005-01-15 22:15:51 +0000165 if (argc < 3 || !strncmp(argv[1], "-h", 2)
166 || !strncmp(argv[1], "--h", 3)) {
Victor van den Elzen0dd450c2009-08-13 15:07:59 +0200167 fputs(usage, stdout);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000168 exit(1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000169 }
170
H. Peter Anvine2c80182005-01-15 22:15:51 +0000171 switch (argv[1][0]) {
172 case 'c': /* create library */
173 fp = fopen(argv[2], "wb");
174 if (!fp) {
175 fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
176 perror("rdflib");
177 exit(1);
178 }
179 fwrite(sig_modname, 1, strlen(sig_modname) + 1, fp);
180 fwrite(rdl_signature, 1, strlen(rdl_signature), fp);
H. Peter Anvin2bc798a2016-02-12 21:21:57 -0800181 t = time(NULL);
182 l = sizeof(t);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000183 fwrite(&l, sizeof(l), 1, fp);
184 fwrite(&t, 1, l, fp);
185 fclose(fp);
186 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000187
H. Peter Anvine2c80182005-01-15 22:15:51 +0000188 case 'a': /* add module */
189 if (argc < 5) {
190 fprintf(stderr, "rdflib: required parameter missing\n");
191 exit(1);
192 }
193 fp = fopen(argv[2], "ab");
194 if (!fp) {
195 fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
196 perror("rdflib");
197 exit(1);
198 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000199
H. Peter Anvine2c80182005-01-15 22:15:51 +0000200 fp2 = fopen(argv[3], "rb");
201 if (!fp2) {
202 fprintf(stderr, "rdflib: could not open '%s'\n", argv[3]);
203 perror("rdflib");
204 exit(1);
205 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000206
H. Peter Anvine2c80182005-01-15 22:15:51 +0000207 p = argv[4];
208 do {
209 if (fputc(*p, fp) == EOF) {
210 fprintf(stderr, "rdflib: write error\n");
211 exit(1);
212 }
213 } while (*p++);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000214
H. Peter Anvine2c80182005-01-15 22:15:51 +0000215 while (!feof(fp2)) {
216 i = fgetc(fp2);
217 if (i == EOF) {
218 break;
219 }
220
221 if (fputc(i, fp) == EOF) {
222 fprintf(stderr, "rdflib: write error\n");
223 exit(1);
224 }
225 }
226 fclose(fp2);
227 fclose(fp);
228 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000229
230 case 'x':
H. Peter Anvine2c80182005-01-15 22:15:51 +0000231 if (argc < 5) {
232 fprintf(stderr, "rdflib: required parameter missing\n");
233 exit(1);
234 }
H. Peter Anvin225c5922002-04-30 21:06:16 +0000235 case 't':
H. Peter Anvine2c80182005-01-15 22:15:51 +0000236 fp = fopen(argv[2], "rb");
237 if (!fp) {
238 fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
239 perror("rdflib");
240 exit(1);
241 }
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000242
H. Peter Anvine2c80182005-01-15 22:15:51 +0000243 fp2 = NULL;
244 while (!feof(fp)) {
245 /* read name */
246 p = buf;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000247 while ((*(p++) = (char)fgetc(fp)))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000248 if (feof(fp))
249 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000250
H. Peter Anvine2c80182005-01-15 22:15:51 +0000251 if (feof(fp))
252 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000253
H. Peter Anvine2c80182005-01-15 22:15:51 +0000254 fp2 = NULL;
255 if (argv[1][0] == 'x') {
256 /* check against desired name */
257 if (!strcmp(buf, argv[3])) {
258 fp2 = fopen(argv[4], "wb");
259 if (!fp2) {
260 fprintf(stderr, "rdflib: could not open '%s'\n",
261 argv[4]);
262 perror("rdflib");
263 exit(1);
264 }
265 }
266 } else
267 printf("%-40s ", buf);
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000268
H. Peter Anvine2c80182005-01-15 22:15:51 +0000269 /* step over the RDOFF file, extracting type information for
270 * the listing, and copying it if fp2 != NULL */
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000271
H. Peter Anvine2c80182005-01-15 22:15:51 +0000272 if (buf[0] == '.') {
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000273
H. Peter Anvine2c80182005-01-15 22:15:51 +0000274 if (argv[1][0] == 't')
275 for (i = 0; i < 6; i++)
276 printf("%c", copybytes(fp, fp2, 1));
277 else
278 copybytes(fp, fp2, 6);
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000279
Keith Kaniosb7a89542007-04-12 02:40:54 +0000280 l = copyint32_t(fp, fp2);
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000281
H. Peter Anvine2c80182005-01-15 22:15:51 +0000282 if (argv[1][0] == 't')
Keith Kanios47776ac2007-04-14 01:24:14 +0000283 printf(" %"PRId32" bytes content\n", l);
H. Peter Anvin41bf8002002-04-30 20:58:18 +0000284
H. Peter Anvine2c80182005-01-15 22:15:51 +0000285 copybytes(fp, fp2, l);
286 } else if ((c = copybytes(fp, fp2, 6)) >= '2') { /* version 2 or above */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000287 l = copyint32_t(fp, fp2);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000288
H. Peter Anvine2c80182005-01-15 22:15:51 +0000289 if (argv[1][0] == 't')
Keith Kanios47776ac2007-04-14 01:24:14 +0000290 printf("RDOFF%c %"PRId32" bytes content\n", c, l);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000291 copybytes(fp, fp2, l); /* entire object */
292 } else {
293 if (argv[1][0] == 't')
294 printf("RDOFF1\n");
295 /*
296 * version 1 object, so we don't have an object content
297 * length field.
298 */
Keith Kaniosb7a89542007-04-12 02:40:54 +0000299 copybytes(fp, fp2, copyint32_t(fp, fp2)); /* header */
300 copybytes(fp, fp2, copyint32_t(fp, fp2)); /* text */
301 copybytes(fp, fp2, copyint32_t(fp, fp2)); /* data */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000302 }
H. Peter Anvin225c5922002-04-30 21:06:16 +0000303
H. Peter Anvine2c80182005-01-15 22:15:51 +0000304 if (fp2)
305 break;
306 }
307 fclose(fp);
308 if (fp2)
309 fclose(fp2);
310 else if (argv[1][0] == 'x') {
311 fprintf(stderr, "rdflib: module '%s' not found in '%s'\n",
312 argv[3], argv[2]);
313 exit(1);
314 }
315 break;
H. Peter Anvin225c5922002-04-30 21:06:16 +0000316
H. Peter Anvine2c80182005-01-15 22:15:51 +0000317 case 'r': /* replace module */
318 argc--;
319 case 'd': /* delete module */
320 if (argc < 4) {
321 fprintf(stderr, "rdflib: required parameter missing\n");
322 exit(1);
323 }
H. Peter Anvin225c5922002-04-30 21:06:16 +0000324
H. Peter Anvine2c80182005-01-15 22:15:51 +0000325 fp = fopen(argv[2], "rb");
326 if (!fp) {
327 fprintf(stderr, "rdflib: could not open '%s'\n", argv[2]);
328 perror("rdflib");
329 exit(1);
330 }
331
332 if (argv[1][0] == 'r') {
333 fp2 = fopen(argv[4], "rb");
334 if (!fp2) {
335 fprintf(stderr, "rdflib: could not open '%s'\n", argv[4]);
336 perror("rdflib");
337 exit(1);
338 }
339 }
340
341 fptmp = tmpfile();
342 if (!fptmp) {
343 fprintf(stderr, "rdflib: could not open temporary file\n");
344 perror("rdflib");
345 exit(1);
346 }
347
348 /* copy library into temporary file */
349 fseek(fp, 0, SEEK_END); /* get file length */
350 l = ftell(fp);
351 fseek(fp, 0, SEEK_SET);
352 copybytes(fp, fptmp, l);
353 rewind(fptmp);
Martin Lindhea6ccf002016-11-17 10:28:58 +0100354 if (freopen(argv[2], "wb", fp) == NULL) {
355 fprintf(stderr, "rdflib: could not reopen '%s'\n", argv[2]);
356 perror("rdflib");
357 exit(1);
358 }
H. Peter Anvine2c80182005-01-15 22:15:51 +0000359
360 while (!feof(fptmp)) {
361 /* read name */
362 p = buf;
Keith Kaniosa6dfa782007-04-13 16:47:53 +0000363 while ((*(p++) = (char)fgetc(fptmp)))
H. Peter Anvine2c80182005-01-15 22:15:51 +0000364 if (feof(fptmp))
365 break;
366
367 if (feof(fptmp))
368 break;
369
370 /* check against desired name */
371 if (!strcmp(buf, argv[3])) {
372 fread(p = rdbuf, 1, sizeof(rdbuf), fptmp);
Keith Kaniosb7a89542007-04-12 02:40:54 +0000373 l = *(int32_t *)(p + 6);
H. Peter Anvine2c80182005-01-15 22:15:51 +0000374 fseek(fptmp, l, SEEK_CUR);
375 break;
376 } else {
377 fwrite(buf, 1, strlen(buf) + 1, fp); /* module name */
378 if ((c = copybytes(fptmp, fp, 6)) >= '2') {
Keith Kaniosb7a89542007-04-12 02:40:54 +0000379 l = copyint32_t(fptmp, fp); /* version 2 or above */
H. Peter Anvine2c80182005-01-15 22:15:51 +0000380 copybytes(fptmp, fp, l); /* entire object */
381 }
382 }
383 }
384
385 if (argv[1][0] == 'r') {
386 /* copy new module into library */
387 p = argv[3];
388 do {
389 if (fputc(*p, fp) == EOF) {
390 fprintf(stderr, "rdflib: write error\n");
391 exit(1);
392 }
393 } while (*p++);
394
395 while (!feof(fp2)) {
396 i = fgetc(fp2);
397 if (i == EOF) {
398 break;
399 }
400 if (fputc(i, fp) == EOF) {
401 fprintf(stderr, "rdflib: write error\n");
402 exit(1);
403 }
404 }
405 fclose(fp2);
406 }
407
408 /* copy rest of library if any */
409 while (!feof(fptmp)) {
410 i = fgetc(fptmp);
411 if (i == EOF) {
412 break;
413 }
414
415 if (fputc(i, fp) == EOF) {
416 fprintf(stderr, "rdflib: write error\n");
417 exit(1);
418 }
419 }
420
421 fclose(fp);
422 fclose(fptmp);
423 break;
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000424
425 default:
H. Peter Anvine2c80182005-01-15 22:15:51 +0000426 fprintf(stderr, "rdflib: command '%c' not recognized\n",
427 argv[1][0]);
428 exit(1);
H. Peter Anvind7ed89e2002-04-30 20:52:08 +0000429 }
430 return 0;
431}