1 /* Library function for scanning an archive file.
2 Copyright (C) 1987-2014 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/>. */
20 /* Hack, the real error() routine eventually pulls in die from main.c */
21 #define error(a, b, c, d)
41 globalvalue unsigned int LBR$_HDRTRUNC;
45 #include <lbr$routines.h>
48 vmsify (const char *name, int type);
50 /* Time conversion from VMS to Unix
51 Conversion from local time (stored in library) to GMT (needed for gmake)
52 Note: The tm_gmtoff element is a VMS extension to the ANSI standard. */
54 vms_time_to_unix(void *vms_time)
59 unix_time = decc$fix_time(vms_time);
60 tmp = localtime(&unix_time);
61 unix_time -= tmp->tm_gmtoff;
67 /* VMS library routines need static variables for callback */
68 static void *VMS_lib_idx;
70 static const void *VMS_saved_arg;
72 static long int (*VMS_function) ();
74 static long int VMS_function_ret;
77 /* This is a callback procedure for lib$get_index */
79 VMS_get_member_info(struct dsc$descriptor_s *module, unsigned long *rfa)
82 const int truncated = 0; /* Member name may be truncated */
83 time_t member_date; /* Member date */
85 unsigned int buffer_length; /* Actual buffer length */
87 /* Unused constants - Make does not actually use most of these */
88 const int file_desc = -1; /* archive file descriptor for reading the data */
89 const int header_position = 0; /* Header position */
90 const int data_position = 0; /* Data position in file */
91 const int data_size = 0; /* Data size */
92 const int uid = 0; /* member gid */
93 const int gid = 0; /* member gid */
94 const int mode = 0; /* member protection mode */
95 /* End of unused constants */
97 static struct dsc$descriptor_s bufdesc =
98 { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
100 /* Only need the module definition */
103 /* If a previous callback is non-zero, just return that status */
104 if (VMS_function_ret)
109 /* lbr_set_module returns more than just the module header. So allocate
110 a buffer which is big enough: the maximum LBR$C_MAXHDRSIZ. That's at
111 least bigger than the size of struct mhddef.
112 If the request is too small, a buffer truncated warning is issued so
113 it can be reissued with a larger buffer.
114 We do not care if the buffer is truncated, so that is still a success. */
115 mhd = xmalloc(LBR$C_MAXHDRSIZ);
116 bufdesc.dsc$a_pointer = (char *) mhd;
117 bufdesc.dsc$w_length = LBR$C_MAXHDRSIZ;
119 status = lbr$set_module(&VMS_lib_idx, rfa, &bufdesc, &buffer_length, 0);
121 if ((status != LBR$_HDRTRUNC) && !$VMS_STATUS_SUCCESS(status))
124 _("lbr$set_module() failed to extract module info, status = %d"),
127 lbr$close(&VMS_lib_idx);
133 /* When testing this code, it is useful to know the length returned */
134 printf("Input length = %d, actual = %d\n",
135 bufdesc.dsc$w_length, buffer_length);
138 /* Conversion from VMS time to C time.
139 VMS defectlet - mhddef is sub-optimal, for the time, it has a 32 bit
140 longword, mhd$l_datim, and a 32 bit fill instead of two longwords, or
142 member_date = vms_time_to_unix(&mhd->mhd$l_datim);
145 /* Here we have a problem. The module name on VMS does not have
146 a file type, but the filename pattern in the "VMS_saved_arg"
148 But only the method being called knows how to interpret the
150 There are currently two different formats being used.
151 This means that we need a VMS specific code in those methods
153 filename = xmalloc(module->dsc$w_length + 1);
155 /* TODO: We may need an option to preserve the case of the module
156 For now force the module name to lower case */
157 for (i = 0; i < module->dsc$w_length; i++)
158 filename[i] = _tolower((unsigned char )module->dsc$a_pointer[i]);
162 VMS_function_ret = (*VMS_function)(file_desc, filename, truncated,
163 header_position, data_position, data_size, member_date, uid, gid, mode,
171 /* Takes three arguments ARCHIVE, FUNCTION and ARG.
173 Open the archive named ARCHIVE, find its members one by one,
174 and for each one call FUNCTION with the following arguments:
175 archive file descriptor for reading the data,
177 member name might be truncated flag,
178 member header position in file,
179 member data position in file,
184 member protection mode,
187 NOTE: on VMS systems, only name, date, and arg are meaningful!
189 The descriptor is poised to read the data of the member
190 when FUNCTION is called. It does not matter how much
193 If FUNCTION returns nonzero, we immediately return
194 what FUNCTION returned.
196 Returns -1 if archive does not exist,
197 Returns -2 if archive has invalid format.
198 Returns 0 if have scanned successfully. */
201 ar_scan (const char *archive, ar_member_func_t function, const void *varg)
205 static struct dsc$descriptor_s libdesc =
206 { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
208 const unsigned long func = LBR$C_READ;
209 const unsigned long type = LBR$C_TYP_UNK;
210 const unsigned long index = 1;
211 unsigned long lib_idx;
214 VMS_saved_arg = varg;
216 /* Null archive string can show up in test and cause an access violation */
219 /* Null filenames do not exist */
223 /* archive path name must be in VMS format */
224 vms_archive = (char *) vmsify(archive, 0);
226 status = lbr$ini_control(&VMS_lib_idx, &func, &type, 0);
228 if (!$VMS_STATUS_SUCCESS(status))
230 ON(error, NILF, _("lbr$ini_control() failed with status = %d"), status);
234 libdesc.dsc$a_pointer = vms_archive;
235 libdesc.dsc$w_length = strlen(vms_archive);
237 status = lbr$open(&VMS_lib_idx, &libdesc, 0, NULL, 0, NULL, 0);
239 if (!$VMS_STATUS_SUCCESS(status))
242 /* TODO: A library format failure could mean that this is a file
243 generated by the GNU AR utility and in that case, we need to
244 take the UNIX codepath. This will also take a change to the
245 GNV AR wrapper program. */
250 /* Archive does not exist */
255 _("unable to open library '%s' to lookup member status %d"),
258 /* For library format errors, specification says to return -2 */
263 VMS_function = function;
265 /* Clear the return status, as we are supposed to stop calling the
266 callback function if it becomes non-zero, and this is a static
268 VMS_function_ret = 0;
270 status = lbr$get_index(&VMS_lib_idx, &index, VMS_get_member_info, NULL, 0);
272 lbr$close(&VMS_lib_idx);
274 /* Unless a failure occurred in the lbr$ routines, return the
275 the status from the 'function' routine. */
276 if ($VMS_STATUS_SUCCESS(status))
278 return VMS_function_ret;
281 /* This must be something wrong with the library and an error
282 message should already have been printed. */
288 /* SCO Unix's compiler defines both of these. */
293 /* On the sun386i and in System V rel 3, ar.h defines two different archive
294 formats depending upon whether you have defined PORTAR (normal) or PORT5AR
295 (System V Release 1). There is no default, one or the other must be defined
296 to have a nonzero value. */
298 #if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0)
301 /* According to Jim Sievert <jas1@rsvl.unisys.com>, for SCO XENIX defining
302 PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the
310 /* On AIX, define these symbols to be sure to get both archive formats.
311 AIX 4.3 introduced the "big" archive format to support 64-bit object
312 files, so on AIX 4.3 systems we need to support both the "normal" and
313 "big" archive formats. An archive's format is indicated in the
314 "fl_magic" field of the "FL_HDR" structure. For a normal archive,
315 this field will be the string defined by the AIAMAG symbol. For a
316 "big" archive, it will be the string defined by the AIAMAGBIG symbol
317 (at least on AIX it works this way).
319 Note: we'll define these symbols regardless of which AIX version
320 we're compiling on, but this is okay since we'll use the new symbols
321 only if they're present. */
323 # define __AR_SMALL__
328 # if !defined (__ANDROID__) && !defined (__BEOS__)
331 /* These platforms don't have <ar.h> but have archives in the same format
332 * as many other Unices. This was taken from GNU binutils for BeOS.
334 # define ARMAG "!<arch>\n" /* String that begins an archive file. */
335 # define SARMAG 8 /* Size of that string. */
336 # define ARFMAG "`\n" /* String in ar_fmag at end of each header. */
339 char ar_name[16]; /* Member file name, sometimes / terminated. */
340 char ar_date[12]; /* File date, decimal seconds since Epoch. */
341 char ar_uid[6], ar_gid[6]; /* User and group IDs, in ASCII decimal. */
342 char ar_mode[8]; /* File mode, in ASCII octal. */
343 char ar_size[10]; /* File size, in ASCII decimal. */
344 char ar_fmag[2]; /* Always contains ARFMAG. */
347 # define TOCHAR(_m) (_m)
349 /* These should allow us to read Windows (VC++) libraries (according to Frank
350 * Libbrecht <frankl@abzx.belgium.hp.com>)
352 # include <windows.h>
355 # define ARMAG IMAGE_ARCHIVE_START
356 # define SARMAG IMAGE_ARCHIVE_START_SIZE
357 # define ar_hdr _IMAGE_ARCHIVE_MEMBER_HEADER
358 # define ar_name Name
359 # define ar_mode Mode
360 # define ar_size Size
361 # define ar_date Date
362 # define ar_uid UserID
363 # define ar_gid GroupID
364 /* In Windows the member names have type BYTE so we must cast them. */
365 # define TOCHAR(_m) ((char *)(_m))
368 /* Cray's <ar.h> apparently defines this. */
370 # define AR_HDR_SIZE (sizeof (struct ar_hdr))
373 /* Takes three arguments ARCHIVE, FUNCTION and ARG.
375 Open the archive named ARCHIVE, find its members one by one,
376 and for each one call FUNCTION with the following arguments:
377 archive file descriptor for reading the data,
379 member name might be truncated flag,
380 member header position in file,
381 member data position in file,
386 member protection mode,
389 The descriptor is poised to read the data of the member
390 when FUNCTION is called. It does not matter how much
393 If FUNCTION returns nonzero, we immediately return
394 what FUNCTION returned.
396 Returns -1 if archive does not exist,
397 Returns -2 if archive has invalid format.
398 Returns 0 if have scanned successfully. */
401 ar_scan (const char *archive, ar_member_func_t function, const void *arg)
407 FL_HDR_BIG fl_header_big;
411 int desc = open (archive, O_RDONLY, 0);
417 register int nread = read (desc, buf, SARMAG);
418 if (nread != SARMAG || memcmp (buf, ARMAG, SARMAG))
427 register int nread = read (desc, &fl_header, FL_HSZ);
435 /* If this is a "big" archive, then set the flag and
436 re-read the header into the "big" structure. */
437 if (!memcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG))
441 /* seek back to beginning of archive */
442 if (lseek (desc, 0, 0) < 0)
448 /* re-read the header into the "big" structure */
449 nread = read (desc, &fl_header_big, FL_HSZ_BIG);
450 if (nread != FL_HSZ_BIG)
458 /* Check to make sure this is a "normal" archive. */
459 if (memcmp (fl_header.fl_magic, AIAMAG, SAIAMAG))
470 unsigned short int buf;
472 register int nread = read (desc, &buf, sizeof (buf));
473 if (nread != sizeof (buf) || buf != ARMAG)
482 /* Now find the members one by one. */
485 register long int member_offset = SARMAG;
488 long int member_offset;
489 long int last_member_offset;
494 sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset);
495 sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset);
500 sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset);
501 sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset);
504 if (member_offset == 0)
512 register long int member_offset = sizeof (int);
514 register long int member_offset = sizeof (unsigned short int);
515 #endif /* Not Xenix. */
522 struct ar_hdr member_header;
524 struct ar_hdr_big member_header_big;
531 long int data_offset;
533 char namebuf[sizeof member_header.ar_name + 1];
535 int is_namemap; /* Nonzero if this entry maps long names. */
542 if (lseek (desc, member_offset, 0) < 0)
549 #define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
554 nread = read (desc, &member_header_big,
555 AR_MEMHDR_SZ(member_header_big) );
557 if (nread != AR_MEMHDR_SZ(member_header_big))
563 sscanf (member_header_big.ar_namlen, "%4d", &name_len);
564 nread = read (desc, name, name_len);
566 if (nread != name_len)
574 sscanf (member_header_big.ar_date, "%12ld", &dateval);
575 sscanf (member_header_big.ar_uid, "%12d", &uidval);
576 sscanf (member_header_big.ar_gid, "%12d", &gidval);
577 sscanf (member_header_big.ar_mode, "%12o", &eltmode);
578 sscanf (member_header_big.ar_size, "%20ld", &eltsize);
580 data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big)
586 nread = read (desc, &member_header,
587 AR_MEMHDR_SZ(member_header) );
589 if (nread != AR_MEMHDR_SZ(member_header))
595 sscanf (member_header.ar_namlen, "%4d", &name_len);
596 nread = read (desc, name, name_len);
598 if (nread != name_len)
606 sscanf (member_header.ar_date, "%12ld", &dateval);
607 sscanf (member_header.ar_uid, "%12d", &uidval);
608 sscanf (member_header.ar_gid, "%12d", &gidval);
609 sscanf (member_header.ar_mode, "%12o", &eltmode);
610 sscanf (member_header.ar_size, "%12ld", &eltsize);
612 data_offset = (member_offset + AR_MEMHDR_SZ(member_header)
615 data_offset += data_offset % 2;
618 (*function) (desc, name, 0,
619 member_offset, data_offset, eltsize,
620 dateval, uidval, gidval,
623 #else /* Not AIAMAG. */
624 nread = read (desc, &member_header, AR_HDR_SIZE);
626 /* No data left means end of file; that is OK. */
629 if (nread != AR_HDR_SIZE
630 #if defined(ARFMAG) || defined(ARFZMAG)
633 memcmp (member_header.ar_fmag, ARFMAG, 2)
639 memcmp (member_header.ar_fmag, ARFZMAG, 2)
652 memcpy (name, member_header.ar_name, sizeof member_header.ar_name);
654 register char *p = name + sizeof member_header.ar_name;
657 while (p > name && *--p == ' ');
660 /* If the member name is "//" or "ARFILENAMES/" this may be
661 a list of file name mappings. The maximum file name
662 length supported by the standard archive format is 14
663 characters. This member will actually always be the
664 first or second entry in the archive, but we don't check
666 is_namemap = (!strcmp (name, "//")
667 || !strcmp (name, "ARFILENAMES/"));
668 #endif /* Not AIAMAG. */
669 /* On some systems, there is a slash after each member name. */
674 /* If the member name starts with a space or a slash, this
675 is an index into the file name mappings (used by GNU ar).
676 Otherwise if the member name looks like #1/NUMBER the
677 real member name appears in the element data (used by
680 && (name[0] == ' ' || name[0] == '/')
683 name = namemap + atoi (name + 1);
686 else if (name[0] == '#'
690 int namesize = atoi (name + 3);
692 name = alloca (namesize + 1);
693 nread = read (desc, name, namesize);
694 if (nread != namesize)
699 name[namesize] = '\0';
703 #endif /* Not AIAMAG. */
707 sscanf (TOCHAR (member_header.ar_mode), "%o", &eltmode);
708 eltsize = atol (TOCHAR (member_header.ar_size));
710 eltmode = (unsigned short int) member_header.ar_mode;
711 eltsize = member_header.ar_size;
712 #endif /* Not Xenix. */
715 (*function) (desc, name, ! long_name, member_offset,
716 member_offset + AR_HDR_SIZE, eltsize,
718 atol (TOCHAR (member_header.ar_date)),
719 atoi (TOCHAR (member_header.ar_uid)),
720 atoi (TOCHAR (member_header.ar_gid)),
722 member_header.ar_date,
723 member_header.ar_uid,
724 member_header.ar_gid,
725 #endif /* Not Xenix. */
737 if (member_offset == last_member_offset)
738 /* End of the chain. */
743 sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset);
746 sscanf (member_header.ar_nxtmem, "%12ld", &member_offset);
748 if (lseek (desc, member_offset, 0) != member_offset)
755 /* If this member maps archive names, we must read it in. The
756 name map will always precede any members whose names must
763 namemap = alloca (eltsize);
764 nread = read (desc, namemap, eltsize);
765 if (nread != eltsize)
771 /* The names are separated by newlines. Some formats have
772 a trailing slash. Null terminate the strings for
774 limit = namemap + eltsize;
775 for (clear = namemap; clear < limit; clear++)
780 if (clear[-1] == '/')
788 member_offset += AR_HDR_SIZE + eltsize;
789 if (member_offset % 2 != 0)
800 /* Return nonzero iff NAME matches MEM.
801 If TRUNCATED is nonzero, MEM may be truncated to
802 sizeof (struct ar_hdr.ar_name) - 1. */
805 ar_name_equal (const char *name, const char *mem, int truncated)
809 p = strrchr (name, '/');
817 /* TRUNCATED should never be set on this system. */
821 #if !defined (__hpux) && !defined (cray)
822 return strneq (name, mem, sizeof (hdr.ar_name) - 1);
824 return strneq (name, mem, sizeof (hdr.ar_name) - 2);
825 #endif /* !__hpux && !cray */
829 return !strcmp (name, mem);
831 /* VMS members do not have suffixes, but the filenames usually
833 Do we need to strip VMS disk/directory format paths?
835 Most VMS compilers etc. by default are case insensitive
836 but produce uppercase external names, incl. module names.
837 However the VMS librarian (ar) and the linker by default
838 are case sensitive: they take what they get, usually
839 uppercase names. So for the non-default settings of the
840 compilers etc. there is a need to have a case sensitive
847 if ((dot=strrchr(name,'.')))
848 match = (len == dot - name) && !strncasecmp(name, mem, len);
850 match = !strcasecmp (name, mem);
859 ar_member_pos (int desc UNUSED, const char *mem, int truncated,
860 long int hdrpos, long int datapos UNUSED, long int size UNUSED,
861 long int date UNUSED, int uid UNUSED, int gid UNUSED,
862 int mode UNUSED, const void *name)
864 if (!ar_name_equal (name, mem, truncated))
869 /* Set date of member MEMNAME in archive ARNAME to current time.
870 Returns 0 if successful,
871 -1 if file ARNAME does not exist,
872 -2 if not a valid archive,
873 -3 if other random system call error (including file read-only),
874 1 if valid but member MEMNAME does not exist. */
877 ar_member_touch (const char *arname, const char *memname)
879 long int pos = ar_scan (arname, ar_member_pos, memname);
881 struct ar_hdr ar_hdr;
891 fd = open (arname, O_RDWR, 0666);
894 /* Read in this member's header */
895 if (lseek (fd, pos, 0) < 0)
897 if (AR_HDR_SIZE != read (fd, &ar_hdr, AR_HDR_SIZE))
899 /* Write back the header, thus touching the archive file. */
900 if (lseek (fd, pos, 0) < 0)
902 if (AR_HDR_SIZE != write (fd, &ar_hdr, AR_HDR_SIZE))
904 /* The file's mtime is the time we we want. */
905 EINTRLOOP (i, fstat (fd, &statbuf));
908 #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
909 /* Advance member's time to that time */
910 for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++)
911 ar_hdr.ar_date[ui] = ' ';
912 sprintf (TOCHAR (ar_hdr.ar_date), "%ld", (long int) statbuf.st_mtime);
914 ar_hdr.ar_date[strlen (ar_hdr.ar_date)] = ' ';
917 ar_hdr.ar_date = statbuf.st_mtime;
919 /* Write back this member's header */
920 if (lseek (fd, pos, 0) < 0)
922 if (AR_HDR_SIZE != write (fd, &ar_hdr, AR_HDR_SIZE))
938 describe_member (int desc, const char *name, int truncated,
939 long int hdrpos, long int datapos, long int size,
940 long int date, int uid, int gid, int mode, const void *arg)
942 extern char *ctime ();
944 printf (_("Member '%s'%s: %ld bytes at %ld (%ld).\n"),
945 name, truncated ? _(" (name might be truncated)") : "",
946 size, hdrpos, datapos);
947 printf (_(" Date %s"), ctime (&date));
948 printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode);
954 main (int argc, char **argv)
956 ar_scan (argv[1], describe_member, NULL);
961 #endif /* NO_ARCHIVES. */