VirtualBox

source: kBuild/trunk/src/kmk/arscan.c@ 3387

Last change on this file since 3387 was 3140, checked in by bird, 6 years ago

kmk: Merged in changes from GNU make 4.2.1 (2e55f5e4abdc0e38c1d64be703b446695e70b3b6 / https://git.savannah.gnu.org/git/make.git).

  • Property svn:eol-style set to native
File size: 27.6 KB
Line 
1/* Library function for scanning an archive file.
2Copyright (C) 1987-2016 Free Software Foundation, Inc.
3This file is part of GNU Make.
4
5GNU Make is free software; you can redistribute it and/or modify it under the
6terms of the GNU General Public License as published by the Free Software
7Foundation; either version 3 of the License, or (at your option) any later
8version.
9
10GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "makeint.h"
18
19#ifdef TEST
20/* Hack, the real error() routine eventually pulls in die from main.c */
21#define error(a, b, c, d)
22#endif
23
24#ifdef HAVE_FCNTL_H
25#include <fcntl.h>
26#else
27#include <sys/file.h>
28#endif
29
30#ifndef NO_ARCHIVES
31
32#ifdef VMS
33#include <lbrdef.h>
34#include <mhddef.h>
35#include <credef.h>
36#include <descrip.h>
37#include <ctype.h>
38#include <ssdef.h>
39#include <stsdef.h>
40#include <rmsdef.h>
41
42/* This symbol should be present in lbrdef.h. */
43#ifndef LBR$_HDRTRUNC
44#pragma extern_model save
45#pragma extern_model globalvalue
46extern unsigned int LBR$_HDRTRUNC;
47#pragma extern_model restore
48#endif
49
50#include <unixlib.h>
51#include <lbr$routines.h>
52
53const char *
54vmsify (const char *name, int type);
55
56/* Time conversion from VMS to Unix
57 Conversion from local time (stored in library) to GMT (needed for gmake)
58 Note: The tm_gmtoff element is a VMS extension to the ANSI standard. */
59static time_t
60vms_time_to_unix(void *vms_time)
61{
62 struct tm *tmp;
63 time_t unix_time;
64
65 unix_time = decc$fix_time(vms_time);
66 tmp = localtime(&unix_time);
67 unix_time -= tmp->tm_gmtoff;
68
69 return unix_time;
70}
71
72
73/* VMS library routines need static variables for callback */
74static void *VMS_lib_idx;
75
76static const void *VMS_saved_arg;
77
78static long int (*VMS_function) ();
79
80static long int VMS_function_ret;
81
82
83/* This is a callback procedure for lib$get_index */
84static int
85VMS_get_member_info(struct dsc$descriptor_s *module, unsigned long *rfa)
86{
87 int status, i;
88 const int truncated = 0; /* Member name may be truncated */
89 time_t member_date; /* Member date */
90 char *filename;
91 unsigned int buffer_length; /* Actual buffer length */
92
93 /* Unused constants - Make does not actually use most of these */
94 const int file_desc = -1; /* archive file descriptor for reading the data */
95 const int header_position = 0; /* Header position */
96 const int data_position = 0; /* Data position in file */
97 const int data_size = 0; /* Data size */
98 const int uid = 0; /* member gid */
99 const int gid = 0; /* member gid */
100 const int mode = 0; /* member protection mode */
101 /* End of unused constants */
102
103 static struct dsc$descriptor_s bufdesc =
104 { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
105
106 /* Only need the module definition */
107 struct mhddef *mhd;
108
109 /* If a previous callback is non-zero, just return that status */
110 if (VMS_function_ret)
111 {
112 return SS$_NORMAL;
113 }
114
115 /* lbr_set_module returns more than just the module header. So allocate
116 a buffer which is big enough: the maximum LBR$C_MAXHDRSIZ. That's at
117 least bigger than the size of struct mhddef.
118 If the request is too small, a buffer truncated warning is issued so
119 it can be reissued with a larger buffer.
120 We do not care if the buffer is truncated, so that is still a success. */
121 mhd = xmalloc(LBR$C_MAXHDRSIZ);
122 bufdesc.dsc$a_pointer = (char *) mhd;
123 bufdesc.dsc$w_length = LBR$C_MAXHDRSIZ;
124
125 status = lbr$set_module(&VMS_lib_idx, rfa, &bufdesc, &buffer_length, 0);
126
127 if ((status != LBR$_HDRTRUNC) && !$VMS_STATUS_SUCCESS(status))
128 {
129 ON(error, NILF,
130 _("lbr$set_module() failed to extract module info, status = %d"),
131 status);
132
133 lbr$close(&VMS_lib_idx);
134
135 return status;
136 }
137
138#ifdef TEST
139 /* When testing this code, it is useful to know the length returned */
140 printf("Input length = %d, actual = %d\n",
141 bufdesc.dsc$w_length, buffer_length);
142#endif
143
144 /* Conversion from VMS time to C time.
145 VMS defectlet - mhddef is sub-optimal, for the time, it has a 32 bit
146 longword, mhd$l_datim, and a 32 bit fill instead of two longwords, or
147 equivalent. */
148 member_date = vms_time_to_unix(&mhd->mhd$l_datim);
149 free(mhd);
150
151 /* Here we have a problem. The module name on VMS does not have
152 a file type, but the filename pattern in the "VMS_saved_arg"
153 may have one.
154 But only the method being called knows how to interpret the
155 filename pattern.
156 There are currently two different formats being used.
157 This means that we need a VMS specific code in those methods
158 to handle it. */
159 filename = xmalloc(module->dsc$w_length + 1);
160
161 /* TODO: We may need an option to preserve the case of the module
162 For now force the module name to lower case */
163 for (i = 0; i < module->dsc$w_length; i++)
164 filename[i] = _tolower((unsigned char )module->dsc$a_pointer[i]);
165
166 filename[i] = '\0';
167
168 VMS_function_ret = (*VMS_function)(file_desc, filename, truncated,
169 header_position, data_position, data_size, member_date, uid, gid, mode,
170 VMS_saved_arg);
171
172 free(filename);
173 return SS$_NORMAL;
174}
175
176
177/* Takes three arguments ARCHIVE, FUNCTION and ARG.
178
179 Open the archive named ARCHIVE, find its members one by one,
180 and for each one call FUNCTION with the following arguments:
181 archive file descriptor for reading the data,
182 member name,
183 member name might be truncated flag,
184 member header position in file,
185 member data position in file,
186 member data size,
187 member date,
188 member uid,
189 member gid,
190 member protection mode,
191 ARG.
192
193 NOTE: on VMS systems, only name, date, and arg are meaningful!
194
195 The descriptor is poised to read the data of the member
196 when FUNCTION is called. It does not matter how much
197 data FUNCTION reads.
198
199 If FUNCTION returns nonzero, we immediately return
200 what FUNCTION returned.
201
202 Returns -1 if archive does not exist,
203 Returns -2 if archive has invalid format.
204 Returns 0 if have scanned successfully. */
205
206long int
207ar_scan (const char *archive, ar_member_func_t function, const void *varg)
208{
209 char *vms_archive;
210
211 static struct dsc$descriptor_s libdesc =
212 { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
213
214 const unsigned long func = LBR$C_READ;
215 const unsigned long type = LBR$C_TYP_UNK;
216 const unsigned long index = 1;
217 unsigned long lib_idx;
218 int status;
219
220 VMS_saved_arg = varg;
221
222 /* Null archive string can show up in test and cause an access violation */
223 if (archive == NULL)
224 {
225 /* Null filenames do not exist */
226 return -1;
227 }
228
229 /* archive path name must be in VMS format */
230 vms_archive = (char *) vmsify(archive, 0);
231
232 status = lbr$ini_control(&VMS_lib_idx, &func, &type, 0);
233
234 if (!$VMS_STATUS_SUCCESS(status))
235 {
236 ON(error, NILF, _("lbr$ini_control() failed with status = %d"), status);
237 return -2;
238 }
239
240 libdesc.dsc$a_pointer = vms_archive;
241 libdesc.dsc$w_length = strlen(vms_archive);
242
243 status = lbr$open(&VMS_lib_idx, &libdesc, 0, NULL, 0, NULL, 0);
244
245 if (!$VMS_STATUS_SUCCESS(status))
246 {
247
248 /* TODO: A library format failure could mean that this is a file
249 generated by the GNU AR utility and in that case, we need to
250 take the UNIX codepath. This will also take a change to the
251 GNV AR wrapper program. */
252
253 switch (status)
254 {
255 case RMS$_FNF:
256 /* Archive does not exist */
257 return -1;
258 default:
259#ifndef TEST
260 OSN(error, NILF,
261 _("unable to open library '%s' to lookup member status %d"),
262 archive, status);
263#endif
264 /* For library format errors, specification says to return -2 */
265 return -2;
266 }
267 }
268
269 VMS_function = function;
270
271 /* Clear the return status, as we are supposed to stop calling the
272 callback function if it becomes non-zero, and this is a static
273 variable. */
274 VMS_function_ret = 0;
275
276 status = lbr$get_index(&VMS_lib_idx, &index, VMS_get_member_info, NULL, 0);
277
278 lbr$close(&VMS_lib_idx);
279
280 /* Unless a failure occurred in the lbr$ routines, return the
281 the status from the 'function' routine. */
282 if ($VMS_STATUS_SUCCESS(status))
283 {
284 return VMS_function_ret;
285 }
286
287 /* This must be something wrong with the library and an error
288 message should already have been printed. */
289 return -2;
290}
291
292#else /* !VMS */
293
294/* SCO Unix's compiler defines both of these. */
295#ifdef M_UNIX
296#undef M_XENIX
297#endif
298
299/* On the sun386i and in System V rel 3, ar.h defines two different archive
300 formats depending upon whether you have defined PORTAR (normal) or PORT5AR
301 (System V Release 1). There is no default, one or the other must be defined
302 to have a nonzero value. */
303
304#if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0)
305#undef PORTAR
306#ifdef M_XENIX
307/* According to Jim Sievert <jas1@rsvl.unisys.com>, for SCO XENIX defining
308 PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the
309 right one. */
310#define PORTAR 0
311#else
312#define PORTAR 1
313#endif
314#endif
315
316/* On AIX, define these symbols to be sure to get both archive formats.
317 AIX 4.3 introduced the "big" archive format to support 64-bit object
318 files, so on AIX 4.3 systems we need to support both the "normal" and
319 "big" archive formats. An archive's format is indicated in the
320 "fl_magic" field of the "FL_HDR" structure. For a normal archive,
321 this field will be the string defined by the AIAMAG symbol. For a
322 "big" archive, it will be the string defined by the AIAMAGBIG symbol
323 (at least on AIX it works this way).
324
325 Note: we'll define these symbols regardless of which AIX version
326 we're compiling on, but this is okay since we'll use the new symbols
327 only if they're present. */
328#ifdef _AIX
329# define __AR_SMALL__
330# define __AR_BIG__
331#endif
332
333#ifndef WINDOWS32
334# if !defined (__ANDROID__) && !defined (__BEOS__) && !defined (__HAIKU__) /* bird: exclude haiku */
335# include <ar.h>
336# else
337 /* These platforms don't have <ar.h> but have archives in the same format
338 * as many other Unices. This was taken from GNU binutils for BeOS.
339 */
340# define ARMAG "!<arch>\n" /* String that begins an archive file. */
341# define SARMAG 8 /* Size of that string. */
342# define ARFMAG "`\n" /* String in ar_fmag at end of each header. */
343struct ar_hdr
344 {
345 char ar_name[16]; /* Member file name, sometimes / terminated. */
346 char ar_date[12]; /* File date, decimal seconds since Epoch. */
347 char ar_uid[6], ar_gid[6]; /* User and group IDs, in ASCII decimal. */
348 char ar_mode[8]; /* File mode, in ASCII octal. */
349 char ar_size[10]; /* File size, in ASCII decimal. */
350 char ar_fmag[2]; /* Always contains ARFMAG. */
351 };
352# endif
353# define TOCHAR(_m) (_m)
354#else
355/* These should allow us to read Windows (VC++) libraries (according to Frank
356 * Libbrecht <frankl@abzx.belgium.hp.com>)
357 */
358# include <windows.h>
359# include <windef.h>
360# include <io.h>
361# define ARMAG IMAGE_ARCHIVE_START
362# define SARMAG IMAGE_ARCHIVE_START_SIZE
363# define ar_hdr _IMAGE_ARCHIVE_MEMBER_HEADER
364# define ar_name Name
365# define ar_mode Mode
366# define ar_size Size
367# define ar_date Date
368# define ar_uid UserID
369# define ar_gid GroupID
370/* In Windows the member names have type BYTE so we must cast them. */
371# define TOCHAR(_m) ((char *)(_m))
372#endif
373
374/* Cray's <ar.h> apparently defines this. */
375#ifndef AR_HDR_SIZE
376# define AR_HDR_SIZE (sizeof (struct ar_hdr))
377#endif
378
379
380/* Takes three arguments ARCHIVE, FUNCTION and ARG.
381
382 Open the archive named ARCHIVE, find its members one by one,
383 and for each one call FUNCTION with the following arguments:
384 archive file descriptor for reading the data,
385 member name,
386 member name might be truncated flag,
387 member header position in file,
388 member data position in file,
389 member data size,
390 member date,
391 member uid,
392 member gid,
393 member protection mode,
394 ARG.
395
396 The descriptor is poised to read the data of the member
397 when FUNCTION is called. It does not matter how much
398 data FUNCTION reads.
399
400 If FUNCTION returns nonzero, we immediately return
401 what FUNCTION returned.
402
403 Returns -1 if archive does not exist,
404 Returns -2 if archive has invalid format.
405 Returns 0 if have scanned successfully. */
406
407long int
408ar_scan (const char *archive, ar_member_func_t function, const void *arg)
409{
410#ifdef AIAMAG
411 FL_HDR fl_header;
412# ifdef AIAMAGBIG
413 int big_archive = 0;
414 FL_HDR_BIG fl_header_big;
415# endif
416#endif
417 char *namemap = 0;
418 int desc = open (archive, O_RDONLY, 0);
419 if (desc < 0)
420 return -1;
421#ifdef SARMAG
422 {
423 char buf[SARMAG];
424 int nread;
425 EINTRLOOP (nread, read (desc, buf, SARMAG));
426 if (nread != SARMAG || memcmp (buf, ARMAG, SARMAG))
427 {
428 (void) close (desc);
429 return -2;
430 }
431 }
432#else
433#ifdef AIAMAG
434 {
435 int nread;
436 EINTRLOOP (nread, read (desc, &fl_header, FL_HSZ));
437 if (nread != FL_HSZ)
438 {
439 (void) close (desc);
440 return -2;
441 }
442#ifdef AIAMAGBIG
443 /* If this is a "big" archive, then set the flag and
444 re-read the header into the "big" structure. */
445 if (!memcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG))
446 {
447 off_t o;
448
449 big_archive = 1;
450
451 /* seek back to beginning of archive */
452 EINTRLOOP (o, lseek (desc, 0, 0));
453 if (o < 0)
454 {
455 (void) close (desc);
456 return -2;
457 }
458
459 /* re-read the header into the "big" structure */
460 EINTRLOOP (nread, read (desc, &fl_header_big, FL_HSZ_BIG));
461 if (nread != FL_HSZ_BIG)
462 {
463 (void) close (desc);
464 return -2;
465 }
466 }
467 else
468#endif
469 /* Check to make sure this is a "normal" archive. */
470 if (memcmp (fl_header.fl_magic, AIAMAG, SAIAMAG))
471 {
472 (void) close (desc);
473 return -2;
474 }
475 }
476#else
477 {
478#ifndef M_XENIX
479 int buf;
480#else
481 unsigned short int buf;
482#endif
483 int nread;
484 EINTRLOOP (nread, read (desc, &buf, sizeof (buf)));
485 if (nread != sizeof (buf) || buf != ARMAG)
486 {
487 (void) close (desc);
488 return -2;
489 }
490 }
491#endif
492#endif
493
494 /* Now find the members one by one. */
495 {
496#ifdef SARMAG
497 register long int member_offset = SARMAG;
498#else
499#ifdef AIAMAG
500 long int member_offset;
501 long int last_member_offset;
502
503#ifdef AIAMAGBIG
504 if ( big_archive )
505 {
506 sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset);
507 sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset);
508 }
509 else
510#endif
511 {
512 sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset);
513 sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset);
514 }
515
516 if (member_offset == 0)
517 {
518 /* Empty archive. */
519 close (desc);
520 return 0;
521 }
522#else
523#ifndef M_XENIX
524 register long int member_offset = sizeof (int);
525#else /* Xenix. */
526 register long int member_offset = sizeof (unsigned short int);
527#endif /* Not Xenix. */
528#endif
529#endif
530
531 while (1)
532 {
533 register int nread;
534 struct ar_hdr member_header;
535#ifdef AIAMAGBIG
536 struct ar_hdr_big member_header_big;
537#endif
538#ifdef AIAMAG
539 char name[256];
540 int name_len;
541 long int dateval;
542 int uidval, gidval;
543 long int data_offset;
544#else
545 char namebuf[sizeof member_header.ar_name + 1];
546 char *name;
547 int is_namemap; /* Nonzero if this entry maps long names. */
548 int long_name = 0;
549#endif
550 long int eltsize;
551 unsigned int eltmode;
552 long int fnval;
553 off_t o;
554
555 EINTRLOOP (o, lseek (desc, member_offset, 0));
556 if (o < 0)
557 {
558 (void) close (desc);
559 return -2;
560 }
561
562#ifdef AIAMAG
563#define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
564
565#ifdef AIAMAGBIG
566 if (big_archive)
567 {
568 EINTRLOOP (nread, read (desc, &member_header_big,
569 AR_MEMHDR_SZ(member_header_big)));
570
571 if (nread != AR_MEMHDR_SZ(member_header_big))
572 {
573 (void) close (desc);
574 return -2;
575 }
576
577 sscanf (member_header_big.ar_namlen, "%4d", &name_len);
578 EINTRLOOP (nread, read (desc, name, name_len));
579
580 if (nread != name_len)
581 {
582 (void) close (desc);
583 return -2;
584 }
585
586 name[name_len] = 0;
587
588 sscanf (member_header_big.ar_date, "%12ld", &dateval);
589 sscanf (member_header_big.ar_uid, "%12d", &uidval);
590 sscanf (member_header_big.ar_gid, "%12d", &gidval);
591 sscanf (member_header_big.ar_mode, "%12o", &eltmode);
592 sscanf (member_header_big.ar_size, "%20ld", &eltsize);
593
594 data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big)
595 + name_len + 2);
596 }
597 else
598#endif
599 {
600 EINTRLOOP (nread, read (desc, &member_header,
601 AR_MEMHDR_SZ(member_header)));
602
603 if (nread != AR_MEMHDR_SZ(member_header))
604 {
605 (void) close (desc);
606 return -2;
607 }
608
609 sscanf (member_header.ar_namlen, "%4d", &name_len);
610 EINTRLOOP (nread, read (desc, name, name_len));
611
612 if (nread != name_len)
613 {
614 (void) close (desc);
615 return -2;
616 }
617
618 name[name_len] = 0;
619
620 sscanf (member_header.ar_date, "%12ld", &dateval);
621 sscanf (member_header.ar_uid, "%12d", &uidval);
622 sscanf (member_header.ar_gid, "%12d", &gidval);
623 sscanf (member_header.ar_mode, "%12o", &eltmode);
624 sscanf (member_header.ar_size, "%12ld", &eltsize);
625
626 data_offset = (member_offset + AR_MEMHDR_SZ(member_header)
627 + name_len + 2);
628 }
629 data_offset += data_offset % 2;
630
631 fnval =
632 (*function) (desc, name, 0,
633 member_offset, data_offset, eltsize,
634 dateval, uidval, gidval,
635 eltmode, arg);
636
637#else /* Not AIAMAG. */
638 EINTRLOOP (nread, read (desc, &member_header, AR_HDR_SIZE));
639 if (nread == 0)
640 /* No data left means end of file; that is OK. */
641 break;
642
643 if (nread != AR_HDR_SIZE
644#if defined(ARFMAG) || defined(ARFZMAG)
645 || (
646# ifdef ARFMAG
647 memcmp (member_header.ar_fmag, ARFMAG, 2)
648# else
649 1
650# endif
651 &&
652# ifdef ARFZMAG
653 memcmp (member_header.ar_fmag, ARFZMAG, 2)
654# else
655 1
656# endif
657 )
658#endif
659 )
660 {
661 (void) close (desc);
662 return -2;
663 }
664
665 name = namebuf;
666 memcpy (name, member_header.ar_name, sizeof member_header.ar_name);
667 {
668 register char *p = name + sizeof member_header.ar_name;
669 do
670 *p = '\0';
671 while (p > name && *--p == ' ');
672
673#ifndef AIAMAG
674 /* If the member name is "//" or "ARFILENAMES/" this may be
675 a list of file name mappings. The maximum file name
676 length supported by the standard archive format is 14
677 characters. This member will actually always be the
678 first or second entry in the archive, but we don't check
679 that. */
680 is_namemap = (!strcmp (name, "//")
681 || !strcmp (name, "ARFILENAMES/"));
682#endif /* Not AIAMAG. */
683 /* On some systems, there is a slash after each member name. */
684 if (*p == '/')
685 *p = '\0';
686
687#ifndef AIAMAG
688 /* If the member name starts with a space or a slash, this
689 is an index into the file name mappings (used by GNU ar).
690 Otherwise if the member name looks like #1/NUMBER the
691 real member name appears in the element data (used by
692 4.4BSD). */
693 if (! is_namemap
694 && (name[0] == ' ' || name[0] == '/')
695 && namemap != 0)
696 {
697 name = namemap + atoi (name + 1);
698 long_name = 1;
699 }
700 else if (name[0] == '#'
701 && name[1] == '1'
702 && name[2] == '/')
703 {
704 int namesize = atoi (name + 3);
705
706 name = alloca (namesize + 1);
707 EINTRLOOP (nread, read (desc, name, namesize));
708 if (nread != namesize)
709 {
710 close (desc);
711 return -2;
712 }
713 name[namesize] = '\0';
714
715 long_name = 1;
716 }
717#endif /* Not AIAMAG. */
718 }
719
720#ifndef M_XENIX
721 sscanf (TOCHAR (member_header.ar_mode), "%o", &eltmode);
722 eltsize = atol (TOCHAR (member_header.ar_size));
723#else /* Xenix. */
724 eltmode = (unsigned short int) member_header.ar_mode;
725 eltsize = member_header.ar_size;
726#endif /* Not Xenix. */
727
728 fnval =
729 (*function) (desc, name, ! long_name, member_offset,
730 member_offset + AR_HDR_SIZE, eltsize,
731#ifndef M_XENIX
732 atol (TOCHAR (member_header.ar_date)),
733 atoi (TOCHAR (member_header.ar_uid)),
734 atoi (TOCHAR (member_header.ar_gid)),
735#else /* Xenix. */
736 member_header.ar_date,
737 member_header.ar_uid,
738 member_header.ar_gid,
739#endif /* Not Xenix. */
740 eltmode, arg);
741
742#endif /* AIAMAG. */
743
744 if (fnval)
745 {
746 (void) close (desc);
747 return fnval;
748 }
749
750#ifdef AIAMAG
751 if (member_offset == last_member_offset)
752 /* End of the chain. */
753 break;
754
755#ifdef AIAMAGBIG
756 if (big_archive)
757 sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset);
758 else
759#endif
760 sscanf (member_header.ar_nxtmem, "%12ld", &member_offset);
761
762 if (lseek (desc, member_offset, 0) != member_offset)
763 {
764 (void) close (desc);
765 return -2;
766 }
767#else
768
769 /* If this member maps archive names, we must read it in. The
770 name map will always precede any members whose names must
771 be mapped. */
772 if (is_namemap)
773 {
774 char *clear;
775 char *limit;
776
777 namemap = alloca (eltsize);
778 EINTRLOOP (nread, read (desc, namemap, eltsize));
779 if (nread != eltsize)
780 {
781 (void) close (desc);
782 return -2;
783 }
784
785 /* The names are separated by newlines. Some formats have
786 a trailing slash. Null terminate the strings for
787 convenience. */
788 limit = namemap + eltsize;
789 for (clear = namemap; clear < limit; clear++)
790 {
791 if (*clear == '\n')
792 {
793 *clear = '\0';
794 if (clear[-1] == '/')
795 clear[-1] = '\0';
796 }
797 }
798
799 is_namemap = 0;
800 }
801
802 member_offset += AR_HDR_SIZE + eltsize;
803 if (member_offset % 2 != 0)
804 member_offset++;
805#endif
806 }
807 }
808
809 close (desc);
810 return 0;
811}
812#endif /* !VMS */
813
814
815/* Return nonzero iff NAME matches MEM.
816 If TRUNCATED is nonzero, MEM may be truncated to
817 sizeof (struct ar_hdr.ar_name) - 1. */
818
819int
820ar_name_equal (const char *name, const char *mem, int truncated)
821{
822 const char *p;
823
824 p = strrchr (name, '/');
825 if (p != 0)
826 name = p + 1;
827
828#ifndef VMS
829 if (truncated)
830 {
831#ifdef AIAMAG
832 /* TRUNCATED should never be set on this system. */
833 abort ();
834#else
835 struct ar_hdr hdr;
836#if !defined (__hpux) && !defined (cray)
837 return strneq (name, mem, sizeof (hdr.ar_name) - 1);
838#else
839 return strneq (name, mem, sizeof (hdr.ar_name) - 2);
840#endif /* !__hpux && !cray */
841#endif /* !AIAMAG */
842 }
843
844 return !strcmp (name, mem);
845#else
846 /* VMS members do not have suffixes, but the filenames usually
847 have.
848 Do we need to strip VMS disk/directory format paths?
849
850 Most VMS compilers etc. by default are case insensitive
851 but produce uppercase external names, incl. module names.
852 However the VMS librarian (ar) and the linker by default
853 are case sensitive: they take what they get, usually
854 uppercase names. So for the non-default settings of the
855 compilers etc. there is a need to have a case sensitive
856 mode. */
857 {
858 int len;
859 len = strlen(mem);
860 int match;
861 char *dot;
862 if ((dot=strrchr(name,'.')))
863 match = (len == dot - name) && !strncasecmp(name, mem, len);
864 else
865 match = !strcasecmp (name, mem);
866 return match;
867 }
868#endif /* !VMS */
869}
870
871
872#ifndef VMS
873/* ARGSUSED */
874static long int
875ar_member_pos (int desc UNUSED, const char *mem, int truncated,
876 long int hdrpos, long int datapos UNUSED, long int size UNUSED,
877 long int date UNUSED, int uid UNUSED, int gid UNUSED,
878 unsigned int mode UNUSED, const void *name)
879{
880 if (!ar_name_equal (name, mem, truncated))
881 return 0;
882 return hdrpos;
883}
884
885/* Set date of member MEMNAME in archive ARNAME to current time.
886 Returns 0 if successful,
887 -1 if file ARNAME does not exist,
888 -2 if not a valid archive,
889 -3 if other random system call error (including file read-only),
890 1 if valid but member MEMNAME does not exist. */
891
892int
893ar_member_touch (const char *arname, const char *memname)
894{
895 long int pos = ar_scan (arname, ar_member_pos, memname);
896 int fd;
897 struct ar_hdr ar_hdr;
898 off_t o;
899 int r;
900 unsigned int ui;
901 struct stat statbuf;
902
903 if (pos < 0)
904 return (int) pos;
905 if (!pos)
906 return 1;
907
908 EINTRLOOP (fd, open (arname, O_RDWR, 0666));
909 if (fd < 0)
910 return -3;
911 /* Read in this member's header */
912 EINTRLOOP (o, lseek (fd, pos, 0));
913 if (o < 0)
914 goto lose;
915 EINTRLOOP (r, read (fd, &ar_hdr, AR_HDR_SIZE));
916 if (r != AR_HDR_SIZE)
917 goto lose;
918 /* Write back the header, thus touching the archive file. */
919 EINTRLOOP (o, lseek (fd, pos, 0));
920 if (o < 0)
921 goto lose;
922 EINTRLOOP (r, write (fd, &ar_hdr, AR_HDR_SIZE));
923 if (r != AR_HDR_SIZE)
924 goto lose;
925 /* The file's mtime is the time we we want. */
926 EINTRLOOP (r, fstat (fd, &statbuf));
927 if (r < 0)
928 goto lose;
929#if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
930 /* Advance member's time to that time */
931 for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++)
932 ar_hdr.ar_date[ui] = ' ';
933 sprintf (TOCHAR (ar_hdr.ar_date), "%lu", (long unsigned) statbuf.st_mtime);
934#ifdef AIAMAG
935 ar_hdr.ar_date[strlen (ar_hdr.ar_date)] = ' ';
936#endif
937#else
938 ar_hdr.ar_date = statbuf.st_mtime;
939#endif
940 /* Write back this member's header */
941 EINTRLOOP (o, lseek (fd, pos, 0));
942 if (o < 0)
943 goto lose;
944 EINTRLOOP (r, write (fd, &ar_hdr, AR_HDR_SIZE));
945 if (r != AR_HDR_SIZE)
946 goto lose;
947 close (fd);
948 return 0;
949
950 lose:
951 r = errno;
952 close (fd);
953 errno = r;
954 return -3;
955}
956#endif
957
958
959#ifdef TEST
960
961long int
962describe_member (int desc, const char *name, int truncated,
963 long int hdrpos, long int datapos, long int size,
964 long int date, int uid, int gid, unsigned int mode,
965 const void *arg)
966{
967 extern char *ctime ();
968
969 printf (_("Member '%s'%s: %ld bytes at %ld (%ld).\n"),
970 name, truncated ? _(" (name might be truncated)") : "",
971 size, hdrpos, datapos);
972 printf (_(" Date %s"), ctime (&date));
973 printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode);
974
975 return 0;
976}
977
978int
979main (int argc, char **argv)
980{
981 ar_scan (argv[1], describe_member, NULL);
982 return 0;
983}
984
985#endif /* TEST. */
986#endif /* NO_ARCHIVES. */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use