* Add new debug header file.
[make.git] / arscan.c
blob6ff271540f0d55d3299685c11193ffe230d8719c
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 val = decc$fix_time (&mhd->mhd$l_datim);
83 for (i = 0; i < module->dsc$w_length; i++)
84 filename[i] = _tolower ((unsigned char)module->dsc$a_pointer[i]);
86 filename[i] = '\0';
88 VMS_member_date = (time_t) -1;
90 fnval =
91 (*VMS_function) (-1, filename, 0, 0, 0, 0, val, 0, 0, 0,
92 VMS_saved_memname);
94 if (fnval)
96 VMS_member_date = fnval;
97 return 0;
99 else
100 return 1;
103 /* Takes three arguments ARCHIVE, FUNCTION and ARG.
105 Open the archive named ARCHIVE, find its members one by one,
106 and for each one call FUNCTION with the following arguments:
107 archive file descriptor for reading the data,
108 member name,
109 member name might be truncated flag,
110 member header position in file,
111 member data position in file,
112 member data size,
113 member date,
114 member uid,
115 member gid,
116 member protection mode,
117 ARG.
119 NOTE: on VMS systems, only name, date, and arg are meaningful!
121 The descriptor is poised to read the data of the member
122 when FUNCTION is called. It does not matter how much
123 data FUNCTION reads.
125 If FUNCTION returns nonzero, we immediately return
126 what FUNCTION returned.
128 Returns -1 if archive does not exist,
129 Returns -2 if archive has invalid format.
130 Returns 0 if have scanned successfully. */
132 long int
133 ar_scan (archive, function, arg)
134 char *archive;
135 long int (*function) ();
136 long int arg;
138 char *p;
140 static struct dsc$descriptor_s libdesc =
141 { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
143 unsigned long func = LBR$C_READ;
144 unsigned long type = LBR$C_TYP_UNK;
145 unsigned long index = 1;
147 int status;
149 status = lbr$ini_control (&VMS_lib_idx, &func, &type, 0);
151 if (! status)
153 error (NILF, _("lbr$ini_control failed with status = %d"),status);
154 return -2;
157 libdesc.dsc$a_pointer = archive;
158 libdesc.dsc$w_length = strlen (archive);
160 status = lbr$open (&VMS_lib_idx, &libdesc, 0, 0, 0, 0, 0);
162 if (! status)
164 error (NILF, _("unable to open library `%s' to lookup member `%s'"),
165 archive, (char *)arg);
166 return -1;
169 VMS_saved_memname = (char *)arg;
171 /* For comparison, delete .obj from arg name. */
173 p = strrchr (VMS_saved_memname, '.');
174 if (p)
175 *p = '\0';
177 VMS_function = function;
179 VMS_member_date = (time_t) -1;
180 lbr$get_index (&VMS_lib_idx, &index, VMS_get_member_info, 0);
182 /* Undo the damage. */
183 if (p)
184 *p = '.';
186 lbr$close (&VMS_lib_idx);
188 return VMS_member_date > 0 ? VMS_member_date : 0;
191 #else /* !VMS */
193 /* SCO Unix's compiler defines both of these. */
194 #ifdef M_UNIX
195 #undef M_XENIX
196 #endif
198 /* On the sun386i and in System V rel 3, ar.h defines two different archive
199 formats depending upon whether you have defined PORTAR (normal) or PORT5AR
200 (System V Release 1). There is no default, one or the other must be defined
201 to have a nonzero value. */
203 #if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0)
204 #undef PORTAR
205 #ifdef M_XENIX
206 /* According to Jim Sievert <jas1@rsvl.unisys.com>, for SCO XENIX defining
207 PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the
208 right one. */
209 #define PORTAR 0
210 #else
211 #define PORTAR 1
212 #endif
213 #endif
215 /* On AIX, define these symbols to be sure to get both archive formats.
216 AIX 4.3 introduced the "big" archive format to support 64-bit object
217 files, so on AIX 4.3 systems we need to support both the "normal" and
218 "big" archive formats. An archive's format is indicated in the
219 "fl_magic" field of the "FL_HDR" structure. For a normal archive,
220 this field will be the string defined by the AIAMAG symbol. For a
221 "big" archive, it will be the string defined by the AIAMAGBIG symbol
222 (at least on AIX it works this way).
224 Note: we'll define these symbols regardless of which AIX version
225 we're compiling on, but this is okay since we'll use the new symbols
226 only if they're present. */
227 #ifdef _AIX
228 # define __AR_SMALL__
229 # define __AR_BIG__
230 #endif
232 #ifndef WINDOWS32
233 # include <ar.h>
234 #else
235 /* These should allow us to read Windows (VC++) libraries (according to Frank
236 * Libbrecht <frankl@abzx.belgium.hp.com>)
238 # include <windows.h>
239 # include <windef.h>
240 # include <io.h>
241 # define ARMAG IMAGE_ARCHIVE_START
242 # define SARMAG IMAGE_ARCHIVE_START_SIZE
243 # define ar_hdr _IMAGE_ARCHIVE_MEMBER_HEADER
244 # define ar_name Name
245 # define ar_mode Mode
246 # define ar_size Size
247 # define ar_date Date
248 # define ar_uid UserID
249 # define ar_gid GroupID
250 #endif
252 /* Cray's <ar.h> apparently defines this. */
253 #ifndef AR_HDR_SIZE
254 # define AR_HDR_SIZE (sizeof (struct ar_hdr))
255 #endif
257 /* Takes three arguments ARCHIVE, FUNCTION and ARG.
259 Open the archive named ARCHIVE, find its members one by one,
260 and for each one call FUNCTION with the following arguments:
261 archive file descriptor for reading the data,
262 member name,
263 member name might be truncated flag,
264 member header position in file,
265 member data position in file,
266 member data size,
267 member date,
268 member uid,
269 member gid,
270 member protection mode,
271 ARG.
273 The descriptor is poised to read the data of the member
274 when FUNCTION is called. It does not matter how much
275 data FUNCTION reads.
277 If FUNCTION returns nonzero, we immediately return
278 what FUNCTION returned.
280 Returns -1 if archive does not exist,
281 Returns -2 if archive has invalid format.
282 Returns 0 if have scanned successfully. */
284 long int
285 ar_scan (archive, function, arg)
286 char *archive;
287 long int (*function) ();
288 long int arg;
290 #ifdef AIAMAG
291 FL_HDR fl_header;
292 #ifdef AIAMAGBIG
293 int big_archive = 0;
294 FL_HDR_BIG fl_header_big;
295 #endif
296 #else
297 int long_name = 0;
298 #endif
299 char *namemap = 0;
300 register int desc = open (archive, O_RDONLY, 0);
301 if (desc < 0)
302 return -1;
303 #ifdef SARMAG
305 char buf[SARMAG];
306 register int nread = read (desc, buf, SARMAG);
307 if (nread != SARMAG || bcmp (buf, ARMAG, SARMAG))
309 (void) close (desc);
310 return -2;
313 #else
314 #ifdef AIAMAG
316 register int nread = read (desc, (char *) &fl_header, FL_HSZ);
318 if (nread != FL_HSZ)
320 (void) close (desc);
321 return -2;
323 #ifdef AIAMAGBIG
324 /* If this is a "big" archive, then set the flag and
325 re-read the header into the "big" structure. */
326 if (!bcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG))
328 big_archive = 1;
330 /* seek back to beginning of archive */
331 if (lseek (desc, 0, 0) < 0)
333 (void) close (desc);
334 return -2;
337 /* re-read the header into the "big" structure */
338 nread = read (desc, (char *) &fl_header_big, FL_HSZ_BIG);
339 if (nread != FL_HSZ_BIG)
341 (void) close (desc);
342 return -2;
345 else
346 #endif
347 /* Check to make sure this is a "normal" archive. */
348 if (bcmp (fl_header.fl_magic, AIAMAG, SAIAMAG))
350 (void) close (desc);
351 return -2;
354 #else
356 #ifndef M_XENIX
357 int buf;
358 #else
359 unsigned short int buf;
360 #endif
361 register int nread = read(desc, &buf, sizeof (buf));
362 if (nread != sizeof (buf) || buf != ARMAG)
364 (void) close (desc);
365 return -2;
368 #endif
369 #endif
371 /* Now find the members one by one. */
373 #ifdef SARMAG
374 register long int member_offset = SARMAG;
375 #else
376 #ifdef AIAMAG
377 long int member_offset;
378 long int last_member_offset;
380 #ifdef AIAMAGBIG
381 if ( big_archive )
383 sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset);
384 sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset);
386 else
387 #endif
389 sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset);
390 sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset);
393 if (member_offset == 0)
395 /* Empty archive. */
396 close (desc);
397 return 0;
399 #else
400 #ifndef M_XENIX
401 register long int member_offset = sizeof (int);
402 #else /* Xenix. */
403 register long int member_offset = sizeof (unsigned short int);
404 #endif /* Not Xenix. */
405 #endif
406 #endif
408 while (1)
410 register int nread;
411 struct ar_hdr member_header;
412 #ifdef AIAMAGBIG
413 struct ar_hdr_big member_header_big;
414 #endif
415 #ifdef AIAMAG
416 char name[256];
417 int name_len;
418 long int dateval;
419 int uidval, gidval;
420 long int data_offset;
421 #else
422 char namebuf[sizeof member_header.ar_name + 1];
423 char *name;
424 int is_namemap; /* Nonzero if this entry maps long names. */
425 #endif
426 long int eltsize;
427 int eltmode;
428 long int fnval;
430 if (lseek (desc, member_offset, 0) < 0)
432 (void) close (desc);
433 return -2;
436 #ifdef AIAMAG
437 #define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
439 #ifdef AIAMAGBIG
440 if (big_archive)
442 nread = read (desc, (char *) &member_header_big,
443 AR_MEMHDR_SZ(member_header_big) );
445 if (nread != AR_MEMHDR_SZ(member_header_big))
447 (void) close (desc);
448 return -2;
451 sscanf (member_header_big.ar_namlen, "%4d", &name_len);
452 nread = read (desc, name, name_len);
454 if (nread != name_len)
456 (void) close (desc);
457 return -2;
460 name[name_len] = 0;
462 sscanf (member_header_big.ar_date, "%12ld", &dateval);
463 sscanf (member_header_big.ar_uid, "%12d", &uidval);
464 sscanf (member_header_big.ar_gid, "%12d", &gidval);
465 sscanf (member_header_big.ar_mode, "%12o", &eltmode);
466 sscanf (member_header_big.ar_size, "%20ld", &eltsize);
468 data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big)
469 + name_len + 2);
471 else
472 #endif
474 nread = read (desc, (char *) &member_header,
475 AR_MEMHDR_SZ(member_header) );
477 if (nread != AR_MEMHDR_SZ(member_header))
479 (void) close (desc);
480 return -2;
483 sscanf (member_header.ar_namlen, "%4d", &name_len);
484 nread = read (desc, name, name_len);
486 if (nread != name_len)
488 (void) close (desc);
489 return -2;
492 name[name_len] = 0;
494 sscanf (member_header.ar_date, "%12ld", &dateval);
495 sscanf (member_header.ar_uid, "%12d", &uidval);
496 sscanf (member_header.ar_gid, "%12d", &gidval);
497 sscanf (member_header.ar_mode, "%12o", &eltmode);
498 sscanf (member_header.ar_size, "%12ld", &eltsize);
500 data_offset = (member_offset + AR_MEMHDR_SZ(member_header)
501 + name_len + 2);
503 data_offset += data_offset % 2;
505 fnval =
506 (*function) (desc, name, 0,
507 member_offset, data_offset, eltsize,
508 dateval, uidval, gidval,
509 eltmode, arg);
511 #else /* Not AIAMAG. */
512 nread = read (desc, (char *) &member_header, AR_HDR_SIZE);
513 if (nread == 0)
514 /* No data left means end of file; that is OK. */
515 break;
517 if (nread != AR_HDR_SIZE
518 #if defined(ARFMAG) || defined(ARFZMAG)
519 || (
520 # ifdef ARFMAG
521 bcmp (member_header.ar_fmag, ARFMAG, 2)
522 # else
524 # endif
526 # ifdef ARFZMAG
527 bcmp (member_header.ar_fmag, ARFZMAG, 2)
528 # else
530 # endif
532 #endif
535 (void) close (desc);
536 return -2;
539 name = namebuf;
540 bcopy (member_header.ar_name, name, sizeof member_header.ar_name);
542 register char *p = name + sizeof member_header.ar_name;
544 *p = '\0';
545 while (p > name && *--p == ' ');
547 #ifndef AIAMAG
548 /* If the member name is "//" or "ARFILENAMES/" this may be
549 a list of file name mappings. The maximum file name
550 length supported by the standard archive format is 14
551 characters. This member will actually always be the
552 first or second entry in the archive, but we don't check
553 that. */
554 is_namemap = (!strcmp (name, "//")
555 || !strcmp (name, "ARFILENAMES/"));
556 #endif /* Not AIAMAG. */
557 /* On some systems, there is a slash after each member name. */
558 if (*p == '/')
559 *p = '\0';
561 #ifndef AIAMAG
562 /* If the member name starts with a space or a slash, this
563 is an index into the file name mappings (used by GNU ar).
564 Otherwise if the member name looks like #1/NUMBER the
565 real member name appears in the element data (used by
566 4.4BSD). */
567 if (! is_namemap
568 && (name[0] == ' ' || name[0] == '/')
569 && namemap != 0)
571 name = namemap + atoi (name + 1);
572 long_name = 1;
574 else if (name[0] == '#'
575 && name[1] == '1'
576 && name[2] == '/')
578 int namesize = atoi (name + 3);
580 name = (char *) alloca (namesize + 1);
581 nread = read (desc, name, namesize);
582 if (nread != namesize)
584 close (desc);
585 return -2;
587 name[namesize] = '\0';
589 long_name = 1;
591 #endif /* Not AIAMAG. */
594 #ifndef M_XENIX
595 sscanf (member_header.ar_mode, "%o", &eltmode);
596 eltsize = atol (member_header.ar_size);
597 #else /* Xenix. */
598 eltmode = (unsigned short int) member_header.ar_mode;
599 eltsize = member_header.ar_size;
600 #endif /* Not Xenix. */
602 fnval =
603 (*function) (desc, name, ! long_name, member_offset,
604 member_offset + AR_HDR_SIZE, eltsize,
605 #ifndef M_XENIX
606 atol (member_header.ar_date),
607 atoi (member_header.ar_uid),
608 atoi (member_header.ar_gid),
609 #else /* Xenix. */
610 member_header.ar_date,
611 member_header.ar_uid,
612 member_header.ar_gid,
613 #endif /* Not Xenix. */
614 eltmode, arg);
616 #endif /* AIAMAG. */
618 if (fnval)
620 (void) close (desc);
621 return fnval;
624 #ifdef AIAMAG
625 if (member_offset == last_member_offset)
626 /* End of the chain. */
627 break;
629 #ifdef AIAMAGBIG
630 if (big_archive)
631 sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset);
632 else
633 #endif
634 sscanf (member_header.ar_nxtmem, "%12ld", &member_offset);
636 if (lseek (desc, member_offset, 0) != member_offset)
638 (void) close (desc);
639 return -2;
641 #else
643 /* If this member maps archive names, we must read it in. The
644 name map will always precede any members whose names must
645 be mapped. */
646 if (is_namemap)
648 char *clear;
649 char *limit;
651 namemap = (char *) alloca (eltsize);
652 nread = read (desc, namemap, eltsize);
653 if (nread != eltsize)
655 (void) close (desc);
656 return -2;
659 /* The names are separated by newlines. Some formats have
660 a trailing slash. Null terminate the strings for
661 convenience. */
662 limit = namemap + eltsize;
663 for (clear = namemap; clear < limit; clear++)
665 if (*clear == '\n')
667 *clear = '\0';
668 if (clear[-1] == '/')
669 clear[-1] = '\0';
673 is_namemap = 0;
676 member_offset += AR_HDR_SIZE + eltsize;
677 if (member_offset % 2 != 0)
678 member_offset++;
679 #endif
683 close (desc);
684 return 0;
686 #endif /* !VMS */
688 /* Return nonzero iff NAME matches MEM.
689 If TRUNCATED is nonzero, MEM may be truncated to
690 sizeof (struct ar_hdr.ar_name) - 1. */
693 ar_name_equal (name, mem, truncated)
694 char *name, *mem;
695 int truncated;
697 char *p;
699 p = strrchr (name, '/');
700 if (p != 0)
701 name = p + 1;
703 #ifndef VMS
704 if (truncated)
706 #ifdef AIAMAG
707 /* TRUNCATED should never be set on this system. */
708 abort ();
709 #else
710 struct ar_hdr hdr;
711 #if !defined (__hpux) && !defined (cray)
712 return strneq (name, mem, sizeof(hdr.ar_name) - 1);
713 #else
714 return strneq (name, mem, sizeof(hdr.ar_name) - 2);
715 #endif /* !__hpux && !cray */
716 #endif /* !AIAMAG */
718 #endif /* !VMS */
720 return !strcmp (name, mem);
723 #ifndef VMS
724 /* ARGSUSED */
725 static long int
726 ar_member_pos (desc, mem, truncated,
727 hdrpos, datapos, size, date, uid, gid, mode, name)
728 int desc;
729 char *mem;
730 int truncated;
731 long int hdrpos, datapos, size, date;
732 int uid, gid, mode;
733 char *name;
735 if (!ar_name_equal (name, mem, truncated))
736 return 0;
737 return hdrpos;
740 /* Set date of member MEMNAME in archive ARNAME to current time.
741 Returns 0 if successful,
742 -1 if file ARNAME does not exist,
743 -2 if not a valid archive,
744 -3 if other random system call error (including file read-only),
745 1 if valid but member MEMNAME does not exist. */
748 ar_member_touch (arname, memname)
749 char *arname, *memname;
751 register long int pos = ar_scan (arname, ar_member_pos, (long int) memname);
752 register int fd;
753 struct ar_hdr ar_hdr;
754 register int i;
755 struct stat statbuf;
757 if (pos < 0)
758 return (int) pos;
759 if (!pos)
760 return 1;
762 fd = open (arname, O_RDWR, 0666);
763 if (fd < 0)
764 return -3;
765 /* Read in this member's header */
766 if (lseek (fd, pos, 0) < 0)
767 goto lose;
768 if (AR_HDR_SIZE != read (fd, (char *) &ar_hdr, AR_HDR_SIZE))
769 goto lose;
770 /* Write back the header, thus touching the archive file. */
771 if (lseek (fd, pos, 0) < 0)
772 goto lose;
773 if (AR_HDR_SIZE != write (fd, (char *) &ar_hdr, AR_HDR_SIZE))
774 goto lose;
775 /* The file's mtime is the time we we want. */
776 while (fstat (fd, &statbuf) < 0 && EINTR_SET)
778 #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
779 /* Advance member's time to that time */
780 for (i = 0; i < sizeof ar_hdr.ar_date; i++)
781 ar_hdr.ar_date[i] = ' ';
782 sprintf (ar_hdr.ar_date, "%ld", (long int) statbuf.st_mtime);
783 #ifdef AIAMAG
784 ar_hdr.ar_date[strlen(ar_hdr.ar_date)] = ' ';
785 #endif
786 #else
787 ar_hdr.ar_date = statbuf.st_mtime;
788 #endif
789 /* Write back this member's header */
790 if (lseek (fd, pos, 0) < 0)
791 goto lose;
792 if (AR_HDR_SIZE != write (fd, (char *) &ar_hdr, AR_HDR_SIZE))
793 goto lose;
794 close (fd);
795 return 0;
797 lose:
798 i = errno;
799 close (fd);
800 errno = i;
801 return -3;
803 #endif
805 #ifdef TEST
807 long int
808 describe_member (desc, name, truncated,
809 hdrpos, datapos, size, date, uid, gid, mode)
810 int desc;
811 char *name;
812 int truncated;
813 long int hdrpos, datapos, size, date;
814 int uid, gid, mode;
816 extern char *ctime ();
818 printf (_("Member `%s'%s: %ld bytes at %ld (%ld).\n"),
819 name, truncated ? _(" (name might be truncated)") : "",
820 size, hdrpos, datapos);
821 printf (_(" Date %s"), ctime (&date));
822 printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode);
824 return 0;
827 main (argc, argv)
828 int argc;
829 char **argv;
831 ar_scan (argv[1], describe_member);
832 return 0;
835 #endif /* TEST. */
837 #endif /* NO_ARCHIVES. */