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__
238 /* BeOS 5 doesn't have <ar.h> but has archives in the same format
239 * as many other Unices. This was taken from GNU binutils for BeOS.
241 # define ARMAG "!<arch>\n" /* String that begins an archive file. */
242 # define SARMAG 8 /* Size of that string. */
243 # define ARFMAG "`\n" /* String in ar_fmag at end of each header. */
246 char ar_name
[16]; /* Member file name, sometimes / terminated. */
247 char ar_date
[12]; /* File date, decimal seconds since Epoch. */
248 char ar_uid
[6], ar_gid
[6]; /* User and group IDs, in ASCII decimal. */
249 char ar_mode
[8]; /* File mode, in ASCII octal. */
250 char ar_size
[10]; /* File size, in ASCII decimal. */
251 char ar_fmag
[2]; /* Always contains ARFMAG. */
255 /* These should allow us to read Windows (VC++) libraries (according to Frank
256 * Libbrecht <frankl@abzx.belgium.hp.com>)
258 # include <windows.h>
261 # define ARMAG IMAGE_ARCHIVE_START
262 # define SARMAG IMAGE_ARCHIVE_START_SIZE
263 # define ar_hdr _IMAGE_ARCHIVE_MEMBER_HEADER
264 # define ar_name Name
265 # define ar_mode Mode
266 # define ar_size Size
267 # define ar_date Date
268 # define ar_uid UserID
269 # define ar_gid GroupID
272 /* Cray's <ar.h> apparently defines this. */
274 # define AR_HDR_SIZE (sizeof (struct ar_hdr))
277 /* Takes three arguments ARCHIVE, FUNCTION and ARG.
279 Open the archive named ARCHIVE, find its members one by one,
280 and for each one call FUNCTION with the following arguments:
281 archive file descriptor for reading the data,
283 member name might be truncated flag,
284 member header position in file,
285 member data position in file,
290 member protection mode,
293 The descriptor is poised to read the data of the member
294 when FUNCTION is called. It does not matter how much
297 If FUNCTION returns nonzero, we immediately return
298 what FUNCTION returned.
300 Returns -1 if archive does not exist,
301 Returns -2 if archive has invalid format.
302 Returns 0 if have scanned successfully. */
305 ar_scan (archive
, function
, arg
)
307 long int (*function
) ();
314 FL_HDR_BIG fl_header_big
;
320 register int desc
= open (archive
, O_RDONLY
, 0);
326 register int nread
= read (desc
, buf
, SARMAG
);
327 if (nread
!= SARMAG
|| bcmp (buf
, ARMAG
, SARMAG
))
336 register int nread
= read (desc
, (char *) &fl_header
, FL_HSZ
);
344 /* If this is a "big" archive, then set the flag and
345 re-read the header into the "big" structure. */
346 if (!bcmp (fl_header
.fl_magic
, AIAMAGBIG
, SAIAMAG
))
350 /* seek back to beginning of archive */
351 if (lseek (desc
, 0, 0) < 0)
357 /* re-read the header into the "big" structure */
358 nread
= read (desc
, (char *) &fl_header_big
, FL_HSZ_BIG
);
359 if (nread
!= FL_HSZ_BIG
)
367 /* Check to make sure this is a "normal" archive. */
368 if (bcmp (fl_header
.fl_magic
, AIAMAG
, SAIAMAG
))
379 unsigned short int buf
;
381 register int nread
= read(desc
, &buf
, sizeof (buf
));
382 if (nread
!= sizeof (buf
) || buf
!= ARMAG
)
391 /* Now find the members one by one. */
394 register long int member_offset
= SARMAG
;
397 long int member_offset
;
398 long int last_member_offset
;
403 sscanf (fl_header_big
.fl_fstmoff
, "%20ld", &member_offset
);
404 sscanf (fl_header_big
.fl_lstmoff
, "%20ld", &last_member_offset
);
409 sscanf (fl_header
.fl_fstmoff
, "%12ld", &member_offset
);
410 sscanf (fl_header
.fl_lstmoff
, "%12ld", &last_member_offset
);
413 if (member_offset
== 0)
421 register long int member_offset
= sizeof (int);
423 register long int member_offset
= sizeof (unsigned short int);
424 #endif /* Not Xenix. */
431 struct ar_hdr member_header
;
433 struct ar_hdr_big member_header_big
;
440 long int data_offset
;
442 char namebuf
[sizeof member_header
.ar_name
+ 1];
444 int is_namemap
; /* Nonzero if this entry maps long names. */
450 if (lseek (desc
, member_offset
, 0) < 0)
457 #define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
462 nread
= read (desc
, (char *) &member_header_big
,
463 AR_MEMHDR_SZ(member_header_big
) );
465 if (nread
!= AR_MEMHDR_SZ(member_header_big
))
471 sscanf (member_header_big
.ar_namlen
, "%4d", &name_len
);
472 nread
= read (desc
, name
, name_len
);
474 if (nread
!= name_len
)
482 sscanf (member_header_big
.ar_date
, "%12ld", &dateval
);
483 sscanf (member_header_big
.ar_uid
, "%12d", &uidval
);
484 sscanf (member_header_big
.ar_gid
, "%12d", &gidval
);
485 sscanf (member_header_big
.ar_mode
, "%12o", &eltmode
);
486 sscanf (member_header_big
.ar_size
, "%20ld", &eltsize
);
488 data_offset
= (member_offset
+ AR_MEMHDR_SZ(member_header_big
)
494 nread
= read (desc
, (char *) &member_header
,
495 AR_MEMHDR_SZ(member_header
) );
497 if (nread
!= AR_MEMHDR_SZ(member_header
))
503 sscanf (member_header
.ar_namlen
, "%4d", &name_len
);
504 nread
= read (desc
, name
, name_len
);
506 if (nread
!= name_len
)
514 sscanf (member_header
.ar_date
, "%12ld", &dateval
);
515 sscanf (member_header
.ar_uid
, "%12d", &uidval
);
516 sscanf (member_header
.ar_gid
, "%12d", &gidval
);
517 sscanf (member_header
.ar_mode
, "%12o", &eltmode
);
518 sscanf (member_header
.ar_size
, "%12ld", &eltsize
);
520 data_offset
= (member_offset
+ AR_MEMHDR_SZ(member_header
)
523 data_offset
+= data_offset
% 2;
526 (*function
) (desc
, name
, 0,
527 member_offset
, data_offset
, eltsize
,
528 dateval
, uidval
, gidval
,
531 #else /* Not AIAMAG. */
532 nread
= read (desc
, (char *) &member_header
, AR_HDR_SIZE
);
534 /* No data left means end of file; that is OK. */
537 if (nread
!= AR_HDR_SIZE
538 #if defined(ARFMAG) || defined(ARFZMAG)
541 bcmp (member_header
.ar_fmag
, ARFMAG
, 2)
547 bcmp (member_header
.ar_fmag
, ARFZMAG
, 2)
560 bcopy (member_header
.ar_name
, name
, sizeof member_header
.ar_name
);
562 register char *p
= name
+ sizeof member_header
.ar_name
;
565 while (p
> name
&& *--p
== ' ');
568 /* If the member name is "//" or "ARFILENAMES/" this may be
569 a list of file name mappings. The maximum file name
570 length supported by the standard archive format is 14
571 characters. This member will actually always be the
572 first or second entry in the archive, but we don't check
574 is_namemap
= (!strcmp (name
, "//")
575 || !strcmp (name
, "ARFILENAMES/"));
576 #endif /* Not AIAMAG. */
577 /* On some systems, there is a slash after each member name. */
582 /* If the member name starts with a space or a slash, this
583 is an index into the file name mappings (used by GNU ar).
584 Otherwise if the member name looks like #1/NUMBER the
585 real member name appears in the element data (used by
588 && (name
[0] == ' ' || name
[0] == '/')
591 name
= namemap
+ atoi (name
+ 1);
594 else if (name
[0] == '#'
598 int namesize
= atoi (name
+ 3);
600 name
= (char *) alloca (namesize
+ 1);
601 nread
= read (desc
, name
, namesize
);
602 if (nread
!= namesize
)
607 name
[namesize
] = '\0';
611 #endif /* Not AIAMAG. */
615 sscanf (member_header
.ar_mode
, "%o", &eltmode
);
616 eltsize
= atol (member_header
.ar_size
);
618 eltmode
= (unsigned short int) member_header
.ar_mode
;
619 eltsize
= member_header
.ar_size
;
620 #endif /* Not Xenix. */
623 (*function
) (desc
, name
, ! long_name
, member_offset
,
624 member_offset
+ AR_HDR_SIZE
, eltsize
,
626 atol (member_header
.ar_date
),
627 atoi (member_header
.ar_uid
),
628 atoi (member_header
.ar_gid
),
630 member_header
.ar_date
,
631 member_header
.ar_uid
,
632 member_header
.ar_gid
,
633 #endif /* Not Xenix. */
645 if (member_offset
== last_member_offset
)
646 /* End of the chain. */
651 sscanf (member_header_big
.ar_nxtmem
, "%20ld", &member_offset
);
654 sscanf (member_header
.ar_nxtmem
, "%12ld", &member_offset
);
656 if (lseek (desc
, member_offset
, 0) != member_offset
)
663 /* If this member maps archive names, we must read it in. The
664 name map will always precede any members whose names must
671 namemap
= (char *) alloca (eltsize
);
672 nread
= read (desc
, namemap
, eltsize
);
673 if (nread
!= eltsize
)
679 /* The names are separated by newlines. Some formats have
680 a trailing slash. Null terminate the strings for
682 limit
= namemap
+ eltsize
;
683 for (clear
= namemap
; clear
< limit
; clear
++)
688 if (clear
[-1] == '/')
696 member_offset
+= AR_HDR_SIZE
+ eltsize
;
697 if (member_offset
% 2 != 0)
708 /* Return nonzero iff NAME matches MEM.
709 If TRUNCATED is nonzero, MEM may be truncated to
710 sizeof (struct ar_hdr.ar_name) - 1. */
713 ar_name_equal (name
, mem
, truncated
)
719 p
= strrchr (name
, '/');
727 /* TRUNCATED should never be set on this system. */
731 #if !defined (__hpux) && !defined (cray)
732 return strneq (name
, mem
, sizeof(hdr
.ar_name
) - 1);
734 return strneq (name
, mem
, sizeof(hdr
.ar_name
) - 2);
735 #endif /* !__hpux && !cray */
740 return !strcmp (name
, mem
);
746 ar_member_pos (desc
, mem
, truncated
,
747 hdrpos
, datapos
, size
, date
, uid
, gid
, mode
, name
)
751 long int hdrpos
, datapos
, size
, date
;
755 if (!ar_name_equal (name
, mem
, truncated
))
760 /* Set date of member MEMNAME in archive ARNAME to current time.
761 Returns 0 if successful,
762 -1 if file ARNAME does not exist,
763 -2 if not a valid archive,
764 -3 if other random system call error (including file read-only),
765 1 if valid but member MEMNAME does not exist. */
768 ar_member_touch (arname
, memname
)
769 char *arname
, *memname
;
771 register long int pos
= ar_scan (arname
, ar_member_pos
, (long int) memname
);
773 struct ar_hdr ar_hdr
;
782 fd
= open (arname
, O_RDWR
, 0666);
785 /* Read in this member's header */
786 if (lseek (fd
, pos
, 0) < 0)
788 if (AR_HDR_SIZE
!= read (fd
, (char *) &ar_hdr
, AR_HDR_SIZE
))
790 /* Write back the header, thus touching the archive file. */
791 if (lseek (fd
, pos
, 0) < 0)
793 if (AR_HDR_SIZE
!= write (fd
, (char *) &ar_hdr
, AR_HDR_SIZE
))
795 /* The file's mtime is the time we we want. */
796 while (fstat (fd
, &statbuf
) < 0 && EINTR_SET
)
798 #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
799 /* Advance member's time to that time */
800 for (i
= 0; i
< sizeof ar_hdr
.ar_date
; i
++)
801 ar_hdr
.ar_date
[i
] = ' ';
802 sprintf (ar_hdr
.ar_date
, "%ld", (long int) statbuf
.st_mtime
);
804 ar_hdr
.ar_date
[strlen(ar_hdr
.ar_date
)] = ' ';
807 ar_hdr
.ar_date
= statbuf
.st_mtime
;
809 /* Write back this member's header */
810 if (lseek (fd
, pos
, 0) < 0)
812 if (AR_HDR_SIZE
!= write (fd
, (char *) &ar_hdr
, AR_HDR_SIZE
))
828 describe_member (desc
, name
, truncated
,
829 hdrpos
, datapos
, size
, date
, uid
, gid
, mode
)
833 long int hdrpos
, datapos
, size
, date
;
836 extern char *ctime ();
838 printf (_("Member `%s'%s: %ld bytes at %ld (%ld).\n"),
839 name
, truncated
? _(" (name might be truncated)") : "",
840 size
, hdrpos
, datapos
);
841 printf (_(" Date %s"), ctime (&date
));
842 printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid
, gid
, mode
);
851 ar_scan (argv
[1], describe_member
);
857 #endif /* NO_ARCHIVES. */