Home | History | Annotate | Line # | Download | only in dist
      1  1.1  christos /* Library function for scanning an archive file.
      2  1.1  christos Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
      3  1.1  christos 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
      4  1.1  christos Inc.
      5  1.1  christos This file is part of GNU Make.
      6  1.1  christos 
      7  1.1  christos GNU Make is free software; you can redistribute it and/or modify it under the
      8  1.1  christos terms of the GNU General Public License as published by the Free Software
      9  1.1  christos Foundation; either version 2, or (at your option) any later version.
     10  1.1  christos 
     11  1.1  christos GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
     12  1.1  christos WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     13  1.1  christos A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     14  1.1  christos 
     15  1.1  christos You should have received a copy of the GNU General Public License along with
     16  1.1  christos GNU Make; see the file COPYING.  If not, write to the Free Software
     17  1.1  christos Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
     18  1.1  christos 
     19  1.1  christos #include "make.h"
     20  1.1  christos 
     21  1.1  christos #ifdef HAVE_FCNTL_H
     22  1.1  christos #include <fcntl.h>
     23  1.1  christos #else
     24  1.1  christos #include <sys/file.h>
     25  1.1  christos #endif
     26  1.1  christos 
     27  1.1  christos #ifndef	NO_ARCHIVES
     28  1.1  christos 
     29  1.1  christos #ifdef VMS
     31  1.1  christos #include <lbrdef.h>
     32  1.1  christos #include <mhddef.h>
     33  1.1  christos #include <credef.h>
     34  1.1  christos #include <descrip.h>
     35  1.1  christos #include <ctype.h>
     36  1.1  christos #if __DECC
     37  1.1  christos #include <unixlib.h>
     38  1.1  christos #include <lbr$routines.h>
     39  1.1  christos #endif
     40  1.1  christos 
     41  1.1  christos static void *VMS_lib_idx;
     42  1.1  christos 
     43  1.1  christos static char *VMS_saved_memname;
     44  1.1  christos 
     45  1.1  christos static time_t VMS_member_date;
     46  1.1  christos 
     47  1.1  christos static long int (*VMS_function) ();
     48  1.1  christos 
     49  1.1  christos static int
     50  1.1  christos VMS_get_member_info (struct dsc$descriptor_s *module, unsigned long *rfa)
     51  1.1  christos {
     52  1.1  christos   int status, i;
     53  1.1  christos   long int fnval;
     54  1.1  christos 
     55  1.1  christos   time_t val;
     56  1.1  christos 
     57  1.1  christos   static struct dsc$descriptor_s bufdesc =
     58  1.1  christos     { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
     59  1.1  christos 
     60  1.1  christos   struct mhddef *mhd;
     61  1.1  christos   char filename[128];
     62  1.1  christos 
     63  1.1  christos   bufdesc.dsc$a_pointer = filename;
     64  1.1  christos   bufdesc.dsc$w_length = sizeof (filename);
     65  1.1  christos 
     66  1.1  christos   status = lbr$set_module (&VMS_lib_idx, rfa, &bufdesc,
     67  1.1  christos 			   &bufdesc.dsc$w_length, 0);
     68  1.1  christos   if (! (status & 1))
     69  1.1  christos     {
     70  1.1  christos       error (NILF, _("lbr$set_module failed to extract module info, status = %d"),
     71  1.1  christos 	     status);
     72  1.1  christos 
     73  1.1  christos       lbr$close (&VMS_lib_idx);
     74  1.1  christos 
     75  1.1  christos       return 0;
     76  1.1  christos     }
     77  1.1  christos 
     78  1.1  christos   mhd = (struct mhddef *) filename;
     79  1.1  christos 
     80  1.1  christos #ifdef __DECC
     81  1.1  christos   /* John Fowler <jfowler (at) nyx.net> writes this is needed in his environment,
     82  1.1  christos    * but that decc$fix_time() isn't documented to work this way.  Let me
     83  1.1  christos    * know if this causes problems in other VMS environments.
     84  1.1  christos    */
     85  1.1  christos   val = decc$fix_time (&mhd->mhd$l_datim) + timezone - daylight*3600;
     86  1.1  christos #endif
     87  1.1  christos 
     88  1.1  christos   for (i = 0; i < module->dsc$w_length; i++)
     89  1.1  christos     filename[i] = _tolower ((unsigned char)module->dsc$a_pointer[i]);
     90  1.1  christos 
     91  1.1  christos   filename[i] = '\0';
     92  1.1  christos 
     93  1.1  christos   VMS_member_date = (time_t) -1;
     94  1.1  christos 
     95  1.1  christos   fnval =
     96  1.1  christos     (*VMS_function) (-1, filename, 0, 0, 0, 0, val, 0, 0, 0,
     97  1.1  christos 		     VMS_saved_memname);
     98  1.1  christos 
     99  1.1  christos   if (fnval)
    100  1.1  christos     {
    101  1.1  christos       VMS_member_date = fnval;
    102  1.1  christos       return 0;
    103  1.1  christos     }
    104  1.1  christos   else
    105  1.1  christos     return 1;
    106  1.1  christos }
    107  1.1  christos 
    108  1.1  christos /* Takes three arguments ARCHIVE, FUNCTION and ARG.
    109  1.1  christos 
    110  1.1  christos    Open the archive named ARCHIVE, find its members one by one,
    111  1.1  christos    and for each one call FUNCTION with the following arguments:
    112  1.1  christos      archive file descriptor for reading the data,
    113  1.1  christos      member name,
    114  1.1  christos      member name might be truncated flag,
    115  1.1  christos      member header position in file,
    116  1.1  christos      member data position in file,
    117  1.1  christos      member data size,
    118  1.1  christos      member date,
    119  1.1  christos      member uid,
    120  1.1  christos      member gid,
    121  1.1  christos      member protection mode,
    122  1.1  christos      ARG.
    123  1.1  christos 
    124  1.1  christos    NOTE: on VMS systems, only name, date, and arg are meaningful!
    125  1.1  christos 
    126  1.1  christos    The descriptor is poised to read the data of the member
    127  1.1  christos    when FUNCTION is called.  It does not matter how much
    128  1.1  christos    data FUNCTION reads.
    129  1.1  christos 
    130  1.1  christos    If FUNCTION returns nonzero, we immediately return
    131  1.1  christos    what FUNCTION returned.
    132  1.1  christos 
    133  1.1  christos    Returns -1 if archive does not exist,
    134  1.1  christos    Returns -2 if archive has invalid format.
    135  1.1  christos    Returns 0 if have scanned successfully.  */
    136  1.1  christos 
    137  1.4     oster long int
    138  1.1  christos ar_scan (char *archive, long int (*function) PARAMS ((int, char *, int, long int, long int, long int, long int, int, int, int, void *)), void *arg)
    139  1.1  christos {
    140  1.1  christos   char *p;
    141  1.1  christos 
    142  1.1  christos   static struct dsc$descriptor_s libdesc =
    143  1.1  christos     { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
    144  1.1  christos 
    145  1.1  christos   unsigned long func = LBR$C_READ;
    146  1.1  christos   unsigned long type = LBR$C_TYP_UNK;
    147  1.1  christos   unsigned long index = 1;
    148  1.1  christos 
    149  1.1  christos   int status;
    150  1.1  christos 
    151  1.1  christos   status = lbr$ini_control (&VMS_lib_idx, &func, &type, 0);
    152  1.1  christos 
    153  1.1  christos   if (! (status & 1))
    154  1.1  christos     {
    155  1.1  christos       error (NILF, _("lbr$ini_control failed with status = %d"),status);
    156  1.1  christos       return -2;
    157  1.1  christos     }
    158  1.1  christos 
    159  1.1  christos   libdesc.dsc$a_pointer = archive;
    160  1.1  christos   libdesc.dsc$w_length = strlen (archive);
    161  1.1  christos 
    162  1.1  christos   status = lbr$open (&VMS_lib_idx, &libdesc, 0, 0, 0, 0, 0);
    163  1.1  christos 
    164  1.1  christos   if (! (status & 1))
    165  1.1  christos     {
    166  1.1  christos       error (NILF, _("unable to open library `%s' to lookup member `%s'"),
    167  1.1  christos 	     archive, (char *)arg);
    168  1.1  christos       return -1;
    169  1.1  christos     }
    170  1.1  christos 
    171  1.1  christos   VMS_saved_memname = (char *)arg;
    172  1.1  christos 
    173  1.1  christos   /* For comparison, delete .obj from arg name.  */
    174  1.1  christos 
    175  1.1  christos   p = strrchr (VMS_saved_memname, '.');
    176  1.1  christos   if (p)
    177  1.1  christos     *p = '\0';
    178  1.1  christos 
    179  1.1  christos   VMS_function = function;
    180  1.1  christos 
    181  1.1  christos   VMS_member_date = (time_t) -1;
    182  1.1  christos   lbr$get_index (&VMS_lib_idx, &index, VMS_get_member_info, 0);
    183  1.1  christos 
    184  1.1  christos   /* Undo the damage.  */
    185  1.1  christos   if (p)
    186  1.1  christos     *p = '.';
    187  1.1  christos 
    188  1.1  christos   lbr$close (&VMS_lib_idx);
    189  1.1  christos 
    190  1.1  christos   return VMS_member_date > 0 ? VMS_member_date : 0;
    191  1.1  christos }
    192  1.1  christos 
    193  1.1  christos #else /* !VMS */
    194  1.1  christos 
    195  1.1  christos /* SCO Unix's compiler defines both of these.  */
    196  1.1  christos #ifdef	M_UNIX
    197  1.1  christos #undef	M_XENIX
    198  1.1  christos #endif
    199  1.1  christos 
    200  1.1  christos /* On the sun386i and in System V rel 3, ar.h defines two different archive
    201  1.1  christos    formats depending upon whether you have defined PORTAR (normal) or PORT5AR
    202  1.1  christos    (System V Release 1).  There is no default, one or the other must be defined
    203  1.1  christos    to have a nonzero value.  */
    204  1.1  christos 
    205  1.1  christos #if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0)
    206  1.1  christos #undef	PORTAR
    207  1.1  christos #ifdef M_XENIX
    208  1.1  christos /* According to Jim Sievert <jas1 (at) rsvl.unisys.com>, for SCO XENIX defining
    209  1.1  christos    PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the
    210  1.1  christos    right one.  */
    211  1.1  christos #define PORTAR 0
    212  1.1  christos #else
    213  1.1  christos #define PORTAR 1
    214  1.1  christos #endif
    215  1.1  christos #endif
    216  1.1  christos 
    217  1.1  christos /* On AIX, define these symbols to be sure to get both archive formats.
    218  1.1  christos    AIX 4.3 introduced the "big" archive format to support 64-bit object
    219  1.1  christos    files, so on AIX 4.3 systems we need to support both the "normal" and
    220  1.1  christos    "big" archive formats.  An archive's format is indicated in the
    221  1.1  christos    "fl_magic" field of the "FL_HDR" structure.  For a normal archive,
    222  1.1  christos    this field will be the string defined by the AIAMAG symbol.  For a
    223  1.1  christos    "big" archive, it will be the string defined by the AIAMAGBIG symbol
    224  1.1  christos    (at least on AIX it works this way).
    225  1.1  christos 
    226  1.1  christos    Note: we'll define these symbols regardless of which AIX version
    227  1.1  christos    we're compiling on, but this is okay since we'll use the new symbols
    228  1.1  christos    only if they're present.  */
    229  1.1  christos #ifdef _AIX
    230  1.1  christos # define __AR_SMALL__
    231  1.1  christos # define __AR_BIG__
    232  1.1  christos #endif
    233  1.1  christos 
    234  1.1  christos #ifndef WINDOWS32
    235  1.1  christos # ifndef __BEOS__
    236  1.1  christos #  include <ar.h>
    237  1.1  christos # else
    238  1.1  christos    /* BeOS 5 doesn't have <ar.h> but has archives in the same format
    239  1.1  christos     * as many other Unices.  This was taken from GNU binutils for BeOS.
    240  1.1  christos     */
    241  1.1  christos #  define ARMAG	"!<arch>\n"	/* String that begins an archive file.  */
    242  1.1  christos #  define SARMAG 8		/* Size of that string.  */
    243  1.1  christos #  define ARFMAG "`\n"		/* String in ar_fmag at end of each header.  */
    244  1.1  christos struct ar_hdr
    245  1.1  christos   {
    246  1.1  christos     char ar_name[16];		/* Member file name, sometimes / terminated. */
    247  1.1  christos     char ar_date[12];		/* File date, decimal seconds since Epoch.  */
    248  1.1  christos     char ar_uid[6], ar_gid[6];	/* User and group IDs, in ASCII decimal.  */
    249  1.1  christos     char ar_mode[8];		/* File mode, in ASCII octal.  */
    250  1.1  christos     char ar_size[10];		/* File size, in ASCII decimal.  */
    251  1.1  christos     char ar_fmag[2];		/* Always contains ARFMAG.  */
    252  1.1  christos   };
    253  1.1  christos # endif
    254  1.1  christos #else
    255  1.1  christos /* These should allow us to read Windows (VC++) libraries (according to Frank
    256  1.1  christos  * Libbrecht <frankl (at) abzx.belgium.hp.com>)
    257  1.1  christos  */
    258  1.1  christos # include <windows.h>
    259  1.1  christos # include <windef.h>
    260  1.1  christos # include <io.h>
    261  1.1  christos # define ARMAG      IMAGE_ARCHIVE_START
    262  1.1  christos # define SARMAG     IMAGE_ARCHIVE_START_SIZE
    263  1.1  christos # define ar_hdr     _IMAGE_ARCHIVE_MEMBER_HEADER
    264  1.1  christos # define ar_name    Name
    265  1.1  christos # define ar_mode    Mode
    266  1.1  christos # define ar_size    Size
    267  1.1  christos # define ar_date    Date
    268  1.1  christos # define ar_uid     UserID
    269  1.1  christos # define ar_gid     GroupID
    270  1.1  christos #endif
    271  1.1  christos 
    272  1.1  christos /* Cray's <ar.h> apparently defines this.  */
    273  1.1  christos #ifndef	AR_HDR_SIZE
    274  1.1  christos # define   AR_HDR_SIZE	(sizeof (struct ar_hdr))
    275  1.1  christos #endif
    276  1.1  christos 
    277  1.1  christos /* Takes three arguments ARCHIVE, FUNCTION and ARG.
    279  1.1  christos 
    280  1.1  christos    Open the archive named ARCHIVE, find its members one by one,
    281  1.1  christos    and for each one call FUNCTION with the following arguments:
    282  1.1  christos      archive file descriptor for reading the data,
    283  1.1  christos      member name,
    284  1.1  christos      member name might be truncated flag,
    285  1.1  christos      member header position in file,
    286  1.1  christos      member data position in file,
    287  1.1  christos      member data size,
    288  1.1  christos      member date,
    289  1.1  christos      member uid,
    290  1.1  christos      member gid,
    291  1.1  christos      member protection mode,
    292  1.1  christos      ARG.
    293  1.1  christos 
    294  1.1  christos    The descriptor is poised to read the data of the member
    295  1.1  christos    when FUNCTION is called.  It does not matter how much
    296  1.1  christos    data FUNCTION reads.
    297  1.1  christos 
    298  1.1  christos    If FUNCTION returns nonzero, we immediately return
    299  1.1  christos    what FUNCTION returned.
    300  1.1  christos 
    301  1.1  christos    Returns -1 if archive does not exist,
    302  1.1  christos    Returns -2 if archive has invalid format.
    303  1.1  christos    Returns 0 if have scanned successfully.  */
    304  1.4     oster 
    305  1.1  christos long int
    306  1.1  christos ar_scan (char *archive, long int (*function)(int, char *, int, long int, long int, long int, long int, int, int, int, void *), void *arg)
    307  1.1  christos {
    308  1.1  christos #ifdef AIAMAG
    309  1.1  christos   FL_HDR fl_header;
    310  1.1  christos #ifdef AIAMAGBIG
    311  1.1  christos   int big_archive = 0;
    312  1.1  christos   FL_HDR_BIG fl_header_big;
    313  1.1  christos #endif
    314  1.1  christos #else
    315  1.1  christos   int long_name = 0;
    316  1.1  christos #endif
    317  1.1  christos   char *namemap = 0;
    318  1.1  christos   register int desc = open (archive, O_RDONLY, 0);
    319  1.1  christos   if (desc < 0)
    320  1.1  christos     return -1;
    321  1.1  christos #ifdef SARMAG
    322  1.1  christos   {
    323  1.1  christos     char buf[SARMAG];
    324  1.1  christos     register int nread = read (desc, buf, SARMAG);
    325  1.1  christos     if (nread != SARMAG || bcmp (buf, ARMAG, SARMAG))
    326  1.1  christos       {
    327  1.1  christos 	(void) close (desc);
    328  1.1  christos 	return -2;
    329  1.1  christos       }
    330  1.1  christos   }
    331  1.1  christos #else
    332  1.1  christos #ifdef AIAMAG
    333  1.1  christos   {
    334  1.1  christos     register int nread = read (desc, (char *) &fl_header, FL_HSZ);
    335  1.1  christos 
    336  1.1  christos     if (nread != FL_HSZ)
    337  1.1  christos       {
    338  1.1  christos 	(void) close (desc);
    339  1.1  christos 	return -2;
    340  1.1  christos       }
    341  1.1  christos #ifdef AIAMAGBIG
    342  1.1  christos     /* If this is a "big" archive, then set the flag and
    343  1.1  christos        re-read the header into the "big" structure. */
    344  1.1  christos     if (!bcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG))
    345  1.1  christos       {
    346  1.1  christos 	big_archive = 1;
    347  1.1  christos 
    348  1.1  christos 	/* seek back to beginning of archive */
    349  1.1  christos 	if (lseek (desc, 0, 0) < 0)
    350  1.1  christos 	  {
    351  1.1  christos 	    (void) close (desc);
    352  1.1  christos 	    return -2;
    353  1.1  christos 	  }
    354  1.1  christos 
    355  1.1  christos 	/* re-read the header into the "big" structure */
    356  1.1  christos 	nread = read (desc, (char *) &fl_header_big, FL_HSZ_BIG);
    357  1.1  christos 	if (nread != FL_HSZ_BIG)
    358  1.1  christos 	  {
    359  1.1  christos 	    (void) close (desc);
    360  1.1  christos 	    return -2;
    361  1.1  christos 	  }
    362  1.1  christos       }
    363  1.1  christos     else
    364  1.1  christos #endif
    365  1.1  christos        /* Check to make sure this is a "normal" archive. */
    366  1.1  christos       if (bcmp (fl_header.fl_magic, AIAMAG, SAIAMAG))
    367  1.1  christos 	{
    368  1.1  christos           (void) close (desc);
    369  1.1  christos           return -2;
    370  1.1  christos 	}
    371  1.1  christos   }
    372  1.1  christos #else
    373  1.1  christos   {
    374  1.1  christos #ifndef M_XENIX
    375  1.1  christos     int buf;
    376  1.1  christos #else
    377  1.1  christos     unsigned short int buf;
    378  1.1  christos #endif
    379  1.1  christos     register int nread = read(desc, &buf, sizeof (buf));
    380  1.1  christos     if (nread != sizeof (buf) || buf != ARMAG)
    381  1.1  christos       {
    382  1.1  christos 	(void) close (desc);
    383  1.1  christos 	return -2;
    384  1.1  christos       }
    385  1.1  christos   }
    386  1.1  christos #endif
    387  1.1  christos #endif
    388  1.1  christos 
    389  1.1  christos   /* Now find the members one by one.  */
    390  1.1  christos   {
    391  1.1  christos #ifdef SARMAG
    392  1.1  christos     register long int member_offset = SARMAG;
    393  1.1  christos #else
    394  1.1  christos #ifdef AIAMAG
    395  1.1  christos     long int member_offset;
    396  1.1  christos     long int last_member_offset;
    397  1.1  christos 
    398  1.1  christos #ifdef AIAMAGBIG
    399  1.1  christos     if ( big_archive )
    400  1.1  christos       {
    401  1.1  christos 	sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset);
    402  1.1  christos 	sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset);
    403  1.1  christos       }
    404  1.1  christos     else
    405  1.1  christos #endif
    406  1.1  christos       {
    407  1.1  christos 	sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset);
    408  1.1  christos 	sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset);
    409  1.1  christos       }
    410  1.1  christos 
    411  1.1  christos     if (member_offset == 0)
    412  1.1  christos       {
    413  1.1  christos 	/* Empty archive.  */
    414  1.1  christos 	close (desc);
    415  1.1  christos 	return 0;
    416  1.1  christos       }
    417  1.1  christos #else
    418  1.1  christos #ifndef	M_XENIX
    419  1.1  christos     register long int member_offset = sizeof (int);
    420  1.1  christos #else	/* Xenix.  */
    421  1.1  christos     register long int member_offset = sizeof (unsigned short int);
    422  1.1  christos #endif	/* Not Xenix.  */
    423  1.1  christos #endif
    424  1.1  christos #endif
    425  1.1  christos 
    426  1.1  christos     while (1)
    427  1.1  christos       {
    428  1.1  christos 	register int nread;
    429  1.1  christos 	struct ar_hdr member_header;
    430  1.1  christos #ifdef AIAMAGBIG
    431  1.1  christos 	struct ar_hdr_big member_header_big;
    432  1.1  christos #endif
    433  1.1  christos #ifdef AIAMAG
    434  1.1  christos 	char name[256];
    435  1.1  christos 	int name_len;
    436  1.1  christos 	long int dateval;
    437  1.1  christos 	int uidval, gidval;
    438  1.1  christos 	long int data_offset;
    439  1.1  christos #else
    440  1.1  christos 	char namebuf[sizeof member_header.ar_name + 1];
    441  1.1  christos 	char *name;
    442  1.1  christos 	int is_namemap;		/* Nonzero if this entry maps long names.  */
    443  1.1  christos #endif
    444  1.1  christos 	long int eltsize;
    445  1.1  christos 	int eltmode;
    446  1.1  christos 	long int fnval;
    447  1.1  christos 
    448  1.1  christos 	if (lseek (desc, member_offset, 0) < 0)
    449  1.1  christos 	  {
    450  1.1  christos 	    (void) close (desc);
    451  1.1  christos 	    return -2;
    452  1.1  christos 	  }
    453  1.1  christos 
    454  1.1  christos #ifdef AIAMAG
    455  1.1  christos #define       AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
    456  1.1  christos 
    457  1.1  christos #ifdef AIAMAGBIG
    458  1.1  christos 	if (big_archive)
    459  1.1  christos 	  {
    460  1.1  christos 	    nread = read (desc, (char *) &member_header_big,
    461  1.1  christos 			  AR_MEMHDR_SZ(member_header_big) );
    462  1.1  christos 
    463  1.1  christos 	    if (nread != AR_MEMHDR_SZ(member_header_big))
    464  1.1  christos 	      {
    465  1.1  christos 		(void) close (desc);
    466  1.1  christos 		return -2;
    467  1.1  christos 	      }
    468  1.1  christos 
    469  1.1  christos 	    sscanf (member_header_big.ar_namlen, "%4d", &name_len);
    470  1.1  christos 	    nread = read (desc, name, name_len);
    471  1.1  christos 
    472  1.1  christos 	    if (nread != name_len)
    473  1.1  christos 	      {
    474  1.1  christos 		(void) close (desc);
    475  1.1  christos 		return -2;
    476  1.1  christos 	      }
    477  1.1  christos 
    478  1.1  christos 	    name[name_len] = 0;
    479  1.1  christos 
    480  1.1  christos 	    sscanf (member_header_big.ar_date, "%12ld", &dateval);
    481  1.1  christos 	    sscanf (member_header_big.ar_uid, "%12d", &uidval);
    482  1.1  christos 	    sscanf (member_header_big.ar_gid, "%12d", &gidval);
    483  1.1  christos 	    sscanf (member_header_big.ar_mode, "%12o", &eltmode);
    484  1.1  christos 	    sscanf (member_header_big.ar_size, "%20ld", &eltsize);
    485  1.1  christos 
    486  1.1  christos 	    data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big)
    487  1.1  christos 			   + name_len + 2);
    488  1.1  christos 	  }
    489  1.1  christos 	else
    490  1.1  christos #endif
    491  1.1  christos 	  {
    492  1.1  christos 	    nread = read (desc, (char *) &member_header,
    493  1.1  christos 			  AR_MEMHDR_SZ(member_header) );
    494  1.1  christos 
    495  1.1  christos 	    if (nread != AR_MEMHDR_SZ(member_header))
    496  1.1  christos 	      {
    497  1.1  christos 		(void) close (desc);
    498  1.1  christos 		return -2;
    499  1.1  christos 	      }
    500  1.1  christos 
    501  1.1  christos 	    sscanf (member_header.ar_namlen, "%4d", &name_len);
    502  1.1  christos 	    nread = read (desc, name, name_len);
    503  1.1  christos 
    504  1.1  christos 	    if (nread != name_len)
    505  1.1  christos 	      {
    506  1.1  christos 		(void) close (desc);
    507  1.1  christos 		return -2;
    508  1.1  christos 	      }
    509  1.1  christos 
    510  1.1  christos 	    name[name_len] = 0;
    511  1.1  christos 
    512  1.1  christos 	    sscanf (member_header.ar_date, "%12ld", &dateval);
    513  1.1  christos 	    sscanf (member_header.ar_uid, "%12d", &uidval);
    514  1.1  christos 	    sscanf (member_header.ar_gid, "%12d", &gidval);
    515  1.1  christos 	    sscanf (member_header.ar_mode, "%12o", &eltmode);
    516  1.1  christos 	    sscanf (member_header.ar_size, "%12ld", &eltsize);
    517  1.1  christos 
    518  1.1  christos 	    data_offset = (member_offset + AR_MEMHDR_SZ(member_header)
    519  1.1  christos 			   + name_len + 2);
    520  1.1  christos 	  }
    521  1.1  christos 	data_offset += data_offset % 2;
    522  1.1  christos 
    523  1.1  christos 	fnval =
    524  1.1  christos 	  (*function) (desc, name, 0,
    525  1.1  christos 		       member_offset, data_offset, eltsize,
    526  1.1  christos 		       dateval, uidval, gidval,
    527  1.1  christos 		       eltmode, arg);
    528  1.1  christos 
    529  1.1  christos #else	/* Not AIAMAG.  */
    530  1.1  christos 	nread = read (desc, (char *) &member_header, AR_HDR_SIZE);
    531  1.1  christos 	if (nread == 0)
    532  1.1  christos 	  /* No data left means end of file; that is OK.  */
    533  1.1  christos 	  break;
    534  1.1  christos 
    535  1.1  christos 	if (nread != AR_HDR_SIZE
    536  1.1  christos #if defined(ARFMAG) || defined(ARFZMAG)
    537  1.1  christos 	    || (
    538  1.1  christos # ifdef ARFMAG
    539  1.1  christos                 bcmp (member_header.ar_fmag, ARFMAG, 2)
    540  1.1  christos # else
    541  1.1  christos                 1
    542  1.1  christos # endif
    543  1.1  christos                 &&
    544  1.1  christos # ifdef ARFZMAG
    545  1.1  christos                 bcmp (member_header.ar_fmag, ARFZMAG, 2)
    546  1.1  christos # else
    547  1.1  christos                 1
    548  1.1  christos # endif
    549  1.1  christos                )
    550  1.1  christos #endif
    551  1.1  christos 	    )
    552  1.1  christos 	  {
    553  1.1  christos 	    (void) close (desc);
    554  1.1  christos 	    return -2;
    555  1.1  christos 	  }
    556  1.1  christos 
    557  1.1  christos 	name = namebuf;
    558  1.1  christos 	bcopy (member_header.ar_name, name, sizeof member_header.ar_name);
    559  1.1  christos 	{
    560  1.1  christos 	  register char *p = name + sizeof member_header.ar_name;
    561  1.1  christos 	  do
    562  1.1  christos 	    *p = '\0';
    563  1.1  christos 	  while (p > name && *--p == ' ');
    564  1.1  christos 
    565  1.1  christos #ifndef AIAMAG
    566  1.1  christos 	  /* If the member name is "//" or "ARFILENAMES/" this may be
    567  1.1  christos 	     a list of file name mappings.  The maximum file name
    568  1.1  christos  	     length supported by the standard archive format is 14
    569  1.1  christos  	     characters.  This member will actually always be the
    570  1.1  christos  	     first or second entry in the archive, but we don't check
    571  1.1  christos  	     that.  */
    572  1.1  christos  	  is_namemap = (!strcmp (name, "//")
    573  1.1  christos 			|| !strcmp (name, "ARFILENAMES/"));
    574  1.1  christos #endif	/* Not AIAMAG. */
    575  1.1  christos 	  /* On some systems, there is a slash after each member name.  */
    576  1.1  christos 	  if (*p == '/')
    577  1.1  christos 	    *p = '\0';
    578  1.1  christos 
    579  1.1  christos #ifndef AIAMAG
    580  1.1  christos  	  /* If the member name starts with a space or a slash, this
    581  1.1  christos  	     is an index into the file name mappings (used by GNU ar).
    582  1.1  christos  	     Otherwise if the member name looks like #1/NUMBER the
    583  1.1  christos  	     real member name appears in the element data (used by
    584  1.1  christos  	     4.4BSD).  */
    585  1.1  christos  	  if (! is_namemap
    586  1.1  christos  	      && (name[0] == ' ' || name[0] == '/')
    587  1.1  christos  	      && namemap != 0)
    588  1.1  christos 	    {
    589  1.1  christos 	      name = namemap + atoi (name + 1);
    590  1.1  christos 	      long_name = 1;
    591  1.1  christos 	    }
    592  1.1  christos  	  else if (name[0] == '#'
    593  1.1  christos  		   && name[1] == '1'
    594  1.1  christos  		   && name[2] == '/')
    595  1.1  christos  	    {
    596  1.1  christos  	      int namesize = atoi (name + 3);
    597  1.1  christos 
    598  1.1  christos  	      name = (char *) alloca (namesize + 1);
    599  1.1  christos  	      nread = read (desc, name, namesize);
    600  1.1  christos  	      if (nread != namesize)
    601  1.1  christos  		{
    602  1.1  christos  		  close (desc);
    603  1.1  christos  		  return -2;
    604  1.1  christos  		}
    605  1.1  christos  	      name[namesize] = '\0';
    606  1.1  christos 
    607  1.1  christos 	      long_name = 1;
    608  1.1  christos  	    }
    609  1.1  christos #endif /* Not AIAMAG. */
    610  1.1  christos 	}
    611  1.1  christos 
    612  1.1  christos #ifndef	M_XENIX
    613  1.1  christos 	sscanf (member_header.ar_mode, "%o", &eltmode);
    614  1.1  christos 	eltsize = atol (member_header.ar_size);
    615  1.1  christos #else	/* Xenix.  */
    616  1.1  christos 	eltmode = (unsigned short int) member_header.ar_mode;
    617  1.1  christos 	eltsize = member_header.ar_size;
    618  1.1  christos #endif	/* Not Xenix.  */
    619  1.1  christos 
    620  1.1  christos 	fnval =
    621  1.1  christos 	  (*function) (desc, name, ! long_name, member_offset,
    622  1.1  christos 		       member_offset + AR_HDR_SIZE, eltsize,
    623  1.1  christos #ifndef	M_XENIX
    624  1.1  christos 		       atol (member_header.ar_date),
    625  1.1  christos 		       atoi (member_header.ar_uid),
    626  1.1  christos 		       atoi (member_header.ar_gid),
    627  1.1  christos #else	/* Xenix.  */
    628  1.1  christos 		       member_header.ar_date,
    629  1.1  christos 		       member_header.ar_uid,
    630  1.1  christos 		       member_header.ar_gid,
    631  1.1  christos #endif	/* Not Xenix.  */
    632  1.1  christos 		       eltmode, arg);
    633  1.1  christos 
    634  1.1  christos #endif  /* AIAMAG.  */
    635  1.1  christos 
    636  1.1  christos 	if (fnval)
    637  1.1  christos 	  {
    638  1.1  christos 	    (void) close (desc);
    639  1.1  christos 	    return fnval;
    640  1.1  christos 	  }
    641  1.1  christos 
    642  1.1  christos #ifdef AIAMAG
    643  1.1  christos 	if (member_offset == last_member_offset)
    644  1.1  christos 	  /* End of the chain.  */
    645  1.1  christos 	  break;
    646  1.1  christos 
    647  1.1  christos #ifdef AIAMAGBIG
    648  1.1  christos 	if (big_archive)
    649  1.1  christos           sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset);
    650  1.1  christos 	else
    651  1.1  christos #endif
    652  1.1  christos 	  sscanf (member_header.ar_nxtmem, "%12ld", &member_offset);
    653  1.1  christos 
    654  1.1  christos 	if (lseek (desc, member_offset, 0) != member_offset)
    655  1.1  christos 	  {
    656  1.1  christos 	    (void) close (desc);
    657  1.1  christos 	    return -2;
    658  1.1  christos 	  }
    659  1.1  christos #else
    660  1.1  christos 
    661  1.1  christos  	/* If this member maps archive names, we must read it in.  The
    662  1.1  christos  	   name map will always precede any members whose names must
    663  1.1  christos  	   be mapped.  */
    664  1.1  christos 	if (is_namemap)
    665  1.1  christos  	  {
    666  1.1  christos  	    char *clear;
    667  1.1  christos  	    char *limit;
    668  1.1  christos 
    669  1.1  christos  	    namemap = (char *) alloca (eltsize);
    670  1.1  christos  	    nread = read (desc, namemap, eltsize);
    671  1.1  christos  	    if (nread != eltsize)
    672  1.1  christos  	      {
    673  1.1  christos  		(void) close (desc);
    674  1.1  christos  		return -2;
    675  1.1  christos  	      }
    676  1.1  christos 
    677  1.1  christos  	    /* The names are separated by newlines.  Some formats have
    678  1.1  christos  	       a trailing slash.  Null terminate the strings for
    679  1.1  christos  	       convenience.  */
    680  1.1  christos  	    limit = namemap + eltsize;
    681  1.1  christos  	    for (clear = namemap; clear < limit; clear++)
    682  1.1  christos  	      {
    683  1.1  christos  		if (*clear == '\n')
    684  1.1  christos  		  {
    685  1.1  christos  		    *clear = '\0';
    686  1.1  christos  		    if (clear[-1] == '/')
    687  1.1  christos  		      clear[-1] = '\0';
    688  1.1  christos  		  }
    689  1.1  christos  	      }
    690  1.1  christos 
    691  1.1  christos 	    is_namemap = 0;
    692  1.1  christos  	  }
    693  1.1  christos 
    694  1.1  christos 	member_offset += AR_HDR_SIZE + eltsize;
    695  1.1  christos 	if (member_offset % 2 != 0)
    696  1.1  christos 	  member_offset++;
    697  1.1  christos #endif
    698  1.1  christos       }
    699  1.1  christos   }
    700  1.1  christos 
    701  1.1  christos   close (desc);
    702  1.1  christos   return 0;
    703  1.1  christos }
    704  1.1  christos #endif /* !VMS */
    705  1.1  christos 
    706  1.1  christos /* Return nonzero iff NAME matches MEM.
    708  1.1  christos    If TRUNCATED is nonzero, MEM may be truncated to
    709  1.1  christos    sizeof (struct ar_hdr.ar_name) - 1.  */
    710  1.1  christos 
    711  1.1  christos int
    712  1.1  christos ar_name_equal (char *name, char *mem, int truncated)
    713  1.1  christos {
    714  1.1  christos   char *p;
    715  1.1  christos 
    716  1.1  christos   p = strrchr (name, '/');
    717  1.1  christos   if (p != 0)
    718  1.1  christos     name = p + 1;
    719  1.1  christos 
    720  1.1  christos #ifndef VMS
    721  1.1  christos   if (truncated)
    722  1.1  christos     {
    723  1.1  christos #ifdef AIAMAG
    724  1.1  christos       /* TRUNCATED should never be set on this system.  */
    725  1.1  christos       abort ();
    726  1.1  christos #else
    727  1.1  christos       struct ar_hdr hdr;
    728  1.1  christos #if !defined (__hpux) && !defined (cray)
    729  1.1  christos       return strneq (name, mem, sizeof(hdr.ar_name) - 1);
    730  1.1  christos #else
    731  1.1  christos       return strneq (name, mem, sizeof(hdr.ar_name) - 2);
    732  1.1  christos #endif /* !__hpux && !cray */
    733  1.1  christos #endif /* !AIAMAG */
    734  1.1  christos     }
    735  1.1  christos #endif /* !VMS */
    736  1.1  christos 
    737  1.1  christos   return !strcmp (name, mem);
    738  1.1  christos }
    739  1.1  christos 
    740  1.1  christos #ifndef VMS
    742  1.1  christos /* ARGSUSED */
    743  1.4     oster static long int
    744  1.1  christos ar_member_pos (int desc UNUSED, char *mem, int truncated,
    745  1.1  christos 	       long int hdrpos, long int datapos UNUSED, long int size UNUSED,
    746  1.1  christos                long int date UNUSED, int uid UNUSED, int gid UNUSED,
    747  1.1  christos                int mode UNUSED, void *name)
    748  1.1  christos {
    749  1.1  christos   if (!ar_name_equal (name, mem, truncated))
    750  1.1  christos     return 0;
    751  1.1  christos   return hdrpos;
    752  1.1  christos }
    753  1.1  christos 
    754  1.1  christos /* Set date of member MEMNAME in archive ARNAME to current time.
    755  1.1  christos    Returns 0 if successful,
    756  1.1  christos    -1 if file ARNAME does not exist,
    757  1.1  christos    -2 if not a valid archive,
    758  1.1  christos    -3 if other random system call error (including file read-only),
    759  1.1  christos    1 if valid but member MEMNAME does not exist.  */
    760  1.4     oster 
    761  1.1  christos int
    762  1.1  christos ar_member_touch (char *arname, char *memname)
    763  1.1  christos {
    764  1.1  christos   long int pos = ar_scan (arname, ar_member_pos, memname);
    765  1.1  christos   int fd;
    766  1.1  christos   struct ar_hdr ar_hdr;
    767  1.1  christos   int i;
    768  1.1  christos   unsigned int ui;
    769  1.1  christos   struct stat statbuf;
    770  1.1  christos 
    771  1.1  christos   if (pos < 0)
    772  1.1  christos     return (int) pos;
    773  1.1  christos   if (!pos)
    774  1.1  christos     return 1;
    775  1.1  christos 
    776  1.1  christos   fd = open (arname, O_RDWR, 0666);
    777  1.1  christos   if (fd < 0)
    778  1.1  christos     return -3;
    779  1.1  christos   /* Read in this member's header */
    780  1.1  christos   if (lseek (fd, pos, 0) < 0)
    781  1.1  christos     goto lose;
    782  1.1  christos   if (AR_HDR_SIZE != read (fd, (char *) &ar_hdr, AR_HDR_SIZE))
    783  1.1  christos     goto lose;
    784  1.1  christos   /* Write back the header, thus touching the archive file.  */
    785  1.1  christos   if (lseek (fd, pos, 0) < 0)
    786  1.1  christos     goto lose;
    787  1.1  christos   if (AR_HDR_SIZE != write (fd, (char *) &ar_hdr, AR_HDR_SIZE))
    788  1.1  christos     goto lose;
    789  1.1  christos   /* The file's mtime is the time we we want.  */
    790  1.1  christos   EINTRLOOP (i, fstat (fd, &statbuf));
    791  1.1  christos   if (i < 0)
    792  1.1  christos     goto lose;
    793  1.1  christos #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
    794  1.1  christos   /* Advance member's time to that time */
    795  1.1  christos   for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++)
    796  1.1  christos     ar_hdr.ar_date[ui] = ' ';
    797  1.1  christos   sprintf (ar_hdr.ar_date, "%ld", (long int) statbuf.st_mtime);
    798  1.1  christos #ifdef AIAMAG
    799  1.1  christos   ar_hdr.ar_date[strlen(ar_hdr.ar_date)] = ' ';
    800  1.1  christos #endif
    801  1.1  christos #else
    802  1.1  christos   ar_hdr.ar_date = statbuf.st_mtime;
    803  1.1  christos #endif
    804  1.1  christos   /* Write back this member's header */
    805  1.1  christos   if (lseek (fd, pos, 0) < 0)
    806  1.1  christos     goto lose;
    807  1.1  christos   if (AR_HDR_SIZE != write (fd, (char *) &ar_hdr, AR_HDR_SIZE))
    808  1.1  christos     goto lose;
    809  1.1  christos   close (fd);
    810  1.1  christos   return 0;
    811  1.1  christos 
    812  1.1  christos  lose:
    813  1.1  christos   i = errno;
    814  1.1  christos   close (fd);
    815  1.1  christos   errno = i;
    816  1.1  christos   return -3;
    817  1.1  christos }
    818  1.1  christos #endif
    819  1.1  christos 
    820  1.1  christos #ifdef TEST
    822  1.1  christos 
    823  1.1  christos long int
    824  1.1  christos describe_member (int desc, char *name, int truncated,
    825  1.1  christos 		 long int hdrpos, long int datapos, long int size,
    826  1.1  christos                  long int date, int uid, int gid, int mode)
    827  1.1  christos {
    828  1.1  christos   extern char *ctime ();
    829  1.1  christos 
    830  1.1  christos   printf (_("Member `%s'%s: %ld bytes at %ld (%ld).\n"),
    831  1.1  christos 	  name, truncated ? _(" (name might be truncated)") : "",
    832  1.1  christos 	  size, hdrpos, datapos);
    833  1.1  christos   printf (_("  Date %s"), ctime (&date));
    834  1.1  christos   printf (_("  uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode);
    835  1.1  christos 
    836  1.1  christos   return 0;
    837  1.1  christos }
    838  1.1  christos 
    839  1.1  christos int
    840  1.1  christos main (int argc, char **argv)
    841  1.1  christos {
    842  1.1  christos   ar_scan (argv[1], describe_member);
    843                  return 0;
    844                }
    845                
    846                #endif	/* TEST.  */
    847                #endif	/* NO_ARCHIVES.  */
    848