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)
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,
37 #include <lbr$routines.h>
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
) ();
49 VMS_get_member_info (module
, rfa
)
50 struct dsc$descriptor_s
*module
;
58 static struct dsc$descriptor_s bufdesc
=
59 { 0, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, NULL
};
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);
71 error (NILF
, _("lbr$set_module failed to extract module info, status = %d"),
74 lbr$
close (&VMS_lib_idx
);
79 mhd
= (struct mhddef
*) filename
;
82 val
= decc$
fix_time (&mhd
->mhd$l_datim
);
85 for (i
= 0; i
< module
->dsc$w_length
; i
++)
86 filename
[i
] = _tolower ((unsigned char)module
->dsc$a_pointer
[i
]);
90 VMS_member_date
= (time_t) -1;
93 (*VMS_function
) (-1, filename
, 0, 0, 0, 0, val
, 0, 0, 0,
98 VMS_member_date
= fnval
;
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,
111 member name might be truncated flag,
112 member header position in file,
113 member data position in file,
118 member protection mode,
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
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. */
135 ar_scan (archive
, function
, arg
)
137 long int (*function
) ();
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;
151 status
= lbr$
ini_control (&VMS_lib_idx
, &func
, &type
, 0);
155 error (NILF
, _("lbr$ini_control failed with status = %d"),status
);
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);
166 error (NILF
, _("unable to open library `%s' to lookup member `%s'"),
167 archive
, (char *)arg
);
171 VMS_saved_memname
= (char *)arg
;
173 /* For comparison, delete .obj from arg name. */
175 p
= strrchr (VMS_saved_memname
, '.');
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. */
188 lbr$
close (&VMS_lib_idx
);
190 return VMS_member_date
> 0 ? VMS_member_date
: 0;
195 /* SCO Unix's compiler defines both of these. */
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)
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
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. */
230 # define __AR_SMALL__
237 /* These should allow us to read Windows (VC++) libraries (according to Frank
238 * Libbrecht <frankl@abzx.belgium.hp.com>)
240 # include <windows.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
254 /* Cray's <ar.h> apparently defines this. */
256 # define AR_HDR_SIZE (sizeof (struct ar_hdr))
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,
265 member name might be truncated flag,
266 member header position in file,
267 member data position in file,
272 member protection mode,
275 The descriptor is poised to read the data of the member
276 when FUNCTION is called. It does not matter how much
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. */
287 ar_scan (archive
, function
, arg
)
289 long int (*function
) ();
296 FL_HDR_BIG fl_header_big
;
302 register int desc
= open (archive
, O_RDONLY
, 0);
308 register int nread
= read (desc
, buf
, SARMAG
);
309 if (nread
!= SARMAG
|| bcmp (buf
, ARMAG
, SARMAG
))
318 register int nread
= read (desc
, (char *) &fl_header
, FL_HSZ
);
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
))
332 /* seek back to beginning of archive */
333 if (lseek (desc
, 0, 0) < 0)
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
)
349 /* Check to make sure this is a "normal" archive. */
350 if (bcmp (fl_header
.fl_magic
, AIAMAG
, SAIAMAG
))
361 unsigned short int buf
;
363 register int nread
= read(desc
, &buf
, sizeof (buf
));
364 if (nread
!= sizeof (buf
) || buf
!= ARMAG
)
373 /* Now find the members one by one. */
376 register long int member_offset
= SARMAG
;
379 long int member_offset
;
380 long int last_member_offset
;
385 sscanf (fl_header_big
.fl_fstmoff
, "%20ld", &member_offset
);
386 sscanf (fl_header_big
.fl_lstmoff
, "%20ld", &last_member_offset
);
391 sscanf (fl_header
.fl_fstmoff
, "%12ld", &member_offset
);
392 sscanf (fl_header
.fl_lstmoff
, "%12ld", &last_member_offset
);
395 if (member_offset
== 0)
403 register long int member_offset
= sizeof (int);
405 register long int member_offset
= sizeof (unsigned short int);
406 #endif /* Not Xenix. */
413 struct ar_hdr member_header
;
415 struct ar_hdr_big member_header_big
;
422 long int data_offset
;
424 char namebuf
[sizeof member_header
.ar_name
+ 1];
426 int is_namemap
; /* Nonzero if this entry maps long names. */
432 if (lseek (desc
, member_offset
, 0) < 0)
439 #define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
444 nread
= read (desc
, (char *) &member_header_big
,
445 AR_MEMHDR_SZ(member_header_big
) );
447 if (nread
!= AR_MEMHDR_SZ(member_header_big
))
453 sscanf (member_header_big
.ar_namlen
, "%4d", &name_len
);
454 nread
= read (desc
, name
, name_len
);
456 if (nread
!= name_len
)
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
)
476 nread
= read (desc
, (char *) &member_header
,
477 AR_MEMHDR_SZ(member_header
) );
479 if (nread
!= AR_MEMHDR_SZ(member_header
))
485 sscanf (member_header
.ar_namlen
, "%4d", &name_len
);
486 nread
= read (desc
, name
, name_len
);
488 if (nread
!= name_len
)
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
)
505 data_offset
+= data_offset
% 2;
508 (*function
) (desc
, name
, 0,
509 member_offset
, data_offset
, eltsize
,
510 dateval
, uidval
, gidval
,
513 #else /* Not AIAMAG. */
514 nread
= read (desc
, (char *) &member_header
, AR_HDR_SIZE
);
516 /* No data left means end of file; that is OK. */
519 if (nread
!= AR_HDR_SIZE
520 #if defined(ARFMAG) || defined(ARFZMAG)
523 bcmp (member_header
.ar_fmag
, ARFMAG
, 2)
529 bcmp (member_header
.ar_fmag
, ARFZMAG
, 2)
542 bcopy (member_header
.ar_name
, name
, sizeof member_header
.ar_name
);
544 register char *p
= name
+ sizeof member_header
.ar_name
;
547 while (p
> name
&& *--p
== ' ');
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
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. */
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
570 && (name
[0] == ' ' || name
[0] == '/')
573 name
= namemap
+ atoi (name
+ 1);
576 else if (name
[0] == '#'
580 int namesize
= atoi (name
+ 3);
582 name
= (char *) alloca (namesize
+ 1);
583 nread
= read (desc
, name
, namesize
);
584 if (nread
!= namesize
)
589 name
[namesize
] = '\0';
593 #endif /* Not AIAMAG. */
597 sscanf (member_header
.ar_mode
, "%o", &eltmode
);
598 eltsize
= atol (member_header
.ar_size
);
600 eltmode
= (unsigned short int) member_header
.ar_mode
;
601 eltsize
= member_header
.ar_size
;
602 #endif /* Not Xenix. */
605 (*function
) (desc
, name
, ! long_name
, member_offset
,
606 member_offset
+ AR_HDR_SIZE
, eltsize
,
608 atol (member_header
.ar_date
),
609 atoi (member_header
.ar_uid
),
610 atoi (member_header
.ar_gid
),
612 member_header
.ar_date
,
613 member_header
.ar_uid
,
614 member_header
.ar_gid
,
615 #endif /* Not Xenix. */
627 if (member_offset
== last_member_offset
)
628 /* End of the chain. */
633 sscanf (member_header_big
.ar_nxtmem
, "%20ld", &member_offset
);
636 sscanf (member_header
.ar_nxtmem
, "%12ld", &member_offset
);
638 if (lseek (desc
, member_offset
, 0) != member_offset
)
645 /* If this member maps archive names, we must read it in. The
646 name map will always precede any members whose names must
653 namemap
= (char *) alloca (eltsize
);
654 nread
= read (desc
, namemap
, eltsize
);
655 if (nread
!= eltsize
)
661 /* The names are separated by newlines. Some formats have
662 a trailing slash. Null terminate the strings for
664 limit
= namemap
+ eltsize
;
665 for (clear
= namemap
; clear
< limit
; clear
++)
670 if (clear
[-1] == '/')
678 member_offset
+= AR_HDR_SIZE
+ eltsize
;
679 if (member_offset
% 2 != 0)
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
)
701 p
= strrchr (name
, '/');
709 /* TRUNCATED should never be set on this system. */
713 #if !defined (__hpux) && !defined (cray)
714 return strneq (name
, mem
, sizeof(hdr
.ar_name
) - 1);
716 return strneq (name
, mem
, sizeof(hdr
.ar_name
) - 2);
717 #endif /* !__hpux && !cray */
722 return !strcmp (name
, mem
);
728 ar_member_pos (desc
, mem
, truncated
,
729 hdrpos
, datapos
, size
, date
, uid
, gid
, mode
, name
)
733 long int hdrpos
, datapos
, size
, date
;
737 if (!ar_name_equal (name
, mem
, truncated
))
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
);
755 struct ar_hdr ar_hdr
;
764 fd
= open (arname
, O_RDWR
, 0666);
767 /* Read in this member's header */
768 if (lseek (fd
, pos
, 0) < 0)
770 if (AR_HDR_SIZE
!= read (fd
, (char *) &ar_hdr
, AR_HDR_SIZE
))
772 /* Write back the header, thus touching the archive file. */
773 if (lseek (fd
, pos
, 0) < 0)
775 if (AR_HDR_SIZE
!= write (fd
, (char *) &ar_hdr
, AR_HDR_SIZE
))
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
);
786 ar_hdr
.ar_date
[strlen(ar_hdr
.ar_date
)] = ' ';
789 ar_hdr
.ar_date
= statbuf
.st_mtime
;
791 /* Write back this member's header */
792 if (lseek (fd
, pos
, 0) < 0)
794 if (AR_HDR_SIZE
!= write (fd
, (char *) &ar_hdr
, AR_HDR_SIZE
))
810 describe_member (desc
, name
, truncated
,
811 hdrpos
, datapos
, size
, date
, uid
, gid
, mode
)
815 long int hdrpos
, datapos
, size
, date
;
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
);
833 ar_scan (argv
[1], describe_member
);
839 #endif /* NO_ARCHIVES. */