(linenum→info "unix/slp.c:2238")

binutils/2.18/binutils/ar.c

    1: /* ar.c - Archive modify and extract.
    2:    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
    3:    2001, 2002, 2003, 2004, 2005, 2006, 2007
    4:    Free Software Foundation, Inc.
    5: 
    6:    This file is part of GNU Binutils.
    7: 
    8:    This program 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 3 of the License, or
   11:    (at your option) any later version.
   12: 
   13:    This program 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 this program; if not, write to the Free Software
   20:    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   21:    MA 02110-1301, USA.  */
   22: ^L
   23: /*
   24:    Bugs: should use getopt the way tar does (complete w/optional -) and
   25:    should have long options too. GNU ar used to check file against filesystem
   26:    in quick_update and replace operations (would check mtime). Doesn't warn
   27:    when name truncated. No way to specify pos_end. Error messages should be
   28:    more consistent.  */
   29: 
   30: #include "sysdep.h"
   31: #include "bfd.h"
   32: #include "libiberty.h"
   33: #include "progress.h"
   34: #include "aout/ar.h"
   35: #include "libbfd.h"
   36: #include "bucomm.h"
   37: #include "arsup.h"
   38: #include "filenames.h"
   39: #include "binemul.h"
   40: #include <sys/stat.h>
   41: 
   42: #ifdef __GO32___
   43: #define EXT_NAME_LEN 3          /* bufflen of addition to name if it's MS-DOS */
   44: #else
   45: #define EXT_NAME_LEN 6          /* ditto for *NIX */
   46: #endif
   47: 
   48: /* We need to open files in binary modes on system where that makes a
   49:    difference.  */
   50: #ifndef O_BINARY
   51: #define O_BINARY 0
   52: #endif
   53: 
   54: /* Kludge declaration from BFD!  This is ugly!  FIXME!  XXX */
   55: 
   56: struct ar_hdr *
   57:   bfd_special_undocumented_glue (bfd * abfd, const char *filename);
   58: 
   59: /* Static declarations */
   60: 
   61: static void mri_emul (void);
   62: static const char *normalize (const char *, bfd *);
   63: static void remove_output (void);
   64: static void map_over_members (bfd *, void (*)(bfd *), char **, int);
   65: static void print_contents (bfd * member);
   66: static void delete_members (bfd *, char **files_to_delete);
   67: 
   68: static void move_members (bfd *, char **files_to_move);
   69: static void replace_members
   70:   (bfd *, char **files_to_replace, bfd_boolean quick);
   71: static void print_descr (bfd * abfd);
   72: static void write_archive (bfd *);
   73: static int  ranlib_only (const char *archname);
   74: static int  ranlib_touch (const char *archname);
   75: static void usage (int);
   76: ^L
   77: /** Globals and flags */
   78: 
   79: static int mri_mode;
   80: 
   81: /* This flag distinguishes between ar and ranlib:
   82:    1 means this is 'ranlib'; 0 means this is 'ar'.
   83:    -1 means if we should use argv[0] to decide.  */
   84: extern int is_ranlib;
   85: 
   86: /* Nonzero means don't warn about creating the archive file if necessary.  */
   87: int silent_create = 0;
   88: 
   89: /* Nonzero means describe each action performed.  */
   90: int verbose = 0;
   91: 
   92: /* Nonzero means preserve dates of members when extracting them.  */
   93: int preserve_dates = 0;
   94: 
   95: /* Nonzero means don't replace existing members whose dates are more recent
   96:    than the corresponding files.  */
   97: int newer_only = 0;
   98: 
   99: /* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
  100:    member).  -1 means we've been explicitly asked to not write a symbol table;
  101:    +1 means we've been explicitly asked to write it;
  102:    0 is the default.
  103:    Traditionally, the default in BSD has been to not write the table.
  104:    However, for POSIX.2 compliance the default is now to write a symbol table
  105:    if any of the members are object files.  */
  106: int write_armap = 0;
  107: 
  108: /* Nonzero means it's the name of an existing member; position new or moved
  109:    files with respect to this one.  */
  110: char *posname = NULL;
  111: 
  112: /* Sez how to use `posname': pos_before means position before that member.
  113:    pos_after means position after that member. pos_end means always at end.
  114:    pos_default means default appropriately. For the latter two, `posname'
  115:    should also be zero.  */
  116: enum pos
  117:   {
  118:     pos_default, pos_before, pos_after, pos_end
  119:   } postype = pos_default;
  120: 
  121: static bfd **
  122: get_pos_bfd (bfd **, enum pos, const char *);
  123: 
  124: /* For extract/delete only.  If COUNTED_NAME_MODE is TRUE, we only
  125:    extract the COUNTED_NAME_COUNTER instance of that name.  */
  126: static bfd_boolean counted_name_mode = 0;
  127: static int counted_name_counter = 0;
  128: 
  129: /* Whether to truncate names of files stored in the archive.  */
  130: static bfd_boolean ar_truncate = FALSE;
  131: 
  132: /* Whether to use a full file name match when searching an archive.
  133:    This is convenient for archives created by the Microsoft lib
  134:    program.  */
  135: static bfd_boolean full_pathname = FALSE;
  136: 
  137: int interactive = 0;
  138: 
  139: static void
  140: mri_emul (void)
  141: {
  142:   interactive = isatty (fileno (stdin));
  143:   yyparse ();
  144: }
  145: 
  146: /* If COUNT is 0, then FUNCTION is called once on each entry.  If nonzero,
  147:    COUNT is the length of the FILES chain; FUNCTION is called on each entry
  148:    whose name matches one in FILES.  */
  149: 
  150: static void
  151: map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
  152: {
  153:   bfd *head;
  154:   int match_count;
  155: 
  156:   if (count == 0)
  157:     {
  158:       for (head = arch->archive_next; head; head = head->archive_next)
  159:         {
  160:           PROGRESS (1);
  161:           function (head);
  162:         }
  163:       return;
  164:     }
  165: 
  166:   /* This may appear to be a baroque way of accomplishing what we want.
  167:      However we have to iterate over the filenames in order to notice where
  168:      a filename is requested but does not exist in the archive.  Ditto
  169:      mapping over each file each time -- we want to hack multiple
  170:      references.  */
  171: 
  172:   for (; count > 0; files++, count--)
  173:     {
  174:       bfd_boolean found = FALSE;
  175: 
  176:       match_count = 0;
  177:       for (head = arch->archive_next; head; head = head->archive_next)
  178:         {
  179:           PROGRESS (1);
  180:           if (head->filename == NULL)
  181:             {
  182:               /* Some archive formats don't get the filenames filled in
  183:                  until the elements are opened.  */
  184:               struct stat buf;
  185:               bfd_stat_arch_elt (head, &buf);
  186:             }
  187:           if ((head->filename != NULL) &&
  188:               (!FILENAME_CMP (normalize (*files, arch), head->filename)))
  189:             {
  190:               ++match_count;
  191:               if (counted_name_mode
  192:                   && match_count != counted_name_counter)
  193:                 {
  194:                   /* Counting, and didn't match on count; go on to the
  195:                      next one.  */
  196:                   continue;
  197:                 }
  198: 
  199:               found = TRUE;
  200:               function (head);
  201:             }
  202:         }
  203:       if (!found)
  204:         /* xgettext:c-format */
  205:         fprintf (stderr, _("no entry %s in archive\n"), *files);
  206:     }
  207: }
  208: ^L
  209: bfd_boolean operation_alters_arch = FALSE;
  210: 
  211: static void
  212: usage (int help)
  213: {
  214:   FILE *s;
  215: 
  216:   s = help ? stdout : stderr;
  217: 
  218:   if (! is_ranlib)
  219:     {
  220:       /* xgettext:c-format */
  221:       fprintf (s, _("Usage: %s [emulation options] [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file file...\n"),
  222:                program_name);
  223:       /* xgettext:c-format */
  224:       fprintf (s, _("       %s -M [<mri-script]\n"), program_name);
  225:       fprintf (s, _(" commands:\n"));
  226:       fprintf (s, _("  d            - delete file(s) from the archive\n"));
  227:       fprintf (s, _("  m[ab]        - move file(s) in the archive\n"));
  228:       fprintf (s, _("  p            - print file(s) found in the archive\n"));
  229:       fprintf (s, _("  q[f]         - quick append file(s) to the archive\n"));
  230:       fprintf (s, _("  r[ab][f][u]  - replace existing or insert new file(s) into the archive\n"));
  231:       fprintf (s, _("  t            - display contents of archive\n"));
  232:       fprintf (s, _("  x[o]         - extract file(s) from the archive\n"));
  233:       fprintf (s, _(" command specific modifiers:\n"));
  234:       fprintf (s, _("  [a]          - put file(s) after [member-name]\n"));
  235:       fprintf (s, _("  [b]          - put file(s) before [member-name] (same as [i])\n"));
  236:       fprintf (s, _("  [N]          - use instance [count] of name\n"));
  237:       fprintf (s, _("  [f]          - truncate inserted file names\n"));
  238:       fprintf (s, _("  [P]          - use full path names when matching\n"));
  239:       fprintf (s, _("  [o]          - preserve original dates\n"));
  240:       fprintf (s, _("  [u]          - only replace files that are newer than current archive contents\n"));
  241:       fprintf (s, _(" generic modifiers:\n"));
  242:       fprintf (s, _("  [c]          - do not warn if the library had to be created\n"));
  243:       fprintf (s, _("  [s]          - create an archive index (cf. ranlib)\n"));
  244:       fprintf (s, _("  [S]          - do not build a symbol table\n"));
  245:       fprintf (s, _("  [v]          - be verbose\n"));
  246:       fprintf (s, _("  [V]          - display the version number\n"));
  247:       fprintf (s, _("  @<file>      - read options from <file>\n"));
  248:  
  249:       ar_emul_usage (s);
  250:     }
  251:   else
  252:     {
  253:       /* xgettext:c-format */
  254:       fprintf (s, _("Usage: %s [options] archive\n"), program_name);
  255:       fprintf (s, _(" Generate an index to speed access to archives\n"));
  256:       fprintf (s, _(" The options are:\n\
  257:   @<file>                      Read options from <file>\n\
  258:   -h --help                    Print this help message\n\
  259:   -V --version                 Print version information\n"));
  260:     }
  261: 
  262:   list_supported_targets (program_name, s);
  263: 
  264:   if (REPORT_BUGS_TO[0] && help)
  265:     fprintf (s, _("Report bugs to %s\n"), REPORT_BUGS_TO);
  266: 
  267:   xexit (help ? 0 : 1);
  268: }
  269: 
  270: /* Normalize a file name specified on the command line into a file
  271:    name which we will use in an archive.  */
  272: 
  273: static const char *
  274: normalize (const char *file, bfd *abfd)
  275: {
  276:   const char *filename;
  277: 
  278:   if (full_pathname)
  279:     return file;
  280: 
  281:   filename = strrchr (file, '/');
  282: #ifdef HAVE_DOS_BASED_FILE_SYSTEM
  283:   {
  284:     /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
  285:     char *bslash = strrchr (file, '\\');
  286:     if (filename == NULL || (bslash != NULL && bslash > filename))
  287:       filename = bslash;
  288:     if (filename == NULL && file[0] != '\0' && file[1] == ':')
  289:       filename = file + 1;
  290:   }
  291: #endif
  292:   if (filename != (char *) NULL)
  293:     filename++;
  294:   else
  295:     filename = file;
  296: 
  297:   if (ar_truncate
  298:       && abfd != NULL
  299:       && strlen (filename) > abfd->xvec->ar_max_namelen)
  300:     {
  301:       char *s;
  302: 
  303:       /* Space leak.  */
  304:       s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
  305:       memcpy (s, filename, abfd->xvec->ar_max_namelen);
  306:       s[abfd->xvec->ar_max_namelen] = '\0';
  307:       filename = s;
  308:     }
  309: 
  310:   return filename;
  311: }
  312: 
  313: /* Remove any output file.  This is only called via xatexit.  */
  314: 
  315: static const char *output_filename = NULL;
  316: static FILE *output_file = NULL;
  317: static bfd *output_bfd = NULL;
  318: 
  319: static void
  320: remove_output (void)
  321: {
  322:   if (output_filename != NULL)
  323:     {
  324:       if (output_bfd != NULL)
  325:         bfd_cache_close (output_bfd);
  326:       if (output_file != NULL)
  327:         fclose (output_file);
  328:       unlink_if_ordinary (output_filename);
  329:     }
  330: }
  331: 
  332: /* The option parsing should be in its own function.
  333:    It will be when I have getopt working.  */
  334: 
  335: int main (int, char **);
  336: 
  337: int
  338: main (int argc, char **argv)
  339: {
  340:   char *arg_ptr;
  341:   char c;
  342:   enum
  343:     {
  344:       none = 0, delete, replace, print_table,
  345:       print_files, extract, move, quick_append
  346:     } operation = none;
  347:   int arg_index;
  348:   char **files;
  349:   int file_count;
  350:   char *inarch_filename;
  351:   int show_version;
  352:   int i;
  353:   int do_posix = 0;
  354: 
  355: #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
  356:   setlocale (LC_MESSAGES, "");
  357: #endif
  358: #if defined (HAVE_SETLOCALE)
  359:   setlocale (LC_CTYPE, "");
  360: #endif
  361:   bindtextdomain (PACKAGE, LOCALEDIR);
  362:   textdomain (PACKAGE);
  363: 
  364:   program_name = argv[0];
  365:   xmalloc_set_program_name (program_name);
  366: 
  367:   expandargv (&argc, &argv);
  368: 
  369:   if (is_ranlib < 0)
  370:     {
  371:       char *temp;
  372: 
  373:       temp = strrchr (program_name, '/');
  374: #ifdef HAVE_DOS_BASED_FILE_SYSTEM
  375:       {
  376:         /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
  377:         char *bslash = strrchr (program_name, '\\');
  378:         if (temp == NULL || (bslash != NULL && bslash > temp))
  379:           temp = bslash;
  380:         if (temp == NULL && program_name[0] != '\0' && program_name[1] == ':')
  381:           temp = program_name + 1;
  382:       }
  383: #endif
  384:       if (temp == NULL)
  385:         temp = program_name;
  386:       else
  387:         ++temp;
  388:       if (strlen (temp) >= 6
  389:           && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib") == 0)
  390:         is_ranlib = 1;
  391:       else
  392:         is_ranlib = 0;
  393:     }
  394: 
  395:   if (argc > 1 && argv[1][0] == '-')
  396:     {
  397:       if (strcmp (argv[1], "--help") == 0)
  398:         usage (1);
  399:       else if (strcmp (argv[1], "--version") == 0)
  400:         {
  401:           if (is_ranlib)
  402:             print_version ("ranlib");
  403:           else
  404:             print_version ("ar");
  405:         }
  406:     }
  407: 
  408:   START_PROGRESS (program_name, 0);
  409: 
  410:   bfd_init ();
  411:   set_default_bfd_target ();
  412: 
  413:   show_version = 0;
  414: 
  415:   xatexit (remove_output);
  416: 
  417:   for (i = 1; i < argc; i++)
  418:     if (! ar_emul_parse_arg (argv[i]))
  419:       break;
  420:   argv += (i - 1);
  421:   argc -= (i - 1);
  422: 
  423:   if (is_ranlib)
  424:     {
  425:       int status = 0;
  426:       bfd_boolean touch = FALSE;
  427: 
  428:       if (argc < 2
  429:           || strcmp (argv[1], "--help") == 0
  430:           || strcmp (argv[1], "-h") == 0
  431:           || strcmp (argv[1], "-H") == 0)
  432:         usage (0);
  433:       if (strcmp (argv[1], "-V") == 0
  434:           || strcmp (argv[1], "-v") == 0
  435:           || CONST_STRNEQ (argv[1], "--v"))
  436:         print_version ("ranlib");
  437:       arg_index = 1;
  438:       if (strcmp (argv[1], "-t") == 0)
  439:         {
  440:           ++arg_index;
  441:           touch = TRUE;
  442:         }
  443:       while (arg_index < argc)
  444:         {
  445:           if (! touch)
  446:             status |= ranlib_only (argv[arg_index]);
  447:           else
  448:             status |= ranlib_touch (argv[arg_index]);
  449:           ++arg_index;
  450:         }
  451:       xexit (status);
  452:     }
  453: 
  454:   if (argc == 2 && strcmp (argv[1], "-M") == 0)
  455:     {
  456:       mri_emul ();
  457:       xexit (0);
  458:     }
  459: 
  460:   if (argc < 2)
  461:     usage (0);
  462: 
  463:   arg_index = 1;
  464:   arg_ptr = argv[arg_index];
  465: 
  466:   if (*arg_ptr == '-')
  467:     {
  468:       /* When the first option starts with '-' we support POSIX-compatible
  469:          option parsing.  */
  470:       do_posix = 1;
  471:       ++arg_ptr;                        /* compatibility */
  472:     }
  473: 
  474:   do
  475:     {
  476:       while ((c = *arg_ptr++) != '\0')
  477:         {
  478:           switch (c)
  479:             {
  480:             case 'd':
  481:             case 'm':
  482:             case 'p':
  483:             case 'q':
  484:             case 'r':
  485:             case 't':
  486:             case 'x':
  487:               if (operation != none)
  488:                 fatal (_("two different operation options specified"));
  489:               switch (c)
  490:                 {
  491:                 case 'd':
  492:                   operation = delete;
  493:                   operation_alters_arch = TRUE;
  494:                   break;
  495:                 case 'm':
  496:                   operation = move;
  497:                   operation_alters_arch = TRUE;
  498:                   break;
  499:                 case 'p':
  500:                   operation = print_files;
  501:                   break;
  502:                 case 'q':
  503:                   operation = quick_append;
  504:                   operation_alters_arch = TRUE;
  505:                   break;
  506:                 case 'r':
  507:                   operation = replace;
  508:                   operation_alters_arch = TRUE;
  509:                   break;
  510:                 case 't':
  511:                   operation = print_table;
  512:                   break;
  513:                 case 'x':
  514:                   operation = extract;
  515:                   break;
  516:                 }
  517:             case 'l':
  518:               break;
  519:             case 'c':
  520:               silent_create = 1;
  521:               break;
  522:             case 'o':
  523:               preserve_dates = 1;
  524:               break;
  525:             case 'V':
  526:               show_version = TRUE;
  527:               break;
  528:             case 's':
  529:               write_armap = 1;
  530:               break;
  531:             case 'S':
  532:               write_armap = -1;
  533:               break;
  534:             case 'u':
  535:               newer_only = 1;
  536:               break;
  537:             case 'v':
  538:               verbose = 1;
  539:               break;
  540:             case 'a':
  541:               postype = pos_after;
  542:               break;
  543:             case 'b':
  544:               postype = pos_before;
  545:               break;
  546:             case 'i':
  547:               postype = pos_before;
  548:               break;
  549:             case 'M':
  550:               mri_mode = 1;
  551:               break;
  552:             case 'N':
  553:               counted_name_mode = TRUE;
  554:               break;
  555:             case 'f':
  556:               ar_truncate = TRUE;
  557:               break;
  558:             case 'P':
  559:               full_pathname = TRUE;
  560:               break;
  561:             default:
  562:               /* xgettext:c-format */
  563:               non_fatal (_("illegal option -- %c"), c);
  564:               usage (0);
  565:             }
  566:         }
  567: 
  568:       /* With POSIX-compatible option parsing continue with the next
  569:          argument if it starts with '-'.  */
  570:       if (do_posix && arg_index + 1 < argc && argv[arg_index + 1][0] == '-')
  571:         arg_ptr = argv[++arg_index] + 1;
  572:       else
  573:         do_posix = 0;
  574:     }
  575:   while (do_posix);
  576: 
  577:   if (show_version)
  578:     print_version ("ar");
  579: 
  580:   ++arg_index;
  581:   if (arg_index >= argc)
  582:     usage (0);
  583: 
  584:   if (mri_mode)
  585:     {
  586:       mri_emul ();
  587:     }
  588:   else
  589:     {
  590:       bfd *arch;
  591: 
  592:       /* We don't use do_quick_append any more.  Too many systems
  593:          expect ar to always rebuild the symbol table even when q is
  594:          used.  */
  595: