root/trunk/freewrt/tools/gmake/arscan.c

Revision 2223, 20.6 kB (checked in by tg, 5 years ago)

add some of the sources from GNU make 3.81
unchanged

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