phash.ph: yet another attempt at getting Perl to behave, arithmetically
[nasm/avx512.git] / rdoff / rdlar.c
blobdf813d12e7884308362d5d5e1654ce9f2b7c87b3
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 <errno.h>
12 #include <time.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
16 #include "rdlar.h"
18 #define PROGRAM_VERSION "0.1"
20 /** Types **/
21 typedef enum { FALSE, TRUE } bool;
23 /** Constants **/
24 const char commands[] = "adnrtx";
25 const char modifiers[] = "cflouvV";
27 /** Global variables **/
28 char *progname = "rdlar";
29 char **_argv = NULL;
30 struct {
31 bool createok;
32 bool usefname;
33 bool align;
34 bool odate;
35 bool fresh;
36 int verbose;
37 } options = {
38 0, 0, 0, 0, 0, 0};
40 #define _ENDIANNESS 0 /* 0 for little, 1 for big */
43 * Convert int32_t to little endian (if we were compiled on big-endian machine)
45 static void int32_ttolocal(int32_t *l)
47 #if _ENDIANNESS
48 uint8_t t;
49 uint8_t *p = (uint8_t *)l;
51 t = p[0];
52 p[0] = p[3];
53 p[3] = t;
54 t = p[1];
55 p[1] = p[2];
56 p[2] = p[1];
57 #endif
61 * Print version information
63 void show_version(void)
65 puts("New RDOFF2 librarian/archiver, version " PROGRAM_VERSION "\n"
66 "Copyright (c) 2002 RET & COM Research.\n"
67 "This program is free software and distributed under GPL (version 2 or later);\n"
68 "see http://www.gnu.org/copyleft/gpl.html for details.");
72 * Print usage instructions
74 void usage(void)
76 printf("Usage: %s [-]{%s}[%s] libfile [module-name] [files]\n",
77 progname, commands, modifiers);
78 puts(" commands:\n"
79 " a - add module(s) to the library\n"
80 " d - delete module(s) from the library\n"
81 " n - create the library\n"
82 " r - replace module(s)\n"
83 " t - display contents of library\n"
84 " x - extract module(s)\n"
85 " command specific modifiers:\n"
86 " o - preserve original dates\n"
87 " u - only replace modules that are newer than library contents\n"
88 " generic modifiers:\n"
89 " c - do not warn if the library had to be created\n"
90 " f - use file name as a module name\n"
91 " v - be verbose\n"
92 " V - display version information");
96 * Print an error message and exit
98 void error_exit(int errcode, bool useperror, const char *fmt, ...)
100 va_list ap;
102 fprintf(stderr, "%s: ", progname);
103 va_start(ap, fmt);
104 vfprintf(stderr, fmt, ap);
105 va_end(ap);
106 putc('\n', stderr);
107 if (useperror)
108 perror(progname);
109 exit(errcode);
113 * Fill in and write a header
115 void put_header(struct rdlm_hdr *hdr, FILE * libfp, char *modname)
117 int n = 0;
119 hdr->hdrsize = sizeof(*hdr);
120 if (modname)
121 hdr->hdrsize += (n = strlen(modname) + 1);
122 if (libfp == NULL)
123 return;
124 if (fwrite(hdr, 1, sizeof(*hdr), libfp) != sizeof(*hdr) ||
125 (modname && (fwrite(modname, 1, n, libfp) != n)))
126 error_exit(3, TRUE, "could not write header");
130 * Copy n bytes from one file to another and return last character read.
132 char copybytes(FILE * fp, FILE * fp2, int n)
134 int i, t = 0;
136 for (i = 0; i < n; i++) {
137 t = fgetc(fp);
138 if (t == EOF)
139 error_exit(1, FALSE, "premature end of file in '%s'",
140 _argv[2]);
141 if (fp2)
142 if (fputc(t, fp2) == EOF)
143 error_exit(1, FALSE, "write error");
145 return (char)t;
149 * Copy uint32_t from one file to another.
150 * Return local presentation of int32_t.
152 int32_t copyint32_t(FILE * fp, FILE * fp2)
154 int32_t l;
155 int i, t;
156 uint8_t *p = (uint8_t *)&l;
158 for (i = 0; i < 4; i++) {
159 t = fgetc(fp);
160 if (t == EOF)
161 error_exit(1, FALSE, "premature end of file in '%s'",
162 _argv[2]);
163 if (fp2)
164 if (fputc(t, fp2) == EOF)
165 error_exit(1, FALSE, "write error");
166 *p++ = t;
168 int32_ttolocal(&l);
169 return l;
173 * Create a new library
175 int create_library(char *libname)
177 FILE *libfp;
178 struct rdlm_hdr hdr;
180 hdr.magic = RDLAMAG;
181 hdr.hdrsize = 0;
182 hdr.date = time(NULL);
183 hdr.owner = getuid();
184 hdr.group = getgid();
185 hdr.mode = umask(022);
186 hdr.size = 0;
188 libfp = fopen(libname, "wb");
189 if (!libfp)
190 error_exit(1, TRUE, "could not open '%s'\n", libname);
192 /* Write library header */
193 put_header(&hdr, libfp, NULL);
195 fclose(libfp);
196 return TRUE;
200 * Add a module to the library
202 int add_module(FILE * libfp, const char *fname, char *modname)
204 FILE *modfp;
205 struct rdlm_hdr hdr = { RDLMMAG, 0, 0, 0, 0, 0, 0 };
206 struct stat finfo;
207 int i;
209 if (options.verbose)
210 fprintf(stderr, "adding module %s\n", modname);
212 /* Initialize some fields in the module header */
213 if (stat(fname, &finfo) < 0)
214 error_exit(1, TRUE, "could not stat '%s'", fname);
215 hdr.date = finfo.st_mtime;
216 hdr.owner = finfo.st_uid;
217 hdr.group = finfo.st_gid;
218 hdr.size = finfo.st_size;
220 modfp = fopen(fname, "rb");
221 if (!modfp)
222 error_exit(1, TRUE, "could not open '%s'", fname);
224 /* Write module header */
225 put_header(&hdr, libfp, modname);
227 /* Put the module itself */
228 while (!feof(modfp)) {
229 i = fgetc(modfp);
230 if (i == EOF)
231 break;
232 if (fputc(i, libfp) == EOF)
233 error_exit(1, FALSE, "write error");
236 fclose(modfp);
237 return TRUE;
241 * Main
243 int main(int argc, char **argv)
245 FILE *libfp, *tmpfp, *modfp = NULL;
246 struct stat finfo;
247 struct rdlm_hdr hdr;
248 char buf[MAXMODNAMELEN], *p = NULL;
249 char c;
250 int i;
252 progname = argv[0];
253 _argv = argv;
255 if (argc < 2) {
256 usage();
257 exit(1);
260 /* Check whether some modifiers were specified */
261 for (i = 1; i < strlen(argv[1]); i++) {
262 switch (c = argv[1][i]) {
263 case 'c':
264 options.createok = TRUE;
265 break;
266 case 'f':
267 options.usefname = TRUE;
268 break;
269 case 'l':
270 options.align = TRUE;
271 break;
272 case 'o':
273 options.odate = TRUE;
274 break;
275 case 'u':
276 options.fresh = TRUE;
277 break;
278 case 'v':
279 options.verbose++;
280 break;
281 case 'V':
282 show_version();
283 exit(0);
284 default:
285 if (strchr(commands, c) == NULL)
286 error_exit(2, FALSE, "invalid command or modifier '%c'",
291 if (argc < 3)
292 error_exit(2, FALSE, "missing library name");
294 /* Process the command */
295 if (argv[1][0] == '-')
296 argv[1]++;
297 switch (c = argv[1][0]) {
298 case 'a': /* add a module */
299 if (argc < 4 || (!options.usefname && argc != 5))
300 error_exit(2, FALSE, "invalid number of arguments");
302 /* Check if a library already exists. If not - create it */
303 if (access(argv[2], F_OK) < 0) {
304 if (!options.createok)
305 fprintf(stderr, "creating library %s\n", argv[2]);
306 create_library(argv[2]);
309 libfp = fopen(argv[2], "ab");
310 if (!libfp)
311 error_exit(1, TRUE, "could not open '%s'", argv[2]);
313 if (!options.usefname)
314 add_module(libfp, argv[4], argv[3]);
315 else
316 for (i = 3; i < argc; i++)
317 add_module(libfp, argv[i], argv[i]);
319 fclose(libfp);
320 break;
322 case 'n': /* create library */
323 create_library(argv[2]);
324 break;
326 case 'x': /* extract module(s) */
327 if (!options.usefname)
328 argc--;
329 if (argc < 4)
330 error_exit(2, FALSE, "required parameter missing");
331 p = options.usefname ? argv[3] : argv[4];
332 case 't': /* list library contents */
333 libfp = fopen(argv[2], "rb");
334 if (!libfp)
335 error_exit(1, TRUE, "could not open '%s'\n", argv[2]);
337 /* Read library header */
338 if (fread(&hdr, 1, sizeof(hdr), libfp) != sizeof(hdr) ||
339 hdr.magic != RDLAMAG)
340 error_exit(1, FALSE, "invalid library format");
342 /* Walk through the library looking for requested module */
343 while (!feof(libfp)) {
344 /* Read module header */
345 i = fread(&hdr, 1, sizeof(hdr), libfp);
346 if (feof(libfp))
347 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) || fread(buf, 1, i, libfp) != i)
353 error_exit(1, FALSE, "invalid module name");
354 if (c == 'x') {
355 /* Check against desired name */
356 if (!strcmp(buf, argv[3])) {
357 if (options.verbose)
358 fprintf(stderr,
359 "extracting module %s to file %s\n", buf,
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)
375 break;
378 fclose(libfp);
379 if (modfp)
380 fclose(modfp);
381 else if (c == 'x')
382 error_exit(1, FALSE, "module '%s' not found in '%s'",
383 argv[3], argv[2]);
384 break;
386 case 'r': /* replace module(s) */
387 argc--;
388 if (stat(argv[4], &finfo) < 0)
389 error_exit(1, TRUE, "could not stat '%s'", argv[4]);
390 case 'd': /* delete module(s) */
391 if (argc < 4)
392 error_exit(2, FALSE, "required parameter missing");
394 libfp = fopen(argv[2], "rb");
395 if (!libfp)
396 error_exit(1, TRUE, "could not open '%s'", argv[2]);
398 /* Copy the library into a temporary file */
399 tmpfp = tmpfile();
400 if (!tmpfp)
401 error_exit(1, TRUE, "could not open temporary file");
403 stat(argv[2], &finfo);
404 copybytes(libfp, tmpfp, finfo.st_size);
405 rewind(tmpfp);
406 freopen(argv[2], "wb", libfp);
408 /* Read library header and write it to a new file */
409 if (fread(&hdr, 1, sizeof(hdr), tmpfp) != sizeof(hdr) ||
410 hdr.magic != RDLAMAG)
411 error_exit(1, FALSE, "invalid library format");
412 put_header(&hdr, libfp, NULL);
414 /* Walk through the library looking for requested module */
415 while (!feof(tmpfp)) {
416 /* Read module header */
417 if (fread(&hdr, 1, sizeof(hdr), tmpfp) != sizeof(hdr) ||
418 hdr.magic != RDLMMAG)
419 error_exit(1, FALSE, "invalid module header");
420 /* Read module name */
421 i = hdr.hdrsize - sizeof(hdr);
422 if (i > sizeof(buf) || 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
427 || finfo.st_mtime <= hdr.date)) {
428 if (options.verbose)
429 fprintf(stderr, "deleting module %s\n", buf);
430 fseek(tmpfp, hdr.size, SEEK_CUR);
431 break;
432 } else {
433 put_header(&hdr, libfp, buf);
434 copybytes(tmpfp, libfp, hdr.size);
438 if (c == 'r') {
439 /* Copy new module into library */
440 p = options.usefname ? argv[4] : argv[3];
441 add_module(libfp, argv[4], p);
444 /* Copy rest of library if any */
445 while (!feof(tmpfp)) {
446 if ((i = fgetc(tmpfp)) == EOF)
447 break;
449 if (fputc(i, libfp) == EOF)
450 error_exit(1, FALSE, "write error");
453 fclose(libfp);
454 fclose(tmpfp);
455 break;
457 default:
458 error_exit(2, FALSE, "invalid command '%c'\n", c);
461 return 0;