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
;
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
]);
88 VMS_member_date
= (time_t) -1;
91 (*VMS_function
) (-1, filename
, 0, 0, 0, 0, val
, 0, 0, 0,
96 VMS_member_date
= fnval
;
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,
109 member name might be truncated flag,
110 member header position in file,
111 member data position in file,
116 member protection mode,
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
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. */
133 ar_scan (archive
, function
, arg
)
135 long int (*function
) ();
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;
149 status
= lbr$
ini_control (&VMS_lib_idx
, &func
, &type
, 0);
153 error (NILF
, _("lbr$ini_control failed with status = %d"),status
);
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);
164 error (NILF
, _("unable to open library `%s' to lookup member `%s'"),
165 archive
, (char *)arg
);
169 VMS_saved_memname
= (char *)arg
;
171 /* For comparison, delete .obj from arg name. */
173 p
= strrchr (VMS_saved_memname
, '.');
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. */
186 lbr$
close (&VMS_lib_idx
);
188 return VMS_member_date
> 0 ? VMS_member_date
: 0;
193 /* SCO Unix's compiler defines both of these. */
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)
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
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. */
228 # define __AR_SMALL__
235 /* These should allow us to read Windows (VC++) libraries (according to Frank
236 * Libbrecht <frankl@abzx.belgium.hp.com>)
238 # include <windows.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
252 /* Cray's <ar.h> apparently defines this. */
254 # define AR_HDR_SIZE (sizeof (struct ar_hdr))
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,
263 member name might be truncated flag,
264 member header position in file,
265 member data position in file,
270 member protection mode,
273 The descriptor is poised to read the data of the member
274 when FUNCTION is called. It does not matter how much
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. */
285 ar_scan (archive
, function
, arg
)
287 long int (*function
) ();
294 FL_HDR_BIG fl_header_big
;
300 register int desc
= open (archive
, O_RDONLY
, 0);
306 register int nread
= read (desc
, buf
, SARMAG
);
307 if (nread
!= SARMAG
|| bcmp (buf
, ARMAG
, SARMAG
))
316 register int nread
= read (desc
, (char *) &fl_header
, FL_HSZ
);
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
))
330 /* seek back to beginning of archive */
331 if (lseek (desc
, 0, 0) < 0)
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
)
347 /* Check to make sure this is a "normal" archive. */
348 if (bcmp (fl_header
.fl_magic
, AIAMAG
, SAIAMAG
))
359 unsigned short int buf
;
361 register int nread
= read(desc
, &buf
, sizeof (buf
));
362 if (nread
!= sizeof (buf
) || buf
!= ARMAG
)
371 /* Now find the members one by one. */
374 register long int member_offset
= SARMAG
;
377 long int member_offset
;
378 long int last_member_offset
;
383 sscanf (fl_header_big
.fl_fstmoff
, "%20ld", &member_offset
);
384 sscanf (fl_header_big
.fl_lstmoff
, "%20ld", &last_member_offset
);
389 sscanf (fl_header
.fl_fstmoff
, "%12ld", &member_offset
);
390 sscanf (fl_header
.fl_lstmoff
, "%12ld", &last_member_offset
);
393 if (member_offset
== 0)
401 register long int member_offset
= sizeof (int);
403 register long int member_offset
= sizeof (unsigned short int);
404 #endif /* Not Xenix. */
411 struct ar_hdr member_header
;
413 struct ar_hdr_big member_header_big
;
420 long int data_offset
;
422 char namebuf
[sizeof member_header
.ar_name
+ 1];
424 int is_namemap
; /* Nonzero if this entry maps long names. */
430 if (lseek (desc
, member_offset
, 0) < 0)
437 #define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
442 nread
= read (desc
, (char *) &member_header_big
,
443 AR_MEMHDR_SZ(member_header_big
) );
445 if (nread
!= AR_MEMHDR_SZ(member_header_big
))
451 sscanf (member_header_big
.ar_namlen
, "%4d", &name_len
);
452 nread
= read (desc
, name
, name_len
);
454 if (nread
!= name_len
)
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
)
474 nread
= read (desc
, (char *) &member_header
,
475 AR_MEMHDR_SZ(member_header
) );
477 if (nread
!= AR_MEMHDR_SZ(member_header
))
483 sscanf (member_header
.ar_namlen
, "%4d", &name_len
);
484 nread
= read (desc
, name
, name_len
);
486 if (nread
!= name_len
)
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
)
503 data_offset
+= data_offset
% 2;
506 (*function
) (desc
, name
, 0,
507 member_offset
, data_offset
, eltsize
,
508 dateval
, uidval
, gidval
,
511 #else /* Not AIAMAG. */
512 nread
= read (desc
, (char *) &member_header
, AR_HDR_SIZE
);
514 /* No data left means end of file; that is OK. */
517 if (nread
!= AR_HDR_SIZE
518 #if defined(ARFMAG) || defined(ARFZMAG)
521 bcmp (member_header
.ar_fmag
, ARFMAG
, 2)
527 bcmp (member_header
.ar_fmag
, ARFZMAG
, 2)
540 bcopy (member_header
.ar_name
, name
, sizeof member_header
.ar_name
);
542 register char *p
= name
+ sizeof member_header
.ar_name
;
545 while (p
> name
&& *--p
== ' ');
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
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. */
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
568 && (name
[0] == ' ' || name
[0] == '/')
571 name
= namemap
+ atoi (name
+ 1);
574 else if (name
[0] == '#'
578 int namesize
= atoi (name
+ 3);
580 name
= (char *) alloca (namesize
+ 1);
581 nread
= read (desc
, name
, namesize
);
582 if (nread
!= namesize
)
587 name
[namesize
] = '\0';
591 #endif /* Not AIAMAG. */
595 sscanf (member_header
.ar_mode
, "%o", &eltmode
);
596 eltsize
= atol (member_header
.ar_size
);
598 eltmode
= (unsigned short int) member_header
.ar_mode
;
599 eltsize
= member_header
.ar_size
;
600 #endif /* Not Xenix. */
603 (*function
) (desc
, name
, ! long_name
, member_offset
,
604 member_offset
+ AR_HDR_SIZE
, eltsize
,
606 atol (member_header
.ar_date
),
607 atoi (member_header
.ar_uid
),
608 atoi (member_header
.ar_gid
),
610 member_header
.ar_date
,
611 member_header
.ar_uid
,
612 member_header
.ar_gid
,
613 #endif /* Not Xenix. */
625 if (member_offset
== last_member_offset
)
626 /* End of the chain. */
631 sscanf (member_header_big
.ar_nxtmem
, "%20ld", &member_offset
);
634 sscanf (member_header
.ar_nxtmem
, "%12ld", &member_offset
);
636 if (lseek (desc
, member_offset
, 0) != member_offset
)
643 /* If this member maps archive names, we must read it in. The
644 name map will always precede any members whose names must
651 namemap
= (char *) alloca (eltsize
);
652 nread
= read (desc
, namemap
, eltsize
);
653 if (nread
!= eltsize
)
659 /* The names are separated by newlines. Some formats have
660 a trailing slash. Null terminate the strings for
662 limit
= namemap
+ eltsize
;
663 for (clear
= namemap
; clear
< limit
; clear
++)
668 if (clear
[-1] == '/')
676 member_offset
+= AR_HDR_SIZE
+ eltsize
;
677 if (member_offset
% 2 != 0)
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
)
699 p
= strrchr (name
, '/');
707 /* TRUNCATED should never be set on this system. */
711 #if !defined (__hpux) && !defined (cray)
712 return strneq (name
, mem
, sizeof(hdr
.ar_name
) - 1);
714 return strneq (name
, mem
, sizeof(hdr
.ar_name
) - 2);
715 #endif /* !__hpux && !cray */
720 return !strcmp (name
, mem
);
726 ar_member_pos (desc
, mem
, truncated
,
727 hdrpos
, datapos
, size
, date
, uid
, gid
, mode
, name
)
731 long int hdrpos
, datapos
, size
, date
;
735 if (!ar_name_equal (name
, mem
, truncated
))
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
);
753 struct ar_hdr ar_hdr
;
762 fd
= open (arname
, O_RDWR
, 0666);
765 /* Read in this member's header */
766 if (lseek (fd
, pos
, 0) < 0)
768 if (AR_HDR_SIZE
!= read (fd
, (char *) &ar_hdr
, AR_HDR_SIZE
))
770 /* Write back the header, thus touching the archive file. */
771 if (lseek (fd
, pos
, 0) < 0)
773 if (AR_HDR_SIZE
!= write (fd
, (char *) &ar_hdr
, AR_HDR_SIZE
))
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
);
784 ar_hdr
.ar_date
[strlen(ar_hdr
.ar_date
)] = ' ';
787 ar_hdr
.ar_date
= statbuf
.st_mtime
;
789 /* Write back this member's header */
790 if (lseek (fd
, pos
, 0) < 0)
792 if (AR_HDR_SIZE
!= write (fd
, (char *) &ar_hdr
, AR_HDR_SIZE
))
808 describe_member (desc
, name
, truncated
,
809 hdrpos
, datapos
, size
, date
, uid
, gid
, mode
)
813 long int hdrpos
, datapos
, size
, date
;
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
);
831 ar_scan (argv
[1], describe_member
);
837 #endif /* NO_ARCHIVES. */