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