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