* New config.sub and config.guess
[make.git] / arscan.c
blob2b9070585c722414ed0913d5d874834e9050997b
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)
7 any later version.
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,
17 USA. */
19 #include "make.h"
21 #ifdef HAVE_FCNTL_H
22 #include <fcntl.h>
23 #else
24 #include <sys/file.h>
25 #endif
27 #ifndef NO_ARCHIVES
29 #ifdef VMS
30 #include <lbrdef.h>
31 #include <mhddef.h>
32 #include <credef.h>
33 #include <descrip.h>
34 #include <ctype.h>
35 #if __DECC
36 #include <unixlib.h>
37 #include <lbr$routines.h>
38 #endif
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) ();
48 static int
49 VMS_get_member_info (module, rfa)
50 struct dsc$descriptor_s *module;
51 unsigned long *rfa;
53 int status, i;
54 long int fnval;
56 time_t val;
58 static struct dsc$descriptor_s bufdesc =
59 { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
61 struct mhddef *mhd;
62 char filename[128];
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);
69 if (! status)
71 error (NILF, _("lbr$set_module failed to extract module info, status = %d"),
72 status);
74 lbr$close (&VMS_lib_idx);
76 return 0;
79 mhd = (struct mhddef *) filename;
81 #ifdef __DECC
82 val = decc$fix_time (&mhd->mhd$l_datim);
83 #endif
85 for (i = 0; i < module->dsc$w_length; i++)
86 filename[i] = _tolower ((unsigned char)module->dsc$a_pointer[i]);
88 filename[i] = '\0';
90 VMS_member_date = (time_t) -1;
92 fnval =
93 (*VMS_function) (-1, filename, 0, 0, 0, 0, val, 0, 0, 0,
94 VMS_saved_memname);
96 if (fnval)
98 VMS_member_date = fnval;
99 return 0;
101 else
102 return 1;
105 /* Takes three arguments ARCHIVE, FUNCTION and ARG.
107 Open the archive named ARCHIVE, find its members one by one,
108 and for each one call FUNCTION with the following arguments:
109 archive file descriptor for reading the data,
110 member name,
111 member name might be truncated flag,
112 member header position in file,
113 member data position in file,
114 member data size,
115 member date,
116 member uid,
117 member gid,
118 member protection mode,
119 ARG.
121 NOTE: on VMS systems, only name, date, and arg are meaningful!
123 The descriptor is poised to read the data of the member
124 when FUNCTION is called. It does not matter how much
125 data FUNCTION reads.
127 If FUNCTION returns nonzero, we immediately return
128 what FUNCTION returned.
130 Returns -1 if archive does not exist,
131 Returns -2 if archive has invalid format.
132 Returns 0 if have scanned successfully. */
134 long int
135 ar_scan (archive, function, arg)
136 char *archive;
137 long int (*function) ();
138 long int arg;
140 char *p;
142 static struct dsc$descriptor_s libdesc =
143 { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
145 unsigned long func = LBR$C_READ;
146 unsigned long type = LBR$C_TYP_UNK;
147 unsigned long index = 1;
149 int status;
151 status = lbr$ini_control (&VMS_lib_idx, &func, &type, 0);
153 if (! status)
155 error (NILF, _("lbr$ini_control failed with status = %d"),status);
156 return -2;
159 libdesc.dsc$a_pointer = archive;
160 libdesc.dsc$w_length = strlen (archive);
162 status = lbr$open (&VMS_lib_idx, &libdesc, 0, 0, 0, 0, 0);
164 if (! status)
166 error (NILF, _("unable to open library `%s' to lookup member `%s'"),
167 archive, (char *)arg);
168 return -1;
171 VMS_saved_memname = (char *)arg;
173 /* For comparison, delete .obj from arg name. */
175 p = strrchr (VMS_saved_memname, '.');
176 if (p)
177 *p = '\0';
179 VMS_function = function;
181 VMS_member_date = (time_t) -1;
182 lbr$get_index (&VMS_lib_idx, &index, VMS_get_member_info, 0);
184 /* Undo the damage. */
185 if (p)
186 *p = '.';
188 lbr$close (&VMS_lib_idx);
190 return VMS_member_date > 0 ? VMS_member_date : 0;
193 #else /* !VMS */
195 /* SCO Unix's compiler defines both of these. */
196 #ifdef M_UNIX
197 #undef M_XENIX
198 #endif
200 /* On the sun386i and in System V rel 3, ar.h defines two different archive
201 formats depending upon whether you have defined PORTAR (normal) or PORT5AR
202 (System V Release 1). There is no default, one or the other must be defined
203 to have a nonzero value. */
205 #if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0)
206 #undef PORTAR
207 #ifdef M_XENIX
208 /* According to Jim Sievert <jas1@rsvl.unisys.com>, for SCO XENIX defining
209 PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the
210 right one. */
211 #define PORTAR 0
212 #else
213 #define PORTAR 1
214 #endif
215 #endif
217 /* On AIX, define these symbols to be sure to get both archive formats.
218 AIX 4.3 introduced the "big" archive format to support 64-bit object
219 files, so on AIX 4.3 systems we need to support both the "normal" and
220 "big" archive formats. An archive's format is indicated in the
221 "fl_magic" field of the "FL_HDR" structure. For a normal archive,
222 this field will be the string defined by the AIAMAG symbol. For a
223 "big" archive, it will be the string defined by the AIAMAGBIG symbol
224 (at least on AIX it works this way).
226 Note: we'll define these symbols regardless of which AIX version
227 we're compiling on, but this is okay since we'll use the new symbols
228 only if they're present. */
229 #ifdef _AIX
230 # define __AR_SMALL__
231 # define __AR_BIG__
232 #endif
234 #ifndef WINDOWS32
235 # include <ar.h>
236 #else
237 /* These should allow us to read Windows (VC++) libraries (according to Frank
238 * Libbrecht <frankl@abzx.belgium.hp.com>)
240 # include <windows.h>
241 # include <windef.h>
242 # include <io.h>
243 # define ARMAG IMAGE_ARCHIVE_START
244 # define SARMAG IMAGE_ARCHIVE_START_SIZE
245 # define ar_hdr _IMAGE_ARCHIVE_MEMBER_HEADER
246 # define ar_name Name
247 # define ar_mode Mode
248 # define ar_size Size
249 # define ar_date Date
250 # define ar_uid UserID
251 # define ar_gid GroupID
252 #endif
254 /* Cray's <ar.h> apparently defines this. */
255 #ifndef AR_HDR_SIZE
256 # define AR_HDR_SIZE (sizeof (struct ar_hdr))
257 #endif
259 /* Takes three arguments ARCHIVE, FUNCTION and ARG.
261 Open the archive named ARCHIVE, find its members one by one,
262 and for each one call FUNCTION with the following arguments:
263 archive file descriptor for reading the data,
264 member name,
265 member name might be truncated flag,
266 member header position in file,
267 member data position in file,
268 member data size,
269 member date,
270 member uid,
271 member gid,
272 member protection mode,
273 ARG.
275 The descriptor is poised to read the data of the member
276 when FUNCTION is called. It does not matter how much
277 data FUNCTION reads.
279 If FUNCTION returns nonzero, we immediately return
280 what FUNCTION returned.
282 Returns -1 if archive does not exist,
283 Returns -2 if archive has invalid format.
284 Returns 0 if have scanned successfully. */
286 long int
287 ar_scan (archive, function, arg)
288 char *archive;
289 long int (*function) ();
290 long int arg;
292 #ifdef AIAMAG
293 FL_HDR fl_header;
294 #ifdef AIAMAGBIG
295 int big_archive = 0;
296 FL_HDR_BIG fl_header_big;
297 #endif
298 #else
299 int long_name = 0;
300 #endif
301 char *namemap = 0;
302 register int desc = open (archive, O_RDONLY, 0);
303 if (desc < 0)
304 return -1;
305 #ifdef SARMAG
307 char buf[SARMAG];
308 register int nread = read (desc, buf, SARMAG);
309 if (nread != SARMAG || bcmp (buf, ARMAG, SARMAG))
311 (void) close (desc);
312 return -2;
315 #else
316 #ifdef AIAMAG
318 register int nread = read (desc, (char *) &fl_header, FL_HSZ);
320 if (nread != FL_HSZ)
322 (void) close (desc);
323 return -2;
325 #ifdef AIAMAGBIG
326 /* If this is a "big" archive, then set the flag and
327 re-read the header into the "big" structure. */
328 if (!bcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG))
330 big_archive = 1;
332 /* seek back to beginning of archive */
333 if (lseek (desc, 0, 0) < 0)
335 (void) close (desc);
336 return -2;
339 /* re-read the header into the "big" structure */
340 nread = read (desc, (char *) &fl_header_big, FL_HSZ_BIG);
341 if (nread != FL_HSZ_BIG)
343 (void) close (desc);
344 return -2;
347 else
348 #endif
349 /* Check to make sure this is a "normal" archive. */
350 if (bcmp (fl_header.fl_magic, AIAMAG, SAIAMAG))
352 (void) close (desc);
353 return -2;
356 #else
358 #ifndef M_XENIX
359 int buf;
360 #else
361 unsigned short int buf;
362 #endif
363 register int nread = read(desc, &buf, sizeof (buf));
364 if (nread != sizeof (buf) || buf != ARMAG)
366 (void) close (desc);
367 return -2;
370 #endif
371 #endif
373 /* Now find the members one by one. */
375 #ifdef SARMAG
376 register long int member_offset = SARMAG;
377 #else
378 #ifdef AIAMAG
379 long int member_offset;
380 long int last_member_offset;
382 #ifdef AIAMAGBIG
383 if ( big_archive )
385 sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset);
386 sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset);
388 else
389 #endif
391 sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset);
392 sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset);
395 if (member_offset == 0)
397 /* Empty archive. */
398 close (desc);
399 return 0;
401 #else
402 #ifndef M_XENIX
403 register long int member_offset = sizeof (int);
404 #else /* Xenix. */
405 register long int member_offset = sizeof (unsigned short int);
406 #endif /* Not Xenix. */
407 #endif
408 #endif
410 while (1)
412 register int nread;
413 struct ar_hdr member_header;
414 #ifdef AIAMAGBIG
415 struct ar_hdr_big member_header_big;
416 #endif
417 #ifdef AIAMAG
418 char name[256];
419 int name_len;
420 long int dateval;
421 int uidval, gidval;
422 long int data_offset;
423 #else
424 char namebuf[sizeof member_header.ar_name + 1];
425 char *name;
426 int is_namemap; /* Nonzero if this entry maps long names. */
427 #endif
428 long int eltsize;
429 int eltmode;
430 long int fnval;
432 if (lseek (desc, member_offset, 0) < 0)
434 (void) close (desc);
435 return -2;
438 #ifdef AIAMAG
439 #define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
441 #ifdef AIAMAGBIG
442 if (big_archive)
444 nread = read (desc, (char *) &member_header_big,
445 AR_MEMHDR_SZ(member_header_big) );
447 if (nread != AR_MEMHDR_SZ(member_header_big))
449 (void) close (desc);
450 return -2;
453 sscanf (member_header_big.ar_namlen, "%4d", &name_len);
454 nread = read (desc, name, name_len);
456 if (nread != name_len)
458 (void) close (desc);
459 return -2;
462 name[name_len] = 0;
464 sscanf (member_header_big.ar_date, "%12ld", &dateval);
465 sscanf (member_header_big.ar_uid, "%12d", &uidval);
466 sscanf (member_header_big.ar_gid, "%12d", &gidval);
467 sscanf (member_header_big.ar_mode, "%12o", &eltmode);
468 sscanf (member_header_big.ar_size, "%20ld", &eltsize);
470 data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big)
471 + name_len + 2);
473 else
474 #endif
476 nread = read (desc, (char *) &member_header,
477 AR_MEMHDR_SZ(member_header) );
479 if (nread != AR_MEMHDR_SZ(member_header))
481 (void) close (desc);
482 return -2;
485 sscanf (member_header.ar_namlen, "%4d", &name_len);
486 nread = read (desc, name, name_len);
488 if (nread != name_len)
490 (void) close (desc);
491 return -2;
494 name[name_len] = 0;
496 sscanf (member_header.ar_date, "%12ld", &dateval);
497 sscanf (member_header.ar_uid, "%12d", &uidval);
498 sscanf (member_header.ar_gid, "%12d", &gidval);
499 sscanf (member_header.ar_mode, "%12o", &eltmode);
500 sscanf (member_header.ar_size, "%12ld", &eltsize);
502 data_offset = (member_offset + AR_MEMHDR_SZ(member_header)
503 + name_len + 2);
505 data_offset += data_offset % 2;
507 fnval =
508 (*function) (desc, name, 0,
509 member_offset, data_offset, eltsize,
510 dateval, uidval, gidval,
511 eltmode, arg);
513 #else /* Not AIAMAG. */
514 nread = read (desc, (char *) &member_header, AR_HDR_SIZE);
515 if (nread == 0)
516 /* No data left means end of file; that is OK. */
517 break;
519 if (nread != AR_HDR_SIZE
520 #if defined(ARFMAG) || defined(ARFZMAG)
521 || (
522 # ifdef ARFMAG
523 bcmp (member_header.ar_fmag, ARFMAG, 2)
524 # else
526 # endif
528 # ifdef ARFZMAG
529 bcmp (member_header.ar_fmag, ARFZMAG, 2)
530 # else
532 # endif
534 #endif
537 (void) close (desc);
538 return -2;
541 name = namebuf;
542 bcopy (member_header.ar_name, name, sizeof member_header.ar_name);
544 register char *p = name + sizeof member_header.ar_name;
546 *p = '\0';
547 while (p > name && *--p == ' ');
549 #ifndef AIAMAG
550 /* If the member name is "//" or "ARFILENAMES/" this may be
551 a list of file name mappings. The maximum file name
552 length supported by the standard archive format is 14
553 characters. This member will actually always be the
554 first or second entry in the archive, but we don't check
555 that. */
556 is_namemap = (!strcmp (name, "//")
557 || !strcmp (name, "ARFILENAMES/"));
558 #endif /* Not AIAMAG. */
559 /* On some systems, there is a slash after each member name. */
560 if (*p == '/')
561 *p = '\0';
563 #ifndef AIAMAG
564 /* If the member name starts with a space or a slash, this
565 is an index into the file name mappings (used by GNU ar).
566 Otherwise if the member name looks like #1/NUMBER the
567 real member name appears in the element data (used by
568 4.4BSD). */
569 if (! is_namemap
570 && (name[0] == ' ' || name[0] == '/')
571 && namemap != 0)
573 name = namemap + atoi (name + 1);
574 long_name = 1;
576 else if (name[0] == '#'
577 && name[1] == '1'
578 && name[2] == '/')
580 int namesize = atoi (name + 3);
582 name = (char *) alloca (namesize + 1);
583 nread = read (desc, name, namesize);
584 if (nread != namesize)
586 close (desc);
587 return -2;
589 name[namesize] = '\0';
591 long_name = 1;
593 #endif /* Not AIAMAG. */
596 #ifndef M_XENIX
597 sscanf (member_header.ar_mode, "%o", &eltmode);
598 eltsize = atol (member_header.ar_size);
599 #else /* Xenix. */
600 eltmode = (unsigned short int) member_header.ar_mode;
601 eltsize = member_header.ar_size;
602 #endif /* Not Xenix. */
604 fnval =
605 (*function) (desc, name, ! long_name, member_offset,
606 member_offset + AR_HDR_SIZE, eltsize,
607 #ifndef M_XENIX
608 atol (member_header.ar_date),
609 atoi (member_header.ar_uid),
610 atoi (member_header.ar_gid),
611 #else /* Xenix. */
612 member_header.ar_date,
613 member_header.ar_uid,
614 member_header.ar_gid,
615 #endif /* Not Xenix. */
616 eltmode, arg);
618 #endif /* AIAMAG. */
620 if (fnval)
622 (void) close (desc);
623 return fnval;
626 #ifdef AIAMAG
627 if (member_offset == last_member_offset)
628 /* End of the chain. */
629 break;
631 #ifdef AIAMAGBIG
632 if (big_archive)
633 sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset);
634 else
635 #endif
636 sscanf (member_header.ar_nxtmem, "%12ld", &member_offset);
638 if (lseek (desc, member_offset, 0) != member_offset)
640 (void) close (desc);
641 return -2;
643 #else
645 /* If this member maps archive names, we must read it in. The
646 name map will always precede any members whose names must
647 be mapped. */
648 if (is_namemap)
650 char *clear;
651 char *limit;
653 namemap = (char *) alloca (eltsize);
654 nread = read (desc, namemap, eltsize);
655 if (nread != eltsize)
657 (void) close (desc);
658 return -2;
661 /* The names are separated by newlines. Some formats have
662 a trailing slash. Null terminate the strings for
663 convenience. */
664 limit = namemap + eltsize;
665 for (clear = namemap; clear < limit; clear++)
667 if (*clear == '\n')
669 *clear = '\0';
670 if (clear[-1] == '/')
671 clear[-1] = '\0';
675 is_namemap = 0;
678 member_offset += AR_HDR_SIZE + eltsize;
679 if (member_offset % 2 != 0)
680 member_offset++;
681 #endif
685 close (desc);
686 return 0;
688 #endif /* !VMS */
690 /* Return nonzero iff NAME matches MEM.
691 If TRUNCATED is nonzero, MEM may be truncated to
692 sizeof (struct ar_hdr.ar_name) - 1. */
695 ar_name_equal (name, mem, truncated)
696 char *name, *mem;
697 int truncated;
699 char *p;
701 p = strrchr (name, '/');
702 if (p != 0)
703 name = p + 1;
705 #ifndef VMS
706 if (truncated)
708 #ifdef AIAMAG
709 /* TRUNCATED should never be set on this system. */
710 abort ();
711 #else
712 struct ar_hdr hdr;
713 #if !defined (__hpux) && !defined (cray)
714 return strneq (name, mem, sizeof(hdr.ar_name) - 1);
715 #else
716 return strneq (name, mem, sizeof(hdr.ar_name) - 2);
717 #endif /* !__hpux && !cray */
718 #endif /* !AIAMAG */
720 #endif /* !VMS */
722 return !strcmp (name, mem);
725 #ifndef VMS
726 /* ARGSUSED */
727 static long int
728 ar_member_pos (desc, mem, truncated,
729 hdrpos, datapos, size, date, uid, gid, mode, name)
730 int desc;
731 char *mem;
732 int truncated;
733 long int hdrpos, datapos, size, date;
734 int uid, gid, mode;
735 char *name;
737 if (!ar_name_equal (name, mem, truncated))
738 return 0;
739 return hdrpos;
742 /* Set date of member MEMNAME in archive ARNAME to current time.
743 Returns 0 if successful,
744 -1 if file ARNAME does not exist,
745 -2 if not a valid archive,
746 -3 if other random system call error (including file read-only),
747 1 if valid but member MEMNAME does not exist. */
750 ar_member_touch (arname, memname)
751 char *arname, *memname;
753 register long int pos = ar_scan (arname, ar_member_pos, (long int) memname);
754 register int fd;
755 struct ar_hdr ar_hdr;
756 register int i;
757 struct stat statbuf;
759 if (pos < 0)
760 return (int) pos;
761 if (!pos)
762 return 1;
764 fd = open (arname, O_RDWR, 0666);
765 if (fd < 0)
766 return -3;
767 /* Read in this member's header */
768 if (lseek (fd, pos, 0) < 0)
769 goto lose;
770 if (AR_HDR_SIZE != read (fd, (char *) &ar_hdr, AR_HDR_SIZE))
771 goto lose;
772 /* Write back the header, thus touching the archive file. */
773 if (lseek (fd, pos, 0) < 0)
774 goto lose;
775 if (AR_HDR_SIZE != write (fd, (char *) &ar_hdr, AR_HDR_SIZE))
776 goto lose;
777 /* The file's mtime is the time we we want. */
778 while (fstat (fd, &statbuf) < 0 && EINTR_SET)
780 #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
781 /* Advance member's time to that time */
782 for (i = 0; i < sizeof ar_hdr.ar_date; i++)
783 ar_hdr.ar_date[i] = ' ';
784 sprintf (ar_hdr.ar_date, "%ld", (long int) statbuf.st_mtime);
785 #ifdef AIAMAG
786 ar_hdr.ar_date[strlen(ar_hdr.ar_date)] = ' ';
787 #endif
788 #else
789 ar_hdr.ar_date = statbuf.st_mtime;
790 #endif
791 /* Write back this member's header */
792 if (lseek (fd, pos, 0) < 0)
793 goto lose;
794 if (AR_HDR_SIZE != write (fd, (char *) &ar_hdr, AR_HDR_SIZE))
795 goto lose;
796 close (fd);
797 return 0;
799 lose:
800 i = errno;
801 close (fd);
802 errno = i;
803 return -3;
805 #endif
807 #ifdef TEST
809 long int
810 describe_member (desc, name, truncated,
811 hdrpos, datapos, size, date, uid, gid, mode)
812 int desc;
813 char *name;
814 int truncated;
815 long int hdrpos, datapos, size, date;
816 int uid, gid, mode;
818 extern char *ctime ();
820 printf (_("Member `%s'%s: %ld bytes at %ld (%ld).\n"),
821 name, truncated ? _(" (name might be truncated)") : "",
822 size, hdrpos, datapos);
823 printf (_(" Date %s"), ctime (&date));
824 printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode);
826 return 0;
829 main (argc, argv)
830 int argc;
831 char **argv;
833 ar_scan (argv[1], describe_member);
834 return 0;
837 #endif /* TEST. */
839 #endif /* NO_ARCHIVES. */