VirtualBox

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

Last change on this file since 2060 was 1993, checked in by bird, 16 years ago

Merged in current GNU Make code (CVS from 2008-10-28). Ref #55.

  • Property svn:eol-style set to native
File size: 20.4 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 Free Software
4Foundation, 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 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
136long int
137ar_scan (const char *archive, ar_member_func_t function, const void *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 <[email protected]>, 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. */
243struct 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 <[email protected]>)
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
277/* Takes three arguments ARCHIVE, FUNCTION and ARG.
278
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,
282 member name,
283 member name might be truncated flag,
284 member header position in file,
285 member data position in file,
286 member data size,
287 member date,
288 member uid,
289 member gid,
290 member protection mode,
291 ARG.
292
293 The descriptor is poised to read the data of the member
294 when FUNCTION is called. It does not matter how much
295 data FUNCTION reads.
296
297 If FUNCTION returns nonzero, we immediately return
298 what FUNCTION returned.
299
300 Returns -1 if archive does not exist,
301 Returns -2 if archive has invalid format.
302 Returns 0 if have scanned successfully. */
303
304long int
305ar_scan (const char *archive, ar_member_func_t function, const void *arg)
306{
307#ifdef AIAMAG
308 FL_HDR fl_header;
309#ifdef AIAMAGBIG
310 int big_archive = 0;
311 FL_HDR_BIG fl_header_big;
312#endif
313#else
314 int long_name = 0;
315#endif
316 char *namemap = 0;
317 int desc = open (archive, O_RDONLY, 0);
318 if (desc < 0)
319 return -1;
320#ifdef SARMAG
321 {
322 char buf[SARMAG];
323 register int nread = read (desc, buf, SARMAG);
324 if (nread != SARMAG || memcmp (buf, ARMAG, SARMAG))
325 {
326 (void) close (desc);
327 return -2;
328 }
329 }
330#else
331#ifdef AIAMAG
332 {
333 register int nread = read (desc, &fl_header, FL_HSZ);
334
335 if (nread != FL_HSZ)
336 {
337 (void) close (desc);
338 return -2;
339 }
340#ifdef AIAMAGBIG
341 /* If this is a "big" archive, then set the flag and
342 re-read the header into the "big" structure. */
343 if (!memcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG))
344 {
345 big_archive = 1;
346
347 /* seek back to beginning of archive */
348 if (lseek (desc, 0, 0) < 0)
349 {
350 (void) close (desc);
351 return -2;
352 }
353
354 /* re-read the header into the "big" structure */
355 nread = read (desc, &fl_header_big, FL_HSZ_BIG);
356 if (nread != FL_HSZ_BIG)
357 {
358 (void) close (desc);
359 return -2;
360 }
361 }
362 else
363#endif
364 /* Check to make sure this is a "normal" archive. */
365 if (memcmp (fl_header.fl_magic, AIAMAG, SAIAMAG))
366 {
367 (void) close (desc);
368 return -2;
369 }
370 }
371#else
372 {
373#ifndef M_XENIX
374 int buf;
375#else
376 unsigned short int buf;
377#endif
378 register int nread = read(desc, &buf, sizeof (buf));
379 if (nread != sizeof (buf) || buf != ARMAG)
380 {
381 (void) close (desc);
382 return -2;
383 }
384 }
385#endif
386#endif
387
388 /* Now find the members one by one. */
389 {
390#ifdef SARMAG
391 register long int member_offset = SARMAG;
392#else
393#ifdef AIAMAG
394 long int member_offset;
395 long int last_member_offset;
396
397#ifdef AIAMAGBIG
398 if ( big_archive )
399 {
400 sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset);
401 sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset);
402 }
403 else
404#endif
405 {
406 sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset);
407 sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset);
408 }
409
410 if (member_offset == 0)
411 {
412 /* Empty archive. */
413 close (desc);
414 return 0;
415 }
416#else
417#ifndef M_XENIX
418 register long int member_offset = sizeof (int);
419#else /* Xenix. */
420 register long int member_offset = sizeof (unsigned short int);
421#endif /* Not Xenix. */
422#endif
423#endif
424
425 while (1)
426 {
427 register int nread;
428 struct ar_hdr member_header;
429#ifdef AIAMAGBIG
430 struct ar_hdr_big member_header_big;
431#endif
432#ifdef AIAMAG
433 char name[256];
434 int name_len;
435 long int dateval;
436 int uidval, gidval;
437 long int data_offset;
438#else
439 char namebuf[sizeof member_header.ar_name + 1];
440 char *name;
441 int is_namemap; /* Nonzero if this entry maps long names. */
442#endif
443 long int eltsize;
444 int eltmode;
445 long int fnval;
446
447 if (lseek (desc, member_offset, 0) < 0)
448 {
449 (void) close (desc);
450 return -2;
451 }
452
453#ifdef AIAMAG
454#define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name))
455
456#ifdef AIAMAGBIG
457 if (big_archive)
458 {
459 nread = read (desc, &member_header_big,
460 AR_MEMHDR_SZ(member_header_big) );
461
462 if (nread != AR_MEMHDR_SZ(member_header_big))
463 {
464 (void) close (desc);
465 return -2;
466 }
467
468 sscanf (member_header_big.ar_namlen, "%4d", &name_len);
469 nread = read (desc, name, name_len);
470
471 if (nread != name_len)
472 {
473 (void) close (desc);
474 return -2;
475 }
476
477 name[name_len] = 0;
478
479 sscanf (member_header_big.ar_date, "%12ld", &dateval);
480 sscanf (member_header_big.ar_uid, "%12d", &uidval);
481 sscanf (member_header_big.ar_gid, "%12d", &gidval);
482 sscanf (member_header_big.ar_mode, "%12o", &eltmode);
483 sscanf (member_header_big.ar_size, "%20ld", &eltsize);
484
485 data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big)
486 + name_len + 2);
487 }
488 else
489#endif
490 {
491 nread = read (desc, &member_header,
492 AR_MEMHDR_SZ(member_header) );
493
494 if (nread != AR_MEMHDR_SZ(member_header))
495 {
496 (void) close (desc);
497 return -2;
498 }
499
500 sscanf (member_header.ar_namlen, "%4d", &name_len);
501 nread = read (desc, name, name_len);
502
503 if (nread != name_len)
504 {
505 (void) close (desc);
506 return -2;
507 }
508
509 name[name_len] = 0;
510
511 sscanf (member_header.ar_date, "%12ld", &dateval);
512 sscanf (member_header.ar_uid, "%12d", &uidval);
513 sscanf (member_header.ar_gid, "%12d", &gidval);
514 sscanf (member_header.ar_mode, "%12o", &eltmode);
515 sscanf (member_header.ar_size, "%12ld", &eltsize);
516
517 data_offset = (member_offset + AR_MEMHDR_SZ(member_header)
518 + name_len + 2);
519 }
520 data_offset += data_offset % 2;
521
522 fnval =
523 (*function) (desc, name, 0,
524 member_offset, data_offset, eltsize,
525 dateval, uidval, gidval,
526 eltmode, arg);
527
528#else /* Not AIAMAG. */
529 nread = read (desc, &member_header, AR_HDR_SIZE);
530 if (nread == 0)
531 /* No data left means end of file; that is OK. */
532 break;
533
534 if (nread != AR_HDR_SIZE
535#if defined(ARFMAG) || defined(ARFZMAG)
536 || (
537# ifdef ARFMAG
538 memcmp (member_header.ar_fmag, ARFMAG, 2)
539# else
540 1
541# endif
542 &&
543# ifdef ARFZMAG
544 memcmp (member_header.ar_fmag, ARFZMAG, 2)
545# else
546 1
547# endif
548 )
549#endif
550 )
551 {
552 (void) close (desc);
553 return -2;
554 }
555
556 name = namebuf;
557 memcpy (name, member_header.ar_name, sizeof member_header.ar_name);
558 {
559 register char *p = name + sizeof member_header.ar_name;
560 do
561 *p = '\0';
562 while (p > name && *--p == ' ');
563
564#ifndef AIAMAG
565 /* If the member name is "//" or "ARFILENAMES/" this may be
566 a list of file name mappings. The maximum file name
567 length supported by the standard archive format is 14
568 characters. This member will actually always be the
569 first or second entry in the archive, but we don't check
570 that. */
571 is_namemap = (!strcmp (name, "//")
572 || !strcmp (name, "ARFILENAMES/"));
573#endif /* Not AIAMAG. */
574 /* On some systems, there is a slash after each member name. */
575 if (*p == '/')
576 *p = '\0';
577
578#ifndef AIAMAG
579 /* If the member name starts with a space or a slash, this
580 is an index into the file name mappings (used by GNU ar).
581 Otherwise if the member name looks like #1/NUMBER the
582 real member name appears in the element data (used by
583 4.4BSD). */
584 if (! is_namemap
585 && (name[0] == ' ' || name[0] == '/')
586 && namemap != 0)
587 {
588 name = namemap + atoi (name + 1);
589 long_name = 1;
590 }
591 else if (name[0] == '#'
592 && name[1] == '1'
593 && name[2] == '/')
594 {
595 int namesize = atoi (name + 3);
596
597 name = alloca (namesize + 1);
598 nread = read (desc, name, namesize);
599 if (nread != namesize)
600 {
601 close (desc);
602 return -2;
603 }
604 name[namesize] = '\0';
605
606 long_name = 1;
607 }
608#endif /* Not AIAMAG. */
609 }
610
611#ifndef M_XENIX
612 sscanf (member_header.ar_mode, "%o", &eltmode);
613 eltsize = atol (member_header.ar_size);
614#else /* Xenix. */
615 eltmode = (unsigned short int) member_header.ar_mode;
616 eltsize = member_header.ar_size;
617#endif /* Not Xenix. */
618
619 fnval =
620 (*function) (desc, name, ! long_name, member_offset,
621 member_offset + AR_HDR_SIZE, eltsize,
622#ifndef M_XENIX
623 atol (member_header.ar_date),
624 atoi (member_header.ar_uid),
625 atoi (member_header.ar_gid),
626#else /* Xenix. */
627 member_header.ar_date,
628 member_header.ar_uid,
629 member_header.ar_gid,
630#endif /* Not Xenix. */
631 eltmode, arg);
632
633#endif /* AIAMAG. */
634
635 if (fnval)
636 {
637 (void) close (desc);
638 return fnval;
639 }
640
641#ifdef AIAMAG
642 if (member_offset == last_member_offset)
643 /* End of the chain. */
644 break;
645
646#ifdef AIAMAGBIG
647 if (big_archive)
648 sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset);
649 else
650#endif
651 sscanf (member_header.ar_nxtmem, "%12ld", &member_offset);
652
653 if (lseek (desc, member_offset, 0) != member_offset)
654 {
655 (void) close (desc);
656 return -2;
657 }
658#else
659
660 /* If this member maps archive names, we must read it in. The
661 name map will always precede any members whose names must
662 be mapped. */
663 if (is_namemap)
664 {
665 char *clear;
666 char *limit;
667
668 namemap = alloca (eltsize);
669 nread = read (desc, namemap, eltsize);
670 if (nread != eltsize)
671 {
672 (void) close (desc);
673 return -2;
674 }
675
676 /* The names are separated by newlines. Some formats have
677 a trailing slash. Null terminate the strings for
678 convenience. */
679 limit = namemap + eltsize;
680 for (clear = namemap; clear < limit; clear++)
681 {
682 if (*clear == '\n')
683 {
684 *clear = '\0';
685 if (clear[-1] == '/')
686 clear[-1] = '\0';
687 }
688 }
689
690 is_namemap = 0;
691 }
692
693 member_offset += AR_HDR_SIZE + eltsize;
694 if (member_offset % 2 != 0)
695 member_offset++;
696#endif
697 }
698 }
699
700 close (desc);
701 return 0;
702}
703#endif /* !VMS */
704
705
706/* Return nonzero iff NAME matches MEM.
707 If TRUNCATED is nonzero, MEM may be truncated to
708 sizeof (struct ar_hdr.ar_name) - 1. */
709
710int
711ar_name_equal (const char *name, const char *mem, int truncated)
712{
713 const char *p;
714
715 p = strrchr (name, '/');
716 if (p != 0)
717 name = p + 1;
718
719#ifndef VMS
720 if (truncated)
721 {
722#ifdef AIAMAG
723 /* TRUNCATED should never be set on this system. */
724 abort ();
725#else
726 struct ar_hdr hdr;
727#if !defined (__hpux) && !defined (cray)
728 return strneq (name, mem, sizeof(hdr.ar_name) - 1);
729#else
730 return strneq (name, mem, sizeof(hdr.ar_name) - 2);
731#endif /* !__hpux && !cray */
732#endif /* !AIAMAG */
733 }
734#endif /* !VMS */
735
736 return !strcmp (name, mem);
737}
738
739
740#ifndef VMS
741/* ARGSUSED */
742static long int
743ar_member_pos (int desc UNUSED, const char *mem, int truncated,
744 long int hdrpos, long int datapos UNUSED, long int size UNUSED,
745 long int date UNUSED, int uid UNUSED, int gid UNUSED,
746 int mode UNUSED, const void *name)
747{
748 if (!ar_name_equal (name, mem, truncated))
749 return 0;
750 return hdrpos;
751}
752
753/* Set date of member MEMNAME in archive ARNAME to current time.
754 Returns 0 if successful,
755 -1 if file ARNAME does not exist,
756 -2 if not a valid archive,
757 -3 if other random system call error (including file read-only),
758 1 if valid but member MEMNAME does not exist. */
759
760int
761ar_member_touch (const char *arname, const char *memname)
762{
763 long int pos = ar_scan (arname, ar_member_pos, memname);
764 int fd;
765 struct ar_hdr ar_hdr;
766 int i;
767 unsigned int ui;
768 struct stat statbuf;
769
770 if (pos < 0)
771 return (int) pos;
772 if (!pos)
773 return 1;
774
775 fd = open (arname, O_RDWR, 0666);
776 if (fd < 0)
777 return -3;
778 /* Read in this member's header */
779 if (lseek (fd, pos, 0) < 0)
780 goto lose;
781 if (AR_HDR_SIZE != read (fd, &ar_hdr, AR_HDR_SIZE))
782 goto lose;
783 /* Write back the header, thus touching the archive file. */
784 if (lseek (fd, pos, 0) < 0)
785 goto lose;
786 if (AR_HDR_SIZE != write (fd, &ar_hdr, AR_HDR_SIZE))
787 goto lose;
788 /* The file's mtime is the time we we want. */
789 EINTRLOOP (i, fstat (fd, &statbuf));
790 if (i < 0)
791 goto lose;
792#if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32)
793 /* Advance member's time to that time */
794 for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++)
795 ar_hdr.ar_date[ui] = ' ';
796 sprintf (ar_hdr.ar_date, "%ld", (long int) statbuf.st_mtime);
797#ifdef AIAMAG
798 ar_hdr.ar_date[strlen(ar_hdr.ar_date)] = ' ';
799#endif
800#else
801 ar_hdr.ar_date = statbuf.st_mtime;
802#endif
803 /* Write back this member's header */
804 if (lseek (fd, pos, 0) < 0)
805 goto lose;
806 if (AR_HDR_SIZE != write (fd, &ar_hdr, AR_HDR_SIZE))
807 goto lose;
808 close (fd);
809 return 0;
810
811 lose:
812 i = errno;
813 close (fd);
814 errno = i;
815 return -3;
816}
817#endif
818
819
820#ifdef TEST
821
822long int
823describe_member (int desc, const char *name, int truncated,
824 long int hdrpos, long int datapos, long int size,
825 long int date, int uid, int gid, int mode, const void *arg)
826{
827 extern char *ctime ();
828
829 printf (_("Member `%s'%s: %ld bytes at %ld (%ld).\n"),
830 name, truncated ? _(" (name might be truncated)") : "",
831 size, hdrpos, datapos);
832 printf (_(" Date %s"), ctime (&date));
833 printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode);
834
835 return 0;
836}
837
838int
839main (int argc, char **argv)
840{
841 ar_scan (argv[1], describe_member, NULL);
842 return 0;
843}
844
845#endif /* TEST. */
846#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