1cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Create, modify, and extract from archives.
2cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Copyright (C) 2005, 2007 Red Hat, Inc.
3cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
4cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
5cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is free software; you can redistribute it and/or modify
6cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   it under the terms of the GNU General Public License as published by the
7cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Free Software Foundation; version 2 of the License.
8cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
9cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is distributed in the hope that it will be useful, but
10cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
11cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   General Public License for more details.
13cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
14cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   You should have received a copy of the GNU General Public License along
15cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   with Red Hat elfutils; if not, write to the Free Software Foundation,
16cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
17cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
18cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Red Hat elfutils is an included package of the Open Invention Network.
19cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   An included package of the Open Invention Network is a package for which
20cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Open Invention Network licensees cross-license their patents.  No patent
21cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   license is granted, either expressly or impliedly, by designation as an
22cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   included package.  Should you wish to participate in the Open Invention
23cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Network licensing program, please visit www.openinventionnetwork.com
24cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   <http://www.openinventionnetwork.com>.  */
25cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
26cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef HAVE_CONFIG_H
27cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# include <config.h>
28cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
29cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
30cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <argp.h>
31cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <assert.h>
32cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <error.h>
33cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <fcntl.h>
34cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <gelf.h>
35cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <libintl.h>
36cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <limits.h>
37cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <locale.h>
38cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <mcheck.h>
39cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <search.h>
40cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdbool.h>
41cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdlib.h>
42cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdio.h>
43cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <stdio_ext.h>
44cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <string.h>
45cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <time.h>
46cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <unistd.h>
47cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <sys/mman.h>
48cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <sys/statfs.h>
49cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <sys/time.h>
50cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
51cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <system.h>
52cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
53cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "arlib.h"
54cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
55cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
56cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Name and version of program.  */
57cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void print_version (FILE *stream, struct argp_state *state);
58cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengvoid (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
59cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Prototypes for local functions.  */
60cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int do_oper_extract (int oper, const char *arfname, char **argv,
61cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    int argc, long int instance);
62cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int do_oper_delete (const char *arfname, char **argv, int argc,
63cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   long int instance);
64cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int do_oper_insert (int oper, const char *arfname, char **argv,
65cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   int argc, const char *member);
66cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
67cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
68cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Bug report address.  */
69cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengconst char *argp_program_bug_address = PACKAGE_BUGREPORT;
70cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
71cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
72cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Definitions of arguments for argp functions.  */
73cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const struct argp_option options[] =
74cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
75cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 0, NULL, 0, N_("Commands:"), 0 },
76cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'd', NULL, 0, N_("Delete files from archive."), 0 },
77cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'm', NULL, 0, N_("Move files in archive."), 0 },
78cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'p', NULL, 0, N_("Print files in archive."), 0 },
79cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'q', NULL, 0, N_("Quick append files to archive."), 0 },
80cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'r', NULL, 0,
81cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    N_("Replace existing or insert new file into archive."), 0 },
82cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 't', NULL, 0, N_("Display content of archive."), 0 },
83cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'x', NULL, 0, N_("Extract files from archive."), 0 },
84cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
85cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 0, NULL, 0, N_("Command Modifiers:"), 0 },
86cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'o', NULL, 0, N_("Preserve original dates."), 0 },
87cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'N', NULL, 0, N_("Use instance [COUNT] of name."), 0 },
88cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'C', NULL, 0,
89cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    N_("Do not replace existing files with extracted files."), 0 },
90cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'T', NULL, 0, N_("Allow filename to be truncated if necessary."),
91cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    0 },
92cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'v', NULL, 0, N_("Provide verbose output."), 0 },
93cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 's', NULL, 0, N_("Force regeneration of symbol table."), 0 },
94cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'a', NULL, 0, N_("Insert file after [MEMBER]."), 0 },
95cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'b', NULL, 0, N_("Insert file before [MEMBER]."), 0 },
96cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'i', NULL, 0, N_("Same as -b."), 0 },
97cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'c', NULL, 0, N_("Suppress message when library has to be created."),
98cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    0 },
99cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'P', NULL, 0, N_("Use full path for file matching."), 0 },
100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 'u', NULL, 0, N_("Update only older files in archive."), 0 },
101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  { NULL, 0, NULL, 0, NULL, 0 }
103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng};
104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Short description of program.  */
106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char doc[] = N_("Create, modify, and extract from archives.");
107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Strings for arguments in help texts.  */
109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic const char args_doc[] = N_("[MEMBER] [COUNT] ARCHIVE [FILE...]");
110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Prototype for option handler.  */
112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic error_t parse_opt (int key, char *arg, struct argp_state *state);
113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Data structure to communicate with argp functions.  */
115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic struct argp argp =
116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  options, parse_opt, args_doc, doc, NULL, NULL, NULL
118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng};
119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* What operation to perform.  */
122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic enum
123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  {
124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    oper_none,
125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    oper_delete,
126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    oper_move,
127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    oper_print,
128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    oper_qappend,
129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    oper_replace,
130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    oper_list,
131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    oper_extract
132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  } operation;
133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Modifiers.  */
135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool verbose;
136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool preserve_dates;
137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool instance_specifed;
138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool dont_replace_existing;
139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool allow_truncate_fname;
140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool force_symtab;
141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool suppress_create_msg;
142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool full_path;
143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool update_newer;
144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic enum { ipos_none, ipos_before, ipos_after } ipos;
145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengint
148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengmain (int argc, char *argv[])
149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Make memory leak detection possible.  */
151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  mtrace ();
152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* We use no threads here which can interfere with handling a stream.  */
154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Set locale.  */
159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  (void) setlocale (LC_ALL, "");
160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Make sure the message catalog can be found.  */
162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Initialize the message catalog.  */
165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  (void) textdomain (PACKAGE_TARNAME);
166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* For historical reasons the options in the first parameter need
168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     not be preceded by a dash.  Add it now if necessary.  */
169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (argc > 1 && argv[1][0] != '-')
170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      size_t len = strlen (argv[1]) + 1;
172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char *newp = alloca (len + 1);
173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      newp[0] = '-';
174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      memcpy (&newp[1], argv[1], len);
175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      argv[1] = newp;
176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Parse and process arguments.  */
179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int remaining;
180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  (void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER, &remaining, NULL);
181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Tell the library which version we are expecting.  */
183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  (void) elf_version (EV_CURRENT);
184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Handle the [MEMBER] parameter.  */
186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const char *member = NULL;
187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (ipos != ipos_none)
188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Only valid for certain operations.  */
190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (operation == oper_extract && operation == oper_delete)
191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (1, 0, gettext ("\
192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng'a', 'b', and 'i' are only allowed with the 'm' and 'r' options"));
193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (remaining == argc)
195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, 0, gettext ("MEMBER parameter required"));
197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  argp_help (&argp, stderr, ARGP_HELP_SEE, AR);
198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  exit (EXIT_FAILURE);
199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      member = argv[remaining++];
202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Handle the [COUNT] parameter.  */
205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  long int instance = -1;
206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (instance_specifed)
207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Only valid for certain operations.  */
209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (operation == oper_extract && operation == oper_delete)
210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (1, 0, gettext ("\
211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng'N' is only meaningful with the 'x' and 'd' options"));
212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (remaining == argc)
214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, 0, gettext ("COUNT parameter required"));
216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  argp_help (&argp, stderr, ARGP_HELP_SEE, AR);
217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  exit (EXIT_FAILURE);
218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      char *endp;
221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      errno = 0;
222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (((instance = strtol (argv[remaining], &endp, 10)) == LONG_MAX
223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   && errno == ERANGE)
224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  || instance <= 0
225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  || *endp != '\0')
226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (1, 0, gettext ("invalid COUNT parameter %s"), argv[remaining]);
227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ++remaining;
229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if ((dont_replace_existing || allow_truncate_fname)
232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      && unlikely (operation != oper_extract))
233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (1, 0, gettext ("'%' is only meaningful with the 'x' option"),
234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   dont_replace_existing ? 'C' : 'T');
235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* There must at least be one more parameter specifying the archive.   */
237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (remaining == argc)
238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, 0, gettext ("Archive name required"));
240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      argp_help (&argp, stderr, ARGP_HELP_SEE, AR);
241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      exit (EXIT_FAILURE);
242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const char *arfname = argv[remaining++];
245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  argv += remaining;
246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  argc -= remaining;
247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int status;
249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  switch (operation)
250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case oper_list:
252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case oper_print:
253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      status = do_oper_extract (operation, arfname, argv, argc, -1);
254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case oper_extract:
257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      status = do_oper_extract (operation, arfname, argv, argc, instance);
258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case oper_delete:
261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      status = do_oper_delete (arfname, argv, argc, instance);
262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case oper_move:
265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case oper_qappend:
266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case oper_replace:
267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      status = do_oper_insert (operation, arfname, argv, argc, member);
268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    default:
271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      assert (! "should not happen");
272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      status = 1;
273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return status;
277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Print the version information.  */
281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  fprintf (stream, "ar (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  fprintf (stream, gettext ("\
286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengCopyright (C) %s Red Hat, Inc.\n\
287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengThis is free software; see the source for copying conditions.  There is NO\n\
288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng"), "2008");
290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Handle program arguments.  */
295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic error_t
296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengparse_opt (int key, char *arg __attribute__ ((unused)),
297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   struct argp_state *state __attribute__ ((unused)))
298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  switch (key)
300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'd':
302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'm':
303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'p':
304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'q':
305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'r':
306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 't':
307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'x':
308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (operation != oper_none)
309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, 0, gettext ("More than one operation specified"));
311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  argp_help (&argp, stderr, ARGP_HELP_SEE, AR);
312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  exit (EXIT_FAILURE);
313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      switch (key)
316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case 'd':
318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  operation = oper_delete;
319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case 'm':
321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  operation = oper_move;
322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case 'p':
324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  operation = oper_print;
325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case 'q':
327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  operation = oper_qappend;
328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case 'r':
330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  operation = oper_replace;
331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case 't':
333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  operation = oper_list;
334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	case 'x':
336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  operation = oper_extract;
337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  break;
338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'a':
342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ipos = ipos_after;
343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'b':
346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'i':
347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ipos = ipos_before;
348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'c':
351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      suppress_create_msg = true;
352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'C':
355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      dont_replace_existing = true;
356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'N':
359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      instance_specifed = true;
360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'o':
363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      preserve_dates = true;
364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'P':
367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      full_path = true;
368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 's':
371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      force_symtab = true;
372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'T':
375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      allow_truncate_fname = true;
376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    case 'v':
379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      verbose = true;
380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      break;
381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    default:
383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return ARGP_ERR_UNKNOWN;
384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengopen_archive (const char *arfname, int flags, int mode, Elf **elf,
391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      struct stat *st, bool miss_allowed)
392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int fd = open (arfname, flags, mode);
394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (fd == -1)
395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (miss_allowed)
397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return -1;
398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (EXIT_FAILURE, errno, gettext ("cannot open archive '%s'"),
400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     arfname);
401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (elf != NULL)
404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Elf_Cmd cmd = flags == O_RDONLY ? ELF_C_READ_MMAP : ELF_C_RDWR_MMAP;
406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *elf = elf_begin (fd, cmd, NULL);
408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (*elf == NULL)
409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (EXIT_FAILURE, 0, gettext ("cannot open archive '%s': %s"),
410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       arfname, elf_errmsg (-1));
411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (flags == O_RDONLY && elf_kind (*elf) != ELF_K_AR)
413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (EXIT_FAILURE, 0, gettext ("%s: not an archive file"), arfname);
414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (st != NULL && fstat (fd, st) != 0)
417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, errno, gettext ("cannot stat archive '%s'"),
418cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   arfname);
419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return fd;
421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengnot_found (int argc, char *argv[argc], bool found[argc])
426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (int i = 0; i < argc; ++i)
428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    if (!found[i])
429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      printf (gettext ("no entry %s in archive\n"), argv[i]);
430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcopy_content (Elf *elf, int newfd, off_t off, size_t n)
435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t len;
437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char *rawfile = elf_rawfile (elf, &len);
438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  assert (off + n <= len);
440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Tell the kernel we will read all the pages sequentially.  */
442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t ps = sysconf (_SC_PAGESIZE);
443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (n > 2 * ps)
444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    posix_madvise (rawfile + (off & ~(ps - 1)), n, POSIX_MADV_SEQUENTIAL);
445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return write_retry (newfd, rawfile + off, n) != (ssize_t) n;
447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdo_oper_extract (int oper, const char *arfname, char **argv, int argc,
452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 long int instance)
453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bool found[argc];
455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  memset (found, '\0', sizeof (found));
456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct statfs f;
458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  f.f_namelen = 0;
459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  off_t index_off = -1;
461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t index_size = 0;
462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  off_t cur_off = SARMAG;
463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int status = 0;
465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf *elf;
466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int fd = open_archive (arfname, O_RDONLY, 0, &elf, NULL, false);
467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (hcreate (2 * argc) == 0)
469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, errno, gettext ("cannot create hash table"));
470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (int cnt = 0; cnt < argc; ++cnt)
472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ENTRY entry = { .key = argv[cnt], .data = &argv[cnt] };
474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (hsearch (entry, ENTER) == NULL)
475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (EXIT_FAILURE, errno,
476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       gettext ("cannot insert into hash table"));
477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct stat st;
480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (force_symtab)
481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (fstat (fd, &st) != 0)
483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  error (0, errno, gettext ("cannot stat '%s'"), arfname);
485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  close (fd);
486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  return 1;
487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      arlib_init ();
489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Cmd cmd = ELF_C_READ_MMAP;
492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf *subelf;
493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (strcmp (arhdr->ar_name, "/") == 0)
498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  index_off = elf_getaroff (subelf);
500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  index_size = arhdr->ar_size;
501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  goto next;
502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (strcmp (arhdr->ar_name, "//") == 0)
504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto next;
505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (force_symtab)
507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  arlib_add_symbols (elf, arfname, arhdr->ar_name, cur_off);
509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  cur_off += (((arhdr->ar_size + 1) & ~((off_t) 1))
510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      + sizeof (struct ar_hdr));
511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      bool do_extract = argc <= 0;
514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (!do_extract)
515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ENTRY entry;
517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  entry.key = arhdr->ar_name;
518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ENTRY *res = hsearch (entry, FIND);
519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (res != NULL && (instance < 0 || instance-- == 0)
520cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      && !found[(char **) res->data - argv])
521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    found[(char **) res->data - argv] = do_extract = true;
522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (do_extract)
525cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (verbose)
527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (oper == oper_print)
529cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  printf ("\n<%s>\n\n", arhdr->ar_name);
531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  /* We have to flush now because now we use the descriptor
533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     directly.  */
534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  fflush (stdout);
535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      else if (oper == oper_list)
537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  char datestr[100];
539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  strftime (datestr, sizeof (datestr), "%b %e %H:%M %Y",
540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    localtime (&arhdr->ar_date));
541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  printf ("%c%c%c%c%c%c%c%c%c %u/%u %6ju %s %s\n",
543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  (arhdr->ar_mode & S_IRUSR) ? 'r' : '-',
544cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  (arhdr->ar_mode & S_IWUSR) ? 'w' : '-',
545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  (arhdr->ar_mode & S_IXUSR)
546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  ? ((arhdr->ar_mode & S_ISUID) ? 's' : 'x')
547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  : ((arhdr->ar_mode & S_ISUID) ? 'S' : '-'),
548cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  (arhdr->ar_mode & S_IRGRP) ? 'r' : '-',
549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  (arhdr->ar_mode & S_IWGRP) ? 'w' : '-',
550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  (arhdr->ar_mode & S_IXGRP)
551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  ? ((arhdr->ar_mode & S_ISGID) ? 's' : 'x')
552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  : ((arhdr->ar_mode & S_ISGID) ? 'S' : '-'),
553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  (arhdr->ar_mode & S_IROTH) ? 'r' : '-',
554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  (arhdr->ar_mode & S_IWOTH) ? 'w' : '-',
555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  (arhdr->ar_mode & S_IXOTH)
556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  ? ((arhdr->ar_mode & S_ISVTX) ? 't' : 'x')
557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  : ((arhdr->ar_mode & S_ISVTX) ? 'T' : '-'),
558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  arhdr->ar_uid,
559cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  arhdr->ar_gid,
560cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  (uintmax_t) arhdr->ar_size,
561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  datestr,
562cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  arhdr->ar_name);
563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      else
565cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		printf ("x - %s\n", arhdr->ar_name);
566cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
568cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (oper == oper_list)
569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
570cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (!verbose)
571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		puts (arhdr->ar_name);
572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      goto next;
574cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  size_t nleft;
577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char *data = elf_rawfile (subelf, &nleft);
578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (data == NULL)
579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      error (0, 0, gettext ("cannot read content of %s: %s"),
581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     arhdr->ar_name, elf_errmsg (-1));
582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      status = 1;
583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      goto next;
584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  int xfd;
587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char tempfname[] = "XXXXXX";
588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  bool use_mkstemp = true;
589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (oper == oper_print)
591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    xfd = STDOUT_FILENO;
592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      xfd = mkstemp (tempfname);
595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (xfd == -1))
596cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  /* We cannot create a temporary file.  Try to overwrite
598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     the file or create it if it does not exist.  */
599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  int flags = O_WRONLY | O_CREAT;
600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (dont_replace_existing)
601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    flags |= O_EXCL;
602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  else
603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    flags |= O_TRUNC;
604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  xfd = open (arhdr->ar_name, flags, 0600);
605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (unlikely (xfd == -1))
606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    {
607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      int printlen = INT_MAX;
608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      if (errno == ENAMETOOLONG && allow_truncate_fname
610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  && (f.f_namelen != 0 || statfs (".", &f) == 0))
611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			{
612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  /* Try to truncate the name.  First find out by how
613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     much.  */
614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  printlen = f.f_namelen;
615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  char truncfname[f.f_namelen + 1];
616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  *((char *) mempcpy (truncfname, arhdr->ar_name,
617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					      f.f_namelen)) = '\0';
618cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  xfd = open (truncfname, flags, 0600);
620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			}
621cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      if (xfd == -1)
623cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			{
624cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  error (0, errno, gettext ("cannot open %.*s"),
625cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				 (int) printlen, arhdr->ar_name);
626cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  status = 1;
627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  goto next;
628cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			}
629cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    }
630cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
631cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  use_mkstemp = false;
632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
633cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
634cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
635cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ssize_t n;
636cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  while ((n = TEMP_FAILURE_RETRY (write (xfd, data, nleft))) != -1)
637cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
638cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      nleft -= n;
639cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (nleft == 0)
640cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		break;
641cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      data += n;
642cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
643cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
644cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (n == -1))
645cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
646cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      error (0, errno, gettext ("failed to write %s"), arhdr->ar_name);
647cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      status = 1;
648cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      unlink (tempfname);
649cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      close (xfd);
650cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      goto next;
651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
652cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
653cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (oper != oper_print)
654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
655cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* Fix up the mode.  */
656cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (fchmod (xfd, arhdr->ar_mode) != 0))
657cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
658cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  error (0, errno, gettext ("cannot change mode of %s"),
659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			 arhdr->ar_name);
660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  status = 0;
661cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
662cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
663cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (preserve_dates)
664cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  struct timeval tv[2];
666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  tv[0].tv_sec = arhdr->ar_date;
667cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  tv[0].tv_usec = 0;
668cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  tv[1].tv_sec = arhdr->ar_date;
669cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  tv[1].tv_usec = 0;
670cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
671cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (unlikely (futimes (xfd, tv) != 0))
672cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    {
673cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      error (0, errno,
674cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     gettext ("cannot change modification time of %s"),
675cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     arhdr->ar_name);
676cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      status = 1;
677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    }
678cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
680cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* If we used a temporary file, move it do the right
681cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 name now.  */
682cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (use_mkstemp)
683cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
684cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  int r;
685cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
686cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (dont_replace_existing)
687cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    {
688cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      r = link (tempfname, arhdr->ar_name);
689cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      if (likely (r == 0))
690cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			unlink (tempfname);
691cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    }
692cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  else
693cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    r = rename (tempfname, arhdr->ar_name);
694cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
695cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (unlikely (r) != 0)
696cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    {
697cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      int printlen = INT_MAX;
698cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
699cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      if (errno == ENAMETOOLONG && allow_truncate_fname
700cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  && (f.f_namelen != 0 || statfs (".", &f) == 0))
701cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			{
702cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  /* Try to truncate the name.  First find out by how
703cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			     much.  */
704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  printlen = f.f_namelen;
705cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  char truncfname[f.f_namelen + 1];
706cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  *((char *) mempcpy (truncfname, arhdr->ar_name,
707cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					      f.f_namelen)) = '\0';
708cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
709cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  if (dont_replace_existing)
710cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    {
711cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      r = link (tempfname, truncfname);
712cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			      if (likely (r == 0))
713cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				unlink (tempfname);
714cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    }
715cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  else
716cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    r = rename (tempfname, truncfname);
717cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			}
718cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
719cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      if (r != 0)
720cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			{
721cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  error (0, errno, gettext ("\
722cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengcannot rename temporary file to %.*s"),
723cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				 printlen, arhdr->ar_name);
724cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  unlink (tempfname);
725cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			  status = 1;
726cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			}
727cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    }
728cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
729cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
730cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      close (xfd);
731cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
732cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
733cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
734cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    next:
735cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      cmd = elf_next (subelf);
736cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (elf_end (subelf) != 0)
737cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (1, 0, "%s: %s", arfname, elf_errmsg (-1));
738cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
739cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
740cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  hdestroy ();
741cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
742cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (force_symtab)
743cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
744cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      arlib_finalize ();
745cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
746cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (symtab.symsnamelen != 0
747cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* We have to rewrite the file also if it initially had an index
748cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     but now does not need one anymore.  */
749cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  || (symtab.symsnamelen == 0 && index_size != 0))
750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
751cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  char tmpfname[strlen (arfname) + 7];
752cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  strcpy (stpcpy (tmpfname, arfname), "XXXXXX");
753cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  int newfd = mkstemp (tmpfname);
754cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (unlikely (newfd == -1))
755cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
756cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    nonew:
757cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      error (0, errno, gettext ("cannot create new file"));
758cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      status = 1;
759cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
760cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
761cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
762cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* Create the header.  */
763cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (write_retry (newfd, ARMAG, SARMAG) != SARMAG))
764cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
765cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  // XXX Use /prof/self/fd/%d ???
766cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		nonew_unlink:
767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  unlink (tmpfname);
768cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (newfd != -1)
769cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    close (newfd);
770cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  goto nonew;
771cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
772cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
773cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* Create the new file.  There are three parts as far we are
774cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 concerned: 1. original context before the index, 2. the
775cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 new index, 3. everything after the new index.  */
776cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      off_t rest_off;
777cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (index_off != -1)
778cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		rest_off = (index_off + sizeof (struct ar_hdr)
779cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    + ((index_size + 1) & ~1ul));
780cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      else
781cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		rest_off = SARMAG;
782cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
783cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if ((symtab.symsnamelen != 0
784cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   && ((write_retry (newfd, symtab.symsoff,
785cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng				     symtab.symsofflen)
786cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			!= (ssize_t) symtab.symsofflen)
787cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		       || (write_retry (newfd, symtab.symsname,
788cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng					symtab.symsnamelen)
789cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			   != (ssize_t) symtab.symsnamelen)))
790cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  /* Even if the original file had content before the
791cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     symbol table, we write it in the correct order.  */
792cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  || (index_off != SARMAG
793cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      && copy_content (elf, newfd, SARMAG, index_off - SARMAG))
794cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  || copy_content (elf, newfd, rest_off, st.st_size - rest_off)
795cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  /* Set the mode of the new file to the same values the
796cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		     original file has.  */
797cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  || fchmod (newfd, st.st_mode & ALLPERMS) != 0
798cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  /* Never complain about fchown failing.  */
799cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  || (({asm ("" :: "r" (fchown (newfd, st.st_uid,
800cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng						st.st_gid))); }),
801cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      close (newfd) != 0)
802cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  || (newfd = -1, rename (tmpfname, arfname) != 0))
803cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		goto nonew_unlink;
804cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
805cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
806cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
807cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
808cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  elf_end (elf);
809cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
810cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  close (fd);
811cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
812cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  not_found (argc, argv, found);
813cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
814cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return status;
815cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
816cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
817cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
818cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct armem
819cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
820cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  off_t off;
821cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  off_t old_off;
822cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  size_t size;
823cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  long int long_name_off;
824cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct armem *next;
825cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  void *mem;
826cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  time_t sec;
827cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  uid_t uid;
828cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  gid_t gid;
829cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  mode_t mode;
830cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  const char *name;
831cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf *elf;
832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng};
833cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
834cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengwrite_member (struct armem *memb, off_t *startp, off_t *lenp, Elf *elf,
837cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      off_t end_off, int newfd)
838cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
839cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct ar_hdr arhdr;
840cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char tmpbuf[sizeof (arhdr.ar_name) + 1];
841cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
842cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bool changed_header = memb->long_name_off != -1;
843cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (changed_header)
844cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
845cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* In case of a long file name we assume the archive header
846cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	 changed and we write it here.  */
847cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      memcpy (&arhdr, elf_rawfile (elf, NULL) + *startp, sizeof (arhdr));
848cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
849cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      snprintf (tmpbuf, sizeof (tmpbuf), "/%-*ld",
850cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		(int) sizeof (arhdr.ar_name), memb->long_name_off);
851cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      changed_header = memcmp (arhdr.ar_name, tmpbuf,
852cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			       sizeof (arhdr.ar_name)) != 0;
853cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
854cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
855cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* If the files are adjacent in the old file extend the range.  */
856cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*startp != -1 && !changed_header && *startp + *lenp == memb->old_off)
857cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
858cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Extend the current range.  */
859cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *lenp += (memb->next != NULL
860cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		? memb->next->off : end_off) - memb->off;
861cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return 0;
862cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
863cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
864cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Write out the old range.  */
865cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (*startp != -1 && copy_content (elf, newfd, *startp, *lenp))
866cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    return -1;
867cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
868cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *startp = memb->old_off;
869cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  *lenp = (memb->next != NULL ? memb->next->off : end_off) - memb->off;
870cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
871cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (changed_header)
872cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
873cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      memcpy (arhdr.ar_name, tmpbuf, sizeof (arhdr.ar_name));
874cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
875cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (unlikely (write_retry (newfd, &arhdr, sizeof (arhdr))
876cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    != sizeof (arhdr)))
877cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return -1;
878cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
879cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *startp += sizeof (struct ar_hdr);
880cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      assert ((size_t) *lenp >= sizeof (struct ar_hdr));
881cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      *lenp -= sizeof (struct ar_hdr);
882cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
883cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
884cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return 0;
885cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
886cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
887cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Store the name in the long name table if necessary.
888cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng   Record its offset or -1 if we did not need to use the table.  */
889cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
890cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengremember_long_name (struct armem *mem, const char *name, size_t namelen)
891cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
892cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  mem->long_name_off = (namelen > MAX_AR_NAME_LEN
893cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			? arlib_add_long_name (name, namelen)
894cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			: -1l);
895cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
896cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
897cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
898cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdo_oper_delete (const char *arfname, char **argv, int argc,
899cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		long int instance)
900cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
901cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  bool *found = alloca (sizeof (bool) * argc);
902cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  memset (found, '\0', sizeof (found));
903cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
904cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* List of the files we keep.  */
905cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct armem *to_copy = NULL;
906cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
907cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int status = 0;
908cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf *elf;
909cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct stat st;
910cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int fd = open_archive (arfname, O_RDONLY, 0, &elf, &st, false);
911cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
912cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (hcreate (2 * argc) == 0)
913cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, errno, gettext ("cannot create hash table"));
914cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
915cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (int cnt = 0; cnt < argc; ++cnt)
916cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
917cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      ENTRY entry = { .key = argv[cnt], .data = &argv[cnt] };
918cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (hsearch (entry, ENTER) == NULL)
919cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (EXIT_FAILURE, errno,
920cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       gettext ("cannot insert into hash table"));
921cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
922cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
923cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  arlib_init ();
924cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
925cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  off_t cur_off = SARMAG;
926cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Cmd cmd = ELF_C_READ_MMAP;
927cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf *subelf;
928cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
929cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
930cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
931cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
932cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Ignore the symbol table and the long file name table here.  */
933cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (strcmp (arhdr->ar_name, "/") == 0
934cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  || strcmp (arhdr->ar_name, "//") == 0)
935cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto next;
936cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
937cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      bool do_delete = argc <= 0;
938cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (!do_delete)
939cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
940cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ENTRY entry;
941cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  entry.key = arhdr->ar_name;
942cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ENTRY *res = hsearch (entry, FIND);
943cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (res != NULL && (instance < 0 || instance-- == 0)
944cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      && !found[(char **) res->data - argv])
945cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    found[(char **) res->data - argv] = do_delete = true;
946cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
947cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
948cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (do_delete)
949cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
950cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (verbose)
951cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf ("d - %s\n", arhdr->ar_name);
952cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
953cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
954cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
955cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  struct armem *newp = alloca (sizeof (struct armem));
956cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  newp->old_off = elf_getaroff (subelf);
957cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  newp->off = cur_off;
958cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
959cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  cur_off += (((arhdr->ar_size + 1) & ~((off_t) 1))
960cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		      + sizeof (struct ar_hdr));
961cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
962cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (to_copy == NULL)
963cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    to_copy = newp->next = newp;
964cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
965cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
966cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      newp->next = to_copy->next;
967cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      to_copy = to_copy->next = newp;
968cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
969cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
970cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* If we recreate the symbol table read the file's symbol
971cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	     table now.  */
972cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  arlib_add_symbols (subelf, arfname, arhdr->ar_name, newp->off);
973cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
974cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* Remember long file names.  */
975cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  remember_long_name (newp, arhdr->ar_name, strlen (arhdr->ar_name));
976cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
977cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
978cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    next:
979cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      cmd = elf_next (subelf);
980cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (elf_end (subelf) != 0)
981cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (1, 0, "%s: %s", arfname, elf_errmsg (-1));
982cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
983cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
984cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  arlib_finalize ();
985cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
986cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  hdestroy ();
987cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
988cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Create a new, temporary file in the same directory as the
989cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     original file.  */
990cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char tmpfname[strlen (arfname) + 7];
991cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  strcpy (stpcpy (tmpfname, arfname), "XXXXXX");
992cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int newfd = mkstemp (tmpfname);
993cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (newfd == -1))
994cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    goto nonew;
995cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
996cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Create the header.  */
997cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (write_retry (newfd, ARMAG, SARMAG) != SARMAG))
998cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
999cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      // XXX Use /prof/self/fd/%d ???
1000cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    nonew_unlink:
1001cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      unlink (tmpfname);
1002cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (newfd != -1)
1003cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	close (newfd);
1004cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    nonew:
1005cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, errno, gettext ("cannot create new file"));
1006cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      status = 1;
1007cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      goto errout;
1008cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1009cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1010cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* If the archive is empty that is all we have to do.  */
1011cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (to_copy != NULL))
1012cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1013cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Write the symbol table or the long file name table or both.  */
1014cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (symtab.symsnamelen != 0
1015cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  && ((write_retry (newfd, symtab.symsoff, symtab.symsofflen)
1016cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       != (ssize_t) symtab.symsofflen)
1017cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      || (write_retry (newfd, symtab.symsname, symtab.symsnamelen)
1018cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  != (ssize_t) symtab.symsnamelen)))
1019cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto nonew_unlink;
1020cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1021cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (symtab.longnameslen > sizeof (struct ar_hdr)
1022cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  && (write_retry (newfd, symtab.longnames, symtab.longnameslen)
1023cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      != (ssize_t) symtab.longnameslen))
1024cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto nonew_unlink;
1025cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1026cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* NULL-terminate the list of files to copy.  */
1027cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      struct armem *last = to_copy;
1028cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      to_copy = to_copy->next;
1029cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      last->next = NULL;
1030cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1031cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      off_t start = -1;
1032cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      off_t len = -1;
1033cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1034cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      do
1035cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	if (write_member (to_copy, &start, &len, elf, cur_off, newfd) != 0)
1036cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  goto nonew_unlink;
1037cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      while ((to_copy = to_copy->next) != NULL);
1038cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1039cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Write the last part.  */
1040cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (copy_content (elf, newfd, start, len))
1041cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto nonew_unlink;
1042cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1043cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1044cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Set the mode of the new file to the same values the original file
1045cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     has.  */
1046cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (fchmod (newfd, st.st_mode & ALLPERMS) != 0
1047cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Never complain about fchown failing.  */
1048cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      || (({asm ("" :: "r" (fchown (newfd, st.st_uid, st.st_gid))); }),
1049cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  close (newfd) != 0)
1050cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      || (newfd = -1, rename (tmpfname, arfname) != 0))
1051cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    goto nonew_unlink;
1052cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1053cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng errout:
1054cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef DEBUG
1055cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  elf_end (elf);
1056cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1057cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  arlib_fini ();
1058cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1059cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  close (fd);
1060cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1061cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1062cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  not_found (argc, argv, found);
1063cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1064cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return status;
1065cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1066cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1067cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1068cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic void
1069cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengno0print (bool ofmt, char *buf, int bufsize, long int val)
1070cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1071cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char tmpbuf[bufsize + 1];
1072cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  snprintf (tmpbuf, sizeof (tmpbuf), ofmt ? "%-*lo" : "%-*ld", bufsize, val);
1073cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  memcpy (buf, tmpbuf, bufsize);
1074cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1075cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1076cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1077cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int
1078cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdo_oper_insert (int oper, const char *arfname, char **argv, int argc,
1079cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		const char *member)
1080cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{
1081cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int status = 0;
1082cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf *elf;
1083cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct stat st;
1084cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int fd = open_archive (arfname, O_RDONLY, 0, &elf, &st, oper != oper_move);
1085cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1086cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* List of the files we keep.  */
1087cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct armem *all = NULL;
1088cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct armem *after_memberelem = NULL;
1089cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct armem **found = alloca (sizeof (*found) * argc);
1090cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  memset (found, '\0', sizeof (*found) * argc);
1091cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1092cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  arlib_init ();
1093cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1094cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Initialize early for no_old case.  */
1095cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  off_t cur_off = SARMAG;
1096cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1097cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (fd == -1)
1098cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1099cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (!suppress_create_msg)
1100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	fprintf (stderr, "%s: creating %s\n", AR, arfname);
1101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      goto no_old;
1103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Store the names of all files from the command line in a hash
1106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     table so that we can match it.  Note that when no file name is
1107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     given we are basically doing nothing except recreating the
1108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     index.  */
1109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (oper != oper_qappend)
1110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (hcreate (2 * argc) == 0)
1112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (EXIT_FAILURE, errno, gettext ("cannot create hash table"));
1113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (int cnt = 0; cnt < argc; ++cnt)
1115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ENTRY entry;
1117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  entry.key = full_path ? argv[cnt] : basename (argv[cnt]);
1118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  entry.data = &argv[cnt];
1119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (hsearch (entry, ENTER) == NULL)
1120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    error (EXIT_FAILURE, errno,
1121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   gettext ("cannot insert into hash table"));
1122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
1123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* While iterating over the current content of the archive we must
1126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     determine a number of things: which archive members to keep,
1127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     which are replaced, and where to insert the new members.  */
1128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf_Cmd cmd = ELF_C_READ_MMAP;
1129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  Elf *subelf;
1130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
1131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
1133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Ignore the symbol table and the long file name table here.  */
1135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (strcmp (arhdr->ar_name, "/") == 0
1136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  || strcmp (arhdr->ar_name, "//") == 0)
1137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto next;
1138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      struct armem *newp = alloca (sizeof (struct armem));
1140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      newp->old_off = elf_getaroff (subelf);
1141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      newp->size = arhdr->ar_size;
1142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      newp->sec = arhdr->ar_date;
1143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      newp->mem = NULL;
1144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Remember long file names.  */
1146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      remember_long_name (newp, arhdr->ar_name, strlen (arhdr->ar_name));
1147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Check whether this is a file we are looking for.  */
1149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (oper != oper_qappend)
1150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* Check whether this is the member used as the insert point.  */
1152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (member != NULL && strcmp (arhdr->ar_name, member) == 0)
1153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* Note that all == NULL means insert at the beginning.  */
1155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (ipos == ipos_before)
1156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		after_memberelem = all;
1157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      else
1158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		after_memberelem = newp;
1159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      member = NULL;
1160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ENTRY entry;
1163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  entry.key = arhdr->ar_name;
1164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  ENTRY *res = hsearch (entry, FIND);
1165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (res != NULL && found[(char **) res->data - argv] == NULL)
1166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      found[(char **) res->data - argv] = newp;
1168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* If we insert before or after a certain element move
1170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 all files to a special list.  */
1171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (ipos != ipos_none || oper == oper_move))
1172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
1173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  if (after_memberelem == newp)
1174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    /* Since we remove this element even though we should
1175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		       insert everything after it, we in fact insert
1176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		       everything after the previous element.  */
1177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    after_memberelem = all;
1178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  goto next;
1180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
1181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
1183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (all == NULL)
1185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	all = newp->next = newp;
1186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      else
1187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  newp->next = all->next;
1189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  all = all->next = newp;
1190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
1191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    next:
1193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      cmd = elf_next (subelf);
1194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (elf_end (subelf) != 0)
1195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	error (EXIT_FAILURE, 0, "%s: %s", arfname, elf_errmsg (-1));
1196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (oper != oper_qappend)
1199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    hdestroy ();
1200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng no_old:
1202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (member != NULL)
1203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    error (EXIT_FAILURE, 0, gettext ("position member %s not found"),
1204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	   member);
1205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (oper == oper_move)
1207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Make sure all requested elements are found in the archive.  */
1209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (int cnt = 0; cnt < argc; ++cnt)
1210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (found[cnt] == NULL)
1212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      fprintf (stderr, gettext ("%s: no entry %s in archive!\n"),
1214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		       AR, argv[cnt]);
1215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      status = 1;
1216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (verbose)
1219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    printf ("m - %s\n", argv[cnt]);
1220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
1221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
1223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Open all the new files, get their sizes and add all symbols.  */
1225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      for (int cnt = 0; cnt < argc; ++cnt)
1226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  const char *bname = basename (argv[cnt]);
1228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  size_t bnamelen = strlen (bname);
1229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (found[cnt] == NULL)
1230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      found[cnt] = alloca (sizeof (struct armem));
1232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      found[cnt]->old_off = -1;
1233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      remember_long_name (found[cnt], bname, bnamelen);
1235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  struct stat newst;
1238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  Elf *newelf;
1239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  int newfd = open (argv[cnt], O_RDONLY);
1240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (newfd == -1)
1241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      error (0, errno, gettext ("cannot open %s"), argv[cnt]);
1243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      status = 1;
1244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else if (fstat (newfd, &newst) == -1)
1246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      error (0, errno, gettext ("cannot stat %s"), argv[cnt]);
1248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      close (newfd);
1249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      status = 1;
1250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else if (!S_ISREG (newst.st_mode))
1252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      error (0, errno, gettext ("%s is no regular file"), argv[cnt]);
1254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      close (newfd);
1255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      status = 1;
1256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else if (update_newer
1258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   && found[cnt]->old_off != -1l
1259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   && found[cnt]->sec > st.st_mtime)
1260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* Do nothing, the file in the archive is younger.  */
1261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    close (newfd);
1262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else if ((newelf = elf_begin (newfd, ELF_C_READ_MMAP, NULL))
1263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		   == NULL)
1264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      fprintf (stderr,
1266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		       gettext ("cannot get ELF descriptor for %s: %s\n"),
1267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		       argv[cnt], elf_errmsg (-1));
1268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      status = 1;
1269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
1271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (verbose)
1273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		printf ("%c - %s\n",
1274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			found[cnt]->old_off == -1l ? 'a' : 'r', argv[cnt]);
1275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      found[cnt]->elf = newelf;
1277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      found[cnt]->sec = newst.st_mtime;
1278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      found[cnt]->uid = newst.st_uid;
1279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      found[cnt]->gid = newst.st_gid;
1280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      found[cnt]->mode = newst.st_mode;
1281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      found[cnt]->name = bname;
1282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      found[cnt]->mem = elf_rawfile (newelf, &found[cnt]->size);
1284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (found[cnt] == NULL || elf_cntl (newelf, ELF_C_FDDONE) != 0)
1285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		error (EXIT_FAILURE, 0, gettext ("cannot read %s: %s"),
1286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		       argv[cnt], elf_errmsg (-1));
1287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      close (newfd);
1289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (found[cnt]->old_off != -1l)
1291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		/* Remember long file names.  */
1292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		remember_long_name (found[cnt], bname, bnamelen);
1293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
1295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (status != 0)
1298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef DEBUG
1300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      elf_end (elf);
1301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      arlib_fini ();
1303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      close (fd);
1305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      return status;
1308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* If we have no entry point so far add at the end.  AFTER_MEMBERELEM
1311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     being NULL when adding before an entry means add at the beginning.  */
1312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (ipos != ipos_before && after_memberelem == NULL)
1313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    after_memberelem = all;
1314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Convert the circular list into a normal list first.  */
1316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (all != NULL)
1317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      struct armem *tmp = all;
1319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      all = all->next;
1320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      tmp->next = NULL;
1321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  struct armem *last_added = after_memberelem;
1324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  for (int cnt = 0; cnt < argc; ++cnt)
1325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    if (oper != oper_replace || found[cnt]->old_off == -1)
1326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      {
1327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	if (last_added == NULL)
1328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  {
1329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    found[cnt]->next = all;
1330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    last_added = all = found[cnt];
1331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  }
1332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	else
1333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  {
1334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    found[cnt]->next = last_added->next;
1335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    last_added = last_added->next = found[cnt];
1336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  }
1337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      }
1338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Finally compute the offset and add the symbols for the files
1340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     after the insert point.  */
1341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (all != NULL))
1342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    for (struct armem *memp = all; memp != NULL; memp = memp->next)
1343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      {
1344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	memp->off = cur_off;
1345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	if (memp->mem == NULL)
1347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  {
1348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    Elf_Arhdr *arhdr;
1349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    /* Fake initializing arhdr and subelf to keep gcc calm.  */
1350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    asm ("" : "=m" (arhdr), "=m" (subelf));
1351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    if (elf_rand (elf, memp->old_off) == 0
1352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		|| (subelf = elf_begin (fd, ELF_C_READ_MMAP, elf)) == NULL
1353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		|| (arhdr = elf_getarhdr (subelf)) == NULL)
1354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* This should never happen since we already looked at the
1355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 archive content.  But who knows...  */
1356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      error (EXIT_FAILURE, 0, "%s: %s", arfname, elf_errmsg (-1));
1357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    arlib_add_symbols (subelf, arfname, arhdr->ar_name, cur_off);
1359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    elf_end (subelf);
1361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  }
1362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	else
1363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  arlib_add_symbols (memp->elf, arfname, memp->name, cur_off);
1364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	cur_off += (((memp->size + 1) & ~((off_t) 1))
1366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		    + sizeof (struct ar_hdr));
1367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      }
1368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Now we have all the information for the symbol table and long
1370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     file name table.  Construct the final layout.  */
1371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  arlib_finalize ();
1372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Create a new, temporary file in the same directory as the
1374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     original file.  */
1375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  char tmpfname[strlen (arfname) + 7];
1376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  strcpy (stpcpy (tmpfname, arfname), "XXXXXX");
1377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  int newfd;
1378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (fd != -1)
1379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    newfd = mkstemp (tmpfname);
1380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  else
1381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      newfd = open (arfname, O_RDWR | O_CREAT | O_EXCL, DEFFILEMODE);
1383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (newfd == -1 && errno == EEXIST)
1384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	/* Bah, first the file did not exist, now it does.  Restart.  */
1385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	return do_oper_insert (oper, arfname, argv, argc, member);
1386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (newfd == -1))
1388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    goto nonew;
1389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Create the header.  */
1391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (unlikely (write_retry (newfd, ARMAG, SARMAG) != SARMAG))
1392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    nonew_unlink:
1394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (fd != -1)
1395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  // XXX Use /prof/self/fd/%d ???
1397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  unlink (tmpfname);
1398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (newfd != -1)
1399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    close (newfd);
1400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
1401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    nonew:
1402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      error (0, errno, gettext ("cannot create new file"));
1403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      status = 1;
1404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      goto errout;
1405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* If the new archive is not empty we actually have something to do.  */
1408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (likely (all != NULL))
1409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    {
1410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Write the symbol table or the long file name table or both.  */
1411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (symtab.symsnamelen != 0
1412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  && ((write_retry (newfd, symtab.symsoff, symtab.symsofflen)
1413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	       != (ssize_t) symtab.symsofflen)
1414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      || (write_retry (newfd, symtab.symsname, symtab.symsnamelen)
1415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  != (ssize_t) symtab.symsnamelen)))
1416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto nonew_unlink;
1417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1418cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (symtab.longnameslen > sizeof (struct ar_hdr)
1419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  && (write_retry (newfd, symtab.longnames, symtab.longnameslen)
1420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      != (ssize_t) symtab.longnameslen))
1421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto nonew_unlink;
1422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      off_t start = -1;
1424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      off_t len = -1;
1425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      while (all != NULL)
1427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	{
1428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  if (all->mem != NULL)
1429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* This is a new file.  If there is anything from the
1431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		 archive left to be written do it now.  */
1432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (start != -1  && copy_content (elf, newfd, start, len))
1433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		goto nonew_unlink;
1434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      start = -1;
1436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      len = -1;
1437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* Create the header.  */
1439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      struct ar_hdr arhdr;
1440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      char tmpbuf[sizeof (arhdr.ar_name) + 1];
1441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (all->long_name_off == -1)
1442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
1443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  size_t namelen = strlen (all->name);
1444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  char *p = mempcpy (arhdr.ar_name, all->name, namelen);
1445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  *p++ = '/';
1446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  memset (p, ' ', sizeof (arhdr.ar_name) - namelen - 1);
1447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
1448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      else
1449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		{
1450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  snprintf (tmpbuf, sizeof (arhdr.ar_name) + 1, "/%-*ld",
1451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    (int) sizeof (arhdr.ar_name), all->long_name_off);
1452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  memcpy (arhdr.ar_name, tmpbuf, sizeof (arhdr.ar_name));
1453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		}
1454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      no0print (false, arhdr.ar_date, sizeof (arhdr.ar_date),
1456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			all->sec);
1457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      no0print (false, arhdr.ar_uid, sizeof (arhdr.ar_uid), all->uid);
1458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      no0print (false, arhdr.ar_gid, sizeof (arhdr.ar_gid), all->gid);
1459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      no0print (true, arhdr.ar_mode, sizeof (arhdr.ar_mode),
1460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			all->mode);
1461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      no0print (false, arhdr.ar_size, sizeof (arhdr.ar_size),
1462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			all->size);
1463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      memcpy (arhdr.ar_fmag, ARFMAG, sizeof (arhdr.ar_fmag));
1464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (write_retry (newfd, &arhdr, sizeof (arhdr))
1466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    != sizeof (arhdr)))
1467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		goto nonew_unlink;
1468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* Now the file itself.  */
1470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (unlikely (write_retry (newfd, all->mem, all->size)
1471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng			    != (off_t) all->size))
1472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		goto nonew_unlink;
1473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* Pad the file if its size is odd.  */
1475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if ((all->size & 1) != 0)
1476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		if (unlikely (write_retry (newfd, "\n", 1) != 1))
1477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  goto nonew_unlink;
1478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  else
1480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    {
1481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      /* This is a member from the archive.  */
1482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      if (write_member (all, &start, &len, elf, cur_off, newfd)
1483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		  != 0)
1484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng		goto nonew_unlink;
1485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	    }
1486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  all = all->next;
1488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	}
1489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      /* Write the last part.  */
1491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      if (start != -1 && copy_content (elf, newfd, start, len))
1492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	goto nonew_unlink;
1493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng    }
1494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  /* Set the mode of the new file to the same values the original file
1496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng     has.  */
1497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  if (fd != -1
1498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      && (fchmod (newfd, st.st_mode & ALLPERMS) != 0
1499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  /* Never complain about fchown failing.  */
1500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  || (({asm ("" :: "r" (fchown (newfd, st.st_uid, st.st_gid))); }),
1501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	      close (newfd) != 0)
1502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng	  || (newfd = -1, rename (tmpfname, arfname) != 0)))
1503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng      goto nonew_unlink;
1504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng errout:
1506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef DEBUG
1507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  elf_end (elf);
1508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  arlib_fini ();
1510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  close (fd);
1512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif
1513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng  return status;
1515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}
1516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng
1518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "debugpred.h"
1519