1 /* Library function for scanning an archive file.
2 Copyright (C) 1987-2012 Free Software Foundation, Inc.
3 This file is part of GNU Make.
5 GNU Make is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3 of the License, or (at your option) any later
10 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License along with
15 this program. If not, see <http://www.gnu.org/licenses/>. */
35 #include <lbr$routines.h>
38 static void *VMS_lib_idx
;
40 static char *VMS_saved_memname
;
42 static time_t VMS_member_date
;
44 static long int (*VMS_function
) ();
47 VMS_get_member_info (struct dsc$descriptor_s
*module
, unsigned long *rfa
)
54 static struct dsc$descriptor_s bufdesc
=
55 { 0, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, NULL
};
60 bufdesc
.dsc$a_pointer
= filename
;
61 bufdesc
.dsc$w_length
= sizeof (filename
);
63 status
= lbr$
set_module (&VMS_lib_idx
, rfa
, &bufdesc
,
64 &bufdesc
.dsc$w_length
, 0);
67 error (NILF
, _("lbr$set_module() failed to extract module info, status = %d"),
70 lbr$
close (&VMS_lib_idx
);
75 mhd
= (struct mhddef
*) filename
;
78 /* John Fowler <jfowler@nyx.net> writes this is needed in his environment,
79 * but that decc$fix_time() isn't documented to work this way. Let me
80 * know if this causes problems in other VMS environments.
83 /* Modified by M. Gehre at 11-JAN-2008 because old formula is wrong:
84 * val = decc$fix_time (&mhd->mhd$l_datim) + timezone - daylight*3600;
85 * a) daylight specifies, if the timezone has daylight saving enabled, not
87 * b) what we need is the information, if daylight saving was active, if
88 * the library module was replaced. This information we get using the
94 /* Conversion from VMS time to C time */
95 val
= decc$
fix_time (&mhd
->mhd$l_datim
);
98 * Conversion from local time (stored in library) to GMT (needed for gmake)
99 * Note: The tm_gmtoff element is a VMS extension to the ANSI standard.
101 tmp
= localtime (&val
);
102 val
-= tmp
->tm_gmtoff
;
106 for (i
= 0; i
< module
->dsc$w_length
; i
++)
107 filename
[i
] = _tolower ((unsigned char)module
->dsc$a_pointer
[i
]);
111 VMS_member_date
= (time_t) -1;
114 (*VMS_function
) (-1, filename
, 0, 0, 0, 0, val
, 0, 0, 0,
119 VMS_member_date
= fnval
;
126 /* Takes three arguments ARCHIVE, FUNCTION and ARG.
128 Open the archive named ARCHIVE, find its members one by one,
129 and for each one call FUNCTION with the following arguments:
130 archive file descriptor for reading the data,
132 member name might be truncated flag,
133 member header position in file,
134 member data position in file,
139 member protection mode,
142 NOTE: on VMS systems, only name, date, and arg are meaningful!
144 The descriptor is poised to read the data of the member
145 when FUNCTION is called. It does not matter how much
148 If FUNCTION returns nonzero, we immediately return
149 what FUNCTION returned.
151 Returns -1 if archive does not exist,
152 Returns -2 if archive has invalid format.
153 Returns 0 if have scanned successfully. */
156 ar_scan (const char *archive
, ar_member_func_t function
, const void *arg
)
160 static struct dsc$descriptor_s libdesc
=
161 { 0, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, NULL
};
163 unsigned long func
= LBR$C_READ
;
164 unsigned long type
= LBR$C_TYP_UNK
;
165 unsigned long index
= 1;
169 status
= lbr$
ini_control (&VMS_lib_idx
, &func
, &type
, 0);
173 error (NILF
, _("lbr$ini_control() failed with status = %d"), status
);
177 /* there is no such descriptor with "const char *dsc$a_pointer" */
178 libdesc
.dsc$a_pointer
= (char *)archive
;
179 libdesc
.dsc$w_length
= strlen (archive
);
181 status
= lbr$
open (&VMS_lib_idx
, &libdesc
, 0, 0, 0, 0, 0);
185 error (NILF
, _("unable to open library '%s' to lookup member '%s'"),
186 archive
, (char *)arg
);
190 VMS_saved_memname
= (char *)arg
;
192 /* For comparison, delete .obj from arg name. */
194 p
= strrchr (VMS_saved_memname
, '.');
198 VMS_function
= function
;
200 VMS_member_date
= (time_t) -1;
201 lbr$
get_index (&VMS_lib_idx
, &index
, VMS_get_member_info
, 0);
203 /* Undo the damage. */
207 lbr$
close (&VMS_lib_idx
);
209 return VMS_member_date
> 0 ? VMS_member_date
: 0;
214 /* SCO Unix's compiler defines both of these. */
219 /* On the sun386i and in System V rel 3, ar.h defines two different archive
220 formats depending upon whether you have defined PORTAR (normal) or PORT5AR
221 (System V Release 1). There is no default, one or the other must be defined
222 to have a nonzero value. */
224 #if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0)
227 /* According to Jim Sievert <jas1@rsvl.unisys.com>, for SCO XENIX defining
228 PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the
236 /* On AIX, define these symbols to be sure to get both archive formats.
237 AIX 4.3 introduced the "big" archive format to support 64-bit object
238 files, so on AIX 4.3 systems we need to support both the "normal" and
239 "big" archive formats. An archive's format is indicated in the
240 "fl_magic" field of the "FL_HDR" structure. For a normal archive,
241 this field will be the string defined by the AIAMAG symbol. For a
242 "big" archive, it will be the string defined by the AIAMAGBIG symbol
243 (at least on AIX it works this way).
245 Note: we'll define these symbols regardless of which AIX version
246 we're compiling on, but this is okay since we'll use the new symbols
247 only if they're present. */
249 # define __AR_SMALL__
257 /* BeOS 5 doesn't have <ar.h> but has archives in the same format
258 * as many other Unices. This was taken from GNU binutils for BeOS.
260 # define ARMAG "!<arch>\n" /* String that begins an archive file. */
261 # define SARMAG 8 /* Size of that string. */
262 # define ARFMAG "`\n" /* String in ar_fmag at end of each header. */
265 char ar_name
[16]; /* Member file name, sometimes / terminated. */
266 char ar_date
[12]; /* File date, decimal seconds since Epoch. */
267 char ar_uid
[6], ar_gid
[6]; /* User and group IDs, in ASCII decimal. */
268 char ar_mode
[8]; /* File mode, in ASCII octal. */
269 char ar_size
[10]; /* File size, in ASCII decimal. */
270 char ar_fmag
[2]; /* Always contains ARFMAG. */
273 # define TOCHAR(_m) (_m)
275 /* These should allow us to read Windows (VC++) libraries (according to Frank
276 * Libbrecht <frankl@abzx.belgium.hp.com>)
278 # include <windows.h>
281 # define ARMAG IMAGE_ARCHIVE_START
282 # define SARMAG IMAGE_ARCHIVE_START_SIZE
283 # define ar_hdr _IMAGE_ARCHIVE_MEMBER_HEADER
284 # define ar_name Name
285 # define ar_mode Mode
286 # define ar_size Size
287 # define ar_date Date
288 # define ar_uid UserID
289 # define ar_gid GroupID
290 /* In Windows the member names have type BYTE so we must cast them. */
291 # define TOCHAR(_m) ((char *)(_m))
294 /* Cray's <ar.h> apparently defines this. */
296 # define AR_HDR_SIZE (sizeof (struct ar_hdr))
299 /* Takes three arguments ARCHIVE, FUNCTION and ARG.
301 Open the archive named ARCHIVE, find its members one by one,
302 and for each one call FUNCTION with the following arguments:
303 archive file descriptor for reading the data,
305 member name might be truncated flag,
306 member header position in file,
307 member data position in file,
312 member protection mode,
315 The descriptor is poised to read the data of the member
316 when FUNCTION is called. It does not matter how much
319 If FUNCTION returns nonzero, we immediately return
320 what FUNCTION returned.
322 Returns -1 if archive does not exist,
323 Returns -2 if archive has invalid format.
324 Returns 0 if have scanned successfully. */
327 ar_scan (const char *archive
, ar_member_func_t function
, const void *arg
)
333 FL_HDR_BIG fl_header_big
;
339 int desc
= open (archive
, O_RDONLY
, 0);
345 register int nread
= read (desc
, buf
, SARMAG
);
346 if (nread
!= SARMAG
|| memcmp (buf
, ARMAG
, SARMAG
))
355 register int nread
= read (desc
, &fl_header
, FL_HSZ
);
363 /* If this is a "big" archive, then set the flag and
364 re-read the header into the "big" structure. */
365 if (!memcmp (fl_header
.fl_magic
, AIAMAGBIG
, SAIAMAG
))
369 /* seek back to beginning of archive */
370 if (lseek (desc
, 0, 0) < 0)
376 /* re-read the header into the "big" structure */
377 nread
= read (desc
, &fl_header_big
, FL_HSZ_BIG
);
378 if (nread
!= FL_HSZ_BIG
)
386 /* Check to make sure this is a "normal" archive. */
387 if (memcmp (fl_header
.fl_magic
, AIAMAG
, SAIAMAG
))
398 unsigned short int buf
;
400 register int nread
= read(desc
, &buf
, sizeof (buf
));
401 if (nread
!= sizeof (buf
) || buf
!= ARMAG
)
410 /* Now find the members one by one. */
413 register long int member_offset
= SARMAG
;
416 long int member_offset
;
417 long int last_member_offset
;
422 sscanf (fl_header_big
.fl_fstmoff
, "%20ld", &member_offset
);
423 sscanf (fl_header_big
.fl_lstmoff
, "%20ld", &last_member_offset
);
428 sscanf (fl_header
.fl_fstmoff
, "%12ld", &member_offset
);
429 sscanf (fl_header
.fl_lstmoff
, "%12ld", &last_member_offset
);
432 if (member_offset
== 0)
440 register long int member_offset
= sizeof (int);
442 register long int member_offset
= sizeof (unsigned short int);
443 #endif /* Not Xenix. */
450 struct ar_hdr member_header
;
452 struct ar_hdr_big member_header_big
;
459 long int data_offset
;
461 char namebuf
[sizeof member_header
.ar_name
+ 1];
463 int is_namemap
; /* Nonzero if this entry maps long names. */
469 if (lseek (desc
, member_offset
, 0) < 0)
476 #define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
481 nread
= read (desc
, &member_header_big
,
482 AR_MEMHDR_SZ(member_header_big
) );
484 if (nread
!= AR_MEMHDR_SZ(member_header_big
))
490 sscanf (member_header_big
.ar_namlen
, "%4d", &name_len
);
491 nread
= read (desc
, name
, name_len
);
493 if (nread
!= name_len
)
501 sscanf (member_header_big
.ar_date
, "%12ld", &dateval
);
502 sscanf (member_header_big
.ar_uid
, "%12d", &uidval
);
503 sscanf (member_header_big
.ar_gid
, "%12d", &gidval
);
504 sscanf (member_header_big
.ar_mode
, "%12o", &eltmode
);
505 sscanf (member_header_big
.ar_size
, "%20ld", &eltsize
);
507 data_offset
= (member_offset
+ AR_MEMHDR_SZ(member_header_big
)
513 nread
= read (desc
, &member_header
,
514 AR_MEMHDR_SZ(member_header
) );
516 if (nread
!= AR_MEMHDR_SZ(member_header
))
522 sscanf (member_header
.ar_namlen
, "%4d", &name_len
);
523 nread
= read (desc
, name
, name_len
);
525 if (nread
!= name_len
)
533 sscanf (member_header
.ar_date
, "%12ld", &dateval
);
534 sscanf (member_header
.ar_uid
, "%12d", &uidval
);
535 sscanf (member_header
.ar_gid
, "%12d", &gidval
);
536 sscanf (member_header
.ar_mode
, "%12o", &eltmode
);
537 sscanf (member_header
.ar_size
, "%12ld", &eltsize
);
539 data_offset
= (member_offset
+ AR_MEMHDR_SZ(member_header
)
542 data_offset
+= data_offset
% 2;
545 (*function
) (desc
, name
, 0,
546 member_offset
, data_offset
, eltsize
,
547 dateval
, uidval
, gidval
,
550 #else /* Not AIAMAG. */
551 nread
= read (desc
, &member_header
, AR_HDR_SIZE
);
553 /* No data left means end of file; that is OK. */
556 if (nread
!= AR_HDR_SIZE
557 #if defined(ARFMAG) || defined(ARFZMAG)
560 memcmp (member_header
.ar_fmag
, ARFMAG
, 2)
566 memcmp (member_header
.ar_fmag
, ARFZMAG
, 2)
579 memcpy (name
, member_header
.ar_name
, sizeof member_header
.ar_name
);
581 register char *p
= name
+ sizeof member_header
.ar_name
;
584 while (p
> name
&& *--p
== ' ');
587 /* If the member name is "//" or "ARFILENAMES/" this may be
588 a list of file name mappings. The maximum file name
589 length supported by the standard archive format is 14
590 characters. This member will actually always be the
591 first or second entry in the archive, but we don't check
593 is_namemap
= (!strcmp (name
, "//")
594 || !strcmp (name
, "ARFILENAMES/"));
595 #endif /* Not AIAMAG. */
596 /* On some systems, there is a slash after each member name. */
601 /* If the member name starts with a space or a slash, this
602 is an index into the file name mappings (used by GNU ar).
603 Otherwise if the member name looks like #1/NUMBER the
604 real member name appears in the element data (used by
607 && (name
[0] == ' ' || name
[0] == '/')
610 name
= namemap
+ atoi (name
+ 1);
613 else if (name
[0] == '#'
617 int namesize
= atoi (name
+ 3);
619 name
= alloca (namesize
+ 1);
620 nread
= read (desc
, name
, namesize
);
621 if (nread
!= namesize
)
626 name
[namesize
] = '\0';
630 #endif /* Not AIAMAG. */
634 sscanf (TOCHAR (member_header
.ar_mode
), "%o", &eltmode
);
635 eltsize
= atol (TOCHAR (member_header
.ar_size
));
637 eltmode
= (unsigned short int) member_header
.ar_mode
;
638 eltsize
= member_header
.ar_size
;
639 #endif /* Not Xenix. */
642 (*function
) (desc
, name
, ! long_name
, member_offset
,
643 member_offset
+ AR_HDR_SIZE
, eltsize
,
645 atol (TOCHAR (member_header
.ar_date
)),
646 atoi (TOCHAR (member_header
.ar_uid
)),
647 atoi (TOCHAR (member_header
.ar_gid
)),
649 member_header
.ar_date
,
650 member_header
.ar_uid
,
651 member_header
.ar_gid
,
652 #endif /* Not Xenix. */
664 if (member_offset
== last_member_offset
)
665 /* End of the chain. */
670 sscanf (member_header_big
.ar_nxtmem
, "%20ld", &member_offset
);
673 sscanf (member_header
.ar_nxtmem
, "%12ld", &member_offset
);
675 if (lseek (desc
, member_offset
, 0) != member_offset
)
682 /* If this member maps archive names, we must read it in. The
683 name map will always precede any members whose names must
690 namemap
= alloca (eltsize
);
691 nread
= read (desc
, namemap
, eltsize
);
692 if (nread
!= eltsize
)
698 /* The names are separated by newlines. Some formats have
699 a trailing slash. Null terminate the strings for
701 limit
= namemap
+ eltsize
;
702 for (clear
= namemap
; clear
< limit
; clear
++)
707 if (clear
[-1] == '/')
715 member_offset
+= AR_HDR_SIZE
+ eltsize
;
716 if (member_offset
% 2 != 0)
727 /* Return nonzero iff NAME matches MEM.
728 If TRUNCATED is nonzero, MEM may be truncated to
729 sizeof (struct ar_hdr.ar_name) - 1. */
732 ar_name_equal (const char *name
, const char *mem
, int truncated
)
736 p
= strrchr (name
, '/');
744 /* TRUNCATED should never be set on this system. */
748 #if !defined (__hpux) && !defined (cray)
749 return strneq (name
, mem
, sizeof(hdr
.ar_name
) - 1);
751 return strneq (name
, mem
, sizeof(hdr
.ar_name
) - 2);
752 #endif /* !__hpux && !cray */
757 return !strcmp (name
, mem
);
763 ar_member_pos (int desc UNUSED
, const char *mem
, int truncated
,
764 long int hdrpos
, long int datapos UNUSED
, long int size UNUSED
,
765 long int date UNUSED
, int uid UNUSED
, int gid UNUSED
,
766 int mode UNUSED
, const void *name
)
768 if (!ar_name_equal (name
, mem
, truncated
))
773 /* Set date of member MEMNAME in archive ARNAME to current time.
774 Returns 0 if successful,
775 -1 if file ARNAME does not exist,
776 -2 if not a valid archive,
777 -3 if other random system call error (including file read-only),
778 1 if valid but member MEMNAME does not exist. */
781 ar_member_touch (const char *arname
, const char *memname
)
783 long int pos
= ar_scan (arname
, ar_member_pos
, memname
);
785 struct ar_hdr ar_hdr
;
795 fd
= open (arname
, O_RDWR
, 0666);
798 /* Read in this member's header */
799 if (lseek (fd
, pos
, 0) < 0)
801 if (AR_HDR_SIZE
!= read (fd
, &ar_hdr
, AR_HDR_SIZE
))
803 /* Write back the header, thus touching the archive file. */
804 if (lseek (fd
, pos
, 0) < 0)
806 if (AR_HDR_SIZE
!= write (fd
, &ar_hdr
, AR_HDR_SIZE
))
808 /* The file's mtime is the time we we want. */
809 EINTRLOOP (i
, fstat (fd
, &statbuf
));
812 #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
813 /* Advance member's time to that time */
814 for (ui
= 0; ui
< sizeof ar_hdr
.ar_date
; ui
++)
815 ar_hdr
.ar_date
[ui
] = ' ';
816 sprintf (TOCHAR (ar_hdr
.ar_date
), "%ld", (long int) statbuf
.st_mtime
);
818 ar_hdr
.ar_date
[strlen(ar_hdr
.ar_date
)] = ' ';
821 ar_hdr
.ar_date
= statbuf
.st_mtime
;
823 /* Write back this member's header */
824 if (lseek (fd
, pos
, 0) < 0)
826 if (AR_HDR_SIZE
!= write (fd
, &ar_hdr
, AR_HDR_SIZE
))
842 describe_member (int desc
, const char *name
, int truncated
,
843 long int hdrpos
, long int datapos
, long int size
,
844 long int date
, int uid
, int gid
, int mode
, const void *arg
)
846 extern char *ctime ();
848 printf (_("Member '%s'%s: %ld bytes at %ld (%ld).\n"),
849 name
, truncated
? _(" (name might be truncated)") : "",
850 size
, hdrpos
, datapos
);
851 printf (_(" Date %s"), ctime (&date
));
852 printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid
, gid
, mode
);
858 main (int argc
, char **argv
)
860 ar_scan (argv
[1], describe_member
, NULL
);
865 #endif /* NO_ARCHIVES. */