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