]> Git Repo - binutils.git/blob - binutils/ar.c
*** empty log message ***
[binutils.git] / binutils / ar.c
1 /* ar.c - Archive modify and extract.
2    Copyright (C) 1991 Free Software Foundation, Inc.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 /*
21    Bugs: should use getopt the way tar does (complete w/optional -) and
22    should have long options too. GNU ar used to check file against filesystem
23    in quick_update and replace operations (would check mtime). Doesn't warn
24    when name truncated. No way to specify pos_end. Error messages should be
25    more consistant.
26 */
27 #include "bfd.h"
28 #include "sysdep.h"
29 #include "ar.h"
30 #include <stdio.h>
31 #include <sys/time.h>
32 #include <errno.h>
33 #define BUFSIZE 8192
34 /* FIXME: Not great to have these here.  Should they be exported or not? */
35 PROTO(size_t, bfd_read, (void *ptr, size_t size, size_t nitems, bfd * abfd));
36 PROTO(size_t, bfd_write, (void *ptr, size_t size, size_t nitems, bfd * abfd));
37 /* PROTO (void, open_inarch, (char *archive_filename)); */
38 #ifdef __STDC__
39 static void     open_inarch(char *archive_filename);
40 #else
41 static void     open_inarch();
42 #endif                          /* __STDC__ */
43
44 PROTO(void, map_over_members, (void (*function) (), char **files, int count));
45 PROTO(void, print_contents, (bfd * member));
46 PROTO(void, extract_file, (bfd * abfd));
47 PROTO(void, delete_members, (char **files_to_delete));
48 PROTO(void, do_quick_append, (char *archive_filename, char **files_to_append));
49 PROTO(void, move_members, (char **files_to_move));
50 PROTO(void, replace_members, (char **files_to_replace));
51 PROTO(void, print_descr, (bfd * abfd));
52 PROTO(void, ranlib_only, (char *archname));
53
54 /** Globals and flags */
55
56 char           *program_name = NULL;
57 bfd             bogus_archive;
58 bfd            *inarch;         /* The input arch we're manipulating */
59
60 /* This flag distinguishes between ar and ranlib:
61    1 means this is 'ranlib'; -1 means this is 'ar'.
62    0 means if we should use argv[0] to decide. */
63 extern int is_ranlib;
64 /* Nonzero means don't warn about creating the archive file if necessary.  */
65 int             silent_create = 0;
66 /* Nonzero means describe each action performed.  */
67 int             verbose = 0;
68 /* Nonzero means preserve dates of members when extracting them.  */
69 int             preserve_dates = 0;
70 /*
71    Nonzero means don't replace existing members whose dates are more recent
72    than the corresponding files.
73 */
74 int             newer_only = 0;
75 /* write a __.SYMDEF member into the modified archive.  */
76 boolean         write_armap = false;
77 /*
78    Nonzero means don't update __.SYMDEF unless command line explicitly
79    requested it
80 */
81 int             ignore_symdef = 0;
82 /*
83    Nonzero means it's the name of an existing member; position new or moved
84    files with respect to this one.
85 */
86 char           *posname = NULL;
87 /*
88    Sez how to use `posname': pos_before means position before that member.
89    pos_after means position after that member. pos_end means always at end.
90    pos_default means default appropriately. For the latter two, `posname'
91    should also be zero.
92 */
93 enum pos {
94     pos_default, pos_before, pos_after, pos_end
95 }               postype = pos_default;
96
97 #ifdef GNU960
98         char *default_target;
99
100         void
101         gnu960_verify_target(abfd)
102         bfd *abfd;
103         {
104             if ( abfd->format == bfd_unknown ){
105                 bfd_check_format(abfd, bfd_object);
106                 /* Don't really care if it's an object --
107                  * just want to get the correct xvec.
108                  */
109             }
110             if ( !BFD_COFF_FILE_P(abfd) ){
111                 fatal( "'%s' not a COFF file -- operation aborted",
112                                                         abfd->filename );
113             }
114         }
115 #endif
116
117
118
119 boolean operation_alters_arch = false;
120
121 /*
122    The option parsing should be in its own function.  It will be when I have
123    getopt working.
124 */
125 int
126 main(argc, argv)
127     int             argc;
128     char          **argv;
129 {
130     char           *arg_ptr;
131     char            c;
132     enum {
133         none = 0, delete, replace, print_table,
134         print_files, extract, move, quick_append
135     }               operation = none;
136     int             arg_index;
137     char          **files;
138     char           *inarch_filename;
139     char           *temp;
140
141     bfd_init();
142
143 #ifdef GNU960
144     check_v960( argc, argv );
145     default_target = bfd_make_targ_name(BFD_COFF_FORMAT,HOST_BYTE_ORDER_BIG_P);
146 #endif
147
148     program_name = argv[0];
149
150     temp = strrchr(program_name, '/');
151     if (temp == (char *) NULL)
152         temp = program_name;    /* shouldn't happen, but... */
153     else
154         ++temp;
155     if (is_ranlib > 0 || (is_ranlib == 0 && strcmp(temp, "ranlib") == 0)) {
156         if (argc < 2)
157             fatal("Too few command arguments.");
158         ranlib_only(argv[1]);
159     }
160
161
162     if (argc < 3)
163         fatal("Too few command arguments.");
164
165     arg_ptr = argv[1];
166
167     if (*arg_ptr == '-')
168         ++arg_ptr;              /* compatibility */
169
170     while (c = *arg_ptr++) {
171         switch (c) {
172         case 'd':
173         case 'm':
174         case 'p':
175         case 'q':
176         case 'r':
177         case 't':
178         case 'x':
179             if (operation != none)
180                 fatal("two different operation switches specified");
181             switch (c) {
182             case 'd':
183                 operation = delete;
184                 operation_alters_arch = true;
185                 break;
186             case 'm':
187                 operation = move;
188                 operation_alters_arch = true;
189                 break;
190             case 'p':
191                 operation = print_files;
192                 break;
193             case 'q':
194                 operation = quick_append;
195                 operation_alters_arch = true;
196                 break;
197             case 'r':
198                 operation = replace;
199                 operation_alters_arch = true;
200                 break;
201             case 't':
202                 operation = print_table;
203                 break;
204             case 'x':
205                 operation = extract;
206                 break;
207             }
208         case 'l':
209             break;
210         case 'c':
211             silent_create = 1;
212             break;
213         case 'o':
214             preserve_dates = 1;
215             break;
216         case 's':
217             write_armap = true;
218             break;
219         case 'u':
220             newer_only = 1;
221             break;
222         case 'v':
223             verbose = 1;
224             break;
225         case 'a':
226             postype = pos_after;
227             break;
228         case 'b':
229             postype = pos_before;
230             break;
231         case 'i':
232             postype = pos_before;
233             break;
234         default:
235             fatal("invalid option %c", c);
236         }
237     }
238
239     if (operation == none && write_armap)
240         ranlib_only(argv[2]);
241
242     if (operation == none)
243         fatal("no operation specified");
244
245     if (newer_only && operation != replace)
246         fatal("'u' only meaningful with 'r' option.");
247
248     arg_index = 2;
249
250     if (postype != pos_default)
251         posname = argv[arg_index++];
252
253     inarch_filename = argv[arg_index++];
254
255     if (arg_index < argc) {
256         files = argv + arg_index;
257         while (arg_index < argc)
258             if (!strcmp(argv[arg_index++], "__.SYMDEF")) {
259                 ignore_symdef = 1;
260                 break;
261             }
262     }
263     else
264         files = NULL;
265
266     if (operation == quick_append) {
267         if (files != NULL)
268             do_quick_append(inarch_filename, files);
269         exit(0);
270     }
271
272
273     open_inarch(inarch_filename);
274     /*
275        If we have no archive, and we've been asked to replace then create one
276     */
277 #if 0
278     if (operation == replace && inarch == &bogus_archive) {
279         silent_create = 1;
280         do_quick_append(inarch_filename, 0);
281         open_inarch(inarch_filename);
282     }
283 #endif
284     switch (operation) {
285
286     case print_table:
287         map_over_members(print_descr, files, argc - 3);
288         break;
289
290     case print_files:
291         map_over_members(print_contents, files, argc - 3);
292         break;
293
294     case extract:
295         map_over_members(extract_file, files, argc - 3);
296         break;
297
298     case delete:
299         if (files != NULL)
300             delete_members(files);
301         break;
302
303     case move:
304         if (files != NULL)
305             move_members(files);
306         break;
307
308     case replace:
309         if (files != NULL || write_armap)
310             replace_members(files);
311         break;
312
313         /* Shouldn't happen! */
314     default:
315         fprintf(stderr, "Sorry; this option not implemented.\n");
316     }
317
318     return (0);
319 }                               /* main() */
320
321 static
322 char *normalize(file)
323 char *file;
324 {
325     char *    filename = strrchr(file, '/');
326     if (filename != (char *)NULL) {
327         filename ++;
328     }
329     else {
330         filename = file;
331     }
332     return filename;
333 }
334
335 static void
336 open_inarch(archive_filename)
337     char           *archive_filename;
338 {
339     bfd           **last_one;
340     bfd            *next_one;
341     struct stat     sbuf;
342     bfd_error = no_error;
343     if (stat(archive_filename, &sbuf) != 0) {
344         if (errno != ENOENT)
345             bfd_fatal(archive_filename);
346         if (!operation_alters_arch) {
347           fprintf (stderr, "%s: %s not found.\n", program_name,
348                    archive_filename);
349           exit (1);
350         }       
351         if (!silent_create)
352             fprintf(stderr,
353                     "%s: creating %s\n", program_name, archive_filename);
354
355         inarch = &bogus_archive;
356         inarch->filename = archive_filename;
357         inarch->has_armap = true;
358
359     }
360     else {
361 #ifdef GNU960
362         inarch = bfd_openr(archive_filename, default_target);
363 #else
364         inarch = bfd_openr(archive_filename, NULL);
365 #endif
366         if (inarch == NULL) {
367     bloser:
368             bfd_perror(archive_filename);
369             exit(1);
370         }
371
372         if (bfd_check_format(inarch, bfd_archive) != true)
373             fatal("File %s is not an archive.", archive_filename);
374 #ifdef GNU960
375         gnu960_verify_target(inarch);   /* Exits on failure */
376 #endif
377         last_one = &(inarch->next);
378         /* Read all the contents right away, regardless. */
379         for (next_one = bfd_openr_next_archived_file(inarch, NULL);
380              next_one;
381              next_one = bfd_openr_next_archived_file(inarch, next_one)) {
382             *last_one = next_one;
383             last_one = &next_one->next;
384         }
385         *last_one = (bfd *) NULL;
386         if (bfd_error != no_more_archived_files)
387             goto bloser;
388     }
389 }
390
391
392
393 /*
394    If count is 0, then function is called once on each entry. if nonzero,
395    count is the length of the files chain; function is called on each entry
396    whose name matches one in files
397 */
398 void
399 map_over_members(function, files, count)
400     void            (*function) ();
401     char          **files;
402     int             count;
403 {
404     bfd            *head;
405
406
407
408
409     if (count == 0) {
410         for (head = inarch->next; head; head = head->next)
411             function(head);
412         return;
413     }
414     /*
415        This may appear to be a baroque way of accomplishing what we want.
416        however we have to iterate over the filenames in order to notice where
417        a filename is requested but does not exist in the archive.  Ditto
418        mapping over each file each time -- we want to hack multiple
419        references.
420     */
421
422     for (; count > 0; files++, count--) {
423         boolean         found = false;
424         for (head = inarch->next; head; head = head->next)
425             if ((head->filename != NULL) &&
426                 (!strcmp(*files, head->filename))) {
427                 found = true;
428                 function(head);
429             }
430         if (!found)
431             fprintf(stderr, "No entry %s in archive.\n", *files);
432     }
433 }
434
435
436 /* Things which are interesting to map over all or some of the files: */
437
438 void
439 print_descr(abfd)
440     bfd            *abfd;
441 {
442     print_arelt_descr(abfd, verbose);
443 }
444
445 void
446 print_contents(abfd)
447     bfd            *abfd;
448 {
449     int             ncopied = 0;
450     struct stat     buf;
451     long            size;
452     if (bfd_stat_arch_elt(abfd, &buf) != 0)
453         fatal("Internal stat error on %s", abfd->filename);
454
455     if (verbose)
456         printf("\n<member %s>\n\n", abfd->filename);
457
458     bfd_seek(abfd, 0, SEEK_SET);
459
460     size = buf.st_size;
461     while (ncopied < size) {
462         char            cbuf[BUFSIZE];
463         int             nread;
464         int             tocopy = size - ncopied;
465         if (tocopy > BUFSIZE)
466             tocopy = BUFSIZE;
467
468         nread = bfd_read(cbuf, 1, tocopy, abfd);        /* oops -- broke
469                                                            abstraction!  */
470
471         if (nread != tocopy)
472             fatal("file %s not a valid archive", abfd->my_archive->filename);
473         fwrite(cbuf, 1, nread, stdout);
474         ncopied += tocopy;
475     }
476 }
477
478
479 /*
480    Extract a member of the archive into its own file.
481
482 We defer opening the new file until after we have read a BUFSIZ chunk of the
483    old one, since we know we have just read the archive header for the old
484    one.  Since most members are shorter than BUFSIZ, this means we will read
485    the old header, read the old data, write a new inode for the new file, and
486    write the new data, and be done. This 'optimization' is what comes from
487    sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
488    Gilmore
489 */
490
491 void
492 extract_file(abfd)
493     bfd            *abfd;
494 {
495     FILE           *ostream;
496     char            cbuf[BUFSIZE];
497     int             nread,
498                     tocopy;
499     int             ncopied = 0;
500     long            size;
501     struct stat     buf;
502     if (bfd_stat_arch_elt(abfd, &buf) != 0)
503         fatal("Internal stat error on %s", abfd->filename);
504     size = buf.st_size;
505
506     if (verbose)
507         printf("x - %s\n", abfd->filename);
508
509     bfd_seek(abfd, 0, SEEK_SET);
510
511     ostream = 0;
512     if (size == 0) {
513       /* Seems like an abstraction violation, eh?  Well it's OK! */
514       ostream = fopen(abfd->filename, "w");
515       if (!ostream) {
516         perror(abfd->filename);
517         exit(1);
518       }
519     } else
520     while (ncopied < size) {
521         tocopy = size - ncopied;
522         if (tocopy > BUFSIZE)
523             tocopy = BUFSIZE;
524
525         nread = bfd_read(cbuf, 1, tocopy, abfd);
526         if (nread != tocopy)
527             fatal("file %s not a valid archive", abfd->my_archive->filename);
528
529         /* See comment above; this saves disk arm motion */
530         if (!ostream) {
531             /* Seems like an abstraction violation, eh?  Well it's OK! */
532             ostream = fopen(abfd->filename, "w");
533             if (!ostream) {
534                 perror(abfd->filename);
535                 exit(1);
536             }
537         }
538         fwrite(cbuf, 1, nread, ostream);
539         ncopied += tocopy;
540     }
541
542     fclose(ostream);
543     chmod(abfd->filename, buf.st_mode);
544
545     if (preserve_dates) {
546 #ifdef USG
547         long            tb[2];
548         tb[0] = buf.st_mtime;
549         tb[1] = buf.st_mtime;
550         utime(abfd->filename, tb);      /* FIXME check result */
551 #else
552         struct timeval  tv[2];
553         tv[0].tv_sec = buf.st_mtime;
554         tv[0].tv_usec = 0;
555         tv[1].tv_sec = buf.st_mtime;
556         tv[1].tv_usec = 0;
557         utimes(abfd->filename, tv);     /* FIXME check result */
558 #endif
559     }
560 }
561
562
563 /* Just do it quickly; don't worry about dups, armap, or anything like that */
564
565 /* This is ugly! XXX */
566
567 PROTO(struct ar_hdr *, bfd_special_undocumented_glue, (bfd *abfd, char *filename));
568
569 void
570 do_quick_append(archive_filename, files_to_append)
571     char           *archive_filename;
572     char          **files_to_append;
573
574 {
575     FILE           *ofile,
576                    *ifile;
577     char            buf[BUFSIZE];
578     long            tocopy,
579                     thistime;
580     bfd            *temp;
581     struct stat     sbuf;
582     boolean         newfile = false;
583     bfd_error = no_error;
584
585     if (stat(archive_filename, &sbuf) != 0) {
586         if (errno != ENOENT)
587             bfd_fatal(archive_filename);
588         newfile = true;
589     }
590
591
592     ofile = fopen(archive_filename, "a+");
593     if (ofile == NULL) {
594         perror(program_name);
595         exit(1);
596     }
597
598     /* bletch */
599 #ifdef GNU960
600     temp = bfd_openr(archive_filename, default_target);
601 #else
602     temp = bfd_openr(archive_filename, NULL);
603 #endif
604     if (temp == NULL) {
605         bfd_perror(archive_filename);
606         exit(1);
607     }
608     if (newfile == false) {
609         if (bfd_check_format(temp, bfd_archive) != true)
610             fatal("File %s is not an archive.", archive_filename);
611 #ifdef GNU960
612         gnu960_verify_target(temp);     /* Exits on failure */
613 #endif
614     }
615     else {
616         fwrite(ARMAG, 1, SARMAG, ofile);
617         if (!silent_create)
618             fprintf(stderr, "%s: creating %s\n", program_name, archive_filename);
619     }
620
621     /* assume it's an achive, go straight to the end, sans $200 */
622     fseek(ofile, 0, 2);
623
624     for (; files_to_append && *files_to_append; ++files_to_append) {
625         struct ar_hdr  *hdr = bfd_special_undocumented_glue(temp, *files_to_append);
626         if (hdr == NULL) {
627             bfd_perror(*files_to_append);
628             exit(1);
629         }
630
631         BFD_SEND(temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
632
633         ifile = fopen(*files_to_append, "r");
634         if (ifile == NULL)
635             bfd_perror(program_name);
636
637         if (stat(*files_to_append, &sbuf) != 0)
638             bfd_perror(*files_to_append);
639
640         tocopy = sbuf.st_size;
641
642         /* XXX should do error-checking! */
643         fwrite(hdr, 1, sizeof(struct ar_hdr), ofile);
644
645
646         while (tocopy > 0) {
647             thistime = tocopy;
648             if (thistime > BUFSIZE)
649                 thistime = BUFSIZE;
650             fread(buf, 1, thistime, ifile);
651             fwrite(buf, 1, thistime, ofile);
652             tocopy -= thistime;
653         }
654         fclose(ifile);
655         if ((sbuf.st_size % 2) == 1)
656             putc('\n', ofile);
657     }
658     fclose(ofile);
659     bfd_close(temp);
660 }
661
662
663 void
664 write_archive()
665 {
666     bfd            *obfd;
667     char           *xmalloc();
668     int             namelen = strlen(inarch->filename);
669     char           *new_name = xmalloc(namelen + 6);
670     bfd            *contents_head = inarch->next;
671 #if 0
672     if (inarch == &bogus_archive) {
673         /* How can this be ? */
674         return;
675     }
676     else {
677 #endif
678         strcpy(new_name, inarch->filename);
679         strcpy(new_name + namelen, ".art");
680         obfd = bfd_openw(new_name,
681                  /* FIXME: violates abstraction; need a better protocol */
682                          (inarch->xvec ? bfd_get_target(inarch) : NULL));
683
684         if (obfd == NULL)
685             bfd_fatal(inarch->filename);
686
687         bfd_set_format(obfd, bfd_archive);
688         obfd->has_armap = write_armap;
689
690         if (bfd_set_archive_head(obfd, contents_head) != true)
691             bfd_fatal(inarch->filename);
692
693         if (!bfd_close(obfd))
694             bfd_fatal(inarch->filename);
695
696         /* We don't care if this fails, we might be creating the
697            archive */
698         (void) unlink(inarch->filename);
699
700         if (rename(new_name, inarch->filename) != 0)
701             bfd_fatal(inarch->filename);
702 #if 0
703     }
704 #endif
705 }
706
707
708
709 /*
710    returns a pointer to the pointer to the entry which should be rplacd'd
711    into when altering.  default_pos should be how to interpret pos_default,
712    and should be a pos value.
713 */
714
715 bfd **
716 get_pos_bfd(contents, default_pos)
717     bfd           **contents;
718     enum pos        default_pos;
719 {
720     bfd           **after_bfd;
721
722     enum pos        realpos = (postype == pos_default ? default_pos : postype);
723     switch (realpos) {
724
725     case pos_end:
726         after_bfd = contents;
727         while (*after_bfd) {
728             after_bfd = &((*after_bfd)->next);
729         }
730
731         break;
732 #if 0
733     case pos_after:
734         for (after_bfd = contents; after_bfd; after_bfd = after_bfd->next)
735             if (!strcpy(after_bfd->filename, posname))
736                 break;
737         break;
738     case pos_before:
739         for (after_bfd = contents; after_bfd; after_bfd = after_bfd->next)
740             if (after_bfd->next && (!strcpy(after_bfd->next->filename, posname)))
741                 break;
742 #endif
743     }
744
745     return after_bfd;
746 }
747
748
749 void
750 delete_members(files_to_delete)
751     char          **files_to_delete;
752 {
753     bfd           **current_ptr_ptr;
754     boolean         found;
755     boolean         something_changed = false;
756     for (; *files_to_delete != NULL; ++files_to_delete) {
757         /*
758            In a.out systems, the armap is optional.  It's also called
759            __.SYMDEF.  So if the user asked to delete it, we should remember
760            that fact. The name is NULL in COFF archives, so using this as a
761            key is as good as anything I suppose
762         */
763         if (!strcmp(*files_to_delete, "__.SYMDEF")) {
764             inarch->has_armap = false;
765             write_armap = false;
766             continue;
767         }
768
769         found = false;
770         current_ptr_ptr = &(inarch->next);
771         while (*current_ptr_ptr) {
772             if (strcmp(*files_to_delete, (*current_ptr_ptr)->filename) == 0) {
773                 found = true;
774                 something_changed = true;
775                 if (verbose)
776                     printf("d - %s\n",
777                            *files_to_delete);
778                 *current_ptr_ptr = ((*current_ptr_ptr)->next);
779                 goto next_file;
780
781             }
782             else {
783                 current_ptr_ptr = &((*current_ptr_ptr)->next);
784             }
785         }
786
787         if (verbose && found == false) {
788             printf("No member named `%s'\n", *files_to_delete);
789         }
790 next_file:;
791
792     }
793
794     if (something_changed == true) {
795         write_archive();
796     }
797 }
798
799
800 /* Reposition existing members within an archive */
801
802 void
803 move_members(files_to_move)
804     char          **files_to_move;
805 {
806     bfd           **after_bfd;  /* New entries go after this one */
807     bfd           **current_ptr_ptr;    /* cdr pointer into contents */
808
809
810
811
812     for (; *files_to_move; ++files_to_move) {
813         current_ptr_ptr = &(inarch->next);
814         while (*current_ptr_ptr) {
815             bfd            *current_ptr = *current_ptr_ptr;
816             if (strcmp(normalize(*files_to_move), current_ptr->filename) == 0) {
817                 /*
818                    Move this file to the end of the list - first cut from
819                    where it is.
820                 */
821                 *current_ptr_ptr = current_ptr->next;
822
823                 /* Now glue to end */
824                 after_bfd = get_pos_bfd(&inarch->next, pos_end);
825                 *after_bfd = current_ptr;
826                 current_ptr->next = (bfd *) NULL;
827
828                 if (verbose)
829                     printf("m - %s\n", *files_to_move);
830
831                 goto next_file;
832             }
833             current_ptr_ptr = &((*current_ptr_ptr)->next);
834         }
835         fprintf(stderr, "No entry %s in archive %s!\n",
836                 *files_to_move, inarch->filename);
837         exit(1);
838 next_file:;
839     }
840
841     write_archive();
842 }
843
844
845 /* Ought to default to replacing in place, but this is existing practice! */
846
847 void
848 replace_members(files_to_move)
849     char          **files_to_move;
850 {
851     bfd           **after_bfd;  /* New entries go after this one */
852     bfd            *current;
853     bfd           **current_ptr;
854     bfd            *temp;
855     /*
856        If the first item in the archive is an __.SYMDEF then remove it
857     */
858     if (inarch->next &&
859         strcmp(inarch->next->filename, "__.SYMDEF") == 0) {
860         inarch->next = inarch->next->next;
861     }
862
863
864
865     while (files_to_move && *files_to_move) {
866         current_ptr = &inarch->next;
867         while (*current_ptr) {
868             current = *current_ptr;
869             
870             if (!strcmp(normalize(*files_to_move), current->filename)) {
871                 if (newer_only) {
872                     struct stat     fsbuf,
873                                     asbuf;
874
875                     if (current->arelt_data == NULL) {
876                       /* This can only happen if you specify a file on the
877                          command line more than once. */
878                       fprintf (stderr, "Duplicate file specified: %s -- skipping.\n", *files_to_move);
879                       goto next_file;
880                     }
881
882                     if (stat(*files_to_move, &fsbuf) != 0) {
883                         if (errno != ENOENT)
884                             bfd_fatal(*files_to_move);
885                         goto next_file;
886                     }
887                     if (bfd_stat_arch_elt(current, &asbuf) != 0)
888                         fatal("Internal stat error on %s", current->filename);
889
890                     if (fsbuf.st_mtime <= asbuf.st_mtime)
891                         goto next_file;
892                 }
893
894                 /* snip out this entry from the chain */
895                 *current_ptr = current->next;
896
897                 after_bfd = get_pos_bfd(&inarch->next, pos_end);
898                 temp = *after_bfd;
899                 *after_bfd = bfd_openr(*files_to_move, NULL);
900                 if (*after_bfd == (bfd *) NULL) {
901                     fprintf(stderr, "Can't open file %s\n", *files_to_move);
902                     exit(1);
903                 }
904 #ifdef GNU960
905                 gnu960_verify_target(*after_bfd);       /* Exits on failure */
906 #endif
907                 (*after_bfd)->next = temp;
908
909                 if (verbose) {
910                     printf("%c - %s\n", (postype == pos_after ? 'r' : 'a'),
911                            *files_to_move);
912                 }
913                 goto next_file;
914             }
915             current_ptr = &(current->next);
916         }
917
918         /* It isn't in there, so add to end */
919
920         after_bfd = get_pos_bfd(&inarch->next, pos_end);
921         temp = *after_bfd;
922         *after_bfd = bfd_openr(*files_to_move, NULL);
923         if (*after_bfd == (bfd *) NULL) {
924             fprintf(stderr, "Can't open file %s\n", *files_to_move);
925             exit(1);
926         }
927 #ifdef GNU960
928         gnu960_verify_target(*after_bfd);       /* Exits on failure */
929 #endif
930         if (verbose) {
931             printf("c - %s\n", *files_to_move);
932         }
933
934         (*after_bfd)->next = temp;
935
936 next_file:;
937
938         files_to_move++;
939     }
940
941
942     write_archive();
943 }
944
945 void
946 ranlib_only(archname)
947     char           *archname;
948 {
949     write_armap = true;
950     open_inarch(archname);
951     write_archive();
952     exit(0);
953 }
954
955
This page took 0.079765 seconds and 4 git commands to generate.