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