*** empty log message ***
[external/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       if (strncmp (nextname, "__.SYMDEF       ", 16)) {
421           bfd_has_map (abfd) = false;
422           return true;
423       }
424
425       mapdata = snarf_ar_hdr (abfd);
426       if (mapdata == NULL) return false;
427
428       raw_armap = (int *) bfd_zalloc(abfd,mapdata->parsed_size);
429       if (raw_armap == NULL) {
430           bfd_error = no_memory;
431   byebye:
432           return false;
433       }
434
435       if (bfd_read ((PTR)raw_armap, 1, mapdata->parsed_size, abfd) !=
436           mapdata->parsed_size) {
437           bfd_error = malformed_archive;
438           goto byebye;
439       }
440
441       ardata->symdef_count = *(raw_armap) / sizeof (struct symdef);
442       ardata->cache = 0;
443       rbase = raw_armap+1;
444       ardata->symdefs = (carsym *) rbase;
445       stringbase = ((char *) (ardata->symdefs + ardata->symdef_count)) + 4;
446
447       for (;counter < (unsigned)( ardata->symdef_count); counter++) {
448           struct symdef *sym = ((struct symdef *) rbase) + counter;
449           sym->s.name = sym->s.string_offset + stringbase;
450       }
451   
452       ardata->first_file_filepos = bfd_tell (abfd);
453       /* Pad to an even boundary if you have to */
454       ardata->first_file_filepos += (ardata-> first_file_filepos) %2;
455       bfd_has_map (abfd) = true;
456   }
457   return true;
458 }
459
460 /* Returns false on error, true otherwise */
461 boolean
462 bfd_slurp_coff_armap (abfd)
463      bfd *abfd;
464 {
465   struct areltdata *mapdata;
466   char nextname;
467   int *raw_armap, *rawptr;
468   struct artdata *ardata = bfd_ardata (abfd);
469   char *stringbase;
470   unsigned int stringsize;
471   carsym *carsyms;
472
473   if (bfd_read ((PTR)&nextname, 1, 1, abfd) != 1) {
474   bfd_seek (abfd, -1L, SEEK_CUR);
475     bfd_has_map(abfd) = false;
476     return true;
477   }
478   bfd_seek (abfd, -1L, SEEK_CUR);
479
480   if (nextname != '/') {
481     /* Actually I think this is an error for a COFF archive */
482     bfd_has_map (abfd) = false;
483     return true;
484   }
485
486   mapdata = snarf_ar_hdr (abfd);
487   if (mapdata == NULL) return false;
488
489   raw_armap = (int *) bfd_alloc(abfd,mapdata->parsed_size);
490   if (raw_armap == NULL) {
491     bfd_error = no_memory;
492   byebye:
493
494     return false;
495   }
496
497   if (bfd_read ((PTR)raw_armap, 1, mapdata->parsed_size, abfd) !=
498       mapdata->parsed_size) {
499     bfd_error = malformed_archive;
500   oops:
501
502     goto byebye;
503   }
504
505   /* The coff armap must be read sequentially.  So we construct a bsd-style
506      one in core all at once, for simplicity. */
507
508   stringsize = mapdata->parsed_size - (4 * (*raw_armap)) - 4;
509
510   {
511     unsigned int nsymz = *raw_armap;
512     unsigned int carsym_size = (nsymz * sizeof (carsym));
513     unsigned int ptrsize = (4 * nsymz);
514     unsigned int i;
515     ardata->symdefs = (carsym *) bfd_zalloc(abfd,carsym_size + stringsize + 1);
516     if (ardata->symdefs == NULL) {
517       bfd_error = no_memory;
518       goto oops;
519     }
520     carsyms = ardata->symdefs;
521
522     stringbase = ((char *) ardata->symdefs) + carsym_size;
523     memcpy (stringbase, (char*)raw_armap + ptrsize + 4,  stringsize);
524
525
526     /* OK, build the carsyms */
527     for (i = 0; i < nsymz; i++) 
528       {
529         rawptr = raw_armap + i + 1;
530         carsyms->file_offset = *rawptr;
531         carsyms->name = stringbase;
532         for (; *(stringbase++););
533         carsyms++;
534       }
535     *stringbase = 0;
536   }
537   ardata->symdef_count = *raw_armap;
538   ardata->first_file_filepos = bfd_tell (abfd);
539   /* Pad to an even boundary if you have to */
540   ardata->first_file_filepos += (ardata->first_file_filepos) %2;
541
542   bfd_has_map (abfd) = true;
543   return true;
544 }
545
546 \f
547 /** Extended name table.
548
549   Normally archives support only 14-character filenames.  Intel has extended
550   the format: longer names are stored in a special element (the first in the
551   archive, or second if there is an armap); the name in the ar_hdr is replaced
552   by <space><index into filename element>.  Index is the P.R. of an int (radix:
553   8). */
554
555 /* Returns false on error, true otherwise */
556 boolean
557 _bfd_slurp_extended_name_table (abfd)
558      bfd *abfd;
559 {
560   char nextname[17];
561   struct areltdata *namedata;
562
563   if (bfd_read ((PTR)nextname, 1, 16, abfd) == 16) {
564
565   bfd_seek (abfd, -16L, SEEK_CUR);
566
567   if (strncmp (nextname, "ARFILENAMES/    ", 16)) {
568     bfd_ardata (abfd)->extended_names = NULL;
569     return true;
570   }
571
572   namedata = snarf_ar_hdr (abfd);
573   if (namedata == NULL) return false;
574   
575   
576   bfd_ardata (abfd)->extended_names = bfd_zalloc(abfd,namedata->parsed_size);
577   if (bfd_ardata (abfd)->extended_names == NULL) {
578     bfd_error = no_memory;
579   byebye:
580
581     return false;
582   }
583
584   if (bfd_read ((PTR)bfd_ardata (abfd)->extended_names, 1,
585                 namedata->parsed_size, abfd) != namedata->parsed_size) {
586     bfd_error = malformed_archive;
587
588     bfd_ardata (abfd)->extended_names = NULL;
589     goto byebye;
590   }
591
592   /* It appears that the extended names are newline-padded, not null padded.
593      */
594   {
595     char *temp = bfd_ardata (abfd)->extended_names;
596     for (; *temp != '\0'; ++temp)
597       if (*temp == '\n') *temp = '\0';
598   }
599   
600   /* Pad to an even boundary if you have to */
601   bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
602   bfd_ardata (abfd)->first_file_filepos +=
603     (bfd_ardata (abfd)->first_file_filepos) %2;
604
605
606 }
607   return true;
608 }
609
610 static
611 char *normalize(file)
612 char *file;
613 {
614     char *    filename = strrchr(file, '/');
615     if (filename != (char *)NULL) {
616         filename ++;
617     }
618     else {
619         filename = file;
620     }
621 return filename;
622 }
623
624 /* Follows archive_head and produces an extended name table if necessary.
625    Returns (in tabloc) a pointer to an extended name table, and in tablen
626    the length of the table.  If it makes an entry it clobbers the filename
627    so that the element may be written without further massage.
628    Returns true if it ran successfully, false if something went wrong.
629    A successful return may still involve a zero-length tablen!
630    */
631 boolean
632 bfd_construct_extended_name_table (abfd, tabloc, tablen)
633      bfd *abfd;
634      char **tabloc;
635      unsigned int *tablen;
636 {
637   unsigned int maxname = abfd->xvec->ar_max_namelen;
638   unsigned int total_namelen = 0;
639   bfd *current;
640   char *strptr;
641
642   *tablen = 0;
643   
644   /* Figure out how long the table should be */
645   for (current = abfd->archive_head; current != NULL; current = current->next){
646     unsigned int thislen = strlen (normalize(current->filename));
647     if (thislen > maxname) total_namelen += thislen + 1; /* leave room for \n */
648   }
649
650   if (total_namelen == 0) return true;
651
652   *tabloc = bfd_zalloc (abfd,total_namelen);
653   if (*tabloc == NULL) {
654     bfd_error = no_memory;
655     return false;
656   }
657
658   *tablen = total_namelen;
659   strptr = *tabloc;
660
661   for (current = abfd->archive_head; current != NULL; current =
662        current->next) {
663     char *normal =normalize( current->filename);
664     unsigned int thislen = strlen (normal);
665     if (thislen > maxname) {
666       /* Works for now; may need to be re-engineered if we encounter an oddball
667          archive format and want to generalise this hack. */
668       struct ar_hdr *hdr = arch_hdr(current);
669       strcpy (strptr, normal);
670       strptr[thislen] = '\n';
671       hdr->ar_name[0] = ' ';
672       /* We know there will always be enough room (one of the few cases
673          where you may safely use sprintf). */
674       sprintf ((hdr->ar_name) + 1, "%-o", (unsigned) (strptr - *tabloc));
675       /* Kinda Kludgy.   We should just use the returned value of sprintf
676          but not all implementations get this right */
677         {
678           char *temp = hdr->ar_name +2; 
679           for (; temp < hdr->ar_name + maxname; temp++)
680             if (*temp == '\0') *temp = ' ';
681         }
682       strptr += thislen + 1;
683     }
684   }
685
686   return true;
687 }
688 \f
689 /** A couple of functions for creating ar_hdrs */
690
691 /* Takes a filename, returns an arelt_data for it, or NULL if it can't make one.
692    The filename must refer to a filename in the filesystem.
693    The filename field of the ar_hdr will NOT be initialized
694 */
695
696 struct areltdata *
697 DEFUN(bfd_ar_hdr_from_filesystem, (abfd,filename),
698       bfd* abfd AND
699       CONST 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 *) bfd_zalloc(abfd, 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 DEFUN(bfd_special_undocumented_glue, (abfd, filename),
749       bfd *abfd AND
750       char *filename)
751 {
752
753   return (struct ar_hdr *) bfd_ar_hdr_from_filesystem (abfd, filename) -> arch_header;
754 }
755
756
757 /* Analogous to stat call */
758 int
759 bfd_generic_stat_arch_elt (abfd, buf)
760      bfd *abfd;
761      struct stat *buf;
762 {
763   struct ar_hdr *hdr;
764   char *aloser;
765   
766   if (abfd->arelt_data == NULL) {
767     bfd_error = invalid_operation;
768     return -1;
769   }
770     
771   hdr = arch_hdr (abfd);
772
773 #define foo(arelt, stelt, size)  \
774   buf->stelt = strtol (hdr->arelt, &aloser, size); \
775   if (aloser == hdr->arelt) return -1;
776   
777   foo (ar_date, st_mtime, 10);
778   foo (ar_uid, st_uid, 10);
779   foo (ar_gid, st_gid, 10);
780   foo (ar_mode, st_mode, 8);
781   foo (ar_size, st_size, 10);
782
783   return 0;
784 }
785
786 void
787 bfd_dont_truncate_arname (abfd, pathname, arhdr)
788      bfd *abfd;
789      char *pathname;
790      char *arhdr;
791 {
792   /* This interacts unpleasantly with ar's quick-append option.
793      Fortunately ic960 users will never use that option.  Fixing this
794      is very hard; fortunately I know how to do it and will do so once
795      intel's release is out the door. */
796    
797   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
798   int length;
799   char *filename = strrchr (pathname, '/');
800   int maxlen = ar_maxnamelen (abfd);
801
802   if (filename == NULL)
803     filename = pathname;
804   else
805     ++filename;
806
807   length = strlen (filename);
808
809   if (length <= maxlen)
810     memcpy (hdr->ar_name, filename, length);
811
812   if (length < maxlen) (hdr->ar_name)[length] = ar_padchar (abfd);
813   return;
814
815 }
816
817 void
818 bfd_bsd_truncate_arname (abfd, pathname, arhdr)
819      bfd *abfd;
820      char *pathname;
821      char *arhdr;
822 {
823   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
824   int length;
825   char *filename = strrchr (pathname, '/');
826   int maxlen = ar_maxnamelen (abfd);
827
828
829   if (filename == NULL)
830     filename = pathname;
831   else
832     ++filename;
833
834   length = strlen (filename);
835
836   if (length <= maxlen)
837     memcpy (hdr->ar_name, filename, length);
838   else {
839     /* pathname: meet procrustes */
840     memcpy (hdr->ar_name, filename, maxlen);
841     length = maxlen;
842   }
843
844   if (length < maxlen) (hdr->ar_name)[length] = ar_padchar (abfd);
845 }
846
847 /* Store name into ar header.  Truncates the name to fit.
848    1> strip pathname to be just the basename.
849    2> if it's short enuf to fit, stuff it in.
850    3> If it doesn't end with .o, truncate it to fit
851    4> truncate it before the .o, append .o, stuff THAT in.
852 */
853
854 /* This is what gnu ar does.  It's better but incompatible with the bsd ar. */
855 void
856 bfd_gnu_truncate_arname (abfd, pathname, arhdr)
857      bfd *abfd;
858      char *pathname;
859      char *arhdr;
860 {
861   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
862   int length;
863   char *filename = strrchr (pathname, '/');
864   int maxlen = ar_maxnamelen (abfd);
865         
866   if (filename == NULL)
867     filename = pathname;
868   else
869     ++filename;
870
871   length = strlen (filename);
872
873   if (length <= maxlen)
874     memcpy (hdr->ar_name, filename, length);
875   else {                        /* pathname: meet procrustes */
876     memcpy (hdr->ar_name, filename, maxlen);
877     if ((filename[length - 2] == '.') && (filename[length - 1] == 'o')) {
878       hdr->ar_name[maxlen - 2] = '.';
879       hdr->ar_name[maxlen - 1] = 'o';
880     }
881     length = maxlen;
882   }
883
884   if (length < 16) (hdr->ar_name)[length] = ar_padchar (abfd);
885 }
886 \f
887
888 PROTO (boolean, compute_and_write_armap, (bfd *arch, unsigned int elength));
889
890 /* The bfd is open for write and has its format set to bfd_archive */
891 boolean
892 _bfd_write_archive_contents (arch)
893      bfd *arch;
894 {
895   bfd *current;
896   char *etable = NULL;
897   unsigned int elength = 0;
898   boolean makemap = bfd_has_map (arch);
899   boolean hasobjects = false;   /* if no .o's, don't bother to make a map */
900   unsigned int i;
901
902
903   /* Verify the viability of all entries; if any of them live in the
904      filesystem (as opposed to living in an archive open for input)
905      then construct a fresh ar_hdr for them.
906      */
907   for (current = arch->archive_head; current; current = current->next) {
908     if (bfd_write_p (current)) {
909       bfd_error = invalid_operation;
910       return false;
911     }
912     if (!current->arelt_data) {
913       current->arelt_data =
914           (PTR) bfd_ar_hdr_from_filesystem (arch, current->filename);
915       if (!current->arelt_data) return false;
916
917       /* Put in the file name */
918     
919     BFD_SEND (arch, _bfd_truncate_arname,(arch, 
920                                           current->filename,
921                                          (char *) arch_hdr(current)));
922
923       
924     }
925
926     if (makemap) {              /* don't bother if we won't make a map! */
927       if ((bfd_check_format (current, bfd_object))
928 #if 0                           /* FIXME -- these are not set correctly */
929           && ((bfd_get_file_flags (current) & HAS_SYMS))
930 #endif
931           )
932         hasobjects = true;
933     }
934   }
935
936   if (!bfd_construct_extended_name_table (arch, &etable, &elength))
937     return false;
938
939   bfd_seek (arch, 0, SEEK_SET);
940 #ifdef GNU960
941   bfd_write (BFD_GNU960_ARMAG(arch), 1, SARMAG, arch);
942 #else
943   bfd_write (ARMAG, 1, SARMAG, arch);
944 #endif
945
946   if (makemap && hasobjects) {
947
948     if (compute_and_write_armap (arch, elength) != true) {
949       return false;
950     }
951   }
952
953   if (elength != 0) {
954     struct ar_hdr hdr;
955
956     memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
957     sprintf (&(hdr.ar_name[0]), "ARFILENAMES/");
958     sprintf (&(hdr.ar_size[0]), "%-10d", (int) elength);
959     hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
960     for (i = 0; i < sizeof (struct ar_hdr); i++)
961       if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
962     bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
963     bfd_write (etable, 1, elength, arch);
964     if ((elength % 2) == 1) bfd_write ("\n", 1, 1, arch);
965
966   }
967
968   for (current = arch->archive_head; current; current = current->next) {
969     char buffer[DEFAULT_BUFFERSIZE];
970     unsigned int remaining = arelt_size (current);
971     struct ar_hdr *hdr = arch_hdr(current);
972     /* write ar header */
973
974     if (bfd_write (hdr, 1, sizeof(*hdr), arch) != sizeof(*hdr)) {
975     syserr:
976         bfd_error = system_call_error;
977         return false;
978       }
979     if (bfd_seek (current, 0L, SEEK_SET) != 0L) goto syserr;
980     while (remaining) 
981         {
982           unsigned int amt = DEFAULT_BUFFERSIZE;
983           if (amt > remaining) {
984             amt = remaining;
985           }
986           if (bfd_read (buffer, amt, 1, current) != amt) goto syserr;
987           if (bfd_write (buffer, amt, 1, arch)   != amt) goto syserr;
988           remaining -= amt;
989         }
990     if ((arelt_size (current) % 2) == 1) bfd_write ("\n", 1, 1, arch);
991   }
992 return true;
993 }
994 \f
995 /* Note that the namidx for the first symbol is 0 */
996
997   
998
999 boolean
1000 compute_and_write_armap (arch, elength)
1001      bfd *arch;
1002      unsigned int elength;
1003 {
1004   bfd *current;
1005   file_ptr elt_no = 0;
1006   struct orl *map;
1007   int orl_max = 15000;          /* fine initial default */
1008   int orl_count = 0;
1009   int stridx = 0;               /* string index */
1010
1011   /* Dunno if this is the best place for this info... */
1012   if (elength != 0) elength += sizeof (struct ar_hdr);
1013   elength += elength %2 ;
1014
1015   map = (struct orl *) bfd_zalloc (arch,orl_max * sizeof (struct orl));
1016   if (map == NULL) {
1017     bfd_error = no_memory;
1018     return false;
1019   }
1020
1021   /* Map over each element */
1022   for (current = arch->archive_head;
1023        current != (bfd *)NULL;
1024        current = current->next, elt_no++) 
1025       {
1026         if ((bfd_check_format (current, bfd_object) == true)
1027             && ((bfd_get_file_flags (current) & HAS_SYMS))) {
1028           asymbol **syms;
1029           unsigned int storage;
1030           unsigned int symcount;
1031           unsigned int src_count;
1032
1033           storage = get_symtab_upper_bound (current);
1034           if (storage != 0) {
1035
1036             syms = (asymbol **) bfd_zalloc (arch,storage);
1037             if (syms == NULL) {
1038               bfd_error = no_memory; /* FIXME -- memory leak */
1039               return false;
1040             }
1041             symcount = bfd_canonicalize_symtab (current, syms);
1042
1043
1044             /* Now map over all the symbols, picking out the ones we want */
1045             for (src_count = 0; src_count <symcount; src_count++) {
1046               flagword flags = (syms[src_count])->flags;
1047               if ((flags & BSF_GLOBAL) ||
1048                   (flags & BSF_FORT_COMM)) {
1049
1050                 /* This symbol will go into the archive header */
1051                 if (orl_count == orl_max) 
1052                     {
1053                       orl_max *= 2;
1054                       map = (struct orl *) bfd_realloc (arch, (char *) map,
1055                                                     orl_max * sizeof (struct orl));
1056                     }
1057
1058                 (map[orl_count]).name = &((syms[src_count])->name);
1059                 (map[orl_count]).pos = elt_no;
1060                 (map[orl_count]).namidx = stridx;
1061
1062                 stridx += strlen ((syms[src_count])->name) + 1;
1063                 ++orl_count;
1064               }
1065             }
1066           }
1067         }
1068       }
1069   /* OK, now we have collected all the data, let's write them out */
1070   if (!BFD_SEND (arch, write_armap,
1071                  (arch, elength, map, orl_count, stridx))) {
1072
1073     return false;
1074   }
1075
1076
1077   return true;
1078 }
1079
1080 \f
1081  /* FIXME -- have to byte-swap this */
1082
1083 boolean
1084 bsd_write_armap (arch, elength, map, orl_count, stridx)
1085      bfd *arch;
1086      unsigned int elength;
1087      struct orl *map;
1088      int orl_count;
1089      int stridx;
1090 {
1091   unsigned int ranlibsize = (orl_count * sizeof (struct ranlib)) + 4;
1092   unsigned int stringsize = stridx + 4;
1093   unsigned int mapsize = stringsize + ranlibsize;
1094   file_ptr firstreal;
1095   bfd *current = arch->archive_head;
1096   int last_eltno = 0;           /* last element arch seen */
1097   int temp;
1098   int count;
1099   struct ar_hdr hdr;
1100   struct stat statbuf;
1101   unsigned int i;
1102   int padit = mapsize & 1;
1103   
1104   if (padit) mapsize ++;
1105
1106   firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
1107
1108   stat (arch->filename, &statbuf);
1109   memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
1110   sprintf (hdr.ar_name, "__.SYMDEF");
1111   sprintf (hdr.ar_size, "%-10d", (int) mapsize);
1112   sprintf (hdr.ar_date, "%ld", statbuf.st_mtime);  
1113   hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
1114   for (i = 0; i < sizeof (struct ar_hdr); i++)
1115     if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
1116   bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
1117
1118   temp = orl_count /* + 4 */;
1119   bfd_write (&temp, 1, sizeof (temp), arch);
1120   
1121   for (count = 0; count < orl_count; count++) {
1122     struct symdef outs;
1123     struct symdef *outp = &outs;
1124     
1125     if ((map[count]).pos != last_eltno) {
1126       firstreal += arelt_size (current) + sizeof (struct ar_hdr);
1127       firstreal += firstreal % 2;
1128     last_eltno = (map[count]).pos;
1129       current = current->next;
1130     }
1131
1132     outs.s.string_offset = ((map[count]).namidx) +4;
1133     outs.file_offset = firstreal;
1134     bfd_write ((char *)outp, 1, sizeof (outs), arch);
1135   }
1136
1137   /* now write the strings themselves */
1138   temp = stridx + 4;
1139   bfd_write (&temp, 1, sizeof (temp), arch);
1140   for (count = 0; count < orl_count; count++)
1141     bfd_write (*((map[count]).name), 1, strlen (*((map[count]).name))+1, arch);
1142
1143   /* The spec sez this should be a newline.  But in order to be
1144      bug-compatible for sun's ar we use a null. */
1145   if (padit)
1146     bfd_write("\0",1,1,arch);
1147
1148   return true;
1149 }
1150 \f
1151
1152 /* A coff armap looks like :
1153  ARMAG
1154  struct ar_hdr with name = '/' 
1155  number of symbols
1156  offset of file for symbol 0
1157  offset of file for symbol 1
1158     ..
1159  offset of file for symbol n-1
1160  symbol name 0
1161  symbol name 1  
1162     ..
1163  symbol name n-1
1164
1165 */
1166   
1167 boolean
1168 coff_write_armap (arch, elength, map, orl_count, stridx)
1169      bfd *arch;
1170      unsigned int elength;
1171      struct orl *map;
1172      int orl_count;
1173      int stridx;
1174 {
1175     unsigned int ranlibsize = (orl_count * 4) + 4;
1176     unsigned int stringsize = stridx;
1177     unsigned int mapsize = stringsize + ranlibsize;
1178     file_ptr archive_member_file_ptr;
1179     bfd *current = arch->archive_head;
1180     int last_eltno = 0;         /* last element arch seen */
1181     int count;
1182     struct ar_hdr hdr;
1183     unsigned int i;
1184     int padit = mapsize & 1;
1185   
1186     if (padit) mapsize ++;
1187
1188     archive_member_file_ptr =
1189         mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
1190
1191     memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
1192     hdr.ar_name[0] = '/';
1193     sprintf (hdr.ar_size, "%-10d", (int) mapsize);
1194     sprintf (hdr.ar_date, "%ld", (long)time (NULL));
1195     /* This, at least, is what Intel coff sets the values to.: */
1196     sprintf ((hdr.ar_uid), "%d", 0);
1197     sprintf ((hdr.ar_gid), "%d", 0);
1198     sprintf ((hdr.ar_mode), "%-7o",(unsigned ) 0);
1199     hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
1200
1201     for (i = 0; i < sizeof (struct ar_hdr); i++)
1202         if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
1203
1204     /* Write the ar header for this item and the number of symbols */
1205
1206     bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
1207     bfd_write (&orl_count, 1, sizeof (orl_count), arch);
1208
1209     /* Two passes, first write the file offsets for each symbol -
1210        remembering that each offset is on a two byte boundary
1211        */
1212
1213     for (count = 0; count < orl_count; count++) {
1214         while ((map[count]).pos != last_eltno) {
1215             /* If this is the first time we've seen a ref to this archive
1216                then remember it's size */
1217             archive_member_file_ptr +=
1218                 arelt_size (current) + sizeof (struct ar_hdr);
1219             archive_member_file_ptr += archive_member_file_ptr % 2;
1220             current = current->next;
1221             last_eltno++;
1222         }
1223         bfd_write (&archive_member_file_ptr,
1224                    1,
1225                    sizeof (archive_member_file_ptr),
1226                    arch);
1227     }
1228
1229     /* now write the strings themselves */
1230     for (count = 0; count < orl_count; count++) {
1231         bfd_write (*((map[count]).name),
1232                    1,
1233                    strlen (*((map[count]).name))+1, arch);
1234
1235     }
1236     /* The spec sez this should be a newline.  But in order to be
1237        bug-compatible for arc960 we use a null. */
1238     if (padit)
1239         bfd_write("\0",1,1,arch);
1240
1241     return true;
1242 }