Various noise
[external/binutils.git] / bfd / archive.c
1 /*** archive.c -- an attempt at combining the machine-independent parts of
2   archives */
3
4 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
5
6 This file is part of BFD, the Binary File Diddler.
7
8 BFD is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 1, or (at your option)
11 any later version.
12
13 BFD is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with BFD; see the file COPYING.  If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
21
22
23 /* Assumes:
24    o - all archive elements start on an even boundary, newline padded;
25    o - all arch headers are char *;
26    o - all arch headers are the same size (across architectures).
27 */
28
29 /* $Id$ 
30  * $Log$
31  * Revision 1.2  1991/04/03 22:09:43  steve
32  * Various noise
33  *
34  * Revision 1.1.1.1  1991/03/21  21:10:42  gumby
35  * Back from Intel with Steve
36  *
37  * Revision 1.1  1991/03/21  21:10:42  gumby
38  * Initial revision
39  *
40  * Revision 1.3  1991/03/16  05:55:25  rich
41  * pop
42  *
43  * Revision 1.2  1991/03/15  18:15:50  rich
44  * *** empty log message ***
45  *
46  * Revision 1.7  1991/03/08  04:18:02  rich
47  * *** empty log message ***
48  *
49  * Revision 1.6  1991/03/07  21:55:31  sac
50  * Added primitive file caching, a file open only for input and
51  * less than BFD_INCORE_FILE_SIZE will be malloced and read in
52  * only once.
53  *
54  * Revision 1.5  1991/03/05  16:31:12  sac
55  * lint
56  *
57  */
58
59
60 #include "sysdep.h"
61 #include "bfd.h"
62 #include "libbfd.h"
63 #include "ar.h"
64 #include "ranlib.h"
65
66 /* We keep a cache of archive filepointers to archive elements to
67    speed up searching the archive by filepos.  We only add an entry to
68    the cache when we actually read one.  We also don't sort the cache;
69    it's short enough to search linearly.
70    Note that the pointers here point to the front of the ar_hdr, not
71    to the front of the contents!
72 */
73 struct ar_cache {
74   file_ptr ptr;
75   bfd* arelt;
76   struct ar_cache *next;
77 };
78
79 #define ar_padchar(abfd) ((abfd)->xvec->ar_pad_char)
80 #define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen)
81
82 #define arch_hdr(bfd) ((struct ar_hdr *)   \
83                        (((struct areltdata *)((bfd)->arelt_data))->arch_header))
84
85 \f
86
87 boolean
88 _bfd_generic_mkarchive (abfd)
89      bfd *abfd;
90 {
91   abfd->tdata =(void *) zalloc (sizeof (struct artdata));
92
93   if (abfd->tdata == NULL) {
94     bfd_error = no_memory;
95     return false;
96   }
97 bfd_ardata(abfd)->cache = 0;
98   return true;
99 }
100
101 symindex
102 bfd_get_next_mapent (abfd, prev, entry)
103      bfd *abfd;
104    symindex prev;
105      carsym **entry;
106 {
107   if (!bfd_has_map (abfd)) {
108     bfd_error = invalid_operation;
109     return BFD_NO_MORE_SYMBOLS;
110   }
111   
112   if (prev == BFD_NO_MORE_SYMBOLS) prev = 0;
113   else if (++prev >= (symindex)(bfd_ardata (abfd)->symdef_count))
114     return BFD_NO_MORE_SYMBOLS;
115
116   *entry = (bfd_ardata (abfd)->symdefs + prev);
117   return prev;
118 }
119
120
121 /* To be called by backends only */
122 bfd *
123 _bfd_create_empty_archive_element_shell (obfd)
124      bfd *obfd;
125 {
126   bfd *nbfd;
127
128   nbfd = new_bfd_contained_in(obfd);
129   if (nbfd == NULL) {
130     bfd_error = no_memory;
131     return NULL;
132   }
133   return nbfd;
134 }
135
136 boolean
137 bfd_set_archive_head (output_archive, new_head)
138      bfd *output_archive, *new_head;
139 {
140  
141   output_archive->archive_head = new_head;
142   return true;
143 }
144
145 bfd *
146 look_for_bfd_in_cache (arch_bfd, filepos)
147      bfd *arch_bfd;
148      file_ptr filepos;
149 {
150   struct ar_cache *current;
151
152   for (current = bfd_ardata (arch_bfd)->cache; current != NULL;
153        current = current->next)
154     if (current->ptr == filepos) return current->arelt;
155
156   return NULL;
157 }
158
159 /* Kind of stupid to call cons for each one, but we don't do too many */
160 boolean
161 add_bfd_to_cache (arch_bfd, filepos, new_elt)
162      bfd *arch_bfd, *new_elt;
163      file_ptr filepos;
164 {
165   struct ar_cache *new_cache = ((struct ar_cache *)
166                                 zalloc (sizeof (struct ar_cache)));
167
168   if (new_cache == NULL) {
169     bfd_error = no_memory;
170     return false;
171   }
172
173   new_cache->ptr = filepos;
174   new_cache->arelt = new_elt;
175   new_cache->next = (struct ar_cache *)NULL;
176   if (bfd_ardata (arch_bfd)->cache == NULL)
177     bfd_ardata (arch_bfd)->cache = new_cache;
178   else {
179     struct ar_cache *current = bfd_ardata (arch_bfd)->cache;
180
181     for (; current->next != NULL; current = current->next);
182     current->next = new_cache;
183   }
184     
185   return true;
186 }
187
188 \f
189
190 /* The name begins with space.  Hence the rest of the name is an index into
191    the string table. */
192
193 char *
194 get_extended_arelt_filename (arch, name)
195      bfd *arch;
196      char *name;
197 {
198     extern int errno;
199     unsigned long index = 0;
200
201     /* Should extract string so that I can guarantee not to overflow into
202        the next region, but I"m too lazy. */
203     errno = 0;
204     index = strtol (name, NULL, 10);
205     if (errno != 0) {
206         bfd_error = malformed_archive;
207         return NULL;
208     }
209
210     return bfd_ardata (arch)->extended_names + index;
211 }  
212
213 /* This functions reads an arch header and returns an areltdata pointer, or
214    NULL on error.
215
216    Presumes the file pointer is already in the right place (ie pointing
217    to the ar_hdr in the file).   Moves the file pointer; on success it
218    should be pointing to the front of the file contents; on failure it
219    could have been moved arbitrarily.
220 */
221
222 struct areltdata *
223 snarf_ar_hdr (abfd)
224      bfd *abfd;
225 {
226     extern int errno;
227     struct ar_hdr hdr;
228     char *hdrp = (char *) &hdr;
229     unsigned int parsed_size;
230     struct areltdata *ared;
231     char *filename = NULL;
232     unsigned int namelen = 0;
233     unsigned int allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
234     char *allocptr;
235
236     if (bfd_read ((void *)hdrp, 1, sizeof (struct ar_hdr), abfd)
237         != sizeof (struct ar_hdr)) {
238         bfd_error = no_more_archived_files;
239         return NULL;
240     }
241     if (strncmp ((hdr.ar_fmag), ARFMAG, 2)) {
242         bfd_error = malformed_archive;
243         return NULL;
244     }
245
246     errno = 0;
247     parsed_size = strtol (hdr.ar_size, NULL, 10);
248     if (errno != 0) {
249         bfd_error = malformed_archive;
250         return NULL;
251     }
252
253     /* extract the filename from the archive */
254     if (hdr.ar_name[0] == ' ' && bfd_ardata (abfd)->extended_names != NULL) {
255         filename = get_extended_arelt_filename (abfd, hdr.ar_name);
256         if (filename == NULL) {
257             bfd_error = malformed_archive;
258             return NULL;
259         }
260     } 
261     else 
262         {
263             /* We judge the end of the name by looking for a space or a
264                padchar */
265
266             namelen = 0;
267
268             while (namelen < (unsigned)ar_maxnamelen(abfd) &&
269                    ( hdr.ar_name[namelen] != 0 &&
270                     hdr.ar_name[namelen] != ' ' &&
271                     hdr.ar_name[namelen] != ar_padchar(abfd))) {
272                 namelen++;
273             }
274
275             allocsize += namelen + 1;
276         }
277
278     allocptr = zalloc (allocsize);
279     if (allocptr == NULL) {
280         bfd_error = no_memory;
281         return NULL;
282     }
283
284     ared = (struct areltdata *) allocptr;
285
286     ared->arch_header = allocptr + sizeof (struct areltdata);
287     memcpy ((char *) ared->arch_header, &hdr, sizeof (struct ar_hdr));
288     ared->parsed_size = parsed_size;
289
290     if (filename != NULL) ared->filename = filename;
291     else {
292         ared->filename = allocptr + (sizeof (struct areltdata) +
293                                      sizeof (struct ar_hdr));
294         if (namelen)
295             memcpy (ared->filename, hdr.ar_name, namelen);
296         ared->filename[namelen] = '\0';
297     }
298   
299     return ared;
300 }
301 \f
302 bfd *
303 get_elt_at_filepos (archive, filepos)
304      bfd *archive;
305      file_ptr filepos;
306 {
307   struct areltdata *new_areldata;
308   bfd *n_nfd;
309
310   n_nfd = look_for_bfd_in_cache (archive, filepos);
311   if (n_nfd) return n_nfd;
312
313   if (0 > bfd_seek (archive, filepos, SEEK_SET)) {
314     bfd_error = system_call_error;
315     return NULL;
316   }
317
318   if ((new_areldata = snarf_ar_hdr (archive)) == NULL) return NULL;
319   
320   n_nfd = _bfd_create_empty_archive_element_shell (archive);
321   if (n_nfd == NULL) {
322     free (new_areldata);
323     return NULL;
324   }
325   n_nfd->origin = bfd_tell (archive);
326   n_nfd->arelt_data = (void *) new_areldata;
327   n_nfd->filename = new_areldata->filename;
328
329   if (add_bfd_to_cache (archive, filepos, n_nfd))
330     return n_nfd;
331
332   /* huh? */
333   free (new_areldata);
334   free (n_nfd);
335   return NULL;
336 }
337
338 bfd *
339 bfd_get_elt_at_index (abfd, index)
340      bfd *abfd;
341      int index;
342 {
343   bfd *result =
344     get_elt_at_filepos
345       (abfd, (bfd_ardata (abfd)->symdefs + index)->file_offset);
346   return result;
347 }
348
349 /* If you've got an archive, call this to read each subfile. */
350 bfd *
351 bfd_openr_next_archived_file (archive, last_file)
352      bfd *archive, *last_file;
353 {
354
355   if ((bfd_get_format (archive) != bfd_archive) ||
356       (archive->direction == write_direction)) {
357     bfd_error = invalid_operation;
358     return NULL;
359   }
360
361
362   return BFD_SEND (archive,
363                    openr_next_archived_file,
364                    (archive,
365                     last_file));
366
367 }
368
369 bfd *bfd_generic_openr_next_archived_file(archive, last_file)
370      bfd *archive;
371      bfd *last_file;
372 {
373   file_ptr filestart;
374
375   if (!last_file)
376     filestart = bfd_ardata (archive)->first_file_filepos;
377   else {
378   unsigned int size = arelt_size(last_file);
379     filestart = last_file->origin +size + size %2;
380 }
381
382
383
384   return get_elt_at_filepos (archive, filestart);
385 }
386 \f
387
388 bfd_target *
389 bfd_generic_archive_p (abfd)
390      bfd *abfd;
391 {
392   char armag[SARMAG+1];
393
394   if (bfd_read ((void *)armag, 1, SARMAG, abfd) != SARMAG) {
395     bfd_error = wrong_format;
396     return 0;
397   }
398
399   if (strncmp (armag, ARMAG, SARMAG)) return 0;
400
401   bfd_set_ardata(abfd, (struct artdata *) zalloc (sizeof (struct artdata)));
402
403   if (bfd_ardata (abfd)  == NULL) {
404     bfd_error = no_memory;
405     return 0;
406   }
407
408   bfd_ardata (abfd)->first_file_filepos = SARMAG;
409   
410   if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))) {
411     free (bfd_ardata (abfd));
412     abfd->tdata = NULL;
413     return 0;
414   }
415
416   /* armap could be left ungc'd! FIXME -- potential storage leak */
417   if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd))) {
418     free (bfd_ardata (abfd));
419     abfd->tdata = NULL;
420     return 0;
421   }
422   
423   return abfd->xvec;
424 }
425
426 /* Returns false on error, true otherwise */
427 boolean
428 bfd_slurp_bsd_armap (abfd)
429      bfd *abfd;
430 {
431   struct areltdata *mapdata;
432   char nextname[17];
433   unsigned int counter = 0;
434   int *raw_armap, *rbase;
435   struct artdata *ardata = bfd_ardata (abfd);
436   char *stringbase;
437
438   if (bfd_read ((void *)nextname, 1, 16, abfd) == 16) {
439       /* The archive has at least 16 bytes in it */
440       bfd_seek (abfd, -16L, SEEK_CUR);
441
442       if (strncmp (nextname, "__.SYMDEF       ", 16)) {
443           bfd_has_map (abfd) = false;
444           return true;
445       }
446
447       mapdata = snarf_ar_hdr (abfd);
448       if (mapdata == NULL) return false;
449
450       raw_armap = (int *) zalloc (mapdata->parsed_size);
451       if (raw_armap == NULL) {
452           bfd_error = no_memory;
453   byebye:
454           free (mapdata);
455           return false;
456       }
457
458       if (bfd_read ((void *)raw_armap, 1, mapdata->parsed_size, abfd) !=
459           mapdata->parsed_size) {
460           bfd_error = malformed_archive;
461           free (raw_armap);
462           goto byebye;
463       }
464
465       ardata->symdef_count = *(raw_armap) / sizeof (struct symdef);
466       ardata->cache = 0;
467       rbase = raw_armap+1;
468       ardata->symdefs = (carsym *) rbase;
469       stringbase = ((char *) (ardata->symdefs + ardata->symdef_count)) + 4;
470
471       for (;counter < (unsigned)( ardata->symdef_count); counter++) {
472           struct symdef *sym = ((struct symdef *) rbase) + counter;
473           sym->s.name = sym->s.string_offset + stringbase;
474       }
475   
476       ardata->first_file_filepos = bfd_tell (abfd);
477       /* Pad to an even boundary if you have to */
478       ardata->first_file_filepos += (ardata-> first_file_filepos) %2;
479       free (mapdata);
480       bfd_has_map (abfd) = true;
481   }
482   return true;
483 }
484
485 /* Returns false on error, true otherwise */
486 boolean
487 bfd_slurp_coff_armap (abfd)
488      bfd *abfd;
489 {
490   struct areltdata *mapdata;
491   char nextname;
492   int *raw_armap, *rawptr;
493   struct artdata *ardata = bfd_ardata (abfd);
494   char *stringbase;
495   unsigned int stringsize;
496   carsym *carsyms;
497
498   if (bfd_read ((void *)&nextname, 1, 1, abfd) != 1) {
499     bfd_has_map(abfd) = false;
500     return true;
501   }
502
503   if (nextname != '/') {
504     /* Actually I think this is an error for a COFF archive */
505     bfd_has_map (abfd) = false;
506     return true;
507   }
508
509   bfd_seek (abfd, -1L, SEEK_CUR);
510   mapdata = snarf_ar_hdr (abfd);
511   if (mapdata == NULL) return false;
512
513   raw_armap = (int *) zalloc (mapdata->parsed_size);
514   if (raw_armap == NULL) {
515     bfd_error = no_memory;
516   byebye:
517     free (mapdata);
518     return false;
519   }
520
521   if (bfd_read ((void *)raw_armap, 1, mapdata->parsed_size, abfd) !=
522       mapdata->parsed_size) {
523     bfd_error = malformed_archive;
524   oops:
525     free (raw_armap);
526     goto byebye;
527   }
528
529   /* The coff armap must be read sequentially.  So we construct a bsd-style
530      one in core all at once, for simplicity. */
531
532   stringsize = mapdata->parsed_size - (4 * (*raw_armap)) - 4;
533
534   {
535     unsigned int nsymz = *raw_armap;
536     unsigned int carsym_size = (nsymz * sizeof (carsym));
537     unsigned int ptrsize = (4 * nsymz);
538     unsigned int i;
539     ardata->symdefs = (carsym *) zalloc (carsym_size + stringsize + 1);
540     if (ardata->symdefs == NULL) {
541       bfd_error = no_memory;
542       goto oops;
543     }
544     carsyms = ardata->symdefs;
545
546     stringbase = ((char *) ardata->symdefs) + carsym_size;
547     memcpy (stringbase, (char*)raw_armap + ptrsize + 4,  stringsize);
548
549
550     /* OK, build the carsyms */
551     for (i = 0; i < nsymz; i++) 
552       {
553         rawptr = raw_armap + i + 1;
554         carsyms->file_offset = *rawptr;
555         carsyms->name = stringbase;
556         for (; *(stringbase++););
557         carsyms++;
558       }
559     *stringbase = 0;
560   }
561   ardata->symdef_count = *raw_armap;
562   ardata->first_file_filepos = bfd_tell (abfd);
563   /* Pad to an even boundary if you have to */
564   ardata->first_file_filepos += (ardata->first_file_filepos) %2;
565   free (raw_armap);
566   free (mapdata);
567   bfd_has_map (abfd) = true;
568   return true;
569 }
570
571 \f
572 /** Extended name table.
573
574   Normally archives support only 14-character filenames.  Intel has extended
575   the format: longer names are stored in a special element (the first in the
576   archive, or second if there is an armap); the name in the ar_hdr is replaced
577   by <space><index into filename element>.  Index is the P.R. of an int (radix:
578   8). */
579
580 /* Returns false on error, true otherwise */
581 boolean
582 _bfd_slurp_extended_name_table (abfd)
583      bfd *abfd;
584 {
585   char nextname[17];
586   struct areltdata *namedata;
587
588   if (bfd_read ((void *)nextname, 1, 16, abfd) == 16) {
589
590   bfd_seek (abfd, -16L, SEEK_CUR);
591
592   if (strncmp (nextname, "ARFILENAMES/    ", 16)) {
593     bfd_ardata (abfd)->extended_names = NULL;
594     return true;
595   }
596
597   namedata = snarf_ar_hdr (abfd);
598   if (namedata == NULL) return false;
599   
600   
601   bfd_ardata (abfd)->extended_names = zalloc (namedata->parsed_size);
602   if (bfd_ardata (abfd)->extended_names == NULL) {
603     bfd_error = no_memory;
604   byebye:
605     free (namedata);
606     return false;
607   }
608
609   if (bfd_read ((void*)bfd_ardata (abfd)->extended_names, 1,
610                 namedata->parsed_size, abfd) != namedata->parsed_size) {
611     bfd_error = malformed_archive;
612     free (bfd_ardata (abfd)->extended_names);
613     bfd_ardata (abfd)->extended_names = NULL;
614     goto byebye;
615   }
616
617   /* Pad to an even boundary if you have to */
618   bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
619   bfd_ardata (abfd)->first_file_filepos +=
620     (bfd_ardata (abfd)->first_file_filepos) %2;
621
622   free (namedata);
623 }
624   return true;
625 }
626
627 static
628 char *normalize(file)
629 char *file;
630 {
631     char *    filename = strrchr(file, '/');
632     if (filename != (char *)NULL) {
633         filename ++;
634     }
635     else {
636         filename = file;
637     }
638 return filename;
639 }
640
641 /* Follows archive_head and produces an extended name table if necessary.
642    Returns (in tabloc) a pointer to an extended name table, and in tablen
643    the length of the table.  If it makes an entry it clobbers the filename
644    so that the element may be written without further massage.
645    Returns true if it ran successfully, false if something went wrong.
646    A successful return may still involve a zero-length tablen!
647    */
648 boolean
649 bfd_construct_extended_name_table (abfd, tabloc, tablen)
650      bfd *abfd;
651      char **tabloc;
652      unsigned int *tablen;
653 {
654     unsigned int maxname = abfd->xvec->ar_max_namelen;
655     unsigned int total_namelen = 0;
656     bfd *current;
657     char *strptr;
658
659     *tablen = 0;
660   
661     /* Figure out how long the table should be */
662     for (current = abfd->archive_head; current != NULL; current = current->next){
663         unsigned int thislen = strlen (normalize(current->filename));
664         if (thislen > maxname) total_namelen += thislen + 1; /* leave room for \0 */
665     }
666
667     if (total_namelen == 0) return true;
668
669     *tabloc = zalloc (total_namelen);
670     if (*tabloc == NULL) {
671         bfd_error = no_memory;
672         return false;
673     }
674
675     *tablen = total_namelen;
676     strptr = *tabloc;
677
678     for (current = abfd->archive_head; current != NULL; current =
679          current->next) {
680         char *normal =normalize( current->filename);
681         unsigned int thislen = strlen (normal);
682         if (thislen > maxname) {
683             strcpy (strptr, normal);
684             current->filename[0] = ' ';
685             /* We know there will always be enough room (one of the few cases
686                where you may safely use sprintf). */
687             sprintf ((current->filename) + 1, "-%o", (unsigned) (strptr - *tabloc));
688
689             strptr += thislen + 1;
690         }
691     }
692
693     return true;
694 }
695 \f
696 /** A couple of functions for creating ar_hdrs */
697
698 /* Takes a filename, returns an arelt_data for it, or NULL if it can't make one.
699    The filename must refer to a filename in the filesystem.
700    The filename field of the ar_hdr will NOT be initialized
701 */
702
703 struct areltdata *
704 bfd_ar_hdr_from_filesystem (filename)
705      char *filename;
706 {
707   struct stat status;
708   struct areltdata *ared;
709   struct ar_hdr *hdr;
710   char *temp, *temp1;
711
712
713   if (stat (filename, &status) != 0) {
714     bfd_error = system_call_error;
715     return NULL;
716   }
717
718   ared = (struct areltdata *) zalloc (sizeof (struct ar_hdr) +
719                                       sizeof (struct areltdata));
720   if (ared == NULL) {
721     bfd_error = no_memory;
722     return NULL;
723   }
724   hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata));
725
726   /* ar headers are space padded, not null padded! */
727   temp = (char *) hdr;
728   temp1 = temp + sizeof (struct ar_hdr) - 2;
729   for (; temp < temp1; *(temp++) = ' ');
730   strncpy (hdr->ar_fmag, ARFMAG, 2);
731   
732   /* Goddamned sprintf doesn't permit MAXIMUM field lengths */
733   sprintf ((hdr->ar_date), "%-12ld", status.st_mtime);
734   sprintf ((hdr->ar_uid), "%d", status.st_uid);
735   sprintf ((hdr->ar_gid), "%d", status.st_gid);
736   sprintf ((hdr->ar_mode), "%-8o", (unsigned) status.st_mode);
737   sprintf ((hdr->ar_size), "%-10ld", status.st_size);
738   /* Correct for a lossage in sprintf whereby it null-terminates.  I cannot
739      understand how these C losers could design such a ramshackle bunch of
740      IO operations */
741   temp = (char *) hdr;
742   temp1 = temp + sizeof (struct ar_hdr) - 2;
743   for (; temp < temp1; temp++) {
744     if (*temp == '\0') *temp = ' ';
745   }
746   strncpy (hdr->ar_fmag, ARFMAG, 2);
747   ared->parsed_size = status.st_size;
748   ared->arch_header = (char *) hdr;
749
750   return ared;
751 }
752
753 struct ar_hdr *
754 bfd_special_undocumented_glue (filename)
755      char *filename;
756 {
757
758   return (struct ar_hdr *) bfd_ar_hdr_from_filesystem (filename) -> arch_header;
759 }
760
761
762 /* Analogous to stat call */
763 int
764 bfd_generic_stat_arch_elt (abfd, buf)
765      bfd *abfd;
766      struct stat *buf;
767 {
768   struct ar_hdr *hdr;
769   char *aloser;
770   
771   if (abfd->arelt_data == NULL) {
772     bfd_error = invalid_operation;
773     return -1;
774   }
775     
776   hdr = arch_hdr (abfd);
777
778 #define foo(arelt, stelt, size)  \
779   buf->stelt = strtol (hdr->arelt, &aloser, size); \
780   if (aloser == hdr->arelt) return -1;
781   
782   foo (ar_date, st_mtime, 10);
783   foo (ar_uid, st_uid, 10);
784   foo (ar_gid, st_gid, 10);
785   foo (ar_mode, st_mode, 8);
786   foo (ar_size, st_size, 10);
787
788   return 0;
789 }
790
791 /* Don't do anything -- it'll be taken care of later */
792 void
793 bfd_dont_truncate_arname (ignore_abfd, ignore_filename, ignore_arhdr)
794      bfd *ignore_abfd;
795      char *ignore_filename;
796      char *ignore_arhdr;
797 {
798   /* FIXME -- Actually this is incorrect.  If the name is short we
799     should insert into the header; only if it is long should we do
800     nothing.
801
802     Anyway, this interacts unpleasantly with ar's quick-append option,
803     for now just be compatible with the old system */
804
805   return;
806 }
807
808 void
809 bfd_bsd_truncate_arname (abfd, pathname, arhdr)
810      bfd *abfd;
811      char *pathname;
812      char *arhdr;
813 {
814   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
815   int length;
816   char *filename = strrchr (pathname, '/');
817   int maxlen = ar_maxnamelen (abfd);
818
819
820   if (filename == NULL)
821     filename = pathname;
822   else
823     ++filename;
824
825   length = strlen (filename);
826
827   if (length <= maxlen)
828     memcpy (hdr->ar_name, filename, length);
829   else {
830     /* pathname: meet procrustes */
831     memcpy (hdr->ar_name, filename, maxlen);
832     length = maxlen;
833   }
834
835   if (length < 16) (hdr->ar_name)[length] = ar_padchar (abfd);
836 }
837
838 /* Store name into ar header.  Truncates the name to fit.
839    1> strip pathname to be just the basename.
840    2> if it's short enuf to fit, stuff it in.
841    3> If it doesn't end with .o, truncate it to fit
842    4> truncate it before the .o, append .o, stuff THAT in.
843 */
844
845 /* This is what gnu ar does.  It's better but incompatible with the bsd ar. */
846 void
847 bfd_gnu_truncate_arname (abfd, pathname, arhdr)
848      bfd *abfd;
849      char *pathname;
850      char *arhdr;
851 {
852   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
853   int length;
854   char *filename = strrchr (pathname, '/');
855   int maxlen = ar_maxnamelen (abfd);
856         
857   if (filename == NULL)
858     filename = pathname;
859   else
860     ++filename;
861
862   length = strlen (filename);
863
864   if (length <= maxlen)
865     memcpy (hdr->ar_name, filename, length);
866   else {                        /* pathname: meet procrustes */
867     memcpy (hdr->ar_name, filename, maxlen);
868     if ((filename[length - 2] == '.') && (filename[length - 1] == 'o')) {
869       hdr->ar_name[maxlen - 2] = '.';
870       hdr->ar_name[maxlen - 1] = 'o';
871     }
872     length = maxlen;
873   }
874
875   if (length < 16) (hdr->ar_name)[length] = ar_padchar (abfd);
876 }
877 \f
878
879 PROTO (boolean, compute_and_write_armap, (bfd *arch, unsigned int elength));
880
881 /* The bfd is open for write and has its format set to bfd_archive */
882 boolean
883 _bfd_write_archive_contents (arch)
884      bfd *arch;
885 {
886   bfd *current;
887   char *etable = NULL;
888   unsigned int elength = 0;
889   boolean makemap = bfd_has_map (arch);
890   boolean hasobjects = false;   /* if no .o's, don't bother to make a map */
891   unsigned int i;
892
893
894   /* Verify the viability of all entries; if any of them live in the
895      filesystem (as opposed to living in an archive open for input)
896      then construct a fresh ar_hdr for them.
897      */
898   for (current = arch->archive_head; current; current = current->next) {
899     if (bfd_write_p (current)) {
900       bfd_error = invalid_operation;
901       return false;
902     }
903     if (!current->arelt_data) {
904       current->arelt_data =
905           (void *) bfd_ar_hdr_from_filesystem (current->filename);
906       if (!current->arelt_data) return false;
907
908       /* Put in the file name */
909     
910     BFD_SEND (arch, _bfd_truncate_arname,(arch, 
911                                           current->filename,
912                                          (char *) arch_hdr(current)));
913
914       
915     }
916
917     if (makemap) {              /* don't bother if we won't make a map! */
918       if ((bfd_check_format (current, bfd_object))
919 #if 0                           /* FIXME -- these are not set correctly */
920           && ((bfd_get_file_flags (current) & HAS_SYMS))
921 #endif
922           )
923         hasobjects = true;
924     }
925   }
926
927   if (!bfd_construct_extended_name_table (arch, &etable, &elength))
928     return false;
929
930   bfd_seek (arch, 0, SEEK_SET);
931   bfd_write (ARMAG, 1, SARMAG, arch);
932
933   if (makemap && hasobjects) {
934
935     if (compute_and_write_armap (arch, elength) != true) {
936       if (etable) free (etable);
937       return false;
938     }
939   }
940
941   if (elength != 0) {
942     struct ar_hdr hdr;
943
944     memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
945     sprintf (&(hdr.ar_name[0]), "ARFILENAMES/");
946     sprintf (&(hdr.ar_size[0]), "%-10d", (int) elength);
947     hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
948     for (i = 0; i < sizeof (struct ar_hdr); i++)
949       if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
950     bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
951     bfd_write (etable, 1, elength, arch);
952     if ((elength % 2) == 1) bfd_write ("\n", 1, 1, arch);
953     if (etable) free (etable);
954   }
955
956   for (current = arch->archive_head; current; current = current->next) {
957     char buffer[DEFAULT_BUFFERSIZE];
958     unsigned int remaining = arelt_size (current);
959     struct ar_hdr *hdr = arch_hdr(current);
960     /* write ar header */
961
962     if (bfd_write (hdr, 1, sizeof(*hdr), arch) != sizeof(*hdr)) {
963     syserr:
964         bfd_error = system_call_error;
965         return false;
966       }
967     if (bfd_seek (current, 0L, SEEK_SET) != 0L) goto syserr;
968     while (remaining) 
969         {
970           unsigned int amt = DEFAULT_BUFFERSIZE;
971           if (amt > remaining) {
972             amt = remaining;
973           }
974           if (bfd_read (buffer, amt, 1, current) != amt) goto syserr;
975           if (bfd_write (buffer, amt, 1, arch)   != amt) goto syserr;
976           remaining -= amt;
977         }
978     if ((arelt_size (current) % 2) == 1) bfd_write ("\n", 1, 1, arch);
979   }
980 return true;
981 }
982 \f
983 /* Note that the namidx for the first symbol is 0 */
984
985   
986
987 boolean
988 compute_and_write_armap (arch, elength)
989      bfd *arch;
990      unsigned int elength;
991 {
992   bfd *current;
993   file_ptr elt_no = 0;
994   struct orl *map;
995   int orl_max = 15000;          /* fine initial default */
996   int orl_count = 0;
997   int stridx = 0;               /* string index */
998
999   /* Dunno if this is the best place for this info... */
1000   if (elength != 0) elength += sizeof (struct ar_hdr);
1001   elength += elength %2 ;
1002
1003   map = (struct orl *) zalloc (orl_max * sizeof (struct orl));
1004   if (map == NULL) {
1005     bfd_error = no_memory;
1006     return false;
1007   }
1008
1009   /* Map over each element */
1010   for (current = arch->archive_head;
1011        current != (bfd *)NULL;
1012        current = current->next, elt_no++) 
1013       {
1014         if ((bfd_check_format (current, bfd_object) == true)
1015             && ((bfd_get_file_flags (current) & HAS_SYMS))) {
1016           asymbol **syms;
1017           unsigned int storage;
1018           unsigned int symcount;
1019           unsigned int src_count;
1020
1021           storage = get_symtab_upper_bound (current);
1022           if (storage != 0) {
1023
1024             syms = (asymbol **) zalloc (storage);
1025             if (syms == NULL) {
1026               bfd_error = no_memory; /* FIXME -- memory leak */
1027               return false;
1028             }
1029             symcount = bfd_canonicalize_symtab (current, syms);
1030
1031
1032             /* Now map over all the symbols, picking out the ones we want */
1033             for (src_count = 0; src_count <symcount; src_count++) {
1034               flagword flags = (syms[src_count])->flags;
1035               if ((flags & BSF_GLOBAL) ||
1036                   (flags & BSF_FORT_COMM)) {
1037
1038                 /* This symbol will go into the archive header */
1039                 if (orl_count == orl_max) 
1040                     {
1041                       orl_max *= 2;
1042                       map = (struct orl *) realloc ((char *) map,
1043                                                     orl_max * sizeof (struct orl));
1044                     }
1045
1046                 (map[orl_count]).name = &((syms[src_count])->name);
1047                 (map[orl_count]).pos = elt_no;
1048                 (map[orl_count]).namidx = stridx;
1049
1050                 stridx += strlen ((syms[src_count])->name) + 1;
1051                 ++orl_count;
1052               }
1053             }
1054           }
1055         }
1056       }
1057   /* OK, now we have collected all the data, let's write them out */
1058   if (!BFD_SEND (arch, write_armap,
1059                  (arch, elength, map, orl_count, stridx))) {
1060     free (map);
1061     return false;
1062   }
1063
1064   free (map);
1065   return true;
1066 }
1067
1068 \f
1069  /* FIXME -- have to byte-swap this */
1070
1071 boolean
1072 bsd_write_armap (arch, elength, map, orl_count, stridx)
1073      bfd *arch;
1074      unsigned int elength;
1075      struct orl *map;
1076      int orl_count;
1077      int stridx;
1078 {
1079   unsigned int ranlibsize = (orl_count * sizeof (struct ranlib)) + 4;
1080   unsigned int stringsize = stridx + 4;
1081   unsigned int mapsize = stringsize + ranlibsize;
1082   file_ptr firstreal;
1083   bfd *current = arch->archive_head;
1084   int last_eltno = 0;           /* last element arch seen */
1085   int temp;
1086   int count;
1087   struct ar_hdr hdr;
1088   struct stat statbuf;
1089   unsigned int i;
1090   int padit = mapsize & 1;
1091   
1092   if (padit) mapsize ++;
1093
1094   firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
1095
1096   fstat (arch->iostream, &statbuf); /* FIXME -- descriptor must be open! */
1097   memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
1098   sprintf (hdr.ar_name, "__.SYMDEF");
1099   sprintf (hdr.ar_size, "%-10d", (int) mapsize);
1100   sprintf (hdr.ar_date, "%ld", statbuf.st_mtime);  
1101   hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
1102   for (i = 0; i < sizeof (struct ar_hdr); i++)
1103     if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
1104   bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
1105
1106   temp = orl_count /* + 4 */;
1107   bfd_write (&temp, 1, sizeof (temp), arch);
1108   
1109   for (count = 0; count < orl_count; count++) {
1110     struct symdef outs;
1111     struct symdef *outp = &outs;
1112     
1113     if ((map[count]).pos != last_eltno) {
1114       firstreal += arelt_size (current) + sizeof (struct ar_hdr);
1115       firstreal += firstreal % 2;
1116     last_eltno = (map[count]).pos;
1117       current = current->next;
1118     }
1119
1120     outs.s.string_offset = ((map[count]).namidx) +4;
1121     outs.file_offset = firstreal;
1122     bfd_write ((char *)outp, 1, sizeof (outs), arch);
1123   }
1124
1125   /* now write the strings themselves */
1126   temp = stridx + 4;
1127   bfd_write (&temp, 1, sizeof (temp), arch);
1128   for (count = 0; count < orl_count; count++)
1129     bfd_write (*((map[count]).name), 1, strlen (*((map[count]).name))+1, arch);
1130
1131   /* The spec sez this should be a newline.  But in order to be
1132      bug-compatible for sun's ar we use a null. */
1133   if (padit)
1134     bfd_write("\0",1,1,arch);
1135
1136   return true;
1137 }
1138 \f
1139
1140 /* A coff armap looks like :
1141  ARMAG
1142  struct ar_hdr with name = '/' 
1143  number of symbols
1144  offset of file for symbol 0
1145  offset of file for symbol 1
1146     ..
1147  offset of file for symbol n-1
1148  symbol name 0
1149  symbol name 1  
1150     ..
1151  symbol name n-1
1152
1153 */
1154   
1155 boolean
1156 coff_write_armap (arch, elength, map, orl_count, stridx)
1157      bfd *arch;
1158      unsigned int elength;
1159      struct orl *map;
1160      int orl_count;
1161      int stridx;
1162 {
1163     unsigned int ranlibsize = (orl_count * 4) + 4;
1164     unsigned int stringsize = stridx;
1165     unsigned int mapsize = stringsize + ranlibsize;
1166     file_ptr archive_member_file_ptr;
1167     bfd *current = arch->archive_head;
1168     int last_eltno = 0;         /* last element arch seen */
1169     int count;
1170     struct ar_hdr hdr;
1171     struct stat statbuf;
1172     unsigned int i;
1173     int padit = mapsize & 1;
1174   
1175     if (padit) mapsize ++;
1176
1177     archive_member_file_ptr =
1178         mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
1179
1180     fstat (arch->iostream, &statbuf); /* FIXME -- descriptor must be open! */
1181     memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
1182     hdr.ar_name[0] = '/';
1183     sprintf (hdr.ar_size, "%-10d", (int) mapsize);
1184     sprintf (hdr.ar_date, "%ld", statbuf.st_mtime);  
1185     hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
1186
1187     for (i = 0; i < sizeof (struct ar_hdr); i++)
1188         if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
1189
1190     /* Write the ar header for this item and the number of symbols */
1191
1192     bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
1193     bfd_write (&orl_count, 1, sizeof (orl_count), arch);
1194
1195     /* Two passes, first write the file offsets for each symbol -
1196        remembering that each offset is on a two byte boundary
1197        */
1198
1199     for (count = 0; count < orl_count; count++) {
1200         while ((map[count]).pos != last_eltno) {
1201             /* If this is the first time we've seen a ref to this archive
1202                then remember it's size */
1203             archive_member_file_ptr +=
1204                 arelt_size (current) + sizeof (struct ar_hdr);
1205             archive_member_file_ptr += archive_member_file_ptr % 2;
1206             current = current->next;
1207             last_eltno++;
1208         }
1209         bfd_write (&archive_member_file_ptr,
1210                    1,
1211                    sizeof (archive_member_file_ptr),
1212                    arch);
1213     }
1214
1215     /* now write the strings themselves */
1216     for (count = 0; count < orl_count; count++) {
1217         bfd_write (*((map[count]).name),
1218                    1,
1219                    strlen (*((map[count]).name))+1, arch);
1220
1221     }
1222     /* The spec sez this should be a newline.  But in order to be
1223        bug-compatible for arc960 we use a null. */
1224     if (padit)
1225         bfd_write("\0",1,1,arch);
1226
1227     return true;
1228 }