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