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