1 /* Library function for scanning an archive file.
2 Copyright (C) 1987-2016 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)
42 /* This symbol should be present in lbrdef.h. */
44 #pragma extern_model save
45 #pragma extern_model globalvalue
46 extern unsigned int LBR$_HDRTRUNC;
47 #pragma extern_model restore
51 #include <lbr$routines.h>
54 vmsify (const char *name, int type);
56 /* Time conversion from VMS to Unix
57 Conversion from local time (stored in library) to GMT (needed for gmake)
58 Note: The tm_gmtoff element is a VMS extension to the ANSI standard. */
60 vms_time_to_unix(void *vms_time)
65 unix_time = decc$fix_time(vms_time);
66 tmp = localtime(&unix_time);
67 unix_time -= tmp->tm_gmtoff;
73 /* VMS library routines need static variables for callback */
74 static void *VMS_lib_idx;
76 static const void *VMS_saved_arg;
78 static long int (*VMS_function) ();
80 static long int VMS_function_ret;
83 /* This is a callback procedure for lib$get_index */
85 VMS_get_member_info(struct dsc$descriptor_s *module, unsigned long *rfa)
88 const int truncated = 0; /* Member name may be truncated */
89 time_t member_date; /* Member date */
91 unsigned int buffer_length; /* Actual buffer length */
93 /* Unused constants - Make does not actually use most of these */
94 const int file_desc = -1; /* archive file descriptor for reading the data */
95 const int header_position = 0; /* Header position */
96 const int data_position = 0; /* Data position in file */
97 const int data_size = 0; /* Data size */
98 const int uid = 0; /* member gid */
99 const int gid = 0; /* member gid */
100 const int mode = 0; /* member protection mode */
101 /* End of unused constants */
103 static struct dsc$descriptor_s bufdesc =
104 { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
106 /* Only need the module definition */
109 /* If a previous callback is non-zero, just return that status */
110 if (VMS_function_ret)
115 /* lbr_set_module returns more than just the module header. So allocate
116 a buffer which is big enough: the maximum LBR$C_MAXHDRSIZ. That's at
117 least bigger than the size of struct mhddef.
118 If the request is too small, a buffer truncated warning is issued so
119 it can be reissued with a larger buffer.
120 We do not care if the buffer is truncated, so that is still a success. */
121 mhd = xmalloc(LBR$C_MAXHDRSIZ);
122 bufdesc.dsc$a_pointer = (char *) mhd;
123 bufdesc.dsc$w_length = LBR$C_MAXHDRSIZ;
125 status = lbr$set_module(&VMS_lib_idx, rfa, &bufdesc, &buffer_length, 0);
127 if ((status != LBR$_HDRTRUNC) && !$VMS_STATUS_SUCCESS(status))
130 _("lbr$set_module() failed to extract module info, status = %d"),
133 lbr$close(&VMS_lib_idx);
139 /* When testing this code, it is useful to know the length returned */
140 printf("Input length = %d, actual = %d\n",
141 bufdesc.dsc$w_length, buffer_length);
144 /* Conversion from VMS time to C time.
145 VMS defectlet - mhddef is sub-optimal, for the time, it has a 32 bit
146 longword, mhd$l_datim, and a 32 bit fill instead of two longwords, or
148 member_date = vms_time_to_unix(&mhd->mhd$l_datim);
151 /* Here we have a problem. The module name on VMS does not have
152 a file type, but the filename pattern in the "VMS_saved_arg"
154 But only the method being called knows how to interpret the
156 There are currently two different formats being used.
157 This means that we need a VMS specific code in those methods
159 filename = xmalloc(module->dsc$w_length + 1);
161 /* TODO: We may need an option to preserve the case of the module
162 For now force the module name to lower case */
163 for (i = 0; i < module->dsc$w_length; i++)
164 filename[i] = _tolower((unsigned char )module->dsc$a_pointer[i]);
168 VMS_function_ret = (*VMS_function)(file_desc, filename, truncated,
169 header_position, data_position, data_size, member_date, uid, gid, mode,
177 /* Takes three arguments ARCHIVE, FUNCTION and ARG.
179 Open the archive named ARCHIVE, find its members one by one,
180 and for each one call FUNCTION with the following arguments:
181 archive file descriptor for reading the data,
183 member name might be truncated flag,
184 member header position in file,
185 member data position in file,
190 member protection mode,
193 NOTE: on VMS systems, only name, date, and arg are meaningful!
195 The descriptor is poised to read the data of the member
196 when FUNCTION is called. It does not matter how much
199 If FUNCTION returns nonzero, we immediately return
200 what FUNCTION returned.
202 Returns -1 if archive does not exist,
203 Returns -2 if archive has invalid format.
204 Returns 0 if have scanned successfully. */
207 ar_scan (const char *archive, ar_member_func_t function, const void *varg)
211 static struct dsc$descriptor_s libdesc =
212 { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
214 const unsigned long func = LBR$C_READ;
215 const unsigned long type = LBR$C_TYP_UNK;
216 const unsigned long index = 1;
217 unsigned long lib_idx;
220 VMS_saved_arg = varg;
222 /* Null archive string can show up in test and cause an access violation */
225 /* Null filenames do not exist */
229 /* archive path name must be in VMS format */
230 vms_archive = (char *) vmsify(archive, 0);
232 status = lbr$ini_control(&VMS_lib_idx, &func, &type, 0);
234 if (!$VMS_STATUS_SUCCESS(status))
236 ON(error, NILF, _("lbr$ini_control() failed with status = %d"), status);
240 libdesc.dsc$a_pointer = vms_archive;
241 libdesc.dsc$w_length = strlen(vms_archive);
243 status = lbr$open(&VMS_lib_idx, &libdesc, 0, NULL, 0, NULL, 0);
245 if (!$VMS_STATUS_SUCCESS(status))
248 /* TODO: A library format failure could mean that this is a file
249 generated by the GNU AR utility and in that case, we need to
250 take the UNIX codepath. This will also take a change to the
251 GNV AR wrapper program. */
256 /* Archive does not exist */
261 _("unable to open library '%s' to lookup member status %d"),
264 /* For library format errors, specification says to return -2 */
269 VMS_function = function;
271 /* Clear the return status, as we are supposed to stop calling the
272 callback function if it becomes non-zero, and this is a static
274 VMS_function_ret = 0;
276 status = lbr$get_index(&VMS_lib_idx, &index, VMS_get_member_info, NULL, 0);
278 lbr$close(&VMS_lib_idx);
280 /* Unless a failure occurred in the lbr$ routines, return the
281 the status from the 'function' routine. */
282 if ($VMS_STATUS_SUCCESS(status))
284 return VMS_function_ret;
287 /* This must be something wrong with the library and an error
288 message should already have been printed. */
294 /* SCO Unix's compiler defines both of these. */
299 /* On the sun386i and in System V rel 3, ar.h defines two different archive
300 formats depending upon whether you have defined PORTAR (normal) or PORT5AR
301 (System V Release 1). There is no default, one or the other must be defined
302 to have a nonzero value. */
304 #if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0)
307 /* According to Jim Sievert <jas1@rsvl.unisys.com>, for SCO XENIX defining
308 PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the
316 /* On AIX, define these symbols to be sure to get both archive formats.
317 AIX 4.3 introduced the "big" archive format to support 64-bit object
318 files, so on AIX 4.3 systems we need to support both the "normal" and
319 "big" archive formats. An archive's format is indicated in the
320 "fl_magic" field of the "FL_HDR" structure. For a normal archive,
321 this field will be the string defined by the AIAMAG symbol. For a
322 "big" archive, it will be the string defined by the AIAMAGBIG symbol
323 (at least on AIX it works this way).
325 Note: we'll define these symbols regardless of which AIX version
326 we're compiling on, but this is okay since we'll use the new symbols
327 only if they're present. */
329 # define __AR_SMALL__
334 # if !defined (__ANDROID__) && !defined (__BEOS__)
337 /* These platforms don't have <ar.h> but have archives in the same format
338 * as many other Unices. This was taken from GNU binutils for BeOS.
340 # define ARMAG "!<arch>\n" /* String that begins an archive file. */
341 # define SARMAG 8 /* Size of that string. */
342 # define ARFMAG "`\n" /* String in ar_fmag at end of each header. */
345 char ar_name[16]; /* Member file name, sometimes / terminated. */
346 char ar_date[12]; /* File date, decimal seconds since Epoch. */
347 char ar_uid[6], ar_gid[6]; /* User and group IDs, in ASCII decimal. */
348 char ar_mode[8]; /* File mode, in ASCII octal. */
349 char ar_size[10]; /* File size, in ASCII decimal. */
350 char ar_fmag[2]; /* Always contains ARFMAG. */
353 # define TOCHAR(_m) (_m)
355 /* These should allow us to read Windows (VC++) libraries (according to Frank
356 * Libbrecht <frankl@abzx.belgium.hp.com>)
358 # include <windows.h>
361 # define ARMAG IMAGE_ARCHIVE_START
362 # define SARMAG IMAGE_ARCHIVE_START_SIZE
363 # define ar_hdr _IMAGE_ARCHIVE_MEMBER_HEADER
364 # define ar_name Name
365 # define ar_mode Mode
366 # define ar_size Size
367 # define ar_date Date
368 # define ar_uid UserID
369 # define ar_gid GroupID
370 /* In Windows the member names have type BYTE so we must cast them. */
371 # define TOCHAR(_m) ((char *)(_m))
374 /* Cray's <ar.h> apparently defines this. */
376 # define AR_HDR_SIZE (sizeof (struct ar_hdr))
379 /* Takes three arguments ARCHIVE, FUNCTION and ARG.
381 Open the archive named ARCHIVE, find its members one by one,
382 and for each one call FUNCTION with the following arguments:
383 archive file descriptor for reading the data,
385 member name might be truncated flag,
386 member header position in file,
387 member data position in file,
392 member protection mode,
395 The descriptor is poised to read the data of the member
396 when FUNCTION is called. It does not matter how much
399 If FUNCTION returns nonzero, we immediately return
400 what FUNCTION returned.
402 Returns -1 if archive does not exist,
403 Returns -2 if archive has invalid format.
404 Returns 0 if have scanned successfully. */
407 ar_scan (const char *archive, ar_member_func_t function, const void *arg)
413 FL_HDR_BIG fl_header_big;
417 int desc = open (archive, O_RDONLY, 0);
424 EINTRLOOP (nread, read (desc, buf, SARMAG));
425 if (nread != SARMAG || memcmp (buf, ARMAG, SARMAG))
435 EINTRLOOP (nread, read (desc, &fl_header, FL_HSZ));
442 /* If this is a "big" archive, then set the flag and
443 re-read the header into the "big" structure. */
444 if (!memcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG))
450 /* seek back to beginning of archive */
451 EINTRLOOP (o, lseek (desc, 0, 0));
458 /* re-read the header into the "big" structure */
459 EINTRLOOP (nread, read (desc, &fl_header_big, FL_HSZ_BIG));
460 if (nread != FL_HSZ_BIG)
468 /* Check to make sure this is a "normal" archive. */
469 if (memcmp (fl_header.fl_magic, AIAMAG, SAIAMAG))
480 unsigned short int buf;
483 EINTRLOOP (nread, read (desc, &buf, sizeof (buf)));
484 if (nread != sizeof (buf) || buf != ARMAG)
493 /* Now find the members one by one. */
496 register long int member_offset = SARMAG;
499 long int member_offset;
500 long int last_member_offset;
505 sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset);
506 sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset);
511 sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset);
512 sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset);
515 if (member_offset == 0)
523 register long int member_offset = sizeof (int);
525 register long int member_offset = sizeof (unsigned short int);
526 #endif /* Not Xenix. */
533 struct ar_hdr member_header;
535 struct ar_hdr_big member_header_big;
542 long int data_offset;
544 char namebuf[sizeof member_header.ar_name + 1];
546 int is_namemap; /* Nonzero if this entry maps long names. */
550 unsigned int eltmode;
554 EINTRLOOP (o, lseek (desc, member_offset, 0));
562 #define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
567 EINTRLOOP (nread, read (desc, &member_header_big,
568 AR_MEMHDR_SZ(member_header_big)));
570 if (nread != AR_MEMHDR_SZ(member_header_big))
576 sscanf (member_header_big.ar_namlen, "%4d", &name_len);
577 EINTRLOOP (nread, read (desc, name, name_len));
579 if (nread != name_len)
587 sscanf (member_header_big.ar_date, "%12ld", &dateval);
588 sscanf (member_header_big.ar_uid, "%12d", &uidval);
589 sscanf (member_header_big.ar_gid, "%12d", &gidval);
590 sscanf (member_header_big.ar_mode, "%12o", &eltmode);
591 sscanf (member_header_big.ar_size, "%20ld", &eltsize);
593 data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big)
599 EINTRLOOP (nread, read (desc, &member_header,
600 AR_MEMHDR_SZ(member_header)));
602 if (nread != AR_MEMHDR_SZ(member_header))
608 sscanf (member_header.ar_namlen, "%4d", &name_len);
609 EINTRLOOP (nread, read (desc, name, name_len));
611 if (nread != name_len)
619 sscanf (member_header.ar_date, "%12ld", &dateval);
620 sscanf (member_header.ar_uid, "%12d", &uidval);
621 sscanf (member_header.ar_gid, "%12d", &gidval);
622 sscanf (member_header.ar_mode, "%12o", &eltmode);
623 sscanf (member_header.ar_size, "%12ld", &eltsize);
625 data_offset = (member_offset + AR_MEMHDR_SZ(member_header)
628 data_offset += data_offset % 2;
631 (*function) (desc, name, 0,
632 member_offset, data_offset, eltsize,
633 dateval, uidval, gidval,
636 #else /* Not AIAMAG. */
637 EINTRLOOP (nread, read (desc, &member_header, AR_HDR_SIZE));
639 /* No data left means end of file; that is OK. */
642 if (nread != AR_HDR_SIZE
643 #if defined(ARFMAG) || defined(ARFZMAG)
646 memcmp (member_header.ar_fmag, ARFMAG, 2)
652 memcmp (member_header.ar_fmag, ARFZMAG, 2)
665 memcpy (name, member_header.ar_name, sizeof member_header.ar_name);
667 register char *p = name + sizeof member_header.ar_name;
670 while (p > name && *--p == ' ');
673 /* If the member name is "//" or "ARFILENAMES/" this may be
674 a list of file name mappings. The maximum file name
675 length supported by the standard archive format is 14
676 characters. This member will actually always be the
677 first or second entry in the archive, but we don't check
679 is_namemap = (!strcmp (name, "//")
680 || !strcmp (name, "ARFILENAMES/"));
681 #endif /* Not AIAMAG. */
682 /* On some systems, there is a slash after each member name. */
687 /* If the member name starts with a space or a slash, this
688 is an index into the file name mappings (used by GNU ar).
689 Otherwise if the member name looks like #1/NUMBER the
690 real member name appears in the element data (used by
693 && (name[0] == ' ' || name[0] == '/')
696 name = namemap + atoi (name + 1);
699 else if (name[0] == '#'
703 int namesize = atoi (name + 3);
705 name = alloca (namesize + 1);
706 EINTRLOOP (nread, read (desc, name, namesize));
707 if (nread != namesize)
712 name[namesize] = '\0';
716 #endif /* Not AIAMAG. */
720 sscanf (TOCHAR (member_header.ar_mode), "%o", &eltmode);
721 eltsize = atol (TOCHAR (member_header.ar_size));
723 eltmode = (unsigned short int) member_header.ar_mode;
724 eltsize = member_header.ar_size;
725 #endif /* Not Xenix. */
728 (*function) (desc, name, ! long_name, member_offset,
729 member_offset + AR_HDR_SIZE, eltsize,
731 atol (TOCHAR (member_header.ar_date)),
732 atoi (TOCHAR (member_header.ar_uid)),
733 atoi (TOCHAR (member_header.ar_gid)),
735 member_header.ar_date,
736 member_header.ar_uid,
737 member_header.ar_gid,
738 #endif /* Not Xenix. */
750 if (member_offset == last_member_offset)
751 /* End of the chain. */
756 sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset);
759 sscanf (member_header.ar_nxtmem, "%12ld", &member_offset);
761 if (lseek (desc, member_offset, 0) != member_offset)
768 /* If this member maps archive names, we must read it in. The
769 name map will always precede any members whose names must
776 namemap = alloca (eltsize);
777 EINTRLOOP (nread, read (desc, namemap, eltsize));
778 if (nread != eltsize)
784 /* The names are separated by newlines. Some formats have
785 a trailing slash. Null terminate the strings for
787 limit = namemap + eltsize;
788 for (clear = namemap; clear < limit; clear++)
793 if (clear[-1] == '/')
801 member_offset += AR_HDR_SIZE + eltsize;
802 if (member_offset % 2 != 0)
813 /* Return nonzero iff NAME matches MEM.
814 If TRUNCATED is nonzero, MEM may be truncated to
815 sizeof (struct ar_hdr.ar_name) - 1. */
818 ar_name_equal (const char *name, const char *mem, int truncated)
822 p = strrchr (name, '/');
830 /* TRUNCATED should never be set on this system. */
834 #if !defined (__hpux) && !defined (cray)
835 return strneq (name, mem, sizeof (hdr.ar_name) - 1);
837 return strneq (name, mem, sizeof (hdr.ar_name) - 2);
838 #endif /* !__hpux && !cray */
842 return !strcmp (name, mem);
844 /* VMS members do not have suffixes, but the filenames usually
846 Do we need to strip VMS disk/directory format paths?
848 Most VMS compilers etc. by default are case insensitive
849 but produce uppercase external names, incl. module names.
850 However the VMS librarian (ar) and the linker by default
851 are case sensitive: they take what they get, usually
852 uppercase names. So for the non-default settings of the
853 compilers etc. there is a need to have a case sensitive
860 if ((dot=strrchr(name,'.')))
861 match = (len == dot - name) && !strncasecmp(name, mem, len);
863 match = !strcasecmp (name, mem);
872 ar_member_pos (int desc UNUSED, const char *mem, int truncated,
873 long int hdrpos, long int datapos UNUSED, long int size UNUSED,
874 long int date UNUSED, int uid UNUSED, int gid UNUSED,
875 unsigned int mode UNUSED, const void *name)
877 if (!ar_name_equal (name, mem, truncated))
882 /* Set date of member MEMNAME in archive ARNAME to current time.
883 Returns 0 if successful,
884 -1 if file ARNAME does not exist,
885 -2 if not a valid archive,
886 -3 if other random system call error (including file read-only),
887 1 if valid but member MEMNAME does not exist. */
890 ar_member_touch (const char *arname, const char *memname)
892 long int pos = ar_scan (arname, ar_member_pos, memname);
894 struct ar_hdr ar_hdr;
905 EINTRLOOP (fd, open (arname, O_RDWR, 0666));
908 /* Read in this member's header */
909 EINTRLOOP (o, lseek (fd, pos, 0));
912 EINTRLOOP (r, read (fd, &ar_hdr, AR_HDR_SIZE));
913 if (r != AR_HDR_SIZE)
915 /* Write back the header, thus touching the archive file. */
916 EINTRLOOP (o, lseek (fd, pos, 0));
919 EINTRLOOP (r, write (fd, &ar_hdr, AR_HDR_SIZE));
920 if (r != AR_HDR_SIZE)
922 /* The file's mtime is the time we we want. */
923 EINTRLOOP (r, fstat (fd, &statbuf));
926 #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
927 /* Advance member's time to that time */
928 for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++)
929 ar_hdr.ar_date[ui] = ' ';
930 sprintf (TOCHAR (ar_hdr.ar_date), "%lu", (long unsigned) statbuf.st_mtime);
932 ar_hdr.ar_date[strlen (ar_hdr.ar_date)] = ' ';
935 ar_hdr.ar_date = statbuf.st_mtime;
937 /* Write back this member's header */
938 EINTRLOOP (o, lseek (fd, pos, 0));
941 EINTRLOOP (r, write (fd, &ar_hdr, AR_HDR_SIZE));
942 if (r != AR_HDR_SIZE)
958 describe_member (int desc, const char *name, int truncated,
959 long int hdrpos, long int datapos, long int size,
960 long int date, int uid, int gid, unsigned int mode,
963 extern char *ctime ();
965 printf (_("Member '%s'%s: %ld bytes at %ld (%ld).\n"),
966 name, truncated ? _(" (name might be truncated)") : "",
967 size, hdrpos, datapos);
968 printf (_(" Date %s"), ctime (&date));
969 printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode);
975 main (int argc, char **argv)
977 ar_scan (argv[1], describe_member, NULL);
982 #endif /* NO_ARCHIVES. */