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