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