summaryrefslogtreecommitdiff
path: root/rdoff/rdlar.c
diff options
context:
space:
mode:
authorFrank Kotler <fbkotler@users.sourceforge.net>2002-12-04 14:01:01 +0000
committerFrank Kotler <fbkotler@users.sourceforge.net>2002-12-04 14:01:01 +0000
commitd16a827be0e7365fbd5de73687165a14244182f0 (patch)
tree96e3e1adcb5419b90a8297d6db56b5e24fb9de81 /rdoff/rdlar.c
parentc7ecf0680a014f8388b3557c9d12b3e4937eb74b (diff)
downloadnasm-d16a827be0e7365fbd5de73687165a14244182f0.tar.gz
nasm-d16a827be0e7365fbd5de73687165a14244182f0.tar.bz2
nasm-d16a827be0e7365fbd5de73687165a14244182f0.zip
try again to finish Yuri's patch
Diffstat (limited to 'rdoff/rdlar.c')
-rw-r--r--rdoff/rdlar.c461
1 files changed, 461 insertions, 0 deletions
diff --git a/rdoff/rdlar.c b/rdoff/rdlar.c
new file mode 100644
index 0000000..cdbd154
--- /dev/null
+++ b/rdoff/rdlar.c
@@ -0,0 +1,461 @@
+/*
+ * rdlar.c - new librarian/archiver for RDOFF2.
+ * Copyright (c) 2002 RET & COM Research.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "rdlar.h"
+
+#define PROGRAM_VERSION "0.1"
+
+/** Types **/
+typedef enum { FALSE, TRUE } bool;
+
+/** Constants **/
+const char commands[] = "adnrtx";
+const char modifiers[] = "cflouvV";
+
+/** Global variables **/
+char *progname = "rdlar";
+char **_argv = NULL;
+struct {
+ bool createok;
+ bool usefname;
+ bool align;
+ bool odate;
+ bool fresh;
+ int verbose;
+} options = { 0, 0, 0, 0, 0, 0 };
+
+#define _ENDIANNESS 0 /* 0 for little, 1 for big */
+
+
+/*
+ * Convert long to little endian (if we were compiled on big-endian machine)
+ */
+static void longtolocal(long * l)
+{
+#if _ENDIANNESS
+ unsigned char t;
+ unsigned char * p = (unsigned char *) l;
+
+ t = p[0];
+ p[0] = p[3];
+ p[3] = t;
+ t = p[1];
+ p[1] = p[2];
+ p[2] = p[1];
+#endif
+}
+
+/*
+ * Print version information
+ */
+void show_version(void)
+{
+ puts("New RDOFF2 librarian/archiver, version " PROGRAM_VERSION "\n"
+ "Copyright (c) 2002 RET & COM Research.\n"
+ "This program is free software and distributed under GPL (version 2 or later);\n"
+ "see http://www.gnu.org/copyleft/gpl.html for details.");
+}
+
+
+/*
+ * Print usage instructions
+ */
+void usage(void)
+{
+ printf("Usage: %s [-]{%s}[%s] libfile [module-name] [files]\n",
+ progname, commands, modifiers);
+ puts(" commands:\n"
+ " a - add module(s) to the library\n"
+ " d - delete module(s) from the library\n"
+ " n - create the library\n"
+ " r - replace module(s)\n"
+ " t - display contents of library\n"
+ " x - extract module(s)\n"
+ " command specific modifiers:\n"
+ " o - preserve original dates\n"
+ " u - only replace modules that are newer than library contents\n"
+ " generic modifiers:\n"
+ " c - do not warn if the library had to be created\n"
+ " f - use file name as a module name\n"
+ " v - be verbose\n"
+ " V - display version information");
+}
+
+
+/*
+ * Print an error message and exit
+ */
+void error_exit(int errcode, bool useperror, const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s: ", progname);
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ putc('\n', stderr);
+ if (useperror) perror(progname);
+ exit(errcode);
+}
+
+
+/*
+ * Fill in and write a header
+ */
+void put_header(struct rdlm_hdr *hdr, FILE *libfp, char *modname)
+{
+ int n = 0;
+
+ hdr->hdrsize = sizeof(*hdr);
+ if (modname) hdr->hdrsize += (n = strlen(modname) + 1);
+ if (libfp == NULL) return;
+ if (fwrite(hdr, 1, sizeof(*hdr), libfp) != sizeof(*hdr) ||
+ (modname && (fwrite(modname, 1, n, libfp) != n)))
+ error_exit(3, TRUE, "could not write header");
+}
+
+/*
+ * Copy n bytes from one file to another and return last character read.
+ */
+char copybytes(FILE *fp, FILE *fp2, int n)
+{
+ int i, t = 0;
+
+ for (i = 0 ; i < n; i++) {
+ t = fgetc(fp);
+ if (t == EOF)
+ error_exit(1, FALSE, "premature end of file in '%s'", _argv[2]);
+ if (fp2)
+ if (fputc(t, fp2) == EOF)
+ error_exit(1, FALSE, "write error");
+ }
+ return (char) t;
+}
+
+
+/*
+ * Copy unsigned long from one file to another.
+ * Return local presentation of long.
+ */
+long copylong(FILE *fp, FILE *fp2)
+{
+ long l;
+ int i,t;
+ unsigned char * p = (unsigned char *) &l;
+
+
+ for (i = 0 ; i < 4; i++ ) {
+ t = fgetc(fp);
+ if (t == EOF)
+ error_exit(1, FALSE, "premature end of file in '%s'", _argv[2]);
+ if (fp2)
+ if (fputc(t, fp2) == EOF)
+ error_exit(1, FALSE, "write error");
+ *p++ = t;
+ }
+ longtolocal (&l);
+ return l;
+}
+
+
+/*
+ * Create a new library
+ */
+int create_library(char *libname)
+{
+ FILE *libfp;
+ struct rdlm_hdr hdr;
+
+ hdr.magic = RDLAMAG;
+ hdr.hdrsize = 0;
+ hdr.date = time(NULL);
+ hdr.owner = getuid();
+ hdr.group = getgid();
+ hdr.mode = umask(022);
+ hdr.size = 0;
+
+ libfp = fopen(libname, "wb");
+ if (!libfp)
+ error_exit(1, TRUE, "could not open '%s'\n", libname);
+
+ /* Write library header */
+ put_header(&hdr, libfp, NULL);
+
+ fclose(libfp);
+ return TRUE;
+}
+
+
+/*
+ * Add a module to the library
+ */
+int add_module(FILE *libfp, const char *fname, char *modname)
+{
+ FILE *modfp;
+ struct rdlm_hdr hdr = { RDLMMAG, 0, 0, 0, 0, 0, 0 };
+ struct stat finfo;
+ int i;
+
+ if (options.verbose)
+ fprintf(stderr, "adding module %s\n", modname);
+
+ /* Initialize some fields in the module header */
+ if (stat(fname, &finfo) < 0)
+ error_exit(1, TRUE, "could not stat '%s'", fname);
+ hdr.date = finfo.st_mtime;
+ hdr.owner = finfo.st_uid;
+ hdr.group = finfo.st_gid;
+ hdr.size = finfo.st_size;
+
+ modfp = fopen(fname, "rb");
+ if (!modfp)
+ error_exit(1, TRUE, "could not open '%s'", fname);
+
+ /* Write module header */
+ put_header(&hdr, libfp, modname);
+
+ /* Put the module itself */
+ while (! feof(modfp)) {
+ i = fgetc(modfp);
+ if (i == EOF) break;
+ if (fputc(i, libfp) == EOF )
+ error_exit(1, FALSE, "write error");
+ }
+
+ fclose(modfp);
+ return TRUE;
+}
+
+
+/*
+ * Main
+ */
+int main(int argc, char *argv[])
+{
+ FILE *libfp, *tmpfp, *modfp = NULL;
+ struct stat finfo;
+ struct rdlm_hdr hdr;
+ char buf[MAXMODNAMELEN], *p = NULL;
+ char c;
+ int i;
+
+ progname = argv[0];
+ _argv = argv;
+
+ if (argc < 2) {
+ usage();
+ exit(1);
+ }
+
+ /* Check whether some modifiers were specified */
+ for (i = 1; i < strlen(argv[1]); i++) {
+ switch (c = argv[1][i]) {
+ case 'c':
+ options.createok = TRUE;
+ break;
+ case 'f':
+ options.usefname = TRUE;
+ break;
+ case 'l':
+ options.align = TRUE;
+ break;
+ case 'o':
+ options.odate = TRUE;
+ break;
+ case 'u':
+ options.fresh = TRUE;
+ break;
+ case 'v':
+ options.verbose++;
+ break;
+ case 'V':
+ show_version();
+ exit(0);
+ default:
+ if (strchr(commands, c) == NULL)
+ error_exit(2, FALSE, "invalid command or modifier '%c'", c);
+ }
+ }
+
+ if (argc < 3)
+ error_exit(2, FALSE, "missing library name");
+
+ /* Process the command */
+ if (argv[1][0] == '-') argv[1]++;
+ switch(c = argv[1][0]) {
+ case 'a': /* add a module */
+ if (argc < 4 || (!options.usefname && argc != 5))
+ error_exit(2, FALSE, "invalid number of arguments");
+
+ /* Check if a library already exists. If not - create it */
+ if (access(argv[2], F_OK) < 0) {
+ if (!options.createok)
+ fprintf(stderr, "creating library %s\n", argv[2]);
+ create_library(argv[2]);
+ }
+
+ libfp = fopen(argv[2], "ab");
+ if (!libfp)
+ error_exit(1, TRUE, "could not open '%s'", argv[2]);
+
+ if (!options.usefname)
+ add_module(libfp, argv[4], argv[3]);
+ else
+ for (i = 3; i < argc; i++)
+ add_module(libfp, argv[i], argv[i]);
+
+ fclose(libfp);
+ break;
+
+ case 'n': /* create library */
+ create_library(argv[2]);
+ break;
+
+ case 'x': /* extract module(s) */
+ if (!options.usefname)
+ argc--;
+ if (argc < 4)
+ error_exit(2, FALSE, "required parameter missing");
+ p = options.usefname ? argv[3] : argv[4];
+ case 't': /* list library contents */
+ libfp = fopen(argv[2],"rb");
+ if (!libfp)
+ error_exit(1, TRUE, "could not open '%s'\n", argv[2]);
+
+ /* Read library header */
+ if (fread(&hdr, 1, sizeof(hdr), libfp) != sizeof(hdr) ||
+ hdr.magic != RDLAMAG)
+ error_exit(1, FALSE, "invalid library format");
+
+ /* Walk through the library looking for requested module */
+ while (!feof(libfp)) {
+ /* Read module header */
+ i = fread(&hdr, 1, sizeof(hdr), libfp);
+ if (feof(libfp)) break;
+ if (i != sizeof(hdr) || hdr.magic != RDLMMAG)
+ error_exit(1, FALSE, "invalid module header");
+ /* Read module name */
+ i = hdr.hdrsize - sizeof(hdr);
+ if (i > sizeof(buf) ||
+ fread(buf, 1, i, libfp) != i)
+ error_exit(1, FALSE, "invalid module name");
+ if (c == 'x') {
+ /* Check against desired name */
+ if (!strcmp(buf, argv[3])) {
+ if (options.verbose)
+ fprintf(stderr, "extracting module %s to file %s\n",
+ buf, p);
+ modfp = fopen(p, "wb");
+ if (!modfp)
+ error_exit(1, TRUE, "could not open '%s'", p);
+ }
+ } else {
+ printf("%-40s ", buf);
+ if (options.verbose) {
+ printf("%ld bytes", hdr.size);
+ }
+ putchar('\n');
+ }
+
+ copybytes(libfp, modfp, hdr.size);
+ if (modfp) break;
+ }
+
+ fclose(libfp);
+ if (modfp)
+ fclose(modfp);
+ else if (c == 'x')
+ error_exit(1, FALSE, "module '%s' not found in '%s'",
+ argv[3], argv[2]);
+ break;
+
+ case 'r': /* replace module(s) */
+ argc--;
+ if (stat(argv[4], &finfo) < 0)
+ error_exit(1, TRUE, "could not stat '%s'", argv[4]);
+ case 'd': /* delete module(s) */
+ if (argc < 4)
+ error_exit(2, FALSE, "required parameter missing");
+
+ libfp = fopen(argv[2], "rb");
+ if (!libfp)
+ error_exit(1, TRUE, "could not open '%s'", argv[2]);
+
+ /* Copy the library into a temporary file */
+ tmpfp = tmpfile();
+ if (!tmpfp)
+ error_exit(1, TRUE, "could not open temporary file");
+
+ stat(argv[2], &finfo);
+ copybytes(libfp, tmpfp, finfo.st_size);
+ rewind(tmpfp);
+ freopen(argv[2], "wb", libfp);
+
+ /* Read library header and write it to a new file */
+ if (fread(&hdr, 1, sizeof(hdr), tmpfp) != sizeof(hdr) ||
+ hdr.magic != RDLAMAG)
+ error_exit(1, FALSE, "invalid library format");
+ put_header(&hdr, libfp, NULL);
+
+ /* Walk through the library looking for requested module */
+ while (!feof(tmpfp)) {
+ /* Read module header */
+ if (fread(&hdr, 1, sizeof(hdr), tmpfp) != sizeof(hdr) ||
+ hdr.magic != RDLMMAG)
+ error_exit(1, FALSE, "invalid module header");
+ /* Read module name */
+ i = hdr.hdrsize - sizeof(hdr);
+ if (i > sizeof(buf) ||
+ fread(buf, 1, i, tmpfp) != i)
+ error_exit(1, FALSE, "invalid module name");
+ /* Check against desired name */
+ if (!strcmp(buf, argv[3]) &&
+ (c == 'd' || !options.odate || finfo.st_mtime <= hdr.date)) {
+ if (options.verbose)
+ fprintf(stderr, "deleting module %s\n", buf);
+ fseek(tmpfp, hdr.size, SEEK_CUR);
+ break;
+ } else {
+ put_header(&hdr, libfp, buf);
+ copybytes(tmpfp, libfp, hdr.size);
+ }
+ }
+
+ if (c == 'r') {
+ /* Copy new module into library */
+ p = options.usefname ? argv[4] : argv[3];
+ add_module(libfp, argv[4], p);
+ }
+
+ /* Copy rest of library if any */
+ while (!feof(tmpfp)) {
+ if ((i = fgetc(tmpfp)) == EOF)
+ break;
+
+ if (fputc(i, libfp) == EOF)
+ error_exit(1, FALSE, "write error");
+ }
+
+ fclose(libfp);
+ fclose(tmpfp);
+ break;
+
+ default:
+ error_exit(2, FALSE, "invalid command '%c'\n", c);
+ }
+
+ return 0;
+}