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