Update dependencies
[nasm/avx512.git] / rdoff / rdlar.c
blobcdbd154997a671247b20fdd71d429eab75c4dd6d
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 = { 0, 0, 0, 0, 0, 0 };
40 #define _ENDIANNESS 0 /* 0 for little, 1 for big */
44 * Convert long to little endian (if we were compiled on big-endian machine)
46 static void longtolocal(long * l)
48 #if _ENDIANNESS
49 unsigned char t;
50 unsigned char * p = (unsigned char *) 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.");
74 * Print usage instructions
76 void usage(void)
78 printf("Usage: %s [-]{%s}[%s] libfile [module-name] [files]\n",
79 progname, commands, modifiers);
80 puts(" commands:\n"
81 " a - add module(s) to the library\n"
82 " d - delete module(s) from the library\n"
83 " n - create the library\n"
84 " r - replace module(s)\n"
85 " t - display contents of library\n"
86 " x - extract module(s)\n"
87 " command specific modifiers:\n"
88 " o - preserve original dates\n"
89 " u - only replace modules that are newer than library contents\n"
90 " generic modifiers:\n"
91 " c - do not warn if the library had to be created\n"
92 " f - use file name as a module name\n"
93 " v - be verbose\n"
94 " V - display version information");
99 * Print an error message and exit
101 void error_exit(int errcode, bool useperror, const char *fmt, ...)
103 va_list ap;
105 fprintf(stderr, "%s: ", progname);
106 va_start(ap, fmt);
107 vfprintf(stderr, fmt, ap);
108 va_end(ap);
109 putc('\n', stderr);
110 if (useperror) perror(progname);
111 exit(errcode);
116 * Fill in and write a header
118 void put_header(struct rdlm_hdr *hdr, FILE *libfp, char *modname)
120 int n = 0;
122 hdr->hdrsize = sizeof(*hdr);
123 if (modname) hdr->hdrsize += (n = strlen(modname) + 1);
124 if (libfp == NULL) 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'", _argv[2]);
141 if (fp2)
142 if (fputc(t, fp2) == EOF)
143 error_exit(1, FALSE, "write error");
145 return (char) t;
150 * Copy unsigned long from one file to another.
151 * Return local presentation of long.
153 long copylong(FILE *fp, FILE *fp2)
155 long l;
156 int i,t;
157 unsigned char * p = (unsigned char *) &l;
160 for (i = 0 ; i < 4; i++ ) {
161 t = fgetc(fp);
162 if (t == EOF)
163 error_exit(1, FALSE, "premature end of file in '%s'", _argv[2]);
164 if (fp2)
165 if (fputc(t, fp2) == EOF)
166 error_exit(1, FALSE, "write error");
167 *p++ = t;
169 longtolocal (&l);
170 return l;
175 * Create a new library
177 int create_library(char *libname)
179 FILE *libfp;
180 struct rdlm_hdr hdr;
182 hdr.magic = RDLAMAG;
183 hdr.hdrsize = 0;
184 hdr.date = time(NULL);
185 hdr.owner = getuid();
186 hdr.group = getgid();
187 hdr.mode = umask(022);
188 hdr.size = 0;
190 libfp = fopen(libname, "wb");
191 if (!libfp)
192 error_exit(1, TRUE, "could not open '%s'\n", libname);
194 /* Write library header */
195 put_header(&hdr, libfp, NULL);
197 fclose(libfp);
198 return TRUE;
203 * Add a module to the library
205 int add_module(FILE *libfp, const char *fname, char *modname)
207 FILE *modfp;
208 struct rdlm_hdr hdr = { RDLMMAG, 0, 0, 0, 0, 0, 0 };
209 struct stat finfo;
210 int i;
212 if (options.verbose)
213 fprintf(stderr, "adding module %s\n", modname);
215 /* Initialize some fields in the module header */
216 if (stat(fname, &finfo) < 0)
217 error_exit(1, TRUE, "could not stat '%s'", fname);
218 hdr.date = finfo.st_mtime;
219 hdr.owner = finfo.st_uid;
220 hdr.group = finfo.st_gid;
221 hdr.size = finfo.st_size;
223 modfp = fopen(fname, "rb");
224 if (!modfp)
225 error_exit(1, TRUE, "could not open '%s'", fname);
227 /* Write module header */
228 put_header(&hdr, libfp, modname);
230 /* Put the module itself */
231 while (! feof(modfp)) {
232 i = fgetc(modfp);
233 if (i == EOF) break;
234 if (fputc(i, libfp) == EOF )
235 error_exit(1, FALSE, "write error");
238 fclose(modfp);
239 return TRUE;
244 * Main
246 int main(int argc, char *argv[])
248 FILE *libfp, *tmpfp, *modfp = NULL;
249 struct stat finfo;
250 struct rdlm_hdr hdr;
251 char buf[MAXMODNAMELEN], *p = NULL;
252 char c;
253 int i;
255 progname = argv[0];
256 _argv = argv;
258 if (argc < 2) {
259 usage();
260 exit(1);
263 /* Check whether some modifiers were specified */
264 for (i = 1; i < strlen(argv[1]); i++) {
265 switch (c = argv[1][i]) {
266 case 'c':
267 options.createok = TRUE;
268 break;
269 case 'f':
270 options.usefname = TRUE;
271 break;
272 case 'l':
273 options.align = TRUE;
274 break;
275 case 'o':
276 options.odate = TRUE;
277 break;
278 case 'u':
279 options.fresh = TRUE;
280 break;
281 case 'v':
282 options.verbose++;
283 break;
284 case 'V':
285 show_version();
286 exit(0);
287 default:
288 if (strchr(commands, c) == NULL)
289 error_exit(2, FALSE, "invalid command or modifier '%c'", c);
293 if (argc < 3)
294 error_exit(2, FALSE, "missing library name");
296 /* Process the command */
297 if (argv[1][0] == '-') 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)) break;
348 if (i != sizeof(hdr) || hdr.magic != RDLMMAG)
349 error_exit(1, FALSE, "invalid module header");
350 /* Read module name */
351 i = hdr.hdrsize - sizeof(hdr);
352 if (i > sizeof(buf) ||
353 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, "extracting module %s to file %s\n",
360 buf, p);
361 modfp = fopen(p, "wb");
362 if (!modfp)
363 error_exit(1, TRUE, "could not open '%s'", p);
365 } else {
366 printf("%-40s ", buf);
367 if (options.verbose) {
368 printf("%ld bytes", hdr.size);
370 putchar('\n');
373 copybytes(libfp, modfp, hdr.size);
374 if (modfp) break;
377 fclose(libfp);
378 if (modfp)
379 fclose(modfp);
380 else if (c == 'x')
381 error_exit(1, FALSE, "module '%s' not found in '%s'",
382 argv[3], argv[2]);
383 break;
385 case 'r': /* replace module(s) */
386 argc--;
387 if (stat(argv[4], &finfo) < 0)
388 error_exit(1, TRUE, "could not stat '%s'", argv[4]);
389 case 'd': /* delete module(s) */
390 if (argc < 4)
391 error_exit(2, FALSE, "required parameter missing");
393 libfp = fopen(argv[2], "rb");
394 if (!libfp)
395 error_exit(1, TRUE, "could not open '%s'", argv[2]);
397 /* Copy the library into a temporary file */
398 tmpfp = tmpfile();
399 if (!tmpfp)
400 error_exit(1, TRUE, "could not open temporary file");
402 stat(argv[2], &finfo);
403 copybytes(libfp, tmpfp, finfo.st_size);
404 rewind(tmpfp);
405 freopen(argv[2], "wb", libfp);
407 /* Read library header and write it to a new file */
408 if (fread(&hdr, 1, sizeof(hdr), tmpfp) != sizeof(hdr) ||
409 hdr.magic != RDLAMAG)
410 error_exit(1, FALSE, "invalid library format");
411 put_header(&hdr, libfp, NULL);
413 /* Walk through the library looking for requested module */
414 while (!feof(tmpfp)) {
415 /* Read module header */
416 if (fread(&hdr, 1, sizeof(hdr), tmpfp) != sizeof(hdr) ||
417 hdr.magic != RDLMMAG)
418 error_exit(1, FALSE, "invalid module header");
419 /* Read module name */
420 i = hdr.hdrsize - sizeof(hdr);
421 if (i > sizeof(buf) ||
422 fread(buf, 1, i, tmpfp) != i)
423 error_exit(1, FALSE, "invalid module name");
424 /* Check against desired name */
425 if (!strcmp(buf, argv[3]) &&
426 (c == 'd' || !options.odate || finfo.st_mtime <= hdr.date)) {
427 if (options.verbose)
428 fprintf(stderr, "deleting module %s\n", buf);
429 fseek(tmpfp, hdr.size, SEEK_CUR);
430 break;
431 } else {
432 put_header(&hdr, libfp, buf);
433 copybytes(tmpfp, libfp, hdr.size);
437 if (c == 'r') {
438 /* Copy new module into library */
439 p = options.usefname ? argv[4] : argv[3];
440 add_module(libfp, argv[4], p);
443 /* Copy rest of library if any */
444 while (!feof(tmpfp)) {
445 if ((i = fgetc(tmpfp)) == EOF)
446 break;
448 if (fputc(i, libfp) == EOF)
449 error_exit(1, FALSE, "write error");
452 fclose(libfp);
453 fclose(tmpfp);
454 break;
456 default:
457 error_exit(2, FALSE, "invalid command '%c'\n", c);
460 return 0;