1 /* Library function for scanning an archive file.
2 Copyright (C) 1987,89,91,92,93,94,95,97 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
37 #include <lbr$routines.h>
40 static void *VMS_lib_idx
;
42 static char *VMS_saved_memname
;
44 static time_t VMS_member_date
;
46 static long int (*VMS_function
) ();
49 VMS_get_member_info (module
, rfa
)
50 struct dsc$descriptor_s
*module
;
58 static struct dsc$descriptor_s bufdesc
=
59 { 0, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, NULL
};
64 bufdesc
.dsc$a_pointer
= filename
;
65 bufdesc
.dsc$w_length
= sizeof (filename
);
67 status
= lbr$
set_module (&VMS_lib_idx
, rfa
, &bufdesc
,
68 &bufdesc
.dsc$w_length
, 0);
71 error (NILF
, _("lbr$set_module failed to extract module info, status = %d"),
74 lbr$
close (&VMS_lib_idx
);
79 mhd
= (struct mhddef
*) filename
;
82 /* John Fowler <jfowler@nyx.net> writes this is needed in his environment,
83 * but that decc$fix_time() isn't documented to work this way. Let me
84 * know if this causes problems in other VMS environments.
86 val
= decc$
fix_time (&mhd
->mhd$l_datim
) + timezone
- daylight
*3600;
89 for (i
= 0; i
< module
->dsc$w_length
; i
++)
90 filename
[i
] = _tolower ((unsigned char)module
->dsc$a_pointer
[i
]);
94 VMS_member_date
= (time_t) -1;
97 (*VMS_function
) (-1, filename
, 0, 0, 0, 0, val
, 0, 0, 0,
102 VMS_member_date
= fnval
;
109 /* Takes three arguments ARCHIVE, FUNCTION and ARG.
111 Open the archive named ARCHIVE, find its members one by one,
112 and for each one call FUNCTION with the following arguments:
113 archive file descriptor for reading the data,
115 member name might be truncated flag,
116 member header position in file,
117 member data position in file,
122 member protection mode,
125 NOTE: on VMS systems, only name, date, and arg are meaningful!
127 The descriptor is poised to read the data of the member
128 when FUNCTION is called. It does not matter how much
131 If FUNCTION returns nonzero, we immediately return
132 what FUNCTION returned.
134 Returns -1 if archive does not exist,
135 Returns -2 if archive has invalid format.
136 Returns 0 if have scanned successfully. */
139 ar_scan (archive
, function
, arg
)
141 long int (*function
) ();
146 static struct dsc$descriptor_s libdesc
=
147 { 0, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, NULL
};
149 unsigned long func
= LBR$C_READ
;
150 unsigned long type
= LBR$C_TYP_UNK
;
151 unsigned long index
= 1;
155 status
= lbr$
ini_control (&VMS_lib_idx
, &func
, &type
, 0);
159 error (NILF
, _("lbr$ini_control failed with status = %d"),status
);
163 libdesc
.dsc$a_pointer
= archive
;
164 libdesc
.dsc$w_length
= strlen (archive
);
166 status
= lbr$
open (&VMS_lib_idx
, &libdesc
, 0, 0, 0, 0, 0);
170 error (NILF
, _("unable to open library `%s' to lookup member `%s'"),
171 archive
, (char *)arg
);
175 VMS_saved_memname
= (char *)arg
;
177 /* For comparison, delete .obj from arg name. */
179 p
= strrchr (VMS_saved_memname
, '.');
183 VMS_function
= function
;
185 VMS_member_date
= (time_t) -1;
186 lbr$
get_index (&VMS_lib_idx
, &index
, VMS_get_member_info
, 0);
188 /* Undo the damage. */
192 lbr$
close (&VMS_lib_idx
);
194 return VMS_member_date
> 0 ? VMS_member_date
: 0;
199 /* SCO Unix's compiler defines both of these. */
204 /* On the sun386i and in System V rel 3, ar.h defines two different archive
205 formats depending upon whether you have defined PORTAR (normal) or PORT5AR
206 (System V Release 1). There is no default, one or the other must be defined
207 to have a nonzero value. */
209 #if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0)
212 /* According to Jim Sievert <jas1@rsvl.unisys.com>, for SCO XENIX defining
213 PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the
221 /* On AIX, define these symbols to be sure to get both archive formats.
222 AIX 4.3 introduced the "big" archive format to support 64-bit object
223 files, so on AIX 4.3 systems we need to support both the "normal" and
224 "big" archive formats. An archive's format is indicated in the
225 "fl_magic" field of the "FL_HDR" structure. For a normal archive,
226 this field will be the string defined by the AIAMAG symbol. For a
227 "big" archive, it will be the string defined by the AIAMAGBIG symbol
228 (at least on AIX it works this way).
230 Note: we'll define these symbols regardless of which AIX version
231 we're compiling on, but this is okay since we'll use the new symbols
232 only if they're present. */
234 # define __AR_SMALL__
242 /* BeOS 5 doesn't have <ar.h> but has archives in the same format
243 * as many other Unices. This was taken from GNU binutils for BeOS.
245 # define ARMAG "!<arch>\n" /* String that begins an archive file. */
246 # define SARMAG 8 /* Size of that string. */
247 # define ARFMAG "`\n" /* String in ar_fmag at end of each header. */
250 char ar_name
[16]; /* Member file name, sometimes / terminated. */
251 char ar_date
[12]; /* File date, decimal seconds since Epoch. */
252 char ar_uid
[6], ar_gid
[6]; /* User and group IDs, in ASCII decimal. */
253 char ar_mode
[8]; /* File mode, in ASCII octal. */
254 char ar_size
[10]; /* File size, in ASCII decimal. */
255 char ar_fmag
[2]; /* Always contains ARFMAG. */
259 /* These should allow us to read Windows (VC++) libraries (according to Frank
260 * Libbrecht <frankl@abzx.belgium.hp.com>)
262 # include <windows.h>
265 # define ARMAG IMAGE_ARCHIVE_START
266 # define SARMAG IMAGE_ARCHIVE_START_SIZE
267 # define ar_hdr _IMAGE_ARCHIVE_MEMBER_HEADER
268 # define ar_name Name
269 # define ar_mode Mode
270 # define ar_size Size
271 # define ar_date Date
272 # define ar_uid UserID
273 # define ar_gid GroupID
276 /* Cray's <ar.h> apparently defines this. */
278 # define AR_HDR_SIZE (sizeof (struct ar_hdr))
281 /* Takes three arguments ARCHIVE, FUNCTION and ARG.
283 Open the archive named ARCHIVE, find its members one by one,
284 and for each one call FUNCTION with the following arguments:
285 archive file descriptor for reading the data,
287 member name might be truncated flag,
288 member header position in file,
289 member data position in file,
294 member protection mode,
297 The descriptor is poised to read the data of the member
298 when FUNCTION is called. It does not matter how much
301 If FUNCTION returns nonzero, we immediately return
302 what FUNCTION returned.
304 Returns -1 if archive does not exist,
305 Returns -2 if archive has invalid format.
306 Returns 0 if have scanned successfully. */
309 ar_scan (archive
, function
, arg
)
311 long int (*function
) ();
318 FL_HDR_BIG fl_header_big
;
324 register int desc
= open (archive
, O_RDONLY
, 0);
330 register int nread
= read (desc
, buf
, SARMAG
);
331 if (nread
!= SARMAG
|| bcmp (buf
, ARMAG
, SARMAG
))
340 register int nread
= read (desc
, (char *) &fl_header
, FL_HSZ
);
348 /* If this is a "big" archive, then set the flag and
349 re-read the header into the "big" structure. */
350 if (!bcmp (fl_header
.fl_magic
, AIAMAGBIG
, SAIAMAG
))
354 /* seek back to beginning of archive */
355 if (lseek (desc
, 0, 0) < 0)
361 /* re-read the header into the "big" structure */
362 nread
= read (desc
, (char *) &fl_header_big
, FL_HSZ_BIG
);
363 if (nread
!= FL_HSZ_BIG
)
371 /* Check to make sure this is a "normal" archive. */
372 if (bcmp (fl_header
.fl_magic
, AIAMAG
, SAIAMAG
))
383 unsigned short int buf
;
385 register int nread
= read(desc
, &buf
, sizeof (buf
));
386 if (nread
!= sizeof (buf
) || buf
!= ARMAG
)
395 /* Now find the members one by one. */
398 register long int member_offset
= SARMAG
;
401 long int member_offset
;
402 long int last_member_offset
;
407 sscanf (fl_header_big
.fl_fstmoff
, "%20ld", &member_offset
);
408 sscanf (fl_header_big
.fl_lstmoff
, "%20ld", &last_member_offset
);
413 sscanf (fl_header
.fl_fstmoff
, "%12ld", &member_offset
);
414 sscanf (fl_header
.fl_lstmoff
, "%12ld", &last_member_offset
);
417 if (member_offset
== 0)
425 register long int member_offset
= sizeof (int);
427 register long int member_offset
= sizeof (unsigned short int);
428 #endif /* Not Xenix. */
435 struct ar_hdr member_header
;
437 struct ar_hdr_big member_header_big
;
444 long int data_offset
;
446 char namebuf
[sizeof member_header
.ar_name
+ 1];
448 int is_namemap
; /* Nonzero if this entry maps long names. */
454 if (lseek (desc
, member_offset
, 0) < 0)
461 #define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
466 nread
= read (desc
, (char *) &member_header_big
,
467 AR_MEMHDR_SZ(member_header_big
) );
469 if (nread
!= AR_MEMHDR_SZ(member_header_big
))
475 sscanf (member_header_big
.ar_namlen
, "%4d", &name_len
);
476 nread
= read (desc
, name
, name_len
);
478 if (nread
!= name_len
)
486 sscanf (member_header_big
.ar_date
, "%12ld", &dateval
);
487 sscanf (member_header_big
.ar_uid
, "%12d", &uidval
);
488 sscanf (member_header_big
.ar_gid
, "%12d", &gidval
);
489 sscanf (member_header_big
.ar_mode
, "%12o", &eltmode
);
490 sscanf (member_header_big
.ar_size
, "%20ld", &eltsize
);
492 data_offset
= (member_offset
+ AR_MEMHDR_SZ(member_header_big
)
498 nread
= read (desc
, (char *) &member_header
,
499 AR_MEMHDR_SZ(member_header
) );
501 if (nread
!= AR_MEMHDR_SZ(member_header
))
507 sscanf (member_header
.ar_namlen
, "%4d", &name_len
);
508 nread
= read (desc
, name
, name_len
);
510 if (nread
!= name_len
)
518 sscanf (member_header
.ar_date
, "%12ld", &dateval
);
519 sscanf (member_header
.ar_uid
, "%12d", &uidval
);
520 sscanf (member_header
.ar_gid
, "%12d", &gidval
);
521 sscanf (member_header
.ar_mode
, "%12o", &eltmode
);
522 sscanf (member_header
.ar_size
, "%12ld", &eltsize
);
524 data_offset
= (member_offset
+ AR_MEMHDR_SZ(member_header
)
527 data_offset
+= data_offset
% 2;
530 (*function
) (desc
, name
, 0,
531 member_offset
, data_offset
, eltsize
,
532 dateval
, uidval
, gidval
,
535 #else /* Not AIAMAG. */
536 nread
= read (desc
, (char *) &member_header
, AR_HDR_SIZE
);
538 /* No data left means end of file; that is OK. */
541 if (nread
!= AR_HDR_SIZE
542 #if defined(ARFMAG) || defined(ARFZMAG)
545 bcmp (member_header
.ar_fmag
, ARFMAG
, 2)
551 bcmp (member_header
.ar_fmag
, ARFZMAG
, 2)
564 bcopy (member_header
.ar_name
, name
, sizeof member_header
.ar_name
);
566 register char *p
= name
+ sizeof member_header
.ar_name
;
569 while (p
> name
&& *--p
== ' ');
572 /* If the member name is "//" or "ARFILENAMES/" this may be
573 a list of file name mappings. The maximum file name
574 length supported by the standard archive format is 14
575 characters. This member will actually always be the
576 first or second entry in the archive, but we don't check
578 is_namemap
= (!strcmp (name
, "//")
579 || !strcmp (name
, "ARFILENAMES/"));
580 #endif /* Not AIAMAG. */
581 /* On some systems, there is a slash after each member name. */
586 /* If the member name starts with a space or a slash, this
587 is an index into the file name mappings (used by GNU ar).
588 Otherwise if the member name looks like #1/NUMBER the
589 real member name appears in the element data (used by
592 && (name
[0] == ' ' || name
[0] == '/')
595 name
= namemap
+ atoi (name
+ 1);
598 else if (name
[0] == '#'
602 int namesize
= atoi (name
+ 3);
604 name
= (char *) alloca (namesize
+ 1);
605 nread
= read (desc
, name
, namesize
);
606 if (nread
!= namesize
)
611 name
[namesize
] = '\0';
615 #endif /* Not AIAMAG. */
619 sscanf (member_header
.ar_mode
, "%o", &eltmode
);
620 eltsize
= atol (member_header
.ar_size
);
622 eltmode
= (unsigned short int) member_header
.ar_mode
;
623 eltsize
= member_header
.ar_size
;
624 #endif /* Not Xenix. */
627 (*function
) (desc
, name
, ! long_name
, member_offset
,
628 member_offset
+ AR_HDR_SIZE
, eltsize
,
630 atol (member_header
.ar_date
),
631 atoi (member_header
.ar_uid
),
632 atoi (member_header
.ar_gid
),
634 member_header
.ar_date
,
635 member_header
.ar_uid
,
636 member_header
.ar_gid
,
637 #endif /* Not Xenix. */
649 if (member_offset
== last_member_offset
)
650 /* End of the chain. */
655 sscanf (member_header_big
.ar_nxtmem
, "%20ld", &member_offset
);
658 sscanf (member_header
.ar_nxtmem
, "%12ld", &member_offset
);
660 if (lseek (desc
, member_offset
, 0) != member_offset
)
667 /* If this member maps archive names, we must read it in. The
668 name map will always precede any members whose names must
675 namemap
= (char *) alloca (eltsize
);
676 nread
= read (desc
, namemap
, eltsize
);
677 if (nread
!= eltsize
)
683 /* The names are separated by newlines. Some formats have
684 a trailing slash. Null terminate the strings for
686 limit
= namemap
+ eltsize
;
687 for (clear
= namemap
; clear
< limit
; clear
++)
692 if (clear
[-1] == '/')
700 member_offset
+= AR_HDR_SIZE
+ eltsize
;
701 if (member_offset
% 2 != 0)
712 /* Return nonzero iff NAME matches MEM.
713 If TRUNCATED is nonzero, MEM may be truncated to
714 sizeof (struct ar_hdr.ar_name) - 1. */
717 ar_name_equal (name
, mem
, truncated
)
723 p
= strrchr (name
, '/');
731 /* TRUNCATED should never be set on this system. */
735 #if !defined (__hpux) && !defined (cray)
736 return strneq (name
, mem
, sizeof(hdr
.ar_name
) - 1);
738 return strneq (name
, mem
, sizeof(hdr
.ar_name
) - 2);
739 #endif /* !__hpux && !cray */
744 return !strcmp (name
, mem
);
750 ar_member_pos (desc
, mem
, truncated
,
751 hdrpos
, datapos
, size
, date
, uid
, gid
, mode
, name
)
755 long int hdrpos
, datapos
, size
, date
;
759 if (!ar_name_equal (name
, mem
, truncated
))
764 /* Set date of member MEMNAME in archive ARNAME to current time.
765 Returns 0 if successful,
766 -1 if file ARNAME does not exist,
767 -2 if not a valid archive,
768 -3 if other random system call error (including file read-only),
769 1 if valid but member MEMNAME does not exist. */
772 ar_member_touch (arname
, memname
)
773 char *arname
, *memname
;
775 register long int pos
= ar_scan (arname
, ar_member_pos
, (long int) memname
);
777 struct ar_hdr ar_hdr
;
786 fd
= open (arname
, O_RDWR
, 0666);
789 /* Read in this member's header */
790 if (lseek (fd
, pos
, 0) < 0)
792 if (AR_HDR_SIZE
!= read (fd
, (char *) &ar_hdr
, AR_HDR_SIZE
))
794 /* Write back the header, thus touching the archive file. */
795 if (lseek (fd
, pos
, 0) < 0)
797 if (AR_HDR_SIZE
!= write (fd
, (char *) &ar_hdr
, AR_HDR_SIZE
))
799 /* The file's mtime is the time we we want. */
800 if (fstat (fd
, &statbuf
) < 0)
802 #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
803 /* Advance member's time to that time */
804 for (i
= 0; i
< sizeof ar_hdr
.ar_date
; i
++)
805 ar_hdr
.ar_date
[i
] = ' ';
806 sprintf (ar_hdr
.ar_date
, "%ld", (long int) statbuf
.st_mtime
);
808 ar_hdr
.ar_date
[strlen(ar_hdr
.ar_date
)] = ' ';
811 ar_hdr
.ar_date
= statbuf
.st_mtime
;
813 /* Write back this member's header */
814 if (lseek (fd
, pos
, 0) < 0)
816 if (AR_HDR_SIZE
!= write (fd
, (char *) &ar_hdr
, AR_HDR_SIZE
))
832 describe_member (desc
, name
, truncated
,
833 hdrpos
, datapos
, size
, date
, uid
, gid
, mode
)
837 long int hdrpos
, datapos
, size
, date
;
840 extern char *ctime ();
842 printf (_("Member `%s'%s: %ld bytes at %ld (%ld).\n"),
843 name
, truncated
? _(" (name might be truncated)") : "",
844 size
, hdrpos
, datapos
);
845 printf (_(" Date %s"), ctime (&date
));
846 printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid
, gid
, mode
);
855 ar_scan (argv
[1], describe_member
);
861 #endif /* NO_ARCHIVES. */