VirtualBox

source: kBuild/vendor/gnumake/2005-05-16/arscan.c@ 1989

Last change on this file since 1989 was 153, checked in by bird, 20 years ago

GNU Make 3.81beta1.

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