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