VirtualBox

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

Last change on this file since 2989 was 2591, checked in by bird, 13 years ago

kmk: Merged in changes from GNU make 3.82. Previous GNU make base version was gnumake-2008-10-28-CVS.

  • Property svn:eol-style set to native
File size: 21.5 KB
Line 
1/* Library function for scanning an archive file.
2Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
31998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
42010 Free Software Foundation, Inc.
5This file is part of GNU Make.
6
7GNU Make is free software; you can redistribute it and/or modify it under the
8terms of the GNU General Public License as published by the Free Software
9Foundation; either version 3 of the License, or (at your option) any later
10version.
11
12GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License along with
17this program. If not, see <http://www.gnu.org/licenses/>. */
18
19#include "make.h"
20
21#ifdef HAVE_FCNTL_H
22#include <fcntl.h>
23#else
24#include <sys/file.h>
25#endif
26
27#ifndef NO_ARCHIVES
28
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
39
40static void *VMS_lib_idx;
41
42static char *VMS_saved_memname;
43
44static time_t VMS_member_date;
45
46static long int (*VMS_function) ();
47
48static int
49VMS_get_member_info (struct dsc$descriptor_s *module, unsigned long *rfa)
50{
51 int status, i;
52 long int fnval;
53
54 time_t val;
55
56 static struct dsc$descriptor_s bufdesc =
57 { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
58
59 struct mhddef *mhd;
60 char filename[128];
61
62 bufdesc.dsc$a_pointer = filename;
63 bufdesc.dsc$w_length = sizeof (filename);
64
65 status = lbr$set_module (&VMS_lib_idx, rfa, &bufdesc,
66 &bufdesc.dsc$w_length, 0);
67 if (! (status & 1))
68 {
69 error (NILF, _("lbr$set_module() failed to extract module info, status = %d"),
70 status);
71
72 lbr$close (&VMS_lib_idx);
73
74 return 0;
75 }
76
77 mhd = (struct mhddef *) filename;
78
79#ifdef __DECC
80 /* John Fowler <[email protected]> writes this is needed in his environment,
81 * but that decc$fix_time() isn't documented to work this way. Let me
82 * know if this causes problems in other VMS environments.
83 */
84 {
85 /* Modified by M. Gehre at 11-JAN-2008 because old formula is wrong:
86 * val = decc$fix_time (&mhd->mhd$l_datim) + timezone - daylight*3600;
87 * a) daylight specifies, if the timezone has daylight saving enabled, not
88 * if it is active
89 * b) what we need is the information, if daylight saving was active, if
90 * the library module was replaced. This information we get using the
91 * localtime function
92 */
93
94 struct tm *tmp;
95
96 /* Conversion from VMS time to C time */
97 val = decc$fix_time (&mhd->mhd$l_datim);
98
99 /*
100 * Conversion from local time (stored in library) to GMT (needed for gmake)
101 * Note: The tm_gmtoff element is a VMS extension to the ANSI standard.
102 */
103 tmp = localtime (&val);
104 val -= tmp->tm_gmtoff;
105 }
106#endif
107
108 for (i = 0; i < module->dsc$w_length; i++)
109 filename[i] = _tolower ((unsigned char)module->dsc$a_pointer[i]);
110
111 filename[i] = '\0';
112
113 VMS_member_date = (time_t) -1;
114
115 fnval =
116 (*VMS_function) (-1, filename, 0, 0, 0, 0, val, 0, 0, 0,
117 VMS_saved_memname);
118
119 if (fnval)
120 {
121 VMS_member_date = fnval;
122 return 0;
123 }
124 else
125 return 1;
126}
127
128/* Takes three arguments ARCHIVE, FUNCTION and ARG.
129
130 Open the archive named ARCHIVE, find its members one by one,
131 and for each one call FUNCTION with the following arguments:
132 archive file descriptor for reading the data,
133 member name,
134 member name might be truncated flag,
135 member header position in file,
136 member data position in file,
137 member data size,
138 member date,
139 member uid,
140 member gid,
141 member protection mode,
142 ARG.
143
144 NOTE: on VMS systems, only name, date, and arg are meaningful!
145
146 The descriptor is poised to read the data of the member
147 when FUNCTION is called. It does not matter how much
148 data FUNCTION reads.
149
150 If FUNCTION returns nonzero, we immediately return
151 what FUNCTION returned.
152
153 Returns -1 if archive does not exist,
154 Returns -2 if archive has invalid format.
155 Returns 0 if have scanned successfully. */
156
157long int
158ar_scan (const char *archive, ar_member_func_t function, const void *arg)
159{
160 char *p;
161
162 static struct dsc$descriptor_s libdesc =
163 { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
164
165 unsigned long func = LBR$C_READ;
166 unsigned long type = LBR$C_TYP_UNK;
167 unsigned long index = 1;
168
169 int status;
170
171 status = lbr$ini_control (&VMS_lib_idx, &func, &type, 0);
172
173 if (! (status & 1))
174 {
175 error (NILF, _("lbr$ini_control() failed with status = %d"), status);
176 return -2;
177 }
178
179 /* there is no such descriptor with "const char *dsc$a_pointer" */
180 libdesc.dsc$a_pointer = (char *)archive;
181 libdesc.dsc$w_length = strlen (archive);
182
183 status = lbr$open (&VMS_lib_idx, &libdesc, 0, 0, 0, 0, 0);
184
185 if (! (status & 1))
186 {
187 error (NILF, _("unable to open library `%s' to lookup member `%s'"),
188 archive, (char *)arg);
189 return -1;
190 }
191
192 VMS_saved_memname = (char *)arg;
193
194 /* For comparison, delete .obj from arg name. */
195
196 p = strrchr (VMS_saved_memname, '.');
197 if (p)
198 *p = '\0';
199
200 VMS_function = function;
201
202 VMS_member_date = (time_t) -1;
203 lbr$get_index (&VMS_lib_idx, &index, VMS_get_member_info, 0);
204
205 /* Undo the damage. */
206 if (p)
207 *p = '.';
208
209 lbr$close (&VMS_lib_idx);
210
211 return VMS_member_date > 0 ? VMS_member_date : 0;
212}
213
214#else /* !VMS */
215
216/* SCO Unix's compiler defines both of these. */
217#ifdef M_UNIX
218#undef M_XENIX
219#endif
220
221/* On the sun386i and in System V rel 3, ar.h defines two different archive
222 formats depending upon whether you have defined PORTAR (normal) or PORT5AR
223 (System V Release 1). There is no default, one or the other must be defined
224 to have a nonzero value. */
225
226#if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0)
227#undef PORTAR
228#ifdef M_XENIX
229/* According to Jim Sievert <[email protected]>, for SCO XENIX defining
230 PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the
231 right one. */
232#define PORTAR 0
233#else
234#define PORTAR 1
235#endif
236#endif
237
238/* On AIX, define these symbols to be sure to get both archive formats.
239 AIX 4.3 introduced the "big" archive format to support 64-bit object
240 files, so on AIX 4.3 systems we need to support both the "normal" and
241 "big" archive formats. An archive's format is indicated in the
242 "fl_magic" field of the "FL_HDR" structure. For a normal archive,
243 this field will be the string defined by the AIAMAG symbol. For a
244 "big" archive, it will be the string defined by the AIAMAGBIG symbol
245 (at least on AIX it works this way).
246
247 Note: we'll define these symbols regardless of which AIX version
248 we're compiling on, but this is okay since we'll use the new symbols
249 only if they're present. */
250#ifdef _AIX
251# define __AR_SMALL__
252# define __AR_BIG__
253#endif
254
255#ifndef WINDOWS32
256# if !defined(__BEOS__) && !defined(__HAIKU__)
257# include <ar.h>
258# else
259 /* BeOS 5 doesn't have <ar.h> but has archives in the same format
260 * as many other Unices. This was taken from GNU binutils for BeOS.
261 */
262# define ARMAG "!<arch>\n" /* String that begins an archive file. */
263# define SARMAG 8 /* Size of that string. */
264# define ARFMAG "`\n" /* String in ar_fmag at end of each header. */
265struct ar_hdr
266 {
267 char ar_name[16]; /* Member file name, sometimes / terminated. */
268 char ar_date[12]; /* File date, decimal seconds since Epoch. */
269 char ar_uid[6], ar_gid[6]; /* User and group IDs, in ASCII decimal. */
270 char ar_mode[8]; /* File mode, in ASCII octal. */
271 char ar_size[10]; /* File size, in ASCII decimal. */
272 char ar_fmag[2]; /* Always contains ARFMAG. */
273 };
274# endif
275# define TOCHAR(_m) (_m)
276#else
277/* These should allow us to read Windows (VC++) libraries (according to Frank
278 * Libbrecht <[email protected]>)
279 */
280# include <windows.h>
281# include <windef.h>
282# include <io.h>
283# define ARMAG IMAGE_ARCHIVE_START
284# define SARMAG IMAGE_ARCHIVE_START_SIZE
285# define ar_hdr _IMAGE_ARCHIVE_MEMBER_HEADER
286# define ar_name Name
287# define ar_mode Mode
288# define ar_size Size
289# define ar_date Date
290# define ar_uid UserID
291# define ar_gid GroupID
292/* In Windows the member names have type BYTE so we must cast them. */
293# define TOCHAR(_m) ((char *)(_m))
294#endif
295
296/* Cray's <ar.h> apparently defines this. */
297#ifndef AR_HDR_SIZE
298# define AR_HDR_SIZE (sizeof (struct ar_hdr))
299#endif
300
301
302/* Takes three arguments ARCHIVE, FUNCTION and ARG.
303
304 Open the archive named ARCHIVE, find its members one by one,
305 and for each one call FUNCTION with the following arguments:
306 archive file descriptor for reading the data,
307 member name,
308 member name might be truncated flag,
309 member header position in file,
310 member data position in file,
311 member data size,
312 member date,
313 member uid,
314 member gid,
315 member protection mode,
316 ARG.
317
318 The descriptor is poised to read the data of the member
319 when FUNCTION is called. It does not matter how much
320 data FUNCTION reads.
321
322 If FUNCTION returns nonzero, we immediately return
323 what FUNCTION returned.
324
325 Returns -1 if archive does not exist,
326 Returns -2 if archive has invalid format.
327 Returns 0 if have scanned successfully. */
328
329long int
330ar_scan (const char *archive, ar_member_func_t function, const void *arg)
331{
332#ifdef AIAMAG
333 FL_HDR fl_header;
334#ifdef AIAMAGBIG
335 int big_archive = 0;
336 FL_HDR_BIG fl_header_big;
337#endif
338#else
339 int long_name = 0;
340#endif
341 char *namemap = 0;
342 int desc = open (archive, O_RDONLY, 0);
343 if (desc < 0)
344 return -1;
345#ifdef SARMAG
346 {
347 char buf[SARMAG];
348 register int nread = read (desc, buf, SARMAG);
349 if (nread != SARMAG || memcmp (buf, ARMAG, SARMAG))
350 {
351 (void) close (desc);
352 return -2;
353 }
354 }
355#else
356#ifdef AIAMAG
357 {
358 register int nread = read (desc, &fl_header, FL_HSZ);
359
360 if (nread != FL_HSZ)
361 {
362 (void) close (desc);
363 return -2;
364 }
365#ifdef AIAMAGBIG
366 /* If this is a "big" archive, then set the flag and
367 re-read the header into the "big" structure. */
368 if (!memcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG))
369 {
370 big_archive = 1;
371
372 /* seek back to beginning of archive */
373 if (lseek (desc, 0, 0) < 0)
374 {
375 (void) close (desc);
376 return -2;
377 }
378
379 /* re-read the header into the "big" structure */
380 nread = read (desc, &fl_header_big, FL_HSZ_BIG);
381 if (nread != FL_HSZ_BIG)
382 {
383 (void) close (desc);
384 return -2;
385 }
386 }
387 else
388#endif
389 /* Check to make sure this is a "normal" archive. */
390 if (memcmp (fl_header.fl_magic, AIAMAG, SAIAMAG))
391 {
392 (void) close (desc);
393 return -2;
394 }
395 }
396#else
397 {
398#ifndef M_XENIX
399 int buf;
400#else
401 unsigned short int buf;
402#endif
403 register int nread = read(desc, &buf, sizeof (buf));
404 if (nread != sizeof (buf) || buf != ARMAG)
405 {
406 (void) close (desc);
407 return -2;
408 }
409 }
410#endif
411#endif
412
413 /* Now find the members one by one. */
414 {
415#ifdef SARMAG
416 register long int member_offset = SARMAG;
417#else
418#ifdef AIAMAG
419 long int member_offset;
420 long int last_member_offset;
421
422#ifdef AIAMAGBIG
423 if ( big_archive )
424 {
425 sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset);
426 sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset);
427 }
428 else
429#endif
430 {
431 sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset);
432 sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset);
433 }
434
435 if (member_offset == 0)
436 {
437 /* Empty archive. */
438 close (desc);
439 return 0;
440 }
441#else
442#ifndef M_XENIX
443 register long int member_offset = sizeof (int);
444#else /* Xenix. */
445 register long int member_offset = sizeof (unsigned short int);
446#endif /* Not Xenix. */
447#endif
448#endif
449
450 while (1)
451 {
452 register int nread;
453 struct ar_hdr member_header;
454#ifdef AIAMAGBIG
455 struct ar_hdr_big member_header_big;
456#endif
457#ifdef AIAMAG
458 char name[256];
459 int name_len;
460 long int dateval;
461 int uidval, gidval;
462 long int data_offset;
463#else
464 char namebuf[sizeof member_header.ar_name + 1];
465 char *name;
466 int is_namemap; /* Nonzero if this entry maps long names. */
467#endif
468 long int eltsize;
469 int eltmode;
470 long int fnval;
471
472 if (lseek (desc, member_offset, 0) < 0)
473 {
474 (void) close (desc);
475 return -2;
476 }
477
478#ifdef AIAMAG
479#define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
480
481#ifdef AIAMAGBIG
482 if (big_archive)
483 {
484 nread = read (desc, &member_header_big,
485 AR_MEMHDR_SZ(member_header_big) );
486
487 if (nread != AR_MEMHDR_SZ(member_header_big))
488 {
489 (void) close (desc);
490 return -2;
491 }
492
493 sscanf (member_header_big.ar_namlen, "%4d", &name_len);
494 nread = read (desc, name, name_len);
495
496 if (nread != name_len)
497 {
498 (void) close (desc);
499 return -2;
500 }
501
502 name[name_len] = 0;
503
504 sscanf (member_header_big.ar_date, "%12ld", &dateval);
505 sscanf (member_header_big.ar_uid, "%12d", &uidval);
506 sscanf (member_header_big.ar_gid, "%12d", &gidval);
507 sscanf (member_header_big.ar_mode, "%12o", &eltmode);
508 sscanf (member_header_big.ar_size, "%20ld", &eltsize);
509
510 data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big)
511 + name_len + 2);
512 }
513 else
514#endif
515 {
516 nread = read (desc, &member_header,
517 AR_MEMHDR_SZ(member_header) );
518
519 if (nread != AR_MEMHDR_SZ(member_header))
520 {
521 (void) close (desc);
522 return -2;
523 }
524
525 sscanf (member_header.ar_namlen, "%4d", &name_len);
526 nread = read (desc, name, name_len);
527
528 if (nread != name_len)
529 {
530 (void) close (desc);
531 return -2;
532 }
533
534 name[name_len] = 0;
535
536 sscanf (member_header.ar_date, "%12ld", &dateval);
537 sscanf (member_header.ar_uid, "%12d", &uidval);
538 sscanf (member_header.ar_gid, "%12d", &gidval);
539 sscanf (member_header.ar_mode, "%12o", &eltmode);
540 sscanf (member_header.ar_size, "%12ld", &eltsize);
541
542 data_offset = (member_offset + AR_MEMHDR_SZ(member_header)
543 + name_len + 2);
544 }
545 data_offset += data_offset % 2;
546
547 fnval =
548 (*function) (desc, name, 0,
549 member_offset, data_offset, eltsize,
550 dateval, uidval, gidval,
551 eltmode, arg);
552
553#else /* Not AIAMAG. */
554 nread = read (desc, &member_header, AR_HDR_SIZE);
555 if (nread == 0)
556 /* No data left means end of file; that is OK. */
557 break;
558
559 if (nread != AR_HDR_SIZE
560#if defined(ARFMAG) || defined(ARFZMAG)
561 || (
562# ifdef ARFMAG
563 memcmp (member_header.ar_fmag, ARFMAG, 2)
564# else
565 1
566# endif
567 &&
568# ifdef ARFZMAG
569 memcmp (member_header.ar_fmag, ARFZMAG, 2)
570# else
571 1
572# endif
573 )
574#endif
575 )
576 {
577 (void) close (desc);
578 return -2;
579 }
580
581 name = namebuf;
582 memcpy (name, member_header.ar_name, sizeof member_header.ar_name);
583 {
584 register char *p = name + sizeof member_header.ar_name;
585 do
586 *p = '\0';
587 while (p > name && *--p == ' ');
588
589#ifndef AIAMAG
590 /* If the member name is "//" or "ARFILENAMES/" this may be
591 a list of file name mappings. The maximum file name
592 length supported by the standard archive format is 14
593 characters. This member will actually always be the
594 first or second entry in the archive, but we don't check
595 that. */
596 is_namemap = (!strcmp (name, "//")
597 || !strcmp (name, "ARFILENAMES/"));
598#endif /* Not AIAMAG. */
599 /* On some systems, there is a slash after each member name. */
600 if (*p == '/')
601 *p = '\0';
602
603#ifndef AIAMAG
604 /* If the member name starts with a space or a slash, this
605 is an index into the file name mappings (used by GNU ar).
606 Otherwise if the member name looks like #1/NUMBER the
607 real member name appears in the element data (used by
608 4.4BSD). */
609 if (! is_namemap
610 && (name[0] == ' ' || name[0] == '/')
611 && namemap != 0)
612 {
613 name = namemap + atoi (name + 1);
614 long_name = 1;
615 }
616 else if (name[0] == '#'
617 && name[1] == '1'
618 && name[2] == '/')
619 {
620 int namesize = atoi (name + 3);
621
622 name = alloca (namesize + 1);
623 nread = read (desc, name, namesize);
624 if (nread != namesize)
625 {
626 close (desc);
627 return -2;
628 }
629 name[namesize] = '\0';
630
631 long_name = 1;
632 }
633#endif /* Not AIAMAG. */
634 }
635
636#ifndef M_XENIX
637 sscanf (TOCHAR (member_header.ar_mode), "%o", &eltmode);
638 eltsize = atol (TOCHAR (member_header.ar_size));
639#else /* Xenix. */
640 eltmode = (unsigned short int) member_header.ar_mode;
641 eltsize = member_header.ar_size;
642#endif /* Not Xenix. */
643
644 fnval =
645 (*function) (desc, name, ! long_name, member_offset,
646 member_offset + AR_HDR_SIZE, eltsize,
647#ifndef M_XENIX
648 atol (TOCHAR (member_header.ar_date)),
649 atoi (TOCHAR (member_header.ar_uid)),
650 atoi (TOCHAR (member_header.ar_gid)),
651#else /* Xenix. */
652 member_header.ar_date,
653 member_header.ar_uid,
654 member_header.ar_gid,
655#endif /* Not Xenix. */
656 eltmode, arg);
657
658#endif /* AIAMAG. */
659
660 if (fnval)
661 {
662 (void) close (desc);
663 return fnval;
664 }
665
666#ifdef AIAMAG
667 if (member_offset == last_member_offset)
668 /* End of the chain. */
669 break;
670
671#ifdef AIAMAGBIG
672 if (big_archive)
673 sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset);
674 else
675#endif
676 sscanf (member_header.ar_nxtmem, "%12ld", &member_offset);
677
678 if (lseek (desc, member_offset, 0) != member_offset)
679 {
680 (void) close (desc);
681 return -2;
682 }
683#else
684
685 /* If this member maps archive names, we must read it in. The
686 name map will always precede any members whose names must
687 be mapped. */
688 if (is_namemap)
689 {
690 char *clear;
691 char *limit;
692
693 namemap = alloca (eltsize);
694 nread = read (desc, namemap, eltsize);
695 if (nread != eltsize)
696 {
697 (void) close (desc);
698 return -2;
699 }
700
701 /* The names are separated by newlines. Some formats have
702 a trailing slash. Null terminate the strings for
703 convenience. */
704 limit = namemap + eltsize;
705 for (clear = namemap; clear < limit; clear++)
706 {
707 if (*clear == '\n')
708 {
709 *clear = '\0';
710 if (clear[-1] == '/')
711 clear[-1] = '\0';
712 }
713 }
714
715 is_namemap = 0;
716 }
717
718 member_offset += AR_HDR_SIZE + eltsize;
719 if (member_offset % 2 != 0)
720 member_offset++;
721#endif
722 }
723 }
724
725 close (desc);
726 return 0;
727}
728#endif /* !VMS */
729
730
731/* Return nonzero iff NAME matches MEM.
732 If TRUNCATED is nonzero, MEM may be truncated to
733 sizeof (struct ar_hdr.ar_name) - 1. */
734
735int
736ar_name_equal (const char *name, const char *mem, int truncated)
737{
738 const char *p;
739
740 p = strrchr (name, '/');
741 if (p != 0)
742 name = p + 1;
743
744#ifndef VMS
745 if (truncated)
746 {
747#ifdef AIAMAG
748 /* TRUNCATED should never be set on this system. */
749 abort ();
750#else
751 struct ar_hdr hdr;
752#if !defined (__hpux) && !defined (cray)
753 return strneq (name, mem, sizeof(hdr.ar_name) - 1);
754#else
755 return strneq (name, mem, sizeof(hdr.ar_name) - 2);
756#endif /* !__hpux && !cray */
757#endif /* !AIAMAG */
758 }
759#endif /* !VMS */
760
761 return !strcmp (name, mem);
762}
763
764
765#ifndef VMS
766/* ARGSUSED */
767static long int
768ar_member_pos (int desc UNUSED, const char *mem, int truncated,
769 long int hdrpos, long int datapos UNUSED, long int size UNUSED,
770 long int date UNUSED, int uid UNUSED, int gid UNUSED,
771 int mode UNUSED, const void *name)
772{
773 if (!ar_name_equal (name, mem, truncated))
774 return 0;
775 return hdrpos;
776}
777
778/* Set date of member MEMNAME in archive ARNAME to current time.
779 Returns 0 if successful,
780 -1 if file ARNAME does not exist,
781 -2 if not a valid archive,
782 -3 if other random system call error (including file read-only),
783 1 if valid but member MEMNAME does not exist. */
784
785int
786ar_member_touch (const char *arname, const char *memname)
787{
788 long int pos = ar_scan (arname, ar_member_pos, memname);
789 int fd;
790 struct ar_hdr ar_hdr;
791 int i;
792 unsigned int ui;
793 struct stat statbuf;
794
795 if (pos < 0)
796 return (int) pos;
797 if (!pos)
798 return 1;
799
800 fd = open (arname, O_RDWR, 0666);
801 if (fd < 0)
802 return -3;
803 /* Read in this member's header */
804 if (lseek (fd, pos, 0) < 0)
805 goto lose;
806 if (AR_HDR_SIZE != read (fd, &ar_hdr, AR_HDR_SIZE))
807 goto lose;
808 /* Write back the header, thus touching the archive file. */
809 if (lseek (fd, pos, 0) < 0)
810 goto lose;
811 if (AR_HDR_SIZE != write (fd, &ar_hdr, AR_HDR_SIZE))
812 goto lose;
813 /* The file's mtime is the time we we want. */
814 EINTRLOOP (i, fstat (fd, &statbuf));
815 if (i < 0)
816 goto lose;
817#if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
818 /* Advance member's time to that time */
819 for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++)
820 ar_hdr.ar_date[ui] = ' ';
821 sprintf (TOCHAR (ar_hdr.ar_date), "%ld", (long int) statbuf.st_mtime);
822#ifdef AIAMAG
823 ar_hdr.ar_date[strlen(ar_hdr.ar_date)] = ' ';
824#endif
825#else
826 ar_hdr.ar_date = statbuf.st_mtime;
827#endif
828 /* Write back this member's header */
829 if (lseek (fd, pos, 0) < 0)
830 goto lose;
831 if (AR_HDR_SIZE != write (fd, &ar_hdr, AR_HDR_SIZE))
832 goto lose;
833 close (fd);
834 return 0;
835
836 lose:
837 i = errno;
838 close (fd);
839 errno = i;
840 return -3;
841}
842#endif
843
844
845#ifdef TEST
846
847long int
848describe_member (int desc, const char *name, int truncated,
849 long int hdrpos, long int datapos, long int size,
850 long int date, int uid, int gid, int mode, const void *arg)
851{
852 extern char *ctime ();
853
854 printf (_("Member `%s'%s: %ld bytes at %ld (%ld).\n"),
855 name, truncated ? _(" (name might be truncated)") : "",
856 size, hdrpos, datapos);
857 printf (_(" Date %s"), ctime (&date));
858 printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode);
859
860 return 0;
861}
862
863int
864main (int argc, char **argv)
865{
866 ar_scan (argv[1], describe_member, NULL);
867 return 0;
868}
869
870#endif /* TEST. */
871#endif /* NO_ARCHIVES. */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette