125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Create, modify, and extract from archives.
225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Copyright (C) 2005-2012 Red Hat, Inc.
325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   it under the terms of the GNU General Public License as published by the
725b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Free Software Foundation; version 2 of the License.
825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   General Public License for more details.
1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   You should have received a copy of the GNU General Public License along
1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Red Hat elfutils is an included package of the Open Invention Network.
1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng   An included package of the Open Invention Network is a package for which
2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Open Invention Network licensees cross-license their patents.  No patent
2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   license is granted, either expressly or impliedly, by designation as an
2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   included package.  Should you wish to participate in the Open Invention
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Network licensing program, please visit www.openinventionnetwork.com
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   <http://www.openinventionnetwork.com>.  */
2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef HAVE_CONFIG_H
2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng# include <config.h>
2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <argp.h>
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <assert.h>
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <error.h>
3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <fcntl.h>
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <gelf.h>
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <libintl.h>
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <limits.h>
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <locale.h>
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <mcheck.h>
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <search.h>
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h>
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h>
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio.h>
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdio_ext.h>
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h>
4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <time.h>
4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h>
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/mman.h>
4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/stat.h>
4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/time.h>
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <system.h>
5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "arlib.h"
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Name and version of program.  */
5725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void print_version (FILE *stream, struct argp_state *state);
5825b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Prototypes for local functions.  */
6125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int do_oper_extract (int oper, const char *arfname, char **argv,
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    int argc, long int instance);
6325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int do_oper_delete (const char *arfname, char **argv, int argc,
6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   long int instance);
6525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int do_oper_insert (int oper, const char *arfname, char **argv,
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   int argc, const char *member);
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Bug report address.  */
7025b3c049e70834cf33790a28643ab058b507b35cBen ChengARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Definitions of arguments for argp functions.  */
7425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const struct argp_option options[] =
7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("Commands:"), 1 },
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'd', NULL, 0, N_("Delete files from archive."), 0 },
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'm', NULL, 0, N_("Move files in archive."), 0 },
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'p', NULL, 0, N_("Print files in archive."), 0 },
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'q', NULL, 0, N_("Quick append files to archive."), 0 },
8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'r', NULL, 0,
8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Replace existing or insert new file into archive."), 0 },
8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 't', NULL, 0, N_("Display content of archive."), 0 },
8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'x', NULL, 0, N_("Extract files from archive."), 0 },
8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, N_("Command Modifiers:"), 2 },
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'o', NULL, 0, N_("Preserve original dates."), 0 },
8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'N', NULL, 0, N_("Use instance [COUNT] of name."), 0 },
8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'C', NULL, 0,
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    N_("Do not replace existing files with extracted files."), 0 },
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'T', NULL, 0, N_("Allow filename to be truncated if necessary."),
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    0 },
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'v', NULL, 0, N_("Provide verbose output."), 0 },
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 's', NULL, 0, N_("Force regeneration of symbol table."), 0 },
9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'a', NULL, 0, N_("Insert file after [MEMBER]."), 0 },
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'b', NULL, 0, N_("Insert file before [MEMBER]."), 0 },
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'i', NULL, 0, N_("Same as -b."), 0 },
9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'c', NULL, 0, N_("Suppress message when library has to be created."),
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    0 },
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'P', NULL, 0, N_("Use full path for file matching."), 0 },
10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 'u', NULL, 0, N_("Update only older files in archive."), 0 },
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  { NULL, 0, NULL, 0, NULL, 0 }
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Short description of program.  */
10725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char doc[] = N_("Create, modify, and extract from archives.");
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Strings for arguments in help texts.  */
11025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic const char args_doc[] = N_("[MEMBER] [COUNT] ARCHIVE [FILE...]");
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Prototype for option handler.  */
11325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Data structure to communicate with argp functions.  */
11625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic struct argp argp =
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  options, parse_opt, args_doc, doc, arlib_argp_children, NULL, NULL
11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* What operation to perform.  */
12325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic enum
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    oper_none,
12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    oper_delete,
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    oper_move,
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    oper_print,
12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    oper_qappend,
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    oper_replace,
13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    oper_list,
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    oper_extract
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  } operation;
13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Modifiers.  */
13625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool verbose;
13725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool preserve_dates;
13825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool instance_specifed;
13925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool dont_replace_existing;
14025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool allow_truncate_fname;
14125b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool force_symtab;
14225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool suppress_create_msg;
14325b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool full_path;
14425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool update_newer;
14525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic enum { ipos_none, ipos_before, ipos_after } ipos;
14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14825b3c049e70834cf33790a28643ab058b507b35cBen Chengint
14925b3c049e70834cf33790a28643ab058b507b35cBen Chengmain (int argc, char *argv[])
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Make memory leak detection possible.  */
15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  mtrace ();
15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We use no threads here which can interfere with handling a stream.  */
15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Set locale.  */
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) setlocale (LC_ALL, "");
16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Make sure the message catalog can be found.  */
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Initialize the message catalog.  */
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) textdomain (PACKAGE_TARNAME);
16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* For historical reasons the options in the first parameter need
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     not be preceded by a dash.  Add it now if necessary.  */
17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (argc > 1 && argv[1][0] != '-')
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t len = strlen (argv[1]) + 1;
17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *newp = alloca (len + 1);
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp[0] = '-';
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memcpy (&newp[1], argv[1], len);
17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      argv[1] = newp;
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Parse and process arguments.  */
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int remaining;
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER, &remaining, NULL);
18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Tell the library which version we are expecting.  */
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) elf_version (EV_CURRENT);
18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Handle the [MEMBER] parameter.  */
18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *member = NULL;
18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ipos != ipos_none)
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Only valid for certain operations.  */
19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (operation != oper_move && operation != oper_replace)
19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (1, 0, gettext ("\
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng'a', 'b', and 'i' are only allowed with the 'm' and 'r' options"));
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (remaining == argc)
19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, 0, gettext ("\
19825b3c049e70834cf33790a28643ab058b507b35cBen ChengMEMBER parameter required for 'a', 'b', and 'i' modifiers"));
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  argp_help (&argp, stderr, ARGP_HELP_USAGE | ARGP_HELP_SEE,
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     program_invocation_short_name);
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  exit (EXIT_FAILURE);
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      member = argv[remaining++];
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Handle the [COUNT] parameter.  */
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  long int instance = -1;
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (instance_specifed)
21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Only valid for certain operations.  */
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (operation == oper_extract && operation == oper_delete)
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (1, 0, gettext ("\
21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng'N' is only meaningful with the 'x' and 'd' options"));
21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (remaining == argc)
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, 0, gettext ("COUNT parameter required"));
21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  argp_help (&argp, stderr, ARGP_HELP_SEE,
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     program_invocation_short_name);
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  exit (EXIT_FAILURE);
22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *endp;
22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      errno = 0;
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (((instance = strtol (argv[remaining], &endp, 10)) == LONG_MAX
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   && errno == ERANGE)
22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || instance <= 0
22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || *endp != '\0')
23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (1, 0, gettext ("invalid COUNT parameter %s"), argv[remaining]);
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ++remaining;
23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if ((dont_replace_existing || allow_truncate_fname)
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      && unlikely (operation != oper_extract))
23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (1, 0, gettext ("'%c' is only meaningful with the 'x' option"),
23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   dont_replace_existing ? 'C' : 'T');
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* There must at least be one more parameter specifying the archive.   */
24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (remaining == argc)
24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("archive name required"));
24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name);
24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      exit (EXIT_FAILURE);
24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *arfname = argv[remaining++];
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  argv += remaining;
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  argc -= remaining;
25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int status;
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (operation)
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case oper_none:
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, 0, gettext ("command option required"));
25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      argp_help (&argp, stderr, ARGP_HELP_STD_ERR,
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 program_invocation_short_name);
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      status = 1;
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case oper_list:
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case oper_print:
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      status = do_oper_extract (operation, arfname, argv, argc, -1);
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case oper_extract:
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      status = do_oper_extract (operation, arfname, argv, argc, instance);
26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case oper_delete:
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      status = do_oper_delete (arfname, argv, argc, instance);
27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case oper_move:
27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case oper_qappend:
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case oper_replace:
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      status = do_oper_insert (operation, arfname, argv, argc, member);
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert (! "should not happen");
28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      status = 1;
28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return status;
28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Print the version information.  */
29225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
29325b3c049e70834cf33790a28643ab058b507b35cBen Chengprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, "ar (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, gettext ("\
29725b3c049e70834cf33790a28643ab058b507b35cBen ChengCopyright (C) %s Red Hat, Inc.\n\
29825b3c049e70834cf33790a28643ab058b507b35cBen ChengThis is free software; see the source for copying conditions.  There is NO\n\
29925b3c049e70834cf33790a28643ab058b507b35cBen Chengwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng"), "2012");
30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Handle program arguments.  */
30625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic error_t
30725b3c049e70834cf33790a28643ab058b507b35cBen Chengparse_opt (int key, char *arg __attribute__ ((unused)),
30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   struct argp_state *state __attribute__ ((unused)))
30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  switch (key)
31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'd':
31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'm':
31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'p':
31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'q':
31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'r':
31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 't':
31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'x':
31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (operation != oper_none)
32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, 0, gettext ("More than one operation specified"));
32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  argp_help (&argp, stderr, ARGP_HELP_SEE,
32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     program_invocation_short_name);
32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  exit (EXIT_FAILURE);
32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (key)
32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'd':
33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  operation = oper_delete;
33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'm':
33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  operation = oper_move;
33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'p':
33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  operation = oper_print;
33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'q':
33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  operation = oper_qappend;
34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'r':
34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  operation = oper_replace;
34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 't':
34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  operation = oper_list;
34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case 'x':
34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  operation = oper_extract;
34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'a':
35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ipos = ipos_after;
35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'b':
35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'i':
35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ipos = ipos_before;
36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'c':
36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      suppress_create_msg = true;
36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'C':
36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      dont_replace_existing = true;
36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'N':
37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      instance_specifed = true;
37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'o':
37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      preserve_dates = true;
37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'P':
37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      full_path = true;
38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 's':
38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      force_symtab = true;
38425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
38525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'T':
38725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      allow_truncate_fname = true;
38825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
38925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'u':
39125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      update_newer = true;
39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
39325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    case 'v':
39525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      verbose = true;
39625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      break;
39725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    default:
39925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return ARGP_ERR_UNKNOWN;
40025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
40125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
40225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
40325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
40525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
40625b3c049e70834cf33790a28643ab058b507b35cBen Chengopen_archive (const char *arfname, int flags, int mode, Elf **elf,
40725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      struct stat *st, bool miss_allowed)
40825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
40925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int fd = open (arfname, flags, mode);
41025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fd == -1)
41125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
41225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (miss_allowed)
41325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
41425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (EXIT_FAILURE, errno, gettext ("cannot open archive '%s'"),
41625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     arfname);
41725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
41825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
41925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf != NULL)
42025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
42125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Cmd cmd = flags == O_RDONLY ? ELF_C_READ_MMAP : ELF_C_RDWR_MMAP;
42225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *elf = elf_begin (fd, cmd, NULL);
42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*elf == NULL)
42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0, gettext ("cannot open archive '%s': %s"),
42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       arfname, elf_errmsg (-1));
42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (flags == O_RDONLY && elf_kind (*elf) != ELF_K_AR)
42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0, gettext ("%s: not an archive file"), arfname);
43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (st != NULL && fstat (fd, st) != 0)
43325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, errno, gettext ("cannot stat archive '%s'"),
43425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   arfname);
43525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return fd;
43725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
43825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44025b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
44125b3c049e70834cf33790a28643ab058b507b35cBen Chengnot_found (int argc, char *argv[argc], bool found[argc])
44225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
44325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int i = 0; i < argc; ++i)
44425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (!found[i])
44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      printf (gettext ("no entry %s in archive\n"), argv[i]);
44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
44925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
45025b3c049e70834cf33790a28643ab058b507b35cBen Chengcopy_content (Elf *elf, int newfd, off_t off, size_t n)
45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t len;
45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char *rawfile = elf_rawfile (elf, &len);
45425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert (off + n <= len);
45625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Tell the kernel we will read all the pages sequentially.  */
45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t ps = sysconf (_SC_PAGESIZE);
45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (n > 2 * ps)
46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    posix_madvise (rawfile + (off & ~(ps - 1)), n, POSIX_MADV_SEQUENTIAL);
46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return write_retry (newfd, rawfile + off, n) != (ssize_t) n;
46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
46625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
46725b3c049e70834cf33790a28643ab058b507b35cBen Chengdo_oper_extract (int oper, const char *arfname, char **argv, int argc,
46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 long int instance)
46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool found[argc];
47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memset (found, '\0', sizeof (found));
47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t name_max = 0;
47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  inline bool should_truncate_fname (void)
47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (errno == ENAMETOOLONG && allow_truncate_fname)
47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (name_max == 0)
47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    long int len = pathconf (".", _PC_NAME_MAX);
48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (len > 0)
48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      name_max = len;
48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return name_max != 0;
48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return false;
48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  }
48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  off_t index_off = -1;
49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t index_size = 0;
49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  off_t cur_off = SARMAG;
49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int status = 0;
49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *elf;
49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int fd = open_archive (arfname, O_RDONLY, 0, &elf, NULL, false);
49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (hcreate (2 * argc) == 0)
49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, errno, gettext ("cannot create hash table"));
49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int cnt = 0; cnt < argc; ++cnt)
50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
50225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ENTRY entry = { .key = argv[cnt], .data = &argv[cnt] };
50325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (hsearch (entry, ENTER) == NULL)
50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, errno,
50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       gettext ("cannot insert into hash table"));
50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct stat st;
50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (force_symtab)
51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (fstat (fd, &st) != 0)
51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  error (0, errno, gettext ("cannot stat '%s'"), arfname);
51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  close (fd);
51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return 1;
51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      arlib_init ();
51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Cmd cmd = ELF_C_READ_MMAP;
52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *subelf;
52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
52625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (strcmp (arhdr->ar_name, "/") == 0)
52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  index_off = elf_getaroff (subelf);
52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  index_size = arhdr->ar_size;
53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  goto next;
53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (strcmp (arhdr->ar_name, "//") == 0)
53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto next;
53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (force_symtab)
53625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
53725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  arlib_add_symbols (elf, arfname, arhdr->ar_name, cur_off);
53825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  cur_off += (((arhdr->ar_size + 1) & ~((off_t) 1))
53925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      + sizeof (struct ar_hdr));
54025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool do_extract = argc <= 0;
54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!do_extract)
54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ENTRY entry;
54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  entry.key = arhdr->ar_name;
54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ENTRY *res = hsearch (entry, FIND);
54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (res != NULL && (instance < 0 || instance-- == 0)
54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && !found[(char **) res->data - argv])
55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    found[(char **) res->data - argv] = do_extract = true;
55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (do_extract)
55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (verbose)
55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (oper == oper_print)
55825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf ("\n<%s>\n\n", arhdr->ar_name);
56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* We have to flush now because now we use the descriptor
56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     directly.  */
56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  fflush (stdout);
56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else if (oper == oper_list)
56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  char datestr[100];
56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  strftime (datestr, sizeof (datestr), "%b %e %H:%M %Y",
56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    localtime (&arhdr->ar_date));
57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  printf ("%c%c%c%c%c%c%c%c%c %u/%u %6ju %s %s\n",
57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (arhdr->ar_mode & S_IRUSR) ? 'r' : '-',
57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (arhdr->ar_mode & S_IWUSR) ? 'w' : '-',
57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (arhdr->ar_mode & S_IXUSR)
57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  ? ((arhdr->ar_mode & S_ISUID) ? 's' : 'x')
57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  : ((arhdr->ar_mode & S_ISUID) ? 'S' : '-'),
57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (arhdr->ar_mode & S_IRGRP) ? 'r' : '-',
57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (arhdr->ar_mode & S_IWGRP) ? 'w' : '-',
57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (arhdr->ar_mode & S_IXGRP)
58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  ? ((arhdr->ar_mode & S_ISGID) ? 's' : 'x')
58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  : ((arhdr->ar_mode & S_ISGID) ? 'S' : '-'),
58225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (arhdr->ar_mode & S_IROTH) ? 'r' : '-',
58325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (arhdr->ar_mode & S_IWOTH) ? 'w' : '-',
58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (arhdr->ar_mode & S_IXOTH)
58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  ? ((arhdr->ar_mode & S_ISVTX) ? 't' : 'x')
58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  : ((arhdr->ar_mode & S_ISVTX) ? 'T' : '-'),
58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  arhdr->ar_uid,
58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  arhdr->ar_gid,
58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  (uintmax_t) arhdr->ar_size,
59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  datestr,
59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  arhdr->ar_name);
59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("x - %s\n", arhdr->ar_name);
59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (oper == oper_list)
59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (!verbose)
60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		puts (arhdr->ar_name);
60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      goto next;
60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
60425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t nleft;
60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char *data = elf_rawfile (subelf, &nleft);
60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (data == NULL)
60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (0, 0, gettext ("cannot read content of %s: %s"),
61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     arhdr->ar_name, elf_errmsg (-1));
61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      status = 1;
61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      goto next;
61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int xfd;
61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char tempfname[] = "XXXXXX";
61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  bool use_mkstemp = true;
61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (oper == oper_print)
62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    xfd = STDOUT_FILENO;
62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      xfd = mkstemp (tempfname);
62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (xfd == -1))
62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* We cannot create a temporary file.  Try to overwrite
62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     the file or create it if it does not exist.  */
62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  int flags = O_WRONLY | O_CREAT;
62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (dont_replace_existing)
63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    flags |= O_EXCL;
63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else
63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    flags |= O_TRUNC;
63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  xfd = open (arhdr->ar_name, flags, 0600);
63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (xfd == -1))
63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      int printlen = INT_MAX;
63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (should_truncate_fname ())
63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  /* Try to truncate the name.  First find out by how
64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     much.  */
64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  printlen = name_max;
64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  char truncfname[name_max + 1];
64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  *((char *) mempcpy (truncfname, arhdr->ar_name,
64525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      name_max)) = '\0';
64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  xfd = open (truncfname, flags, 0600);
64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (xfd == -1)
65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  error (0, errno, gettext ("cannot open %.*s"),
65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 (int) printlen, arhdr->ar_name);
65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  status = 1;
65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  goto next;
65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  use_mkstemp = false;
66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ssize_t n;
66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while ((n = TEMP_FAILURE_RETRY (write (xfd, data, nleft))) != -1)
66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      nleft -= n;
66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (nleft == 0)
66825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		break;
66925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      data += n;
67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (n == -1))
67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (0, errno, gettext ("failed to write %s"), arhdr->ar_name);
67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      status = 1;
67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      unlink (tempfname);
67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      close (xfd);
67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      goto next;
67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (oper != oper_print)
68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Fix up the mode.  */
68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (fchmod (xfd, arhdr->ar_mode) != 0))
68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  error (0, errno, gettext ("cannot change mode of %s"),
68725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 arhdr->ar_name);
68825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  status = 0;
68925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
69025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (preserve_dates)
69225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
69325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  struct timeval tv[2];
69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  tv[0].tv_sec = arhdr->ar_date;
69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  tv[0].tv_usec = 0;
69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  tv[1].tv_sec = arhdr->ar_date;
69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  tv[1].tv_usec = 0;
69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (futimes (xfd, tv) != 0))
70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
70125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      error (0, errno,
70225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     gettext ("cannot change modification time of %s"),
70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     arhdr->ar_name);
70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      status = 1;
70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
70725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
70825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* If we used a temporary file, move it do the right
70925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 name now.  */
71025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (use_mkstemp)
71125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
71225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  int r;
71325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
71425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (dont_replace_existing)
71525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
71625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      r = link (tempfname, arhdr->ar_name);
71725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (likely (r == 0))
71825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			unlink (tempfname);
71925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
72025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  else
72125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    r = rename (tempfname, arhdr->ar_name);
72225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
72325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (unlikely (r) != 0)
72425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    {
72525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      int printlen = INT_MAX;
72625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
72725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (should_truncate_fname ())
72825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
72925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  /* Try to truncate the name.  First find out by how
73025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			     much.  */
73125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  printlen = name_max;
73225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  char truncfname[name_max + 1];
73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  *((char *) mempcpy (truncfname, arhdr->ar_name,
73425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      name_max)) = '\0';
73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  if (dont_replace_existing)
73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    {
73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      r = link (tempfname, truncfname);
73925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			      if (likely (r == 0))
74025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				unlink (tempfname);
74125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    }
74225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  else
74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    r = rename (tempfname, truncfname);
74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
74525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
74625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      if (r != 0)
74725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			{
74825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  error (0, errno, gettext ("\
74925b3c049e70834cf33790a28643ab058b507b35cBen Chengcannot rename temporary file to %.*s"),
75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng				 printlen, arhdr->ar_name);
75125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  unlink (tempfname);
75225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			  status = 1;
75325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			}
75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    }
75525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      close (xfd);
75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    next:
76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      cmd = elf_next (subelf);
76325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf_end (subelf) != 0)
76425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (1, 0, "%s: %s", arfname, elf_errmsg (-1));
76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  hdestroy ();
76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
76925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (force_symtab)
77025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      arlib_finalize ();
77225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
77325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (symtab.symsnamelen != 0
77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We have to rewrite the file also if it initially had an index
77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     but now does not need one anymore.  */
77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || (symtab.symsnamelen == 0 && index_size != 0))
77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  char tmpfname[strlen (arfname) + 7];
77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  strcpy (stpcpy (tmpfname, arfname), "XXXXXX");
78025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int newfd = mkstemp (tmpfname);
78125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (newfd == -1))
78225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
78325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    nonew:
78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (0, errno, gettext ("cannot create new file"));
78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      status = 1;
78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
78725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Create the header.  */
79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (write_retry (newfd, ARMAG, SARMAG) != SARMAG))
79125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
79225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  // XXX Use /prof/self/fd/%d ???
79325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		nonew_unlink:
79425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  unlink (tmpfname);
79525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (newfd != -1)
79625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    close (newfd);
79725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  goto nonew;
79825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
79925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
80025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Create the new file.  There are three parts as far we are
80125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 concerned: 1. original context before the index, 2. the
80225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 new index, 3. everything after the new index.  */
80325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      off_t rest_off;
80425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (index_off != -1)
80525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		rest_off = (index_off + sizeof (struct ar_hdr)
80625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    + ((index_size + 1) & ~1ul));
80725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
80825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		rest_off = SARMAG;
80925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
81025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if ((symtab.symsnamelen != 0
81125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   && ((write_retry (newfd, symtab.symsoff,
81225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				     symtab.symsofflen)
81325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			!= (ssize_t) symtab.symsofflen)
81425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       || (write_retry (newfd, symtab.symsname,
81525b3c049e70834cf33790a28643ab058b507b35cBen Cheng					symtab.symsnamelen)
81625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			   != (ssize_t) symtab.symsnamelen)))
81725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Even if the original file had content before the
81825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     symbol table, we write it in the correct order.  */
81925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  || (index_off != SARMAG
82025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      && copy_content (elf, newfd, SARMAG, index_off - SARMAG))
82125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  || copy_content (elf, newfd, rest_off, st.st_size - rest_off)
82225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Set the mode of the new file to the same values the
82325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		     original file has.  */
82425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  || fchmod (newfd, st.st_mode & ALLPERMS) != 0
82525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  /* Never complain about fchown failing.  */
82625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  || (({asm ("" :: "r" (fchown (newfd, st.st_uid,
82725b3c049e70834cf33790a28643ab058b507b35cBen Cheng						st.st_gid))); }),
82825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      close (newfd) != 0)
82925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  || (newfd = -1, rename (tmpfname, arfname) != 0))
83025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		goto nonew_unlink;
83125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
83225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
83325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
83425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
83525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf_end (elf);
83625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
83725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  close (fd);
83825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
83925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  not_found (argc, argv, found);
84025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
84125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return status;
84225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
84325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
84425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
84525b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct armem
84625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
84725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  off_t off;
84825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  off_t old_off;
84925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t size;
85025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  long int long_name_off;
85125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct armem *next;
85225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  void *mem;
85325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  time_t sec;
85425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  uid_t uid;
85525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  gid_t gid;
85625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  mode_t mode;
85725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const char *name;
85825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *elf;
85925b3c049e70834cf33790a28643ab058b507b35cBen Cheng};
86025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
86125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
86225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
86325b3c049e70834cf33790a28643ab058b507b35cBen Chengwrite_member (struct armem *memb, off_t *startp, off_t *lenp, Elf *elf,
86425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      off_t end_off, int newfd)
86525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
86625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct ar_hdr arhdr;
86725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char tmpbuf[sizeof (arhdr.ar_name) + 1];
86825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
86925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool changed_header = memb->long_name_off != -1;
87025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (changed_header)
87125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
87225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* In case of a long file name we assume the archive header
87325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 changed and we write it here.  */
87425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memcpy (&arhdr, elf_rawfile (elf, NULL) + *startp, sizeof (arhdr));
87525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
87625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      snprintf (tmpbuf, sizeof (tmpbuf), "/%-*ld",
87725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(int) sizeof (arhdr.ar_name), memb->long_name_off);
87825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      changed_header = memcmp (arhdr.ar_name, tmpbuf,
87925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       sizeof (arhdr.ar_name)) != 0;
88025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
88125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
88225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If the files are adjacent in the old file extend the range.  */
88325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*startp != -1 && !changed_header && *startp + *lenp == memb->old_off)
88425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
88525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Extend the current range.  */
88625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *lenp += (memb->next != NULL
88725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		? memb->next->off : end_off) - memb->off;
88825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return 0;
88925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
89025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
89125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Write out the old range.  */
89225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (*startp != -1 && copy_content (elf, newfd, *startp, *lenp))
89325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
89425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
89525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *startp = memb->old_off;
89625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  *lenp = (memb->next != NULL ? memb->next->off : end_off) - memb->off;
89725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
89825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (changed_header)
89925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
90025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      memcpy (arhdr.ar_name, tmpbuf, sizeof (arhdr.ar_name));
90125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
90225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (write_retry (newfd, &arhdr, sizeof (arhdr))
90325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    != sizeof (arhdr)))
90425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return -1;
90525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
90625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *startp += sizeof (struct ar_hdr);
90725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      assert ((size_t) *lenp >= sizeof (struct ar_hdr));
90825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *lenp -= sizeof (struct ar_hdr);
90925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
91025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
91125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return 0;
91225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
91325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
91425b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Store the name in the long name table if necessary.
91525b3c049e70834cf33790a28643ab058b507b35cBen Cheng   Record its offset or -1 if we did not need to use the table.  */
91625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
91725b3c049e70834cf33790a28643ab058b507b35cBen Chengremember_long_name (struct armem *mem, const char *name, size_t namelen)
91825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
91925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  mem->long_name_off = (namelen > MAX_AR_NAME_LEN
92025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			? arlib_add_long_name (name, namelen)
92125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			: -1l);
92225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
92325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
92425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
92525b3c049e70834cf33790a28643ab058b507b35cBen Chengdo_oper_delete (const char *arfname, char **argv, int argc,
92625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		long int instance)
92725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
92825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  bool *found = alloca (sizeof (bool) * argc);
92925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memset (found, '\0', sizeof (found));
93025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
93125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* List of the files we keep.  */
93225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct armem *to_copy = NULL;
93325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
93425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int status = 0;
93525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *elf;
93625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct stat st;
93725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int fd = open_archive (arfname, O_RDONLY, 0, &elf, &st, false);
93825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
93925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (hcreate (2 * argc) == 0)
94025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, errno, gettext ("cannot create hash table"));
94125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
94225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int cnt = 0; cnt < argc; ++cnt)
94325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
94425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ENTRY entry = { .key = argv[cnt], .data = &argv[cnt] };
94525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (hsearch (entry, ENTER) == NULL)
94625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, errno,
94725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       gettext ("cannot insert into hash table"));
94825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
94925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
95025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  arlib_init ();
95125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
95225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  off_t cur_off = SARMAG;
95325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Cmd cmd = ELF_C_READ_MMAP;
95425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *subelf;
95525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
95625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
95725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
95825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
95925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Ignore the symbol table and the long file name table here.  */
96025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (strcmp (arhdr->ar_name, "/") == 0
96125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || strcmp (arhdr->ar_name, "//") == 0)
96225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto next;
96325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
96425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      bool do_delete = argc <= 0;
96525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!do_delete)
96625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
96725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ENTRY entry;
96825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  entry.key = arhdr->ar_name;
96925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ENTRY *res = hsearch (entry, FIND);
97025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (res != NULL && (instance < 0 || instance-- == 0)
97125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      && !found[(char **) res->data - argv])
97225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    found[(char **) res->data - argv] = do_delete = true;
97325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
97425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
97525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (do_delete)
97625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
97725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (verbose)
97825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("d - %s\n", arhdr->ar_name);
97925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
98025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
98125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
98225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  struct armem *newp = alloca (sizeof (struct armem));
98325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  newp->old_off = elf_getaroff (subelf);
98425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  newp->off = cur_off;
98525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
98625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  cur_off += (((arhdr->ar_size + 1) & ~((off_t) 1))
98725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		      + sizeof (struct ar_hdr));
98825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
98925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (to_copy == NULL)
99025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    to_copy = newp->next = newp;
99125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
99225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
99325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      newp->next = to_copy->next;
99425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      to_copy = to_copy->next = newp;
99525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
99625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
99725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* If we recreate the symbol table read the file's symbol
99825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	     table now.  */
99925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  arlib_add_symbols (subelf, arfname, arhdr->ar_name, newp->off);
100025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
100125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Remember long file names.  */
100225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  remember_long_name (newp, arhdr->ar_name, strlen (arhdr->ar_name));
100325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
100425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
100525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    next:
100625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      cmd = elf_next (subelf);
100725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf_end (subelf) != 0)
100825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (1, 0, "%s: %s", arfname, elf_errmsg (-1));
100925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
101025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
101125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  arlib_finalize ();
101225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
101325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  hdestroy ();
101425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
101525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Create a new, temporary file in the same directory as the
101625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     original file.  */
101725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char tmpfname[strlen (arfname) + 7];
101825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  strcpy (stpcpy (tmpfname, arfname), "XXXXXX");
101925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int newfd = mkstemp (tmpfname);
102025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (newfd == -1))
102125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto nonew;
102225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
102325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Create the header.  */
102425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (write_retry (newfd, ARMAG, SARMAG) != SARMAG))
102525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
102625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      // XXX Use /prof/self/fd/%d ???
102725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    nonew_unlink:
102825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      unlink (tmpfname);
102925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (newfd != -1)
103025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	close (newfd);
103125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    nonew:
103225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, errno, gettext ("cannot create new file"));
103325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      status = 1;
103425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      goto errout;
103525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
103625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
103725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If the archive is empty that is all we have to do.  */
103825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (to_copy != NULL))
103925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
104025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Write the symbol table or the long file name table or both.  */
104125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (symtab.symsnamelen != 0
104225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && ((write_retry (newfd, symtab.symsoff, symtab.symsofflen)
104325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       != (ssize_t) symtab.symsofflen)
104425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      || (write_retry (newfd, symtab.symsname, symtab.symsnamelen)
104525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  != (ssize_t) symtab.symsnamelen)))
104625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto nonew_unlink;
104725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
104825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (symtab.longnameslen > sizeof (struct ar_hdr)
104925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && (write_retry (newfd, symtab.longnames, symtab.longnameslen)
105025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      != (ssize_t) symtab.longnameslen))
105125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto nonew_unlink;
105225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
105325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* NULL-terminate the list of files to copy.  */
105425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct armem *last = to_copy;
105525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      to_copy = to_copy->next;
105625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      last->next = NULL;
105725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
105825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      off_t start = -1;
105925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      off_t len = -1;
106025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
106125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      do
106225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (write_member (to_copy, &start, &len, elf, cur_off, newfd) != 0)
106325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  goto nonew_unlink;
106425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while ((to_copy = to_copy->next) != NULL);
106525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
106625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Write the last part.  */
106725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (copy_content (elf, newfd, start, len))
106825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto nonew_unlink;
106925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
107025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
107125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Set the mode of the new file to the same values the original file
107225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     has.  */
107325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fchmod (newfd, st.st_mode & ALLPERMS) != 0
107425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Never complain about fchown failing.  */
107525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      || (({asm ("" :: "r" (fchown (newfd, st.st_uid, st.st_gid))); }),
107625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  close (newfd) != 0)
107725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      || (newfd = -1, rename (tmpfname, arfname) != 0))
107825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto nonew_unlink;
107925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
108025b3c049e70834cf33790a28643ab058b507b35cBen Cheng errout:
108125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef DEBUG
108225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf_end (elf);
108325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
108425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  arlib_fini ();
108525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
108625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  close (fd);
108725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
108825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
108925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  not_found (argc, argv, found);
109025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
109125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return status;
109225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
109325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
109425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
109525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic void
109625b3c049e70834cf33790a28643ab058b507b35cBen Chengno0print (bool ofmt, char *buf, int bufsize, long int val)
109725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
109825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char tmpbuf[bufsize + 1];
109925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  snprintf (tmpbuf, sizeof (tmpbuf), ofmt ? "%-*lo" : "%-*ld", bufsize, val);
110025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memcpy (buf, tmpbuf, bufsize);
110125b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
110225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
110325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
110425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int
110525b3c049e70834cf33790a28643ab058b507b35cBen Chengdo_oper_insert (int oper, const char *arfname, char **argv, int argc,
110625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		const char *member)
110725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
110825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int status = 0;
110925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *elf;
111025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct stat st;
111125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int fd = open_archive (arfname, O_RDONLY, 0, &elf, &st, oper != oper_move);
111225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
111325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* List of the files we keep.  */
111425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct armem *all = NULL;
111525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct armem *after_memberelem = NULL;
111625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct armem **found = alloca (sizeof (*found) * argc);
111725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  memset (found, '\0', sizeof (*found) * argc);
111825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
111925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  arlib_init ();
112025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
112125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Initialize early for no_old case.  */
112225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  off_t cur_off = SARMAG;
112325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
112425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fd == -1)
112525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
112625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (!suppress_create_msg)
112725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	fprintf (stderr, "%s: creating %s\n",
112825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 program_invocation_short_name, arfname);
112925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
113025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      goto no_old;
113125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
113225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
113325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Store the names of all files from the command line in a hash
113425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     table so that we can match it.  Note that when no file name is
113525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     given we are basically doing nothing except recreating the
113625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     index.  */
113725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (oper != oper_qappend)
113825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
113925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (hcreate (2 * argc) == 0)
114025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, errno, gettext ("cannot create hash table"));
114125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
114225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (int cnt = 0; cnt < argc; ++cnt)
114325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
114425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ENTRY entry;
114525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  entry.key = full_path ? argv[cnt] : basename (argv[cnt]);
114625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  entry.data = &argv[cnt];
114725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (hsearch (entry, ENTER) == NULL)
114825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    error (EXIT_FAILURE, errno,
114925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   gettext ("cannot insert into hash table"));
115025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
115125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
115225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
115325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* While iterating over the current content of the archive we must
115425b3c049e70834cf33790a28643ab058b507b35cBen Cheng     determine a number of things: which archive members to keep,
115525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     which are replaced, and where to insert the new members.  */
115625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Cmd cmd = ELF_C_READ_MMAP;
115725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *subelf;
115825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
115925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
116025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
116125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
116225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Ignore the symbol table and the long file name table here.  */
116325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (strcmp (arhdr->ar_name, "/") == 0
116425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || strcmp (arhdr->ar_name, "//") == 0)
116525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto next;
116625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
116725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct armem *newp = alloca (sizeof (struct armem));
116825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->old_off = elf_getaroff (subelf);
116925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->size = arhdr->ar_size;
117025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->sec = arhdr->ar_date;
117125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newp->mem = NULL;
117225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
117325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Remember long file names.  */
117425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      remember_long_name (newp, arhdr->ar_name, strlen (arhdr->ar_name));
117525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
117625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Check whether this is a file we are looking for.  */
117725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (oper != oper_qappend)
117825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
117925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Check whether this is the member used as the insert point.  */
118025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (member != NULL && strcmp (arhdr->ar_name, member) == 0)
118125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
118225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Note that all == NULL means insert at the beginning.  */
118325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (ipos == ipos_before)
118425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		after_memberelem = all;
118525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
118625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		after_memberelem = newp;
118725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      member = NULL;
118825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
118925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
119025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ENTRY entry;
119125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  entry.key = arhdr->ar_name;
119225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  ENTRY *res = hsearch (entry, FIND);
119325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (res != NULL && found[(char **) res->data - argv] == NULL)
119425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
119525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      found[(char **) res->data - argv] = newp;
119625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
119725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* If we insert before or after a certain element move
119825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 all files to a special list.  */
119925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (ipos != ipos_none || oper == oper_move))
120025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
120125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  if (after_memberelem == newp)
120225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    /* Since we remove this element even though we should
120325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       insert everything after it, we in fact insert
120425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       everything after the previous element.  */
120525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    after_memberelem = all;
120625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
120725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  goto next;
120825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
120925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
121025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
121125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
121225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (all == NULL)
121325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	all = newp->next = newp;
121425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
121525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
121625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  newp->next = all->next;
121725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  all = all->next = newp;
121825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
121925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
122025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    next:
122125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      cmd = elf_next (subelf);
122225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf_end (subelf) != 0)
122325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	error (EXIT_FAILURE, 0, "%s: %s", arfname, elf_errmsg (-1));
122425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
122525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
122625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (oper != oper_qappend)
122725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    hdestroy ();
122825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
122925b3c049e70834cf33790a28643ab058b507b35cBen Cheng no_old:
123025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (member != NULL)
123125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    error (EXIT_FAILURE, 0, gettext ("position member %s not found"),
123225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	   member);
123325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
123425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (oper == oper_move)
123525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
123625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Make sure all requested elements are found in the archive.  */
123725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (int cnt = 0; cnt < argc; ++cnt)
123825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
123925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (found[cnt] == NULL)
124025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
124125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      fprintf (stderr, gettext ("%s: no entry %s in archive!\n"),
124225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       program_invocation_short_name, argv[cnt]);
124325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      status = 1;
124425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
124525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
124625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (verbose)
124725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    printf ("m - %s\n", argv[cnt]);
124825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
124925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
125025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
125125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
125225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Open all the new files, get their sizes and add all symbols.  */
125325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      for (int cnt = 0; cnt < argc; ++cnt)
125425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
125525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const char *bname = basename (argv[cnt]);
125625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t bnamelen = strlen (bname);
125725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (found[cnt] == NULL)
125825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
125925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      found[cnt] = alloca (sizeof (struct armem));
126025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      found[cnt]->old_off = -1;
126125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
126225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      remember_long_name (found[cnt], bname, bnamelen);
126325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
126425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
126525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  struct stat newst;
126625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  Elf *newelf;
126725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  int newfd = open (argv[cnt], O_RDONLY);
126825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (newfd == -1)
126925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
127025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (0, errno, gettext ("cannot open %s"), argv[cnt]);
127125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      status = 1;
127225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
127325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (fstat (newfd, &newst) == -1)
127425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
127525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (0, errno, gettext ("cannot stat %s"), argv[cnt]);
127625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      close (newfd);
127725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      status = 1;
127825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
127925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (!S_ISREG (newst.st_mode))
128025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
128125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (0, errno, gettext ("%s is no regular file"), argv[cnt]);
128225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      close (newfd);
128325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      status = 1;
128425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
128525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if (update_newer
128625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   && found[cnt]->old_off != -1l
128725b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   && found[cnt]->sec > st.st_mtime)
128825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Do nothing, the file in the archive is younger.  */
128925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    close (newfd);
129025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else if ((newelf = elf_begin (newfd, ELF_C_READ_MMAP, NULL))
129125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		   == NULL)
129225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
129325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      fprintf (stderr,
129425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       gettext ("cannot get ELF descriptor for %s: %s\n"),
129525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       argv[cnt], elf_errmsg (-1));
129625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      status = 1;
129725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
129825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
129925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
130025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (verbose)
130125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		printf ("%c - %s\n",
130225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			found[cnt]->old_off == -1l ? 'a' : 'r', argv[cnt]);
130325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
130425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      found[cnt]->elf = newelf;
130525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      found[cnt]->sec = arlib_deterministic_output ? 0 : newst.st_mtime;
130625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      found[cnt]->uid = arlib_deterministic_output ? 0 : newst.st_uid;
130725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      found[cnt]->gid = arlib_deterministic_output ? 0 : newst.st_gid;
130825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      found[cnt]->mode = newst.st_mode;
130925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      found[cnt]->name = bname;
131025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
131125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      found[cnt]->mem = elf_rawfile (newelf, &found[cnt]->size);
131225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (found[cnt]->mem == NULL
131325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  || elf_cntl (newelf, ELF_C_FDDONE) != 0)
131425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		error (EXIT_FAILURE, 0, gettext ("cannot read %s: %s"),
131525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		       argv[cnt], elf_errmsg (-1));
131625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
131725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      close (newfd);
131825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
131925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (found[cnt]->old_off != -1l)
132025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		/* Remember long file names.  */
132125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		remember_long_name (found[cnt], bname, bnamelen);
132225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
132325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
132425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
132525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
132625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (status != 0)
132725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
132825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef DEBUG
132925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      elf_end (elf);
133025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
133125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      arlib_fini ();
133225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
133325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      close (fd);
133425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
133525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
133625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return status;
133725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
133825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
133925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If we have no entry point so far add at the end.  AFTER_MEMBERELEM
134025b3c049e70834cf33790a28643ab058b507b35cBen Cheng     being NULL when adding before an entry means add at the beginning.  */
134125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ipos != ipos_before && after_memberelem == NULL)
134225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    after_memberelem = all;
134325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
134425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Convert the circular list into a normal list first.  */
134525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (all != NULL)
134625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
134725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct armem *tmp = all;
134825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      all = all->next;
134925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      tmp->next = NULL;
135025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
135125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
135225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  struct armem *last_added = after_memberelem;
135325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (int cnt = 0; cnt < argc; ++cnt)
135425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (oper != oper_replace || found[cnt]->old_off == -1)
135525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
135625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (last_added == NULL)
135725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
135825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    found[cnt]->next = all;
135925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    last_added = all = found[cnt];
136025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
136125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	else
136225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
136325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    found[cnt]->next = last_added->next;
136425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    last_added = last_added->next = found[cnt];
136525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
136625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
136725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
136825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Finally compute the offset and add the symbols for the files
136925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     after the insert point.  */
137025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (all != NULL))
137125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    for (struct armem *memp = all; memp != NULL; memp = memp->next)
137225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
137325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	memp->off = cur_off;
137425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
137525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (memp->mem == NULL)
137625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
137725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    Elf_Arhdr *arhdr;
137825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    /* Fake initializing arhdr and subelf to keep gcc calm.  */
137925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    asm ("" : "=m" (arhdr), "=m" (subelf));
138025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (elf_rand (elf, memp->old_off) == 0
138125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		|| (subelf = elf_begin (fd, ELF_C_READ_MMAP, elf)) == NULL
138225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		|| (arhdr = elf_getarhdr (subelf)) == NULL)
138325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This should never happen since we already looked at the
138425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 archive content.  But who knows...  */
138525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      error (EXIT_FAILURE, 0, "%s: %s", arfname, elf_errmsg (-1));
138625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
138725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    arlib_add_symbols (subelf, arfname, arhdr->ar_name, cur_off);
138825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
138925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    elf_end (subelf);
139025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
139125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	else
139225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  arlib_add_symbols (memp->elf, arfname, memp->name, cur_off);
139325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
139425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	cur_off += (((memp->size + 1) & ~((off_t) 1))
139525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		    + sizeof (struct ar_hdr));
139625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
139725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
139825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Now we have all the information for the symbol table and long
139925b3c049e70834cf33790a28643ab058b507b35cBen Cheng     file name table.  Construct the final layout.  */
140025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  arlib_finalize ();
140125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
140225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Create a new, temporary file in the same directory as the
140325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     original file.  */
140425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  char tmpfname[strlen (arfname) + 7];
140525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  strcpy (stpcpy (tmpfname, arfname), "XXXXXX");
140625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int newfd;
140725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fd != -1)
140825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    newfd = mkstemp (tmpfname);
140925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
141025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
141125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      newfd = open (arfname, O_RDWR | O_CREAT | O_EXCL, DEFFILEMODE);
141225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (newfd == -1 && errno == EEXIST)
141325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	/* Bah, first the file did not exist, now it does.  Restart.  */
141425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return do_oper_insert (oper, arfname, argv, argc, member);
141525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
141625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (newfd == -1))
141725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    goto nonew;
141825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
141925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Create the header.  */
142025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (write_retry (newfd, ARMAG, SARMAG) != SARMAG))
142125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
142225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    nonew_unlink:
142325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (fd != -1)
142425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
142525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  // XXX Use /prof/self/fd/%d ???
142625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  unlink (tmpfname);
142725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (newfd != -1)
142825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    close (newfd);
142925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
143025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    nonew:
143125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      error (0, errno, gettext ("cannot create new file"));
143225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      status = 1;
143325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      goto errout;
143425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
143525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
143625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If the new archive is not empty we actually have something to do.  */
143725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (all != NULL))
143825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
143925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Write the symbol table or the long file name table or both.  */
144025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (symtab.symsnamelen != 0
144125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && ((write_retry (newfd, symtab.symsoff, symtab.symsofflen)
144225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	       != (ssize_t) symtab.symsofflen)
144325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      || (write_retry (newfd, symtab.symsname, symtab.symsnamelen)
144425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  != (ssize_t) symtab.symsnamelen)))
144525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto nonew_unlink;
144625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
144725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (symtab.longnameslen > sizeof (struct ar_hdr)
144825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  && (write_retry (newfd, symtab.longnames, symtab.longnameslen)
144925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      != (ssize_t) symtab.longnameslen))
145025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto nonew_unlink;
145125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
145225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      off_t start = -1;
145325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      off_t len = -1;
145425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
145525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      while (all != NULL)
145625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
145725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (all->mem != NULL)
145825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
145925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This is a new file.  If there is anything from the
146025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 archive left to be written do it now.  */
146125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (start != -1  && copy_content (elf, newfd, start, len))
146225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		goto nonew_unlink;
146325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
146425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      start = -1;
146525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      len = -1;
146625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
146725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Create the header.  */
146825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      struct ar_hdr arhdr;
146925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      char tmpbuf[sizeof (arhdr.ar_name) + 1];
147025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (all->long_name_off == -1)
147125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
147225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  size_t namelen = strlen (all->name);
147325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  char *p = mempcpy (arhdr.ar_name, all->name, namelen);
147425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  *p++ = '/';
147525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  memset (p, ' ', sizeof (arhdr.ar_name) - namelen - 1);
147625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
147725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      else
147825b3c049e70834cf33790a28643ab058b507b35cBen Cheng		{
147925b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  snprintf (tmpbuf, sizeof (arhdr.ar_name) + 1, "/%-*ld",
148025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    (int) sizeof (arhdr.ar_name), all->long_name_off);
148125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  memcpy (arhdr.ar_name, tmpbuf, sizeof (arhdr.ar_name));
148225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		}
148325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
148425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      no0print (false, arhdr.ar_date, sizeof (arhdr.ar_date),
148525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			all->sec);
148625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      no0print (false, arhdr.ar_uid, sizeof (arhdr.ar_uid), all->uid);
148725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      no0print (false, arhdr.ar_gid, sizeof (arhdr.ar_gid), all->gid);
148825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      no0print (true, arhdr.ar_mode, sizeof (arhdr.ar_mode),
148925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			all->mode);
149025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      no0print (false, arhdr.ar_size, sizeof (arhdr.ar_size),
149125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			all->size);
149225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      memcpy (arhdr.ar_fmag, ARFMAG, sizeof (arhdr.ar_fmag));
149325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
149425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (write_retry (newfd, &arhdr, sizeof (arhdr))
149525b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    != sizeof (arhdr)))
149625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		goto nonew_unlink;
149725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
149825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Now the file itself.  */
149925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (unlikely (write_retry (newfd, all->mem, all->size)
150025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			    != (off_t) all->size))
150125b3c049e70834cf33790a28643ab058b507b35cBen Cheng		goto nonew_unlink;
150225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
150325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* Pad the file if its size is odd.  */
150425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if ((all->size & 1) != 0)
150525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		if (unlikely (write_retry (newfd, "\n", 1) != 1))
150625b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  goto nonew_unlink;
150725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
150825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  else
150925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
151025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* This is a member from the archive.  */
151125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (write_member (all, &start, &len, elf, cur_off, newfd)
151225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		  != 0)
151325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		goto nonew_unlink;
151425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
151525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
151625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  all = all->next;
151725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
151825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
151925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Write the last part.  */
152025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (start != -1 && copy_content (elf, newfd, start, len))
152125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	goto nonew_unlink;
152225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
152325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
152425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Set the mode of the new file to the same values the original file
152525b3c049e70834cf33790a28643ab058b507b35cBen Cheng     has.  */
152625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (fd != -1
152725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      && (fchmod (newfd, st.st_mode & ALLPERMS) != 0
152825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* Never complain about fchown failing.  */
152925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || (({asm ("" :: "r" (fchown (newfd, st.st_uid, st.st_gid))); }),
153025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      close (newfd) != 0)
153125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || (newfd = -1, rename (tmpfname, arfname) != 0)))
153225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      goto nonew_unlink;
153325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
153425b3c049e70834cf33790a28643ab058b507b35cBen Cheng errout:
153525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#ifdef DEBUG
153625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  elf_end (elf);
153725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
153825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  arlib_fini ();
153925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
154025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  close (fd);
154125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif
154225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
154325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return status;
154425b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
154525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
154625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
154725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "debugpred.h"
1548