diff options
Diffstat (limited to 'dmake/unix/arlib.c')
-rw-r--r-- | dmake/unix/arlib.c | 608 |
1 files changed, 0 insertions, 608 deletions
diff --git a/dmake/unix/arlib.c b/dmake/unix/arlib.c deleted file mode 100644 index 708063f95885..000000000000 --- a/dmake/unix/arlib.c +++ /dev/null @@ -1,608 +0,0 @@ -/* --- --- SYNOPSIS --- Unix archive manipulation code. --- --- DESCRIPTION --- Originally this code was provided by Eric Gisin of MKS. I took --- his code and completely rewrote it adding cacheing of lib members --- and other various optimizations. I kept the overal functional --- idea of the library routines as they are similar to those in GNU --- make and felt it advantageous to maintain a similar interface. --- --- AUTHOR --- Dennis Vadura, dvadura@dmake.wticorp.com --- --- WWW --- http://dmake.wticorp.com/ --- --- COPYRIGHT --- Copyright (c) 1996,1997 by WTI Corp. All rights reserved. --- --- This program is NOT free software; you can redistribute it and/or --- modify it under the terms of the Software License Agreement Provided --- in the file <distribution-root>/readme/license.txt. --- --- LOG --- Use cvs log to obtain detailed change logs. -*/ - -/* Sun unix on 386i's has a broken ar.h that does not assume PORTAR format - * by default, so we fix it here. */ -#if defined(i386) || defined(__DGUX__) -#define PORTAR 1 -#endif - -#if !defined (COHERENT) && !defined(__COHERENT__) -#include <ar.h> -#else -#include <arcoff.h> -#endif /* COHERENT, __COHERENT__ */ -#include "extern.h" -#include "sysintf.h" - -/* By defining the defines below it is possible to configure the library - * code for library cacheing/non-cacheing, ASCII archive headers, and a full - * decode of the ar_hdr fields in the scan_ar function. */ - -#ifndef ASCARCH -#define ASCARCH 1 /* ASCII time stored in archive */ -#endif - -#ifndef LC -#define LC 1 /* Turn on library cacheing */ -#endif - -#ifndef CHECKELF -#define CHECKELF 1 /* Enable Elf long member names */ -#endif - -#ifndef DECODE_ALL_AR_FIELDS -#define DECODE_ALL_AR_FIELDS 0 /* decode only fields make needs*/ -#endif - -#ifndef AR_TRUNCATE_MEMBER_NAMES -#define AR_TRUNCATE_MEMBER_NAMES 0 /* truncate member names for */ -#endif /* comparison. */ - -#if LC -# define FOUND_MEMBER FALSE -#else -# define FOUND_MEMBER TRUE -# define _cache_member(a, b, c) -# define _check_cache(a, b, c, d) FALSE -#endif - -#define MAXFNAME 255 /* Max length of member name */ -#define MAXMNAME 8 /* Max module name < MAXFNAME */ - - -/* This struct is used to pass the library and member inrmation about the - * routines that perform the library seeking/cacheing */ -struct ar_args { - char *lib; - char *member; - time_t time; -}; - - -typedef struct AR { - char ar_name[MAXFNAME+1]; /* File name */ - long ar_size; /* Size in bytes */ - time_t ar_time; /* Modification time */ - -#ifdef DOS - char ar_modname[MAXMNAME+1]; /* DOS module name */ -#endif - -#if DECODE_ALL_AR_FIELDS - uint16 ar_mode; /* File mode */ - uint16 ar_uid; /* File owner */ - uint16 ar_gid; /* File group owner */ -#endif -} AR, *ARPTR; - - -static int ar_scan ANSI((FILE *, - int (*) ANSI((FILE *, struct AR *,struct ar_args *)), - struct ar_args *)); -static int ar_touch ANSI(( FILE *, time_t )); -static int time_function ANSI(( FILE *, struct AR *, struct ar_args * )); -static int touch_function ANSI(( FILE *, struct AR *, struct ar_args * )); -static int ar_name_equal ANSI((char *, char *)); - -#if LC -static int _cache_member ANSI((char *, char *, time_t)); -static int _check_cache ANSI((char *, char *, time_t *, int)); -#endif - -/* decoded archive header */ -static AR _ar; -static off_t arhdroffset; /* member seek offset */ - - -PUBLIC time_t -seek_arch(name, lib)/* -====================== - Look for module 'name' inside 'lib'. If compiled with cacheing then first - check to see if the specified lib is cached. If so then return that time - stamp instead of looking into the library. */ -char *name; -char *lib; -{ - FILE *f; - int rv; - time_t mtime; - struct ar_args args; - - /* Check the cache first (if there is a cache) */ - if( _check_cache(name, lib, &mtime, FALSE) ) return( mtime ); - - /* Open the lib file and perform the scan of the members, looking - * for our particular member. If cacheing is enabled it will be - * taken care of automatically during the scan. */ - - args.lib = lib; - args.member = name; - args.time = (time_t)0L; - - if( (f = fopen(lib, "r")) == NIL(FILE) ) return( (time_t)0L ); - rv = ar_scan(f, time_function, &args ); - fclose( f ); - - if( rv < 0 ) Fatal("(%s): Invalid library format", lib); - - return( args.time ); -} - - -PUBLIC int -touch_arch(name, lib)/* -======================= - Look for module 'name' inside 'lib'. If compiled with cacheing then first - check to see if the specified lib is cached. If so then set that time - stamp and write it into the library. Returns 0 on success, non-zero - on failure. */ -char *name; -char *lib; -{ - FILE *f; - int rv; - struct ar_args args; - - /* Open the lib file and perform the scan of the members, looking - * for our particular member. If cacheing is enabled it will be - * taken care of automatically during the scan. */ - - args.lib = lib; - args.member = name; - args.time = (time_t)0L; - - if( (f = fopen(lib, "r+")) == NIL(FILE) ) return( (time_t)1L ); - rv = ar_scan(f, touch_function, &args ); - fclose( f ); - - if( rv < 0 ) Fatal("(%s): Invalid library format", lib); - - return( 0 ); -} - - - -static int -time_function(f, arp, argp)/* -============================= - get library member's time, if it matches than return it in argp, if - cacheing is enabled than cache the library members also. */ -FILE *f; /* library file */ -struct AR *arp; /* library member header */ -struct ar_args *argp; -{ - int rv = _cache_member( arp->ar_name, argp->lib, arp->ar_time ); - - if( ar_name_equal (argp->member, arp->ar_name)) { - argp->time = arp->ar_time; - - if( arp->ar_time == 0 && !(Glob_attr & A_SILENT) ) - Warning( "(%s): Can't extract library member timestamp; using EPOCH", - argp->member); - - return( rv ); /* 1 => no cacheing, 0 => cacheing */ - } - - return( FALSE ); /* continue scan */ -} - - - -static int -touch_function(f, arp, argp)/* -============================== - Update library member's time stamp, and write new time value into cache - if required. */ -FILE *f; /* library file */ -struct AR *arp; /* library member header */ -struct ar_args *argp; -{ - extern time_t time ANSI(( time_t * )); - time_t now = time((time_t*) NULL); /* Current time. */ - - if( ar_name_equal(argp->member, arp->ar_name) ) { - _check_cache( argp->member, argp->lib, &now, TRUE ); - ar_touch(f, now ); - - return( TRUE ); - } - - return( FALSE ); /* continue scan */ -} - - -static int -ar_name_equal (char * name1, char * name2) -{ - int equal; - -#if AR_TRUNCATE_MEMBER_NAMES - struct ar_hdr hdr; - - equal = !strncmp (name1, name2, sizeof (hdr.ar_name)-1); -#else - equal = !strcmp (name1, name2); -#endif - - return equal; -} - - -static int -ar_scan(f, function, arg)/* -=========================== - Scan the opened archive, and call the given function for each member found. - The function will be called with the file positioned at the beginning of - the member and it can read up to arp->ar_size bytes of the archive member. - If the function returns 1, we stop and return 1. We return 0 at the end - of the archive, or -1 if the archive has invalid format. This interface - is more general than required by "make", but it can be used by other - utilities. */ -register FILE *f; -int (*function) ANSI((FILE *, struct AR *, struct ar_args *)); -struct ar_args *arg; -{ - extern long atol (); - register char *p; - struct ar_hdr arhdr; /* archive member header */ - long nsize; /* size of member name */ - long arind=0; /* archive index offset */ - int process; -#if defined(_AIX) - struct fl_hdr flhdr; /* archive file header */ - char magic[SAIAMAG]; /* size of magic string */ -#else -#if ASCARCH - char magic[SARMAG]; -#else - unsigned short word; -#endif -#endif - - fseek( f, 0L, 0 ); /* Start at the beginning of the archive file */ - -#if ASCARCH -#if defined(_AIX) - if( fread( (char *)&flhdr, sizeof(flhdr), 1, f ) != 1 ) return (-1); - if( strncmp(flhdr.fl_magic,AIAMAG, SAIAMAG) != 0 ) return(-1); - fseek(f, atol(flhdr.fl_fstmoff), 0 ); /* postition to first member */ -#else - if( fread( magic, sizeof(magic), 1, f ) != 1 ) return( -1 ); - if( strncmp(magic, ARMAG, SARMAG) != 0 ) return( -1 ); -#endif -#else - if( fread( (char*)&word, sizeof(word), 1, f ) != 1 ) return( -1 ); - if( word != ARMAG ) return( -1 ); -#endif - - /* scan the library, calling `function' for each member - */ - while( 1 ) { - arhdroffset = ftell(f); -#if defined(_AIX) - if( fread((char*)&arhdr,sizeof(arhdr)-sizeof(arhdr._ar_name),1,f)!=1) - break; - nsize = atoi(arhdr.ar_namlen); - fseek(f, arhdroffset+(unsigned long)(((struct ar_hdr *)0)->_ar_name.ar_name), 0); - if( fread((char*)_ar.ar_name,nsize,1,f)!=1) - break; - _ar.ar_name[nsize]='\0'; -#else - if( fread((char*) &arhdr, sizeof(arhdr), 1, f) != 1 ) break; - strncpy(_ar.ar_name, arhdr.ar_name, nsize = sizeof(arhdr.ar_name)); -#endif - - for( p = &_ar.ar_name[nsize]; - --p >= _ar.ar_name && *p == ' ';); - - p[1] = '\0'; - if( *p == '/' ) *p = 0; /* SysV has trailing '/' */ - - /* check to see if this is an archive index using SsysV Index scheme. - * see ar(4) man page for more info */ -#if CHECKELF - if( _ar.ar_name[0] == '/' && _ar.ar_name[1] == '\0' ) { - arind = arhdroffset+sizeof(arhdr); - process = 0; - } - else -#endif - process = 1; - -#if !defined(_AIX) -#if ASCARCH - if( strncmp(arhdr.ar_fmag, ARFMAG, sizeof(arhdr.ar_fmag)) != 0 ) - return( -1 ); - _ar.ar_time = atol(arhdr.ar_date); - _ar.ar_size = atol(arhdr.ar_size); -#else - _ar.ar_time = arhdr.ar_date; - _ar.ar_size = arhdr.ar_size; -#endif -#if CHECKELF - /* check for names of the form /xxxx where xxxx is an offset into the - * name table pointed at by arind. */ - if(arind && _ar.ar_name[0] == '/') { - long offset = atol(_ar.ar_name+1); - long here = ftell(f); - int c; - - fseek(f, arind+offset, 0); - p = _ar.ar_name; - while((c=fgetc(f)) != EOF) { - *p++ = c; - if(c == '/') { - p[-1] = '\0'; - break; - } - } - - if (c==EOF) return(-1); /* 'c' should never be EOF */ - fseek(f, here, 0); - } -#endif -#else -#if ASCARCH - _ar.ar_time = atol(arhdr.ar_date); - _ar.ar_size = atol(arhdr.ar_nxtmem); -#else - _ar.ar_time = arhdr.ar_date; - _ar.ar_size = arhdr.ar_nxtmem; -#endif -#endif - - -#if DECODE_ALL_AR_FIELDS -#if ASCARCH - _ar.ar_mode = atoi(arhdr.ar_mode); - _ar.ar_uid = atoi(arhdr.ar_uid); - _ar.ar_gid = atoi(arhdr.ar_gid); -#else - _ar.ar_mode = arhdr.ar_mode; - _ar.ar_uid = arhdr.ar_uid; - _ar.ar_gid = arhdr.ar_gid; -#endif -#endif - if( process && (*function)(f, &_ar, arg) ) return( 1 ); - -#if defined(_AIX) - if( _ar.ar_size == 0L ) break; - fseek( f, (long) _ar.ar_size, 0 ); -#else - fseek( f, arhdroffset + sizeof(arhdr) + ((_ar.ar_size+1) & ~1L), 0 ); -#endif - } - -#if !defined(_AIX) - if( !feof(f) ) return( -1 ); -#endif - return 0; -} - - - -static int -ar_touch( f, now )/* -==================== - touch module header timestamp. */ -FILE *f; -time_t now; -{ - - fseek(f, arhdroffset + (unsigned long)(((struct ar_hdr *)0)->ar_date), 0); - -#if ASCARCH - fprintf(f, "%lu", now); -#else - fwrite((char *)now, sizeof(now), 1, f); -#endif - - return( ferror(f) ? 0 : 1 ); -} - - -#if LC -typedef struct mem { - time_t m_time; /* modify time of member*/ - struct mem *m_next; /* next member in lib */ - char m_valid; /* valid cache entry */ - char m_name[1]; /* lib member name */ -} MEM, *MEMPTR; - -typedef struct lib { - struct lib *lb_next; /* next library in list */ - struct mem *lb_members; /* list of lib members */ - char lb_valid; /* valid cache entry */ - char *lb_name; /* library name */ -} LIB, *LIBPTR; - -static LIBPTR _cache = NIL(LIB); -static MEMPTR _find_member ANSI(( LIBPTR, char * )); - -static int -_check_cache( name, lib, pmtime, touch )/* -========================================== - Check to see if we have cached member in lib, if so return time in pmtime - and return TRUE, otherwise return FALSE, if touch is TRUE then touch - the archive member instead. */ -char *name; -char *lib; -time_t *pmtime; -int touch; -{ - register MEMPTR mp; - register LIBPTR lp; - - for( lp=_cache; lp != NIL(LIB) && lp->lb_name != lib; lp=lp->lb_next ); - if( lp == NIL(LIB) ) return( FALSE ); - - mp = _find_member( lp, name ); - if( mp == NIL(MEM) || !mp->m_valid ) return( FALSE ); - - if( touch == TRUE ) - { - mp->m_time = *pmtime; - mp->m_valid = 1; - } - else - *pmtime = mp->m_time; - - lp->lb_valid = 1; - lp->lb_members = mp; - - return( TRUE ); -} - - - -static int -_cache_member( name, lib, mtime )/* -=================================== - Cache name in lib along with it's time */ -char *name; -char *lib; -time_t mtime; -{ - register MEMPTR mp; - register LIBPTR lp; - - for( lp=_cache; - lp != NIL(LIB) && lp->lb_name != NIL(char) && lp->lb_name != lib; - lp=lp->lb_next); - - if( lp == NIL(LIB) ) - { - lp = (LIBPTR) malloc(sizeof(LIB)); - if( lp == NIL(LIB) ) No_ram(); - - lp->lb_name = lib; - lp->lb_members = NIL(MEM); - lp->lb_next = _cache; - lp->lb_valid = 0; - _cache = lp; - } - - /* On UNIX ar does not allow multiple copies of the same .o file to live - * in the same AR file. If this is not TRUE then use the commented out - * version to set the value of mp. */ - - /*mp = _find_member(lp, name);*/ - mp = NIL(MEM); - - if( mp == NIL(MEM) ) - { - mp = (MEMPTR) malloc(sizeof(char)*offsetof(MEM,m_name[strlen(name)+1])); - if( mp == NIL(MEM) ) No_ram(); - - strcpy( mp->m_name, name ); - mp->m_time = mtime; - - if( lp->lb_members == NIL(MEM) ) { - mp->m_next = mp; - lp->lb_members = mp; - } - else { - mp->m_next = lp->lb_members->m_next; - lp->lb_members->m_next = mp; - lp->lb_members = mp; - } - } - else - mp->m_time = mtime; - - mp->m_valid = 1; - - return( lp->lb_valid ); -} - - -static MEMPTR -_find_member( lp, name ) -LIBPTR lp; -char *name; -{ - register MEMPTR mp = lp->lb_members; - - if( mp == NIL(MEM) ) return(mp); - - do { - if( !strcmp(mp->m_name, name ) ) return( mp ); - mp = mp->m_next; - } - while( mp != lp->lb_members ); - - return( NIL(MEM) ); -} -#endif - - - -PUBLIC void -void_lcache( lib, member )/* -============================ - Void the library cache for lib. If member is NIL(char) then nuke all - of the members, if member is NOT NIL(char) then invalidate only that - member. */ -char *lib; -char *member; -{ -#if LC - register LIBPTR lp; - register MEMPTR mp; - register MEMPTR tmp; - - for( lp=_cache; lp != NIL(LIB) && lp->lb_name != lib; lp=lp->lb_next ); - if( lp == NIL(LIB) ) return; - - if( member == NIL(char) ) { - mp = lp->lb_members; - do { - tmp = mp->m_next; - (void) free( mp ); - mp = tmp; - } while( mp != lp->lb_members ); - - lp->lb_valid = 0; - lp->lb_members = NIL(MEM); - lp->lb_name = NIL(char); - } - else { - mp=lp->lb_members; - do { - if( strcmp( member, mp->m_name) == 0 ) { - lp->lb_members = mp->m_next; - mp->m_valid = 0; - } - - mp=mp->m_next; - } while( mp != lp->lb_members ); - } -#endif -} |