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