Fixed distinction between char and int8_t data types.
[nasm.git] / rdoff / rdlar.c
blob07a2a16ea00d82407ea1fa03161fb72253d0731e
1 /*
2 * rdlar.c - new librarian/archiver for RDOFF2.
3 * Copyright (c) 2002 RET & COM Research.
4 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <ctype.h>
9 #include <stdarg.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <errno.h>
13 #include <time.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
17 #include "rdlar.h"
19 #define PROGRAM_VERSION "0.1"
21 /** Types **/
22 typedef enum { FALSE, TRUE } bool;
24 /** Constants **/
25 const char commands[] = "adnrtx";
26 const char modifiers[] = "cflouvV";
28 /** Global variables **/
29 char *progname = "rdlar";
30 char **_argv = NULL;
31 struct {
32 bool createok;
33 bool usefname;
34 bool align;
35 bool odate;
36 bool fresh;
37 int verbose;
38 } options = {
39 0, 0, 0, 0, 0, 0};
41 #define _ENDIANNESS 0 /* 0 for little, 1 for big */
44 * Convert int32_t to little endian (if we were compiled on big-endian machine)
46 static void int32_ttolocal(int32_t *l)
48 #if _ENDIANNESS
49 uint8_t t;
50 uint8_t *p = (uint8_t *)l;
52 t = p[0];
53 p[0] = p[3];
54 p[3] = t;
55 t = p[1];
56 p[1] = p[2];
57 p[2] = p[1];
58 #endif
62 * Print version information
64 void show_version(void)
66 puts("New RDOFF2 librarian/archiver, version " PROGRAM_VERSION "\n"
67 "Copyright (c) 2002 RET & COM Research.\n"
68 "This program is free software and distributed under GPL (version 2 or later);\n"
69 "see http://www.gnu.org/copyleft/gpl.html for details.");
73 * Print usage instructions
75 void usage(void)
77 printf("Usage: %s [-]{%s}[%s] libfile [module-name] [files]\n",
78 progname, commands, modifiers);
79 puts(" commands:\n"
80 " a - add module(s) to the library\n"
81 " d - delete module(s) from the library\n"
82 " n - create the library\n"
83 " r - replace module(s)\n"
84 " t - display contents of library\n"
85 " x - extract module(s)\n"
86 " command specific modifiers:\n"
87 " o - preserve original dates\n"
88 " u - only replace modules that are newer than library contents\n"
89 " generic modifiers:\n"
90 " c - do not warn if the library had to be created\n"
91 " f - use file name as a module name\n"
92 " v - be verbose\n"
93 " V - display version information");
97 * Print an error message and exit
99 void error_exit(int errcode, bool useperror, const char *fmt, ...)
101 va_list ap;
103 fprintf(stderr, "%s: ", progname);
104 va_start(ap, fmt);
105 vfprintf(stderr, fmt, ap);
106 va_end(ap);
107 putc('\n', stderr);
108 if (useperror)
109 perror(progname);
110 exit(errcode);
114 * Fill in and write a header
116 void put_header(struct rdlm_hdr *hdr, FILE * libfp, char *modname)
118 int n = 0;
120 hdr->hdrsize = sizeof(*hdr);
121 if (modname)
122 hdr->hdrsize += (n = strlen(modname) + 1);
123 if (libfp == NULL)
124 return;
125 if (fwrite(hdr, 1, sizeof(*hdr), libfp) != sizeof(*hdr) ||
126 (modname && (fwrite(modname, 1, n, libfp) != n)))
127 error_exit(3, TRUE, "could not write header");
131 * Copy n bytes from one file to another and return last character read.
133 char copybytes(FILE * fp, FILE * fp2, int n)
135 int i, t = 0;
137 for (i = 0; i < n; i++) {
138 t = fgetc(fp);
139 if (t == EOF)
140 error_exit(1, FALSE, "premature end of file in '%s'",
141 _argv[2]);
142 if (fp2)
143 if (fputc(t, fp2) == EOF)
144 error_exit(1, FALSE, "write error");
146 return (char)t;
150 * Copy uint32_t from one file to another.
151 * Return local presentation of int32_t.
153 int32_t copyint32_t(FILE * fp, FILE * fp2)
155 int32_t l;
156 int i, t;
157 uint8_t *p = (uint8_t *)&l;
159 for (i = 0; i < 4; i++) {
160 t = fgetc(fp);
161 if (t == EOF)
162 error_exit(1, FALSE, "premature end of file in '%s'",
163 _argv[2]);
164 if (fp2)
165 if (fputc(t, fp2) == EOF)
166 error_exit(1, FALSE, "write error");
167 *p++ = t;
169 int32_ttolocal(&l);
170 return l;
174 * Create a new library
176 int create_library(char *libname)
178 FILE *libfp;
179 struct rdlm_hdr hdr;
181 hdr.magic = RDLAMAG;
182 hdr.hdrsize = 0;
183 hdr.date = time(NULL);
184 hdr.owner = getuid();
185 hdr.group = getgid();
186 hdr.mode = umask(022);
187 hdr.size = 0;
189 libfp = fopen(libname, "wb");
190 if (!libfp)
191 error_exit(1, TRUE, "could not open '%s'\n", libname);
193 /* Write library header */
194 put_header(&hdr, libfp, NULL);
196 fclose(libfp);
197 return TRUE;
201 * Add a module to the library
203 int add_module(FILE * libfp, const char *fname, char *modname)
205 FILE *modfp;
206 struct rdlm_hdr hdr = { RDLMMAG, 0, 0, 0, 0, 0, 0 };
207 struct stat finfo;
208 int i;
210 if (options.verbose)
211 fprintf(stderr, "adding module %s\n", modname);
213 /* Initialize some fields in the module header */
214 if (stat(fname, &finfo) < 0)
215 error_exit(1, TRUE, "could not stat '%s'", fname);
216 hdr.date = finfo.st_mtime;
217 hdr.owner = finfo.st_uid;
218 hdr.group = finfo.st_gid;
219 hdr.size = finfo.st_size;
221 modfp = fopen(fname, "rb");
222 if (!modfp)
223 error_exit(1, TRUE, "could not open '%s'", fname);
225 /* Write module header */
226 put_header(&hdr, libfp, modname);
228 /* Put the module itself */
229 while (!feof(modfp)) {
230 i = fgetc(modfp);
231 if (i == EOF)
232 break;
233 if (fputc(i, libfp) == EOF)
234 error_exit(1, FALSE, "write error");
237 fclose(modfp);
238 return TRUE;
242 * Main
244 int main(int argc, char **argv)
246 FILE *libfp, *tmpfp, *modfp = NULL;
247 struct stat finfo;
248 struct rdlm_hdr hdr;
249 char buf[MAXMODNAMELEN], *p = NULL;
250 char c;
251 int i;
253 progname = argv[0];
254 _argv = argv;
256 if (argc < 2) {
257 usage();
258 exit(1);
261 /* Check whether some modifiers were specified */
262 for (i = 1; i < strlen(argv[1]); i++) {
263 switch (c = argv[1][i]) {
264 case 'c':
265 options.createok = TRUE;
266 break;
267 case 'f':
268 options.usefname = TRUE;
269 break;
270 case 'l':
271 options.align = TRUE;
272 break;
273 case 'o':
274 options.odate = TRUE;
275 break;
276 case 'u':
277 options.fresh = TRUE;
278 break;
279 case 'v':
280 options.verbose++;
281 break;
282 case 'V':
283 show_version();
284 exit(0);
285 default:
286 if (strchr(commands, c) == NULL)
287 error_exit(2, FALSE, "invalid command or modifier '%c'",
292 if (argc < 3)
293 error_exit(2, FALSE, "missing library name");
295 /* Process the command */
296 if (argv[1][0] == '-')
297 argv[1]++;
298 switch (c = argv[1][0]) {
299 case 'a': /* add a module */
300 if (argc < 4 || (!options.usefname && argc != 5))
301 error_exit(2, FALSE, "invalid number of arguments");
303 /* Check if a library already exists. If not - create it */
304 if (access(argv[2], F_OK) < 0) {
305 if (!options.createok)
306 fprintf(stderr, "creating library %s\n", argv[2]);
307 create_library(argv[2]);
310 libfp = fopen(argv[2], "ab");
311 if (!libfp)
312 error_exit(1, TRUE, "could not open '%s'", argv[2]);
314 if (!options.usefname)
315 add_module(libfp, argv[4], argv[3]);
316 else
317 for (i = 3; i < argc; i++)
318 add_module(libfp, argv[i], argv[i]);
320 fclose(libfp);
321 break;
323 case 'n': /* create library */
324 create_library(argv[2]);
325 break;
327 case 'x': /* extract module(s) */
328 if (!options.usefname)
329 argc--;
330 if (argc < 4)
331 error_exit(2, FALSE, "required parameter missing");
332 p = options.usefname ? argv[3] : argv[4];
333 case 't': /* list library contents */
334 libfp = fopen(argv[2], "rb");
335 if (!libfp)
336 error_exit(1, TRUE, "could not open '%s'\n", argv[2]);
338 /* Read library header */
339 if (fread(&hdr, 1, sizeof(hdr), libfp) != sizeof(hdr) ||
340 hdr.magic != RDLAMAG)
341 error_exit(1, FALSE, "invalid library format");
343 /* Walk through the library looking for requested module */
344 while (!feof(libfp)) {
345 /* Read module header */
346 i = fread(&hdr, 1, sizeof(hdr), libfp);
347 if (feof(libfp))
348 break;
349 if (i != sizeof(hdr) || hdr.magic != RDLMMAG)
350 error_exit(1, FALSE, "invalid module header");
351 /* Read module name */
352 i = hdr.hdrsize - sizeof(hdr);
353 if (i > sizeof(buf) || fread(buf, 1, i, libfp) != i)
354 error_exit(1, FALSE, "invalid module name");
355 if (c == 'x') {
356 /* Check against desired name */
357 if (!strcmp(buf, argv[3])) {
358 if (options.verbose)
359 fprintf(stderr,
360 "extracting module %s to file %s\n", buf,
362 modfp = fopen(p, "wb");
363 if (!modfp)
364 error_exit(1, TRUE, "could not open '%s'", p);
366 } else {
367 printf("%-40s ", buf);
368 if (options.verbose) {
369 printf("%ld bytes", hdr.size);
371 putchar('\n');
374 copybytes(libfp, modfp, hdr.size);
375 if (modfp)
376 break;
379 fclose(libfp);
380 if (modfp)
381 fclose(modfp);
382 else if (c == 'x')
383 error_exit(1, FALSE, "module '%s' not found in '%s'",
384 argv[3], argv[2]);
385 break;
387 case 'r': /* replace module(s) */
388 argc--;
389 if (stat(argv[4], &finfo) < 0)
390 error_exit(1, TRUE, "could not stat '%s'", argv[4]);
391 case 'd': /* delete module(s) */
392 if (argc < 4)
393 error_exit(2, FALSE, "required parameter missing");
395 libfp = fopen(argv[2], "rb");
396 if (!libfp)
397 error_exit(1, TRUE, "could not open '%s'", argv[2]);
399 /* Copy the library into a temporary file */
400 tmpfp = tmpfile();
401 if (!tmpfp)
402 error_exit(1, TRUE, "could not open temporary file");
404 stat(argv[2], &finfo);
405 copybytes(libfp, tmpfp, finfo.st_size);
406 rewind(tmpfp);
407 freopen(argv[2], "wb", libfp);
409 /* Read library header and write it to a new file */
410 if (fread(&hdr, 1, sizeof(hdr), tmpfp) != sizeof(hdr) ||
411 hdr.magic != RDLAMAG)
412 error_exit(1, FALSE, "invalid library format");
413 put_header(&hdr, libfp, NULL);
415 /* Walk through the library looking for requested module */
416 while (!feof(tmpfp)) {
417 /* Read module header */
418 if (fread(&hdr, 1, sizeof(hdr), tmpfp) != sizeof(hdr) ||
419 hdr.magic != RDLMMAG)
420 error_exit(1, FALSE, "invalid module header");
421 /* Read module name */
422 i = hdr.hdrsize - sizeof(hdr);
423 if (i > sizeof(buf) || fread(buf, 1, i, tmpfp) != i)
424 error_exit(1, FALSE, "invalid module name");
425 /* Check against desired name */
426 if (!strcmp(buf, argv[3]) &&
427 (c == 'd' || !options.odate
428 || finfo.st_mtime <= hdr.date)) {
429 if (options.verbose)
430 fprintf(stderr, "deleting module %s\n", buf);
431 fseek(tmpfp, hdr.size, SEEK_CUR);
432 break;
433 } else {
434 put_header(&hdr, libfp, buf);
435 copybytes(tmpfp, libfp, hdr.size);
439 if (c == 'r') {
440 /* Copy new module into library */
441 p = options.usefname ? argv[4] : argv[3];
442 add_module(libfp, argv[4], p);
445 /* Copy rest of library if any */
446 while (!feof(tmpfp)) {
447 if ((i = fgetc(tmpfp)) == EOF)
448 break;
450 if (fputc(i, libfp) == EOF)
451 error_exit(1, FALSE, "write error");
454 fclose(libfp);
455 fclose(tmpfp);
456 break;
458 default:
459 error_exit(2, FALSE, "invalid command '%c'\n", c);
462 return 0;