diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
commit | fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch) | |
tree | bdda434976bc09c864f2e4fa6f16ba1952b1e555 /unix/boot/mkpkg/scanlib.c | |
download | iraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz |
Initial commit
Diffstat (limited to 'unix/boot/mkpkg/scanlib.c')
-rw-r--r-- | unix/boot/mkpkg/scanlib.c | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/unix/boot/mkpkg/scanlib.c b/unix/boot/mkpkg/scanlib.c new file mode 100644 index 00000000..cb70efd5 --- /dev/null +++ b/unix/boot/mkpkg/scanlib.c @@ -0,0 +1,355 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <ctype.h> + +#include <ar.h> +#ifdef MACOSX +#include <ranlib.h> +#include <mach-o/fat.h> +#endif + +#define import_spp +#include <iraf.h> +#include "mkpkg.h" +#include "extern.h" + +#ifdef OLD_MACOSX +#define AR_EFMT1 1 +#endif + + +/* + * SCANLIB.C -- Routines to scan a 4.2BSD UNIX archive file and create a + * symbol table naming the files in the archive and their dates. + * + * External entry points: + * + * h_scanlibrary (libname) extract list of modules and their dates + * h_ardate (modname) return long integer module date + */ + +#define SZ_KEY 128 /* arbitrary */ +extern int forceupdate; /* NOT IMPLEMENTED for UNIX */ + +char mlb_sbuf[SZ_SBUF]; /* string buffer */ +int mlb_op = 0; /* index into string buffer */ +int mlb_index[MAX_LIBFILES]; /* sbuf indices for each symbol */ +long mlb_fdate[MAX_LIBFILES]; /* file date of each module */ +int mlb_modified; /* modified flag */ +char *mlb_filename(); + +struct dbentry { /* module entry on disk */ + long fdate; + int keylen; + /* key chars */ +}; + + +/** + * Local procedure declarations. + */ +int mlb_setdate (char *modname, long fdate); + + + +/* SCANLIBRARY -- Scan the archive file, extract module names and dates, + * building the "ar" module list. + */ +int +h_scanlibrary (char *library) +{ + register char *ip, *op; + register int i, is_fat = 0; + char libfname[SZ_PATHNAME+1]; + char modname[SZ_KEY+1]; + char lbuf[SZ_LINE]; + struct ar_hdr arf; + long length, fdate; + int len=0, len_arfmag, nmodules; + FILE *fp; + + /* Get the library file name. */ + h_getlibname (library, libfname); + + /* Clear the symbol table. + */ + mlb_modified = NO; + mlb_op = 1; + nmodules = 0; + + len = 0; + for (i=0; i < MAX_LIBFILES; i++) + mlb_index[i] = 0; + + /* Open the UNIX archive file. + */ + if ((fp = fopen (libfname, "r")) == NULL) { + printf ("warning: library `%s' not found\n", libfname); + fflush (stdout); + return (0); + } + + if (debug) { + printf ("scan unix archive %s:\n", libfname); + fflush (stdout); + } + + /* Verify that file is indeed an archive file. + */ + memset (lbuf, 0, SZ_LINE); + fread (lbuf, 1, SARMAG, fp); + if (strncmp (lbuf, ARMAG, SARMAG) != 0) { +#ifndef MACOSX + printf ("file `%s' is not a library\n", libfname); + goto err; +#else + /* See if it's a FAT archive file. + */ + struct fat_header fh; + struct fat_arch fa; + char *ip; + + rewind (fp); + memset (&fh, 0, sizeof(struct fat_header)); + fread (&fh, 1, sizeof(struct fat_header), fp); /* read header */ + if (fh.magic == FAT_MAGIC || fh.magic == FAT_CIGAM) { + int narch = 0; + + is_fat++; + + /* The following is a cheat to avoid byte swapping the + * nfat_arch field in Intel systems. Assumes we'll never + * see more that 8-bits worth of architectures. 8-) + */ + ip = (char *) &fh, ip += 7; + memmove (&narch, ip, 1); + for (i=0; i < narch; i++) { /* skip headers */ + memset (&fa, 0, sizeof(struct fat_arch)); + fread (&fa, 1, sizeof(struct fat_arch), fp); + } + + /* Read the AR header. + */ + memset (lbuf, 0, SZ_LINE); + fread (lbuf, 1, SARMAG, fp); + if (strncmp (lbuf, ARMAG, SARMAG) != 0) { + printf ("file `%s' is not a library\n", libfname); + goto err; + } + } else { + printf ("file `%s' is not a library\n", libfname); + goto err; + } +#endif + } + + len_arfmag = strlen (ARFMAG); + memset (&arf, 0, sizeof(arf)); + while ((int)(fread (&arf, 1, sizeof(arf), fp)) > 0) { + + /* Don't scan past the first architecture for FAT libs. + */ + if (is_fat && strncmp (arf.ar_name, ARMAG, SARMAG) == 0) + break; + + if (strncmp (arf.ar_fmag, ARFMAG, len_arfmag) != 0) { + printf ("cannot decode library `%s'\n", libfname); + goto err; + } + + if (debug > 1) { + char name[17], date[13]; + strncpy (name, arf.ar_name, 16); name[16] = '\0'; + strncpy (date, arf.ar_date, 12); date[12] = '\0'; + printf ("objname='%s', date='%s'\n", name, date); + } + + /* Extract module name. */ + for (ip=arf.ar_name; *ip == ' '; ip++) ; + for (op=modname; (*op = *ip++) != ' ' && *op != '/'; op++) ; + *op++ = EOS; + + /* Skip dummy entry with null modname (COFF format) as well + * as the __SYMDEF from ranlib. + */ +#ifdef MACOSX + if (strncmp (modname, RANLIBMAG, 9) || modname[0] != EOS) { +#else + if (modname[0] != EOS) { +#endif +#if defined(AR_EFMT1) && !defined(__CYGWIN__) + /* + * BSD 4.4 extended AR format: #1/<namelen>, with name as the + * first <namelen> bytes of the file + */ + if ((arf.ar_name[0] == '#') && + (arf.ar_name[1] == '1') && + (arf.ar_name[2] == '/') && (isdigit(arf.ar_name[3]))) { + + char p[SZ_PATHNAME]; + + len = atoi(&arf.ar_name[3]); + bzero (p, SZ_PATHNAME); + if (fread(p, len, 1, fp) != 1) { + fprintf (stderr, "%s: premature EOF", libfname); + } + bzero (modname, SZ_KEY+1); + sprintf (modname, "%s", p); + } else + len = 0; +#endif + /* Get module date. */ + sscanf (arf.ar_date, "%ld", &fdate); + + /* Insert entry into symbol table. */ + mlb_setdate (modname, fdate); + } + + /* Advance to the next entry. + */ + if (sscanf (arf.ar_size, "%ld", &length) == 1) { + if (length & 1) /* must be even */ + length++; +#if defined(AR_EFMT1) && !defined(__CYGWIN__) + fseek (fp, length-len, 1); +#else + fseek (fp, length, 1); +#endif + } else { + printf ("could not decode length `%s' of library module\n", + arf.ar_size); + goto err; + } + + memset (&arf, 0, sizeof(arf)); + } + + fclose (fp); + return (nmodules); + +err: + fflush (stdout); + fclose (fp); + return (ERR); +} + + +/* H_ARDATE -- Look up file in archive. If found, return date of archive + * version, otherwise return zero. This is the entry point called by MKLIB + * to get the update date of a library module. + */ +long +h_ardate (char *fname) +{ + extern char *makeobj(); + long mlb_getdate(); + + return (mlb_getdate (makeobj (fname))); +} + + +/* MLB_SETDATE -- Enter the given module and file date into the symbol table, + * or update the file date if the module is already present in the table. + */ +int +mlb_setdate ( + char *modname, /* module name */ + long fdate /* object file date */ +) +{ + register int hashval, keylen, i; + register char *ip; + int start; + + + if (*modname == EOS || fdate <= 0) { + printf ("warning, mlb_setdate: attempted illegal entry for %s\n", + modname); + fflush (stdout); + return (ERR); + } + + /* Hash the key. + */ + for (hashval=0, keylen=0, ip=modname; *ip; ip++, keylen++) + hashval += hashval + *ip; + start = hashval % MAX_LIBFILES; + + mlb_modified = YES; + + /* Update the entry if the module is already in the table, else find + * an empty slot, checking for table overflow in the process. + */ + for (i=start; mlb_index[i]; ) { + ip = &mlb_sbuf[mlb_index[i]]; + if (*ip == *modname) + if (strncmp (modname, ip, keylen) == 0) { + mlb_fdate[i] = fdate; + return (OK); + } + if (++i >= MAX_LIBFILES) + i = 0; + if (i == start) { + printf ("error: library module list overflow\n"); + fflush (stdout); + return (ERR); + } + } + + if (mlb_op + keylen + 1 >= SZ_SBUF) { + printf ("error: library module list string buffer overflow\n"); + fflush (stdout); + return (ERR); + } + + /* Enter the module into the symbol table. + */ + mlb_index[i] = mlb_op; + mlb_fdate[i] = fdate; + + strcpy (&mlb_sbuf[mlb_op], modname); + mlb_op += (keylen + 1); + + return (OK); +} + + +/* MLB_GETDATE -- Lookup a module in the symbol table and return its date. + * Return zero if the module is not found. + */ +long +mlb_getdate (char *modname) +{ + register int hashval, keylen, i; + register char *ip; + int start; + + if (*modname == EOS) + return (0L); + + /* Hash the key. + */ + for (hashval=0, keylen=0, ip=modname; *ip; ip++, keylen++) + hashval += hashval + *ip; + start = hashval % MAX_LIBFILES; + + /* Search the symbol table for the named module. + */ + for (i=start; mlb_index[i]; ) { + ip = &mlb_sbuf[mlb_index[i]]; + if (*ip == *modname) + if (strncmp (modname, ip, keylen) == 0) + return (mlb_fdate[i]); + if (++i >= MAX_LIBFILES) + i = 0; + if (i == start) + return (0L); + } + + return (0L); +} |