Print this page
make: remove SCCS ident stuff
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/make/bin/make/common/ar.cc
+++ new/usr/src/cmd/make/bin/make/common/ar.cc
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 -/*
26 - * @(#)ar.cc 1.28 06/12/12
27 - */
28 -
29 -#pragma ident "@(#)ar.cc 1.28 06/12/12"
30 25
31 26 /*
32 27 * ar.c
33 28 *
34 29 * Deal with the lib.a(member.o) and lib.a((entry-point)) notations
35 30 *
36 31 * Look inside archives for notations a(b) and a((b))
37 32 * a(b) is file member b in archive a
38 33 * a((b)) is entry point b in object archive a
39 34 *
40 35 * For 6.0, create a make which can understand all archive
41 36 * formats. This is kind of tricky, and <ar.h> isnt any help.
42 37 */
43 38
44 39 /*
45 40 * Included files
46 41 */
47 42 #include <avo/avo_alloca.h> /* alloca() */
48 43 #include <ar.h>
49 44 #include <errno.h> /* errno */
50 45 #include <fcntl.h> /* open() */
51 46 #include <mk/defs.h>
52 47 #include <mksh/misc.h> /* retmem_mb() */
53 48
54 49 #if defined(SUN5_0) || defined(HP_UX) || defined(linux)
55 50 struct ranlib {
56 51 union {
57 52 off_t ran_strx; /* string table index of */
58 53 char *ran_name; /* symbol defined by */
59 54 } ran_un;
60 55 off_t ran_off; /* library member at this offset */
61 56 };
62 57 #else
63 58 #include <ranlib.h>
64 59 #endif
65 60
66 61 #if defined(linux)
67 62 #include <ctype.h> /* isspace */
68 63 #else
69 64 #include <unistd.h> /* close() */
70 65 #endif
71 66
72 67
73 68 /*
74 69 * Defined macros
75 70 */
76 71 #ifndef S5EMUL
77 72 #undef BITSPERBYTE
78 73 #define BITSPERBYTE 8
79 74 #endif
80 75
81 76 /*
82 77 * Defines for all the different archive formats. See next comment
83 78 * block for justification for not using <ar.h>s versions.
84 79 */
85 80 #define AR_5_MAGIC "<ar>" /* 5.0 format magic string */
86 81 #define AR_5_MAGIC_LENGTH 4 /* 5.0 format string length */
87 82
88 83 #define AR_PORT_MAGIC "!<arch>\n" /* Port. (6.0) magic string */
89 84 #define AR_PORT_MAGIC_LENGTH 8 /* Port. (6.0) string length */
90 85 #define AR_PORT_END_MAGIC "`\n" /* Port. (6.0) end of header */
91 86 #define AR_PORT_WORD 4 /* Port. (6.0) 'word' length */
92 87
93 88 /*
94 89 * typedefs & structs
95 90 */
96 91 /*
97 92 * These are the archive file headers for the formats. Note
98 93 * that it really doesnt matter if these structures are defined
99 94 * here. They are correct as of the respective archive format
100 95 * releases. If the archive format is changed, then since backwards
101 96 * compatability is the desired behavior, a new structure is added
102 97 * to the list.
103 98 */
104 99 typedef struct { /* 5.0 ar header format: vax family; 3b family */
105 100 char ar_magic[AR_5_MAGIC_LENGTH]; /* AR_5_MAGIC*/
106 101 char ar_name[16]; /* Space terminated */
107 102 char ar_date[AR_PORT_WORD]; /* sgetl() accessed */
108 103 char ar_syms[AR_PORT_WORD]; /* sgetl() accessed */
109 104 } Arh_5;
110 105
111 106 typedef struct { /* 5.0 ar symbol format: vax family; 3b family */
112 107 char sym_name[8]; /* Space terminated */
113 108 char sym_ptr[AR_PORT_WORD]; /* sgetl() accessed */
114 109 } Ars_5;
115 110
116 111 typedef struct { /* 5.0 ar member format: vax family; 3b family */
117 112 char arf_name[16]; /* Space terminated */
118 113 char arf_date[AR_PORT_WORD]; /* sgetl() accessed */
119 114 char arf_uid[AR_PORT_WORD]; /* sgetl() accessed */
120 115 char arf_gid[AR_PORT_WORD]; /* sgetl() accessed */
121 116 char arf_mode[AR_PORT_WORD]; /* sgetl() accessed */
122 117 char arf_size[AR_PORT_WORD]; /* sgetl() accessed */
123 118 } Arf_5;
124 119
125 120 typedef struct { /* Portable (6.0) ar format: vax family; 3b family */
126 121 char ar_name[16]; /* Space terminated */
127 122 /* left-adjusted fields; decimal ascii; blank filled */
128 123 char ar_date[12];
129 124 char ar_uid[6];
130 125 char ar_gid[6];
131 126 char ar_mode[8]; /* octal ascii */
132 127 char ar_size[10];
133 128 /* special end-of-header string (AR_PORT_END_MAGIC) */
134 129 char ar_fmag[2];
135 130 } Ar_port;
136 131
137 132 enum ar_type {
138 133 AR_5,
139 134 AR_PORT
140 135 };
141 136
142 137 typedef unsigned int ar_port_word; // must be 4-bytes long
143 138
144 139 typedef struct {
145 140 FILE *fd;
146 141 /* to distiguish ar format */
147 142 enum ar_type type;
148 143 /* where first ar member header is at */
149 144 long first_ar_mem;
150 145 /* where the symbol lookup starts */
151 146 long sym_begin;
152 147 /* the number of symbols available */
153 148 long num_symbols;
154 149 /* length of symbol directory file */
155 150 long sym_size;
156 151 Arh_5 arh_5;
157 152 Ars_5 ars_5;
158 153 Arf_5 arf_5;
159 154 Ar_port ar_port;
160 155 } Ar;
161 156
162 157 /*
163 158 * Static variables
164 159 */
165 160
166 161 /*
167 162 * File table of contents
168 163 */
169 164 extern timestruc_t& read_archive(register Name target);
170 165 static Boolean open_archive(char *filename, register Ar *arp);
171 166 static void close_archive(register Ar *arp);
172 167 static Boolean read_archive_dir(register Ar *arp, Name library, char **long_names_table);
173 168 static void translate_entry(register Ar *arp, Name target, register Property member, char **long_names_table);
174 169 static long sgetl(char *);
175 170
176 171 /*
177 172 * read_archive(target)
178 173 *
179 174 * Read the contents of an ar file.
180 175 *
181 176 * Return value:
182 177 * The time the member was created
183 178 *
184 179 * Parameters:
185 180 * target The member to find time for
186 181 *
187 182 * Global variables used:
188 183 * empty_name The Name ""
189 184 */
190 185
191 186 int read_member_header (Ar_port *header, FILE *fd, char* filename);
192 187 int process_long_names_member (register Ar *arp, char **long_names_table, char *filename);
193 188
194 189 timestruc_t&
195 190 read_archive(register Name target)
196 191 {
197 192 register Property member;
198 193 wchar_t *slash;
199 194 String_rec true_member_name;
200 195 wchar_t buffer[STRING_BUFFER_LENGTH];
201 196 register Name true_member = NULL;
202 197 Ar ar;
203 198 char *long_names_table = NULL; /* Table of long
204 199 member names */
205 200
206 201 member = get_prop(target->prop, member_prop);
207 202 /*
208 203 * Check if the member has directory component.
209 204 * If so, remove the dir and see if we know the date.
210 205 */
211 206 if (member->body.member.member != NULL) {
212 207 Wstring member_string(member->body.member.member);
213 208 wchar_t * wcb = member_string.get_string();
214 209 if((slash = (wchar_t *) wsrchr(wcb, (int) slash_char)) != NULL) {
215 210 INIT_STRING_FROM_STACK(true_member_name, buffer);
216 211 append_string(member->body.member.library->string_mb,
217 212 &true_member_name,
218 213 FIND_LENGTH);
219 214 append_char((int) parenleft_char, &true_member_name);
220 215 append_string(slash + 1, &true_member_name, FIND_LENGTH);
221 216 append_char((int) parenright_char, &true_member_name);
222 217 true_member = GETNAME(true_member_name.buffer.start,
223 218 FIND_LENGTH);
224 219 if (true_member->stat.time != file_no_time) {
225 220 target->stat.time = true_member->stat.time;
226 221 return target->stat.time;
227 222 }
228 223 }
229 224 }
230 225 if (open_archive(member->body.member.library->string_mb, &ar) == failed) {
231 226 if (errno == ENOENT) {
232 227 target->stat.stat_errno = ENOENT;
233 228 close_archive(&ar);
234 229 if (member->body.member.member == NULL) {
235 230 member->body.member.member = empty_name;
236 231 }
237 232 return target->stat.time = file_doesnt_exist;
238 233 } else {
239 234 fatal(catgets(catd, 1, 1, "Can't access archive `%s': %s"),
240 235 member->body.member.library->string_mb,
241 236 errmsg(errno));
242 237 }
243 238 }
244 239 if (target->stat.time == file_no_time) {
245 240 if (read_archive_dir(&ar, member->body.member.library,
246 241 &long_names_table)
247 242 == failed){
248 243 fatal(catgets(catd, 1, 2, "Can't access archive `%s': %s"),
249 244 member->body.member.library->string_mb,
250 245 errmsg(errno));
251 246 }
252 247 }
253 248 if (member->body.member.entry != NULL) {
254 249 translate_entry(&ar, target, member,&long_names_table);
255 250 }
256 251 close_archive(&ar);
257 252 if (long_names_table) {
258 253 retmem_mb(long_names_table);
259 254 }
260 255 if (true_member != NULL) {
261 256 target->stat.time = true_member->stat.time;
262 257 }
263 258 if (target->stat.time == file_no_time) {
264 259 target->stat.time = file_doesnt_exist;
265 260 }
266 261 return target->stat.time;
267 262 }
268 263
269 264 /*
270 265 * open_archive(filename, arp)
271 266 *
272 267 * Return value:
273 268 * Indicates if open failed or not
274 269 *
275 270 * Parameters:
276 271 * filename The name of the archive we need to read
277 272 * arp Pointer to ar file description block
278 273 *
279 274 * Global variables used:
280 275 */
281 276 static Boolean
282 277 open_archive(char *filename, register Ar *arp)
283 278 {
284 279 int fd;
285 280 char mag_5[AR_5_MAGIC_LENGTH];
286 281 char mag_port[AR_PORT_MAGIC_LENGTH];
287 282 char buffer[4];
288 283
289 284 arp->fd = NULL;
290 285 fd = open_vroot(filename, O_RDONLY, 0, NULL, VROOT_DEFAULT);
291 286 if ((fd < 0) || ((arp->fd = fdopen(fd, "r")) == NULL)) {
292 287 return failed;
293 288 }
294 289 (void) fcntl(fileno(arp->fd), F_SETFD, 1);
295 290
296 291 #if !defined(SUN5_0) && !defined(linux) //XXX
297 292 /* Read enough of the archive to distinguish between the formats */
298 293 if (fread(mag_5, AR_5_MAGIC_LENGTH, 1, arp->fd) != 1) {
299 294 return failed;
300 295 }
301 296 if (IS_EQUALN(mag_5, AR_5_MAGIC, AR_5_MAGIC_LENGTH)) {
302 297 arp->type = AR_5;
303 298 /* Must read in header to set necessary info */
304 299 if (fseek(arp->fd, 0L, 0) != 0 ||
305 300 fread((char *) &arp->arh_5, sizeof (Arh_5), 1, arp->fd) !=
306 301 1) {
307 302 return failed;
308 303 }
309 304 arp->sym_begin = ftell(arp->fd);
310 305 arp->num_symbols = sgetl(arp->arh_5.ar_syms);
311 306 arp->first_ar_mem = arp->sym_begin +
312 307 sizeof (Ars_5) * arp->num_symbols;
313 308 arp->sym_size = 0L;
314 309 return succeeded;
315 310 }
316 311 if (fseek(arp->fd, 0L, 0) != 0) {
317 312 return failed;
318 313 }
319 314 #endif
320 315 if (fread(mag_port, AR_PORT_MAGIC_LENGTH, 1, arp->fd) != 1) {
321 316 return failed;
322 317 }
323 318 if (IS_EQUALN(mag_port, AR_PORT_MAGIC, AR_PORT_MAGIC_LENGTH)) {
324 319 arp->type = AR_PORT;
325 320 /*
326 321 * Read in first member header to find out if there is
327 322 * a symbol definition table.
328 323 */
329 324
330 325 int ret = read_member_header(&arp->ar_port, arp->fd, filename);
331 326 if (ret == failed) {
332 327 return failed;
333 328 } else if(ret == -1) {
334 329 /* There is no member header - empty archive */
335 330 arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
336 331 arp->first_ar_mem = ftell(arp->fd);
337 332 return succeeded;
338 333 }
339 334 /*
340 335 * The following values are the default if there is
341 336 * no symbol directory and long member names.
342 337 */
343 338 arp->sym_size = arp->num_symbols = arp->sym_begin = 0L;
344 339 arp->first_ar_mem = ftell(arp->fd) - (long) sizeof (Ar_port);
345 340
346 341 /*
347 342 * Do we have a symbol table? A symbol table is always
348 343 * the first member in an archive. In 4.1.x it has the
349 344 * name __.SYMDEF, in SVr4, it has the name "/ "
350 345 */
351 346 /*
352 347 #ifdef SUN5_0
353 348 MBSTOWCS(wcs_buffer, NOCATGETS("/ "));
354 349 if (IS_WEQUALN(arp->ar_port.ar_name, wcs_buffer, 16)) {
355 350 #else
356 351 MBSTOWCS(wcs_buffer, NOCATGETS("__.SYMDEF "));
357 352 if (IS_WEQUALN(arp->ar_port.ar_name, wcs_buffer, 16)) {
358 353 #endif
359 354 */
360 355 #if defined(SUN5_0) || defined(HP_UX) || defined(linux)
361 356 if (IS_EQUALN(arp->ar_port.ar_name,
362 357 NOCATGETS("/ "),
363 358 16)) {
364 359 #else
365 360 if (IS_EQUALN(arp->ar_port.ar_name,
366 361 NOCATGETS("__.SYMDEF "),
367 362 16)) {
368 363 #endif
369 364 if (sscanf(arp->ar_port.ar_size,
370 365 "%ld",
371 366 &arp->sym_size) != 1) {
372 367 return failed;
373 368 }
374 369 arp->sym_size += (arp->sym_size & 1); /* round up */
375 370 if (fread(buffer, sizeof buffer, 1, arp->fd) != 1) {
376 371 return failed;
377 372 }
378 373 arp->num_symbols = sgetl(buffer);
379 374 arp->sym_begin = ftell(arp->fd);
380 375 arp->first_ar_mem = arp->sym_begin +
381 376 arp->sym_size - sizeof buffer;
382 377 }
383 378 return succeeded;
384 379 }
385 380 fatal(catgets(catd, 1, 3, "`%s' is not an archive"), filename);
386 381 /* NOTREACHED */
387 382 return failed;
388 383 }
389 384
390 385
391 386 /*
392 387 * close_archive(arp)
393 388 *
394 389 * Parameters:
395 390 * arp Pointer to ar file description block
396 391 *
397 392 * Global variables used:
398 393 */
399 394 static void
400 395 close_archive(register Ar *arp)
401 396 {
402 397 if (arp->fd != NULL) {
403 398 (void) fclose(arp->fd);
404 399 }
405 400 }
406 401
407 402 /*
408 403 * read_archive_dir(arp, library, long_names_table)
409 404 *
410 405 * Reads the directory of an archive and enters all
411 406 * the members into the make symboltable in lib(member) format
412 407 * with their dates.
413 408 *
414 409 * Parameters:
415 410 * arp Pointer to ar file description block
416 411 * library Name of lib to enter members for.
417 412 * Used to form "lib(member)" string.
418 413 * long_names_table table that contains list of members
419 414 * with names > 15 characters long
420 415 *
421 416 * Global variables used:
422 417 */
423 418 static Boolean
424 419 #if defined(SUN5_0) || defined(linux) //XXX
425 420 read_archive_dir(register Ar *arp, Name library, char **long_names_table)
426 421 #else
427 422 read_archive_dir(register Ar *arp, Name library, char **)
428 423 #endif
429 424 {
430 425 wchar_t *name_string;
431 426 wchar_t *member_string;
432 427 register long len;
433 428 register wchar_t *p;
434 429 register char *q;
435 430 register Name name;
436 431 Property member;
437 432 long ptr;
438 433 long date;
439 434
440 435 #if defined(SUN5_0) || defined(linux) //XXX
441 436 int offset;
442 437
443 438 /*
444 439 * If any of the members has a name > 15 chars,
445 440 * it will be found here.
446 441 */
447 442 if (process_long_names_member(arp, long_names_table, library->string_mb) == failed) {
448 443 return failed;
449 444 }
450 445 #endif
451 446 name_string = ALLOC_WC((int) (library->hash.length +
452 447 (int) ar_member_name_len * 2));
453 448 (void) mbstowcs(name_string, library->string_mb, (int) library->hash.length);
454 449 member_string = name_string + library->hash.length;
455 450 *member_string++ = (int) parenleft_char;
456 451
457 452 if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) {
458 453 goto read_error;
459 454 }
460 455 /* Read the directory using the appropriate format */
461 456 switch (arp->type) {
462 457 case AR_5:
463 458 for (;;) {
464 459 if (fread((char *) &arp->arf_5, sizeof arp->arf_5, 1, arp->fd)
465 460 != 1) {
466 461 if (feof(arp->fd)) {
467 462 return succeeded;
468 463 }
469 464 break;
470 465 }
471 466 len = sizeof arp->arf_5.arf_name;
472 467 for (p = member_string, q = arp->arf_5.arf_name;
473 468 (len > 0) && (*q != (int) nul_char) && !isspace(*q);
474 469 ) {
475 470 MBTOWC(p, q);
476 471 p++;
477 472 q++;
478 473 }
479 474 *p++ = (int) parenright_char;
480 475 *p = (int) nul_char;
481 476 name = GETNAME(name_string, FIND_LENGTH);
482 477 /*
483 478 * [tolik] Fix for dmake bug 1234018.
484 479 * If name->stat.time is already set, then it should not
485 480 * be changed. (D)make propogates time stamp for one
486 481 * member, and when it calls exists() for another member,
487 482 * the first one may be changed.
488 483 */
489 484 if(name->stat.time == file_no_time) {
490 485 name->stat.time.tv_sec = sgetl(arp->arf_5.arf_date);
491 486 name->stat.time.tv_nsec = LONG_MAX;
492 487 }
493 488 name->is_member = library->is_member;
494 489 member = maybe_append_prop(name, member_prop);
495 490 member->body.member.library = library;
496 491 *--p = (int) nul_char;
497 492 if (member->body.member.member == NULL) {
498 493 member->body.member.member =
499 494 GETNAME(member_string, FIND_LENGTH);
500 495 }
501 496 ptr = sgetl(arp->arf_5.arf_size);
502 497 ptr += (ptr & 1);
503 498 if (fseek(arp->fd, ptr, 1) != 0) {
504 499 goto read_error;
505 500 }
506 501 }
507 502 break;
508 503 case AR_PORT:
509 504 for (;;) {
510 505 if ((fread((char *) &arp->ar_port,
511 506 sizeof arp->ar_port,
512 507 1,
513 508 arp->fd) != 1) ||
514 509 !IS_EQUALN(arp->ar_port.ar_fmag,
515 510 AR_PORT_END_MAGIC,
516 511 sizeof arp->ar_port.ar_fmag)) {
517 512 if (feof(arp->fd)) {
518 513 return succeeded;
519 514 }
520 515 fatal(
521 516 catgets(catd, 1, 28, "Read error in archive `%s': invalid archive file member header at 0x%x"),
522 517 library->string_mb,
523 518 ftell(arp->fd)
524 519 );
525 520 }
526 521 #if defined(SUN5_0) || defined(linux) //XXX
527 522 /* If it's a long name, retrieve it from long name table */
528 523 if (arp->ar_port.ar_name[0] == '/') {
529 524 /*
530 525 * "len" is used for hashing the string.
531 526 * We're using "ar_member_name_len" instead of
532 527 * the actual name length since it's the longest
533 528 * string the "ar" command can handle at this
534 529 * point.
535 530 */
536 531 len = ar_member_name_len;
537 532 sscanf(arp->ar_port.ar_name + 1,
538 533 "%ld",
539 534 &offset);
540 535 q = *long_names_table + offset;
541 536 } else {
542 537 q = arp->ar_port.ar_name;
543 538 len = sizeof arp->ar_port.ar_name;
544 539 }
545 540 #else
546 541 q = arp->ar_port.ar_name;
547 542 len = sizeof arp->ar_port.ar_name;
548 543 #endif
549 544
550 545 for (p = member_string;
551 546 (len > 0) &&
552 547 (*q != (int) nul_char) &&
553 548 !isspace(*q) &&
554 549 (*q != (int) slash_char);
555 550 ) {
556 551 MBTOWC(p, q);
557 552 p++;
558 553 q++;
559 554 }
560 555 *p++ = (int) parenright_char;
561 556 *p = (int) nul_char;
562 557 name = GETNAME(name_string, FIND_LENGTH);
563 558 name->is_member = library->is_member;
564 559 member = maybe_append_prop(name, member_prop);
565 560 member->body.member.library = library;
566 561 *--p = (int) nul_char;
567 562 if (member->body.member.member == NULL) {
568 563 member->body.member.member =
569 564 GETNAME(member_string, FIND_LENGTH);
570 565 }
571 566 if (sscanf(arp->ar_port.ar_date, "%ld", &date) != 1) {
572 567 WCSTOMBS(mbs_buffer, name_string);
573 568 fatal(catgets(catd, 1, 4, "Bad date field for member `%s' in archive `%s'"),
574 569 mbs_buffer,
575 570 library->string_mb);
576 571 }
577 572 /*
578 573 * [tolik] Fix for dmake bug 1234018.
579 574 */
580 575 if(name->stat.time == file_no_time) {
581 576 name->stat.time.tv_sec = date;
582 577 name->stat.time.tv_nsec = LONG_MAX;
583 578 }
584 579 if (sscanf(arp->ar_port.ar_size, "%ld", &ptr) != 1) {
585 580 WCSTOMBS(mbs_buffer, name_string);
586 581 fatal(catgets(catd, 1, 5, "Bad size field for member `%s' in archive `%s'"),
587 582 mbs_buffer,
588 583 library->string_mb);
589 584 }
590 585 ptr += (ptr & 1);
591 586 if (fseek(arp->fd, ptr, 1) != 0) {
592 587 goto read_error;
593 588 }
594 589 }
595 590 break;
596 591 }
597 592
598 593 /* Only here if fread() [or IS_EQUALN()] failed and not at EOF */
599 594 read_error:
600 595 fatal(catgets(catd, 1, 6, "Read error in archive `%s': %s"),
601 596 library->string_mb,
602 597 errmsg(errno));
603 598 /* NOTREACHED */
604 599 }
605 600
606 601
607 602 /*
608 603 * process_long_names_member(arp)
609 604 *
610 605 * If the archive contains members with names longer
611 606 * than 15 characters, then it has a special member
612 607 * with the name "// " that contains a table
613 608 * of null-terminated long names. This member
614 609 * is always the first member, after the symbol table
615 610 * if it exists.
616 611 *
617 612 * Parameters:
618 613 * arp Pointer to ar file description block
619 614 *
620 615 * Global variables used:
621 616 */
622 617 int
623 618 process_long_names_member(register Ar *arp, char **long_names_table, char *filename)
624 619 {
625 620 Ar_port *ar_member_header;
626 621 int table_size;
627 622
628 623 if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) {
629 624 return failed;
630 625 }
631 626 if ((ar_member_header =
632 627 (Ar_port *) alloca((int) sizeof(Ar_port))) == NULL){
633 628 perror(catgets(catd, 1, 7, "memory allocation failure"));
634 629 return failed;
635 630 }
636 631 int ret = read_member_header(ar_member_header, arp->fd, filename);
637 632 if (ret == failed) {
638 633 return failed;
639 634 } else if(ret == -1) {
640 635 /* There is no member header - empty archive */
641 636 return succeeded;
642 637 }
643 638 /* Do we have special member containing long names? */
644 639 if (IS_EQUALN(ar_member_header->ar_name,
645 640 NOCATGETS("// "),
646 641 16)){
647 642 if (sscanf(ar_member_header->ar_size,
648 643 "%ld",
649 644 &table_size) != 1) {
650 645 return failed;
651 646 }
652 647 *long_names_table = (char *) malloc(table_size);
653 648 /* Read the list of long member names into the table */
654 649 if (fread(*long_names_table, table_size, 1, arp->fd) != 1) {
655 650 return failed;
656 651 }
657 652 arp->first_ar_mem = ftell(arp->fd);
658 653 }
659 654 return succeeded;
660 655 }
661 656
662 657 /*
663 658 * translate_entry(arp, target, member)
664 659 *
665 660 * Finds the member for one lib.a((entry))
666 661 *
667 662 * Parameters:
668 663 * arp Pointer to ar file description block
669 664 * target Target to find member name for
670 665 * member Property to fill in with info
671 666 *
672 667 * Global variables used:
673 668 */
674 669 static void
675 670 translate_entry(register Ar *arp, Name target, register Property member, char **long_names_table)
676 671 {
677 672 register int len;
678 673 register int i;
679 674 wchar_t *member_string;
680 675 ar_port_word *offs;
681 676 int strtablen;
682 677 char *syms; /* string table */
683 678 char *csym; /* string table */
684 679 ar_port_word *offend; /* end of offsets table */
685 680 int date;
686 681 register wchar_t *ap;
687 682 register char *hp;
688 683 int maxs;
689 684 int offset;
690 685 char buffer[4];
691 686
692 687 if (arp->sym_begin == 0L || arp->num_symbols == 0L) {
693 688 fatal(catgets(catd, 1, 8, "Cannot find symbol `%s' in archive `%s'"),
694 689 member->body.member.entry->string_mb,
695 690 member->body.member.library->string_mb);
696 691 }
697 692
698 693 if (fseek(arp->fd, arp->sym_begin, 0) != 0) {
699 694 goto read_error;
700 695 }
701 696 member_string = ALLOC_WC((int) ((int) ar_member_name_len * 2));
702 697
703 698 switch (arp->type) {
704 699 case AR_5:
705 700 if ((len = member->body.member.entry->hash.length) > 8) {
706 701 len = 8;
707 702 }
708 703 for (i = 0; i < arp->num_symbols; i++) {
709 704 if (fread((char *) &arp->ars_5,
710 705 sizeof arp->ars_5,
711 706 1,
712 707 arp->fd) != 1) {
713 708 goto read_error;
714 709 }
715 710 if (IS_EQUALN(arp->ars_5.sym_name,
716 711 member->body.member.entry->string_mb,
717 712 len)) {
718 713 if ((fseek(arp->fd,
719 714 sgetl(arp->ars_5.sym_ptr),
720 715 0) != 0) ||
721 716 (fread((char *) &arp->arf_5,
722 717 sizeof arp->arf_5,
723 718 1,
724 719 arp->fd) != 1)) {
725 720 goto read_error;
726 721 }
727 722 MBSTOWCS(wcs_buffer, arp->arf_5.arf_name);
728 723 (void) wsncpy(member_string,
729 724 wcs_buffer,
730 725 wslen(wcs_buffer));
731 726 member_string[sizeof(arp->arf_5.arf_name)] =
732 727 (int) nul_char;
733 728 member->body.member.member =
734 729 GETNAME(member_string, FIND_LENGTH);
735 730 target->stat.time.tv_sec = sgetl(arp->arf_5.arf_date);
736 731 target->stat.time.tv_nsec = LONG_MAX;
737 732 return;
738 733 }
739 734 }
740 735 break;
741 736 case AR_PORT:
742 737 offs = (ar_port_word *) alloca((int) (arp->num_symbols * AR_PORT_WORD));
743 738 if (fread((char *) offs,
744 739 AR_PORT_WORD,
745 740 (int) arp->num_symbols,
746 741 arp->fd) != arp->num_symbols) {
747 742 goto read_error;
748 743 }
749 744
750 745 for(i=0;i<arp->num_symbols;i++) {
751 746 *((int*)buffer)=offs[i];
752 747 offs[i]=(ar_port_word)sgetl(buffer);
753 748 }
754 749
755 750 strtablen=arp->sym_size-4-(int) (arp->num_symbols * AR_PORT_WORD);
756 751 syms = (char *) alloca(strtablen);
757 752 if (fread(syms,
758 753 sizeof (char),
759 754 strtablen,
760 755 arp->fd) != strtablen) {
761 756 goto read_error;
762 757 }
763 758 offend = &offs[arp->num_symbols];
764 759 while (offs < offend) {
765 760 maxs = strlen(member->body.member.entry->string_mb);
766 761 if(strlen(syms) > maxs)
767 762 maxs = strlen(syms);
768 763 if (IS_EQUALN(syms,
769 764 member->body.member.entry->string_mb,
770 765 maxs)) {
771 766 if (fseek(arp->fd,
772 767 (long) *offs,
773 768 0) != 0) {
774 769 goto read_error;
775 770 }
776 771 if ((fread((char *) &arp->ar_port,
777 772 sizeof arp->ar_port,
778 773 1,
779 774 arp->fd) != 1) ||
780 775 !IS_EQUALN(arp->ar_port.ar_fmag,
781 776 AR_PORT_END_MAGIC,
782 777 sizeof arp->ar_port.ar_fmag)) {
783 778 goto read_error;
784 779 }
785 780 if (sscanf(arp->ar_port.ar_date,
786 781 "%ld",
787 782 &date) != 1) {
788 783 fatal(catgets(catd, 1, 9, "Bad date field for member `%s' in archive `%s'"),
789 784 arp->ar_port.ar_name,
790 785 target->string_mb);
791 786 }
792 787 #if defined(SUN5_0) || defined(linux) //XXX
793 788 /* If it's a long name, retrieve it from long name table */
794 789 if (arp->ar_port.ar_name[0] == '/') {
795 790 sscanf(arp->ar_port.ar_name + 1,
796 791 "%ld",
797 792 &offset);
798 793 len = ar_member_name_len;
799 794 hp = *long_names_table + offset;
800 795 } else {
801 796 len = sizeof arp->ar_port.ar_name;
802 797 hp = arp->ar_port.ar_name;
803 798 }
804 799 #else
805 800 hp = arp->ar_port.ar_name;
806 801 #endif
807 802 ap = member_string;
808 803 while (*hp &&
809 804 (*hp != (int) slash_char) &&
810 805 (ap < &member_string[len])) {
811 806 MBTOWC(ap, hp);
812 807 ap++;
813 808 hp++;
814 809 }
815 810 *ap = (int) nul_char;
816 811 member->body.member.member =
817 812 GETNAME(member_string, FIND_LENGTH);
818 813 target->stat.time.tv_sec = date;
819 814 target->stat.time.tv_nsec = LONG_MAX;
820 815 return;
821 816 }
822 817 offs++;
823 818 while(*syms!='\0') syms++;
824 819 syms++;
825 820 }
826 821 }
827 822 fatal(catgets(catd, 1, 10, "Cannot find symbol `%s' in archive `%s'"),
828 823 member->body.member.entry->string_mb,
829 824 member->body.member.library->string_mb);
830 825 /*NOTREACHED*/
831 826
832 827 read_error:
833 828 if (ferror(arp->fd)) {
834 829 fatal(catgets(catd, 1, 11, "Read error in archive `%s': %s"),
835 830 member->body.member.library->string_mb,
836 831 errmsg(errno));
837 832 } else {
838 833 fatal(catgets(catd, 1, 12, "Read error in archive `%s': Premature EOF"),
839 834 member->body.member.library->string_mb);
840 835 }
841 836 }
842 837
843 838 /*
844 839 * sgetl(buffer)
845 840 *
846 841 * The intent here is to provide a means to make the value of
847 842 * bytes in an io-buffer correspond to the value of a long
848 843 * in the memory while doing the io a long at a time.
849 844 * Files written and read in this way are machine-independent.
850 845 *
851 846 * Return value:
852 847 * Long int read from buffer
853 848 * Parameters:
854 849 * buffer buffer we need to read long int from
855 850 *
856 851 * Global variables used:
857 852 */
858 853 static long
859 854 sgetl(register char *buffer)
860 855 {
861 856 register long w = 0;
862 857 register int i = BITSPERBYTE * AR_PORT_WORD;
863 858
864 859 while ((i -= BITSPERBYTE) >= 0) {
865 860 w |= (long) ((unsigned char) *buffer++) << i;
866 861 }
867 862 return w;
868 863 }
869 864
870 865
871 866 /*
872 867 * read_member_header(header, fd, filename)
873 868 *
874 869 * reads the member header for the 4.1.x and SVr4 archives.
875 870 *
876 871 * Return value:
877 872 * fails if read error or member
878 873 * header is not the right format
879 874 * Parameters:
880 875 * header There's one before each archive member
881 876 * fd file descriptor for the archive file.
882 877 *
883 878 * Global variables used:
884 879 */
885 880 int
886 881 read_member_header(Ar_port *header, FILE *fd, char* filename)
887 882 {
888 883 int num = fread((char *) header, sizeof (Ar_port), 1, fd);
889 884 if (num != 1 && feof(fd)) {
890 885 /* There is no member header - empty archive */
891 886 return -1;
892 887 }
893 888 if ((num != 1) ||
894 889 !IS_EQUALN(
895 890 AR_PORT_END_MAGIC,
896 891 header->ar_fmag,
897 892 sizeof (header->ar_fmag)
898 893 )
899 894 ) {
900 895 fatal(
901 896 catgets(catd, 1, 28, "Read error in archive `%s': invalid archive file member header at 0x%x"),
902 897 filename,
903 898 ftell(fd)
904 899 );
905 900 }
906 901 return succeeded;
907 902 }
908 903
↓ open down ↓ |
869 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX