1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* 28*7c478bd9Sstevel@tonic-gate * Copyright (c) 1988 AT&T 29*7c478bd9Sstevel@tonic-gate * All Rights Reserved 30*7c478bd9Sstevel@tonic-gate * 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate /* 36*7c478bd9Sstevel@tonic-gate * Incompatible Archive Header 37*7c478bd9Sstevel@tonic-gate * 38*7c478bd9Sstevel@tonic-gate * The archive file member header used in SunOS 4.1 archive files and 39*7c478bd9Sstevel@tonic-gate * Solaris archive files are incompatible. The header file is: 40*7c478bd9Sstevel@tonic-gate * /usr/include/ar.h, struct ar_hdr. 41*7c478bd9Sstevel@tonic-gate * The member ar_name[] in Solaris comforms with Standard and the 42*7c478bd9Sstevel@tonic-gate * member name terminates with '/'. The SunOS's member does not terminate 43*7c478bd9Sstevel@tonic-gate * with '/' character. A bug 4046054 was filed: 44*7c478bd9Sstevel@tonic-gate * The ar command in Solaris 2.5.1 is incompatible with archives 45*7c478bd9Sstevel@tonic-gate * created on 4.x. 46*7c478bd9Sstevel@tonic-gate * 47*7c478bd9Sstevel@tonic-gate * To handle archive files created in SunOS 4.1 system on Solaris, the 48*7c478bd9Sstevel@tonic-gate * following changes were made: 49*7c478bd9Sstevel@tonic-gate * 50*7c478bd9Sstevel@tonic-gate * 1. file.c/writefile() 51*7c478bd9Sstevel@tonic-gate * Before writing each member files into the output 52*7c478bd9Sstevel@tonic-gate * archive file, ar_name[] is checked. If it is NULL, 53*7c478bd9Sstevel@tonic-gate * it means that the original archive header for this 54*7c478bd9Sstevel@tonic-gate * member was incompatible with Solaris format. 55*7c478bd9Sstevel@tonic-gate * 56*7c478bd9Sstevel@tonic-gate * The original Solaris ar command ended up having 57*7c478bd9Sstevel@tonic-gate * NULL name for the header. The change here uses the 58*7c478bd9Sstevel@tonic-gate * ar_rawname, which is much closer to the original 59*7c478bd9Sstevel@tonic-gate * name. 60*7c478bd9Sstevel@tonic-gate * 61*7c478bd9Sstevel@tonic-gate * 2. cmd.c 62*7c478bd9Sstevel@tonic-gate * For the p command, the code used to use only ar_longname 63*7c478bd9Sstevel@tonic-gate * to seach the matching name. The member is set to NULL 64*7c478bd9Sstevel@tonic-gate * if the archive member header was incompatible. 65*7c478bd9Sstevel@tonic-gate * The ar_rawname is also used to find the matching member name. 66*7c478bd9Sstevel@tonic-gate * 67*7c478bd9Sstevel@tonic-gate * For commands to update the archive file, we do not 68*7c478bd9Sstevel@tonic-gate * use ar_rawname, and just use the ar_longname. The commands are 69*7c478bd9Sstevel@tonic-gate * r (replace), m (modify the position) and d (delete). 70*7c478bd9Sstevel@tonic-gate */ 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate #include "inc.h" 73*7c478bd9Sstevel@tonic-gate #include "extern.h" 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate /* 76*7c478bd9Sstevel@tonic-gate * Function prototypes 77*7c478bd9Sstevel@tonic-gate */ 78*7c478bd9Sstevel@tonic-gate static char *match(char *, Cmd_info *); 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate static void cleanup(Cmd_info *); 81*7c478bd9Sstevel@tonic-gate static void movefil(ARFILE *, struct stat *); 82*7c478bd9Sstevel@tonic-gate static void mesg(int, char *, Cmd_info *); 83*7c478bd9Sstevel@tonic-gate static void ar_select(int *, unsigned long); 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate static FILE *stats(char *, struct stat *); 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate static int create_extract(ARFILE *, int, int, Cmd_info *); 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate /* 90*7c478bd9Sstevel@tonic-gate * Commands 91*7c478bd9Sstevel@tonic-gate */ 92*7c478bd9Sstevel@tonic-gate int 93*7c478bd9Sstevel@tonic-gate rcmd(Cmd_info *cmd_info) 94*7c478bd9Sstevel@tonic-gate { 95*7c478bd9Sstevel@tonic-gate register FILE *f; 96*7c478bd9Sstevel@tonic-gate register ARFILE *fileptr; 97*7c478bd9Sstevel@tonic-gate register ARFILE *abifile = NULL; 98*7c478bd9Sstevel@tonic-gate register ARFILE *backptr = NULL; 99*7c478bd9Sstevel@tonic-gate ARFILE *endptr; 100*7c478bd9Sstevel@tonic-gate ARFILE *moved_files; 101*7c478bd9Sstevel@tonic-gate ARFILE *prev_entry, *new_listhead, *new_listend; 102*7c478bd9Sstevel@tonic-gate int deleted; 103*7c478bd9Sstevel@tonic-gate struct stat stbuf; 104*7c478bd9Sstevel@tonic-gate char *gfile; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate new_listhead = NULL; 107*7c478bd9Sstevel@tonic-gate new_listend = NULL; 108*7c478bd9Sstevel@tonic-gate prev_entry = NULL; 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate for (fileptr = getfile(cmd_info); 111*7c478bd9Sstevel@tonic-gate fileptr; fileptr = getfile(cmd_info)) { 112*7c478bd9Sstevel@tonic-gate deleted = 0; 113*7c478bd9Sstevel@tonic-gate if (!abifile && cmd_info-> ponam && 114*7c478bd9Sstevel@tonic-gate strcmp(fileptr->ar_longname, cmd_info->ponam) == 0) 115*7c478bd9Sstevel@tonic-gate abifile = fileptr; 116*7c478bd9Sstevel@tonic-gate else if (!abifile) 117*7c478bd9Sstevel@tonic-gate backptr = fileptr; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate if (cmd_info->namc == 0 || 120*7c478bd9Sstevel@tonic-gate (gfile = match(fileptr->ar_longname, cmd_info)) != NULL) { 121*7c478bd9Sstevel@tonic-gate /* 122*7c478bd9Sstevel@tonic-gate * NOTE: 123*7c478bd9Sstevel@tonic-gate * Refer to "Incompatible Archive Header" 124*7c478bd9Sstevel@tonic-gate * blocked comment at the beginning of this file. 125*7c478bd9Sstevel@tonic-gate */ 126*7c478bd9Sstevel@tonic-gate f = stats(gfile, &stbuf); /* gfile is set by match */ 127*7c478bd9Sstevel@tonic-gate if (f == NULL) { 128*7c478bd9Sstevel@tonic-gate if (cmd_info->namc) 129*7c478bd9Sstevel@tonic-gate error_message(SYS_OPEN_ERROR, 130*7c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), 131*7c478bd9Sstevel@tonic-gate gfile); 132*7c478bd9Sstevel@tonic-gate /* 133*7c478bd9Sstevel@tonic-gate * Created 134*7c478bd9Sstevel@tonic-gate */ 135*7c478bd9Sstevel@tonic-gate mesg('c', gfile, cmd_info); 136*7c478bd9Sstevel@tonic-gate } else { 137*7c478bd9Sstevel@tonic-gate if (opt_FLAG(cmd_info, u_FLAG) && 138*7c478bd9Sstevel@tonic-gate stbuf.st_mtime <= fileptr->ar_date) { 139*7c478bd9Sstevel@tonic-gate (void) fclose(f); 140*7c478bd9Sstevel@tonic-gate continue; 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate /* 143*7c478bd9Sstevel@tonic-gate * Replaced 144*7c478bd9Sstevel@tonic-gate */ 145*7c478bd9Sstevel@tonic-gate mesg('r', fileptr->ar_longname, cmd_info); 146*7c478bd9Sstevel@tonic-gate movefil(fileptr, &stbuf); 147*7c478bd9Sstevel@tonic-gate /* 148*7c478bd9Sstevel@tonic-gate * Clear the previous contents. 149*7c478bd9Sstevel@tonic-gate */ 150*7c478bd9Sstevel@tonic-gate if (fileptr->ar_flag & F_MALLOCED) 151*7c478bd9Sstevel@tonic-gate free(fileptr->ar_contents); 152*7c478bd9Sstevel@tonic-gate else if (fileptr->ar_flag & F_ELFRAW) { 153*7c478bd9Sstevel@tonic-gate /* 154*7c478bd9Sstevel@tonic-gate * clear ar_elf 155*7c478bd9Sstevel@tonic-gate */ 156*7c478bd9Sstevel@tonic-gate (void) elf_end(fileptr->ar_elf); 157*7c478bd9Sstevel@tonic-gate fileptr->ar_elf = 0; 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate /* clear 'ar_flag' */ 160*7c478bd9Sstevel@tonic-gate fileptr->ar_flag &= 161*7c478bd9Sstevel@tonic-gate ~(F_ELFRAW | F_MMAPED | F_MALLOCED); 162*7c478bd9Sstevel@tonic-gate if ((cmd_info->OPT_flgs & M_FLAG) == 0) { 163*7c478bd9Sstevel@tonic-gate if ((cmd_info->bytes_in_mem + 164*7c478bd9Sstevel@tonic-gate stbuf.st_size) 165*7c478bd9Sstevel@tonic-gate < AR_MAX_BYTES_IN_MEM) { 166*7c478bd9Sstevel@tonic-gate if ((fileptr->ar_contents = 167*7c478bd9Sstevel@tonic-gate malloc(ROUNDUP( 168*7c478bd9Sstevel@tonic-gate stbuf.st_size))) == NULL) { 169*7c478bd9Sstevel@tonic-gate error_message( 170*7c478bd9Sstevel@tonic-gate MALLOC_ERROR, 171*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, 172*7c478bd9Sstevel@tonic-gate (char *)0); 173*7c478bd9Sstevel@tonic-gate exit(1); 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate fileptr->ar_flag &= 176*7c478bd9Sstevel@tonic-gate ~(F_ELFRAW | F_MMAPED); 177*7c478bd9Sstevel@tonic-gate fileptr->ar_flag |= F_MALLOCED; 178*7c478bd9Sstevel@tonic-gate if (fread(fileptr->ar_contents, 179*7c478bd9Sstevel@tonic-gate sizeof (char), 180*7c478bd9Sstevel@tonic-gate stbuf.st_size, f) != 181*7c478bd9Sstevel@tonic-gate stbuf.st_size) { 182*7c478bd9Sstevel@tonic-gate error_message( 183*7c478bd9Sstevel@tonic-gate SYS_READ_ERROR, 184*7c478bd9Sstevel@tonic-gate SYSTEM_ERROR, 185*7c478bd9Sstevel@tonic-gate strerror(errno), 186*7c478bd9Sstevel@tonic-gate fileptr-> 187*7c478bd9Sstevel@tonic-gate ar_longname); 188*7c478bd9Sstevel@tonic-gate exit(1); 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate cmd_info->bytes_in_mem += 191*7c478bd9Sstevel@tonic-gate stbuf.st_size; 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate } else { 194*7c478bd9Sstevel@tonic-gate if ((fileptr->ar_contents = (char *) 195*7c478bd9Sstevel@tonic-gate mmap(0, stbuf.st_size, 196*7c478bd9Sstevel@tonic-gate PROT_READ, 197*7c478bd9Sstevel@tonic-gate MAP_SHARED, 198*7c478bd9Sstevel@tonic-gate fileno(f), 0)) == (char *)-1) { 199*7c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 200*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 201*7c478bd9Sstevel@tonic-gate exit(1); 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate fileptr->ar_flag &= 204*7c478bd9Sstevel@tonic-gate ~(F_ELFRAW | F_MALLOCED); 205*7c478bd9Sstevel@tonic-gate fileptr->ar_flag |= F_MMAPED; 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate if (fileptr->ar_pathname != NULL) 208*7c478bd9Sstevel@tonic-gate free(fileptr->ar_pathname); 209*7c478bd9Sstevel@tonic-gate if ((fileptr->ar_pathname = 210*7c478bd9Sstevel@tonic-gate malloc(strlen(gfile) + 1)) == NULL) { 211*7c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 212*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 213*7c478bd9Sstevel@tonic-gate exit(1); 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate (void) strcpy(fileptr->ar_pathname, gfile); 217*7c478bd9Sstevel@tonic-gate (void) fclose(f); 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate if (cmd_info->ponam && (abifile != fileptr)) { 220*7c478bd9Sstevel@tonic-gate deleted = 1; 221*7c478bd9Sstevel@tonic-gate /* remove from archive list */ 222*7c478bd9Sstevel@tonic-gate if (prev_entry != NULL) 223*7c478bd9Sstevel@tonic-gate prev_entry->ar_next = NULL; 224*7c478bd9Sstevel@tonic-gate else 225*7c478bd9Sstevel@tonic-gate listhead = NULL; 226*7c478bd9Sstevel@tonic-gate listend = prev_entry; 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate /* add to moved list */ 229*7c478bd9Sstevel@tonic-gate if (new_listhead == NULL) 230*7c478bd9Sstevel@tonic-gate new_listhead = fileptr; 231*7c478bd9Sstevel@tonic-gate else 232*7c478bd9Sstevel@tonic-gate new_listend->ar_next = fileptr; 233*7c478bd9Sstevel@tonic-gate new_listend = fileptr; 234*7c478bd9Sstevel@tonic-gate } 235*7c478bd9Sstevel@tonic-gate cmd_info->modified++; 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate else 239*7c478bd9Sstevel@tonic-gate /* 240*7c478bd9Sstevel@tonic-gate * Unchaged 241*7c478bd9Sstevel@tonic-gate */ 242*7c478bd9Sstevel@tonic-gate mesg('u', fileptr->ar_longname, cmd_info); 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate if (deleted) 245*7c478bd9Sstevel@tonic-gate deleted = 0; 246*7c478bd9Sstevel@tonic-gate else 247*7c478bd9Sstevel@tonic-gate prev_entry = fileptr; 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate endptr = listend; 251*7c478bd9Sstevel@tonic-gate cleanup(cmd_info); 252*7c478bd9Sstevel@tonic-gate if (cmd_info->ponam && endptr && 253*7c478bd9Sstevel@tonic-gate (((moved_files = endptr->ar_next) != NULL) || new_listhead)) { 254*7c478bd9Sstevel@tonic-gate if (!abifile) { 255*7c478bd9Sstevel@tonic-gate error_message(NOT_FOUND_02_ERROR, 256*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, cmd_info->ponam); 257*7c478bd9Sstevel@tonic-gate exit(2); 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate endptr->ar_next = NULL; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate /* 262*7c478bd9Sstevel@tonic-gate * link new/moved files into archive entry list... 263*7c478bd9Sstevel@tonic-gate * 1: prepend newlist to moved/appended list 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate if (new_listhead) { 266*7c478bd9Sstevel@tonic-gate if (!moved_files) 267*7c478bd9Sstevel@tonic-gate listend = new_listend; 268*7c478bd9Sstevel@tonic-gate new_listend->ar_next = moved_files; 269*7c478bd9Sstevel@tonic-gate moved_files = new_listhead; 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate /* 2: insert at appropriate position... */ 272*7c478bd9Sstevel@tonic-gate if (opt_FLAG(cmd_info, b_FLAG)) 273*7c478bd9Sstevel@tonic-gate abifile = backptr; 274*7c478bd9Sstevel@tonic-gate if (abifile) { 275*7c478bd9Sstevel@tonic-gate listend->ar_next = abifile->ar_next; 276*7c478bd9Sstevel@tonic-gate abifile->ar_next = moved_files; 277*7c478bd9Sstevel@tonic-gate } else { 278*7c478bd9Sstevel@tonic-gate listend->ar_next = listhead; 279*7c478bd9Sstevel@tonic-gate listhead = moved_files; 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate listend = endptr; 282*7c478bd9Sstevel@tonic-gate } else if (cmd_info->ponam && !abifile) 283*7c478bd9Sstevel@tonic-gate error_message(NOT_FOUND_02_ERROR, 284*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, cmd_info->ponam); 285*7c478bd9Sstevel@tonic-gate return (0); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate int 289*7c478bd9Sstevel@tonic-gate dcmd(Cmd_info *cmd_info) 290*7c478bd9Sstevel@tonic-gate { 291*7c478bd9Sstevel@tonic-gate register ARFILE *fptr; 292*7c478bd9Sstevel@tonic-gate register ARFILE *backptr = NULL; 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate for (fptr = getfile(cmd_info); fptr; fptr = getfile(cmd_info)) { 295*7c478bd9Sstevel@tonic-gate if (match(fptr->ar_longname, cmd_info) != NULL) { 296*7c478bd9Sstevel@tonic-gate /* 297*7c478bd9Sstevel@tonic-gate * NOTE: 298*7c478bd9Sstevel@tonic-gate * Refer to "Incompatible Archive Header" 299*7c478bd9Sstevel@tonic-gate * blocked comment at the beginning of this file. 300*7c478bd9Sstevel@tonic-gate */ 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate /* 303*7c478bd9Sstevel@tonic-gate * Deleted 304*7c478bd9Sstevel@tonic-gate */ 305*7c478bd9Sstevel@tonic-gate mesg('d', fptr->ar_longname, cmd_info); 306*7c478bd9Sstevel@tonic-gate if (backptr == NULL) { 307*7c478bd9Sstevel@tonic-gate listhead = NULL; 308*7c478bd9Sstevel@tonic-gate listend = NULL; 309*7c478bd9Sstevel@tonic-gate } else { 310*7c478bd9Sstevel@tonic-gate backptr->ar_next = NULL; 311*7c478bd9Sstevel@tonic-gate listend = backptr; 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate cmd_info->modified = 1; 314*7c478bd9Sstevel@tonic-gate } else { 315*7c478bd9Sstevel@tonic-gate /* 316*7c478bd9Sstevel@tonic-gate * Unchaged 317*7c478bd9Sstevel@tonic-gate */ 318*7c478bd9Sstevel@tonic-gate mesg('u', fptr->ar_longname, cmd_info); 319*7c478bd9Sstevel@tonic-gate backptr = fptr; 320*7c478bd9Sstevel@tonic-gate } 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate return (0); 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate int 326*7c478bd9Sstevel@tonic-gate xcmd(Cmd_info *cmd_info) 327*7c478bd9Sstevel@tonic-gate { 328*7c478bd9Sstevel@tonic-gate register int f; 329*7c478bd9Sstevel@tonic-gate register ARFILE *next; 330*7c478bd9Sstevel@tonic-gate int rawname = 0; 331*7c478bd9Sstevel@tonic-gate int f_len = 0; 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate /* 334*7c478bd9Sstevel@tonic-gate * If -T is specified, get the maximum file name length. 335*7c478bd9Sstevel@tonic-gate */ 336*7c478bd9Sstevel@tonic-gate if (cmd_info->OPT_flgs & T_FLAG) { 337*7c478bd9Sstevel@tonic-gate f_len = pathconf(".", _PC_NAME_MAX); 338*7c478bd9Sstevel@tonic-gate if (f_len == -1) { 339*7c478bd9Sstevel@tonic-gate error_message(PATHCONF_ERROR, 340*7c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno)); 341*7c478bd9Sstevel@tonic-gate exit(1); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate for (next = getfile(cmd_info); next; next = getfile(cmd_info)) { 345*7c478bd9Sstevel@tonic-gate if ((next->ar_longname[0] == 0) && (next->ar_rawname[0] != 0)) 346*7c478bd9Sstevel@tonic-gate rawname = 1; 347*7c478bd9Sstevel@tonic-gate if (cmd_info->namc == 0 || 348*7c478bd9Sstevel@tonic-gate match(next->ar_longname, cmd_info) != NULL || 349*7c478bd9Sstevel@tonic-gate match(next->ar_rawname, cmd_info) != NULL) { 350*7c478bd9Sstevel@tonic-gate /* 351*7c478bd9Sstevel@tonic-gate * NOTE: 352*7c478bd9Sstevel@tonic-gate * Refer to "Incompatible Archive Header" 353*7c478bd9Sstevel@tonic-gate * blocked comment at the beginning of this file. 354*7c478bd9Sstevel@tonic-gate */ 355*7c478bd9Sstevel@tonic-gate f = create_extract(next, rawname, f_len, cmd_info); 356*7c478bd9Sstevel@tonic-gate if (f >= 0) { 357*7c478bd9Sstevel@tonic-gate if (rawname) { 358*7c478bd9Sstevel@tonic-gate /* 359*7c478bd9Sstevel@tonic-gate * eXtracted 360*7c478bd9Sstevel@tonic-gate */ 361*7c478bd9Sstevel@tonic-gate mesg('x', next->ar_rawname, cmd_info); 362*7c478bd9Sstevel@tonic-gate if (write(f, next->ar_contents, 363*7c478bd9Sstevel@tonic-gate (unsigned)next->ar_size) != 364*7c478bd9Sstevel@tonic-gate next->ar_size) { 365*7c478bd9Sstevel@tonic-gate error_message(SYS_WRITE_ERROR, 366*7c478bd9Sstevel@tonic-gate SYSTEM_ERROR, 367*7c478bd9Sstevel@tonic-gate strerror(errno), 368*7c478bd9Sstevel@tonic-gate next->ar_rawname); 369*7c478bd9Sstevel@tonic-gate exit(1); 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate } else { 372*7c478bd9Sstevel@tonic-gate /* 373*7c478bd9Sstevel@tonic-gate * eXtracted 374*7c478bd9Sstevel@tonic-gate */ 375*7c478bd9Sstevel@tonic-gate mesg('x', next->ar_longname, cmd_info); 376*7c478bd9Sstevel@tonic-gate if (write(f, next->ar_contents, 377*7c478bd9Sstevel@tonic-gate (unsigned)next->ar_size) != 378*7c478bd9Sstevel@tonic-gate next->ar_size) { 379*7c478bd9Sstevel@tonic-gate error_message(SYS_WRITE_ERROR, 380*7c478bd9Sstevel@tonic-gate SYSTEM_ERROR, 381*7c478bd9Sstevel@tonic-gate strerror(errno), 382*7c478bd9Sstevel@tonic-gate next->ar_longname); 383*7c478bd9Sstevel@tonic-gate exit(1); 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate (void) close(f); 387*7c478bd9Sstevel@tonic-gate } else 388*7c478bd9Sstevel@tonic-gate exit(1); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate rawname = 0; 391*7c478bd9Sstevel@tonic-gate } /* for */ 392*7c478bd9Sstevel@tonic-gate return (0); 393*7c478bd9Sstevel@tonic-gate } 394*7c478bd9Sstevel@tonic-gate 395*7c478bd9Sstevel@tonic-gate int 396*7c478bd9Sstevel@tonic-gate pcmd(Cmd_info *cmd_info) 397*7c478bd9Sstevel@tonic-gate { 398*7c478bd9Sstevel@tonic-gate register ARFILE *next; 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate for (next = getfile(cmd_info); next; next = getfile(cmd_info)) { 401*7c478bd9Sstevel@tonic-gate if (cmd_info->namc == 0 || 402*7c478bd9Sstevel@tonic-gate match(next->ar_longname, cmd_info) != NULL || 403*7c478bd9Sstevel@tonic-gate match(next->ar_rawname, cmd_info) != NULL) { 404*7c478bd9Sstevel@tonic-gate /* 405*7c478bd9Sstevel@tonic-gate * NOTE: 406*7c478bd9Sstevel@tonic-gate * Refer to "Incompatible Archive Header" 407*7c478bd9Sstevel@tonic-gate * blocked comment at the beginning of this file. 408*7c478bd9Sstevel@tonic-gate */ 409*7c478bd9Sstevel@tonic-gate if (opt_FLAG(cmd_info, v_FLAG)) { 410*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, 411*7c478bd9Sstevel@tonic-gate "\n<%s>\n\n", next->ar_longname); 412*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate (void) fwrite(next->ar_contents, sizeof (char), 415*7c478bd9Sstevel@tonic-gate next->ar_size, stdout); 416*7c478bd9Sstevel@tonic-gate } 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate return (0); 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate 421*7c478bd9Sstevel@tonic-gate int 422*7c478bd9Sstevel@tonic-gate mcmd(Cmd_info *cmd_info) 423*7c478bd9Sstevel@tonic-gate { 424*7c478bd9Sstevel@tonic-gate register ARFILE *fileptr; 425*7c478bd9Sstevel@tonic-gate register ARFILE *abifile = NULL; 426*7c478bd9Sstevel@tonic-gate register ARFILE *tmphead = NULL; 427*7c478bd9Sstevel@tonic-gate register ARFILE *tmpend = NULL; 428*7c478bd9Sstevel@tonic-gate ARFILE *backptr1 = NULL; 429*7c478bd9Sstevel@tonic-gate ARFILE *backptr2 = NULL; 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate for (fileptr = getfile(cmd_info); 432*7c478bd9Sstevel@tonic-gate fileptr; fileptr = getfile(cmd_info)) { 433*7c478bd9Sstevel@tonic-gate if (match(fileptr->ar_longname, cmd_info) != NULL) { 434*7c478bd9Sstevel@tonic-gate /* 435*7c478bd9Sstevel@tonic-gate * position Modified 436*7c478bd9Sstevel@tonic-gate */ 437*7c478bd9Sstevel@tonic-gate mesg('m', fileptr->ar_longname, cmd_info); 438*7c478bd9Sstevel@tonic-gate if (tmphead) 439*7c478bd9Sstevel@tonic-gate tmpend->ar_next = fileptr; 440*7c478bd9Sstevel@tonic-gate else 441*7c478bd9Sstevel@tonic-gate tmphead = fileptr; 442*7c478bd9Sstevel@tonic-gate tmpend = fileptr; 443*7c478bd9Sstevel@tonic-gate if (backptr1) { 444*7c478bd9Sstevel@tonic-gate listend = backptr1; 445*7c478bd9Sstevel@tonic-gate listend->ar_next = NULL; 446*7c478bd9Sstevel@tonic-gate } 447*7c478bd9Sstevel@tonic-gate else 448*7c478bd9Sstevel@tonic-gate listhead = NULL; 449*7c478bd9Sstevel@tonic-gate continue; 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate /* 452*7c478bd9Sstevel@tonic-gate * position Unchaged 453*7c478bd9Sstevel@tonic-gate */ 454*7c478bd9Sstevel@tonic-gate mesg('u', fileptr->ar_longname, cmd_info); 455*7c478bd9Sstevel@tonic-gate backptr1 = fileptr; 456*7c478bd9Sstevel@tonic-gate if (cmd_info->ponam && !abifile) { 457*7c478bd9Sstevel@tonic-gate if (strcmp(fileptr->ar_longname, cmd_info->ponam) == 0) 458*7c478bd9Sstevel@tonic-gate abifile = fileptr; 459*7c478bd9Sstevel@tonic-gate else 460*7c478bd9Sstevel@tonic-gate backptr2 = fileptr; 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate } 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate if (!tmphead) 465*7c478bd9Sstevel@tonic-gate return (1); 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate if (!cmd_info->ponam) 468*7c478bd9Sstevel@tonic-gate listend->ar_next = tmphead; 469*7c478bd9Sstevel@tonic-gate else { 470*7c478bd9Sstevel@tonic-gate if (!abifile) { 471*7c478bd9Sstevel@tonic-gate error_message(NOT_FOUND_02_ERROR, 472*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, cmd_info->ponam); 473*7c478bd9Sstevel@tonic-gate exit(2); 474*7c478bd9Sstevel@tonic-gate } 475*7c478bd9Sstevel@tonic-gate if (opt_FLAG(cmd_info, b_FLAG)) 476*7c478bd9Sstevel@tonic-gate abifile = backptr2; 477*7c478bd9Sstevel@tonic-gate if (abifile) { 478*7c478bd9Sstevel@tonic-gate tmpend->ar_next = abifile->ar_next; 479*7c478bd9Sstevel@tonic-gate abifile->ar_next = tmphead; 480*7c478bd9Sstevel@tonic-gate } else { 481*7c478bd9Sstevel@tonic-gate tmphead->ar_next = listhead; 482*7c478bd9Sstevel@tonic-gate listhead = tmphead; 483*7c478bd9Sstevel@tonic-gate } 484*7c478bd9Sstevel@tonic-gate } 485*7c478bd9Sstevel@tonic-gate (cmd_info->modified)++; 486*7c478bd9Sstevel@tonic-gate return (0); 487*7c478bd9Sstevel@tonic-gate } 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate int 490*7c478bd9Sstevel@tonic-gate tcmd(Cmd_info *cmd_info) 491*7c478bd9Sstevel@tonic-gate { 492*7c478bd9Sstevel@tonic-gate register ARFILE *next; 493*7c478bd9Sstevel@tonic-gate register int **mp; 494*7c478bd9Sstevel@tonic-gate char buf[DATESIZE]; 495*7c478bd9Sstevel@tonic-gate int m1[] = {1, ROWN, 'r', '-'}; 496*7c478bd9Sstevel@tonic-gate int m2[] = {1, WOWN, 'w', '-'}; 497*7c478bd9Sstevel@tonic-gate int m3[] = {2, SUID, 's', XOWN, 'x', '-'}; 498*7c478bd9Sstevel@tonic-gate int m4[] = {1, RGRP, 'r', '-'}; 499*7c478bd9Sstevel@tonic-gate int m5[] = {1, WGRP, 'w', '-'}; 500*7c478bd9Sstevel@tonic-gate int m6[] = {2, SGID, 's', XGRP, 'x', '-'}; 501*7c478bd9Sstevel@tonic-gate int m7[] = {1, ROTH, 'r', '-'}; 502*7c478bd9Sstevel@tonic-gate int m8[] = {1, WOTH, 'w', '-'}; 503*7c478bd9Sstevel@tonic-gate int m9[] = {2, STXT, 't', XOTH, 'x', '-'}; 504*7c478bd9Sstevel@tonic-gate int *m[10]; 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate m[0] = m1; 507*7c478bd9Sstevel@tonic-gate m[1] = m2; 508*7c478bd9Sstevel@tonic-gate m[2] = m3; 509*7c478bd9Sstevel@tonic-gate m[3] = m4; 510*7c478bd9Sstevel@tonic-gate m[4] = m5; 511*7c478bd9Sstevel@tonic-gate m[5] = m6; 512*7c478bd9Sstevel@tonic-gate m[6] = m7; 513*7c478bd9Sstevel@tonic-gate m[7] = m8; 514*7c478bd9Sstevel@tonic-gate m[8] = m9; 515*7c478bd9Sstevel@tonic-gate m[9] = 0; 516*7c478bd9Sstevel@tonic-gate 517*7c478bd9Sstevel@tonic-gate for (next = getfile(cmd_info); next; next = getfile(cmd_info)) { 518*7c478bd9Sstevel@tonic-gate if (cmd_info->namc == 0 || 519*7c478bd9Sstevel@tonic-gate match(next->ar_longname, cmd_info) != NULL || 520*7c478bd9Sstevel@tonic-gate match(next->ar_rawname, cmd_info) != NULL) { 521*7c478bd9Sstevel@tonic-gate /* 522*7c478bd9Sstevel@tonic-gate * NOTE: 523*7c478bd9Sstevel@tonic-gate * Refer to "Incompatible Archive Header" 524*7c478bd9Sstevel@tonic-gate * blocked comment at the beginning of this file. 525*7c478bd9Sstevel@tonic-gate */ 526*7c478bd9Sstevel@tonic-gate if (opt_FLAG(cmd_info, v_FLAG)) { 527*7c478bd9Sstevel@tonic-gate for (mp = &m[0]; mp < &m[9]; ) 528*7c478bd9Sstevel@tonic-gate ar_select(*mp++, next->ar_mode); 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%6d/%6d", next->ar_uid, 531*7c478bd9Sstevel@tonic-gate next->ar_gid); 532*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%7ld", next->ar_size); 533*7c478bd9Sstevel@tonic-gate if ((strftime(buf, 534*7c478bd9Sstevel@tonic-gate DATESIZE, 535*7c478bd9Sstevel@tonic-gate "%b %e %H:%M %Y", 536*7c478bd9Sstevel@tonic-gate localtime(&(next->ar_date)))) == 0) { 537*7c478bd9Sstevel@tonic-gate error_message(LOCALTIME_ERROR, 538*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 539*7c478bd9Sstevel@tonic-gate exit(1); 540*7c478bd9Sstevel@tonic-gate } 541*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, " %s ", buf); 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate if ((next->ar_longname[0] == 0) && 544*7c478bd9Sstevel@tonic-gate (next->ar_rawname[0] != 0)) 545*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, 546*7c478bd9Sstevel@tonic-gate "%s\n", trim(next->ar_rawname)); 547*7c478bd9Sstevel@tonic-gate else 548*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, 549*7c478bd9Sstevel@tonic-gate "%s\n", trim(next->ar_longname)); 550*7c478bd9Sstevel@tonic-gate } 551*7c478bd9Sstevel@tonic-gate } /* for */ 552*7c478bd9Sstevel@tonic-gate return (0); 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate int 556*7c478bd9Sstevel@tonic-gate qcmd(Cmd_info *cmd_info) 557*7c478bd9Sstevel@tonic-gate { 558*7c478bd9Sstevel@tonic-gate register ARFILE *fptr; 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate if (opt_FLAG(cmd_info, a_FLAG) || opt_FLAG(cmd_info, b_FLAG)) { 561*7c478bd9Sstevel@tonic-gate error_message(USAGE_05_ERROR, 562*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 563*7c478bd9Sstevel@tonic-gate exit(1); 564*7c478bd9Sstevel@tonic-gate } 565*7c478bd9Sstevel@tonic-gate for (fptr = getfile(cmd_info); fptr; fptr = getfile(cmd_info)) 566*7c478bd9Sstevel@tonic-gate ; 567*7c478bd9Sstevel@tonic-gate cleanup(cmd_info); 568*7c478bd9Sstevel@tonic-gate return (0); 569*7c478bd9Sstevel@tonic-gate } 570*7c478bd9Sstevel@tonic-gate 571*7c478bd9Sstevel@tonic-gate /* 572*7c478bd9Sstevel@tonic-gate * Supplementary functions 573*7c478bd9Sstevel@tonic-gate */ 574*7c478bd9Sstevel@tonic-gate static char * 575*7c478bd9Sstevel@tonic-gate match(char *file, Cmd_info *cmd_info) 576*7c478bd9Sstevel@tonic-gate { 577*7c478bd9Sstevel@tonic-gate register int i; 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate for (i = 0; i < cmd_info->namc; i++) { 580*7c478bd9Sstevel@tonic-gate if (cmd_info->namv[i] == 0) 581*7c478bd9Sstevel@tonic-gate continue; 582*7c478bd9Sstevel@tonic-gate if (strcmp(trim(cmd_info->namv[i]), file) == 0) { 583*7c478bd9Sstevel@tonic-gate file = cmd_info->namv[i]; 584*7c478bd9Sstevel@tonic-gate cmd_info->namv[i] = 0; 585*7c478bd9Sstevel@tonic-gate return (file); 586*7c478bd9Sstevel@tonic-gate } 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate return (NULL); 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate /* 592*7c478bd9Sstevel@tonic-gate * puts the file which was in the list in the linked list 593*7c478bd9Sstevel@tonic-gate */ 594*7c478bd9Sstevel@tonic-gate static void 595*7c478bd9Sstevel@tonic-gate cleanup(Cmd_info *cmd_info) 596*7c478bd9Sstevel@tonic-gate { 597*7c478bd9Sstevel@tonic-gate register int i; 598*7c478bd9Sstevel@tonic-gate register FILE *f; 599*7c478bd9Sstevel@tonic-gate register ARFILE *fileptr; 600*7c478bd9Sstevel@tonic-gate struct stat stbuf; 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate for (i = 0; i < cmd_info->namc; i++) { 603*7c478bd9Sstevel@tonic-gate if (cmd_info->namv[i] == 0) 604*7c478bd9Sstevel@tonic-gate continue; 605*7c478bd9Sstevel@tonic-gate /* 606*7c478bd9Sstevel@tonic-gate * Appended 607*7c478bd9Sstevel@tonic-gate */ 608*7c478bd9Sstevel@tonic-gate mesg('a', cmd_info->namv[i], cmd_info); 609*7c478bd9Sstevel@tonic-gate f = stats(cmd_info->namv[i], &stbuf); 610*7c478bd9Sstevel@tonic-gate if (f == NULL) 611*7c478bd9Sstevel@tonic-gate error_message(SYS_OPEN_ERROR, 612*7c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), cmd_info->namv[i]); 613*7c478bd9Sstevel@tonic-gate else { 614*7c478bd9Sstevel@tonic-gate fileptr = newfile(); 615*7c478bd9Sstevel@tonic-gate /* if short name */ 616*7c478bd9Sstevel@tonic-gate (void) strncpy(fileptr->ar_name, 617*7c478bd9Sstevel@tonic-gate trim(cmd_info->namv[i]), SNAME); 618*7c478bd9Sstevel@tonic-gate 619*7c478bd9Sstevel@tonic-gate if ((fileptr->ar_longname = 620*7c478bd9Sstevel@tonic-gate malloc(strlen(trim(cmd_info->namv[i])) + 1)) == 621*7c478bd9Sstevel@tonic-gate NULL) { 622*7c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 623*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 624*7c478bd9Sstevel@tonic-gate exit(1); 625*7c478bd9Sstevel@tonic-gate } 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate (void) strcpy(fileptr->ar_longname, 628*7c478bd9Sstevel@tonic-gate trim(cmd_info->namv[i])); 629*7c478bd9Sstevel@tonic-gate 630*7c478bd9Sstevel@tonic-gate if ((fileptr->ar_pathname = 631*7c478bd9Sstevel@tonic-gate malloc(strlen(cmd_info->namv[i]) + 1)) == NULL) { 632*7c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 633*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 634*7c478bd9Sstevel@tonic-gate exit(1); 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate (void) strcpy(fileptr->ar_pathname, cmd_info->namv[i]); 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate movefil(fileptr, &stbuf); 640*7c478bd9Sstevel@tonic-gate 641*7c478bd9Sstevel@tonic-gate /* clear 'ar_flag' */ 642*7c478bd9Sstevel@tonic-gate fileptr->ar_flag &= ~(F_ELFRAW | F_MMAPED | F_MALLOCED); 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate if ((cmd_info->OPT_flgs & M_FLAG) == 0) { 645*7c478bd9Sstevel@tonic-gate if ((cmd_info->bytes_in_mem + stbuf.st_size) < 646*7c478bd9Sstevel@tonic-gate AR_MAX_BYTES_IN_MEM) { 647*7c478bd9Sstevel@tonic-gate fileptr->ar_flag &= 648*7c478bd9Sstevel@tonic-gate ~(F_ELFRAW | F_MMAPED); 649*7c478bd9Sstevel@tonic-gate fileptr->ar_flag |= F_MALLOCED; 650*7c478bd9Sstevel@tonic-gate if ((fileptr->ar_contents = 651*7c478bd9Sstevel@tonic-gate malloc(ROUNDUP(stbuf.st_size))) == 652*7c478bd9Sstevel@tonic-gate NULL) { 653*7c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 654*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 655*7c478bd9Sstevel@tonic-gate exit(1); 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate if (fread(fileptr->ar_contents, 658*7c478bd9Sstevel@tonic-gate sizeof (char), stbuf.st_size, 659*7c478bd9Sstevel@tonic-gate f) != stbuf.st_size) { 660*7c478bd9Sstevel@tonic-gate error_message(SYS_READ_ERROR, 661*7c478bd9Sstevel@tonic-gate SYSTEM_ERROR, 662*7c478bd9Sstevel@tonic-gate strerror(errno), 663*7c478bd9Sstevel@tonic-gate fileptr->ar_longname); 664*7c478bd9Sstevel@tonic-gate exit(1); 665*7c478bd9Sstevel@tonic-gate } 666*7c478bd9Sstevel@tonic-gate cmd_info->bytes_in_mem += stbuf.st_size; 667*7c478bd9Sstevel@tonic-gate } 668*7c478bd9Sstevel@tonic-gate } else { 669*7c478bd9Sstevel@tonic-gate fileptr->ar_flag &= ~(F_ELFRAW | F_MALLOCED); 670*7c478bd9Sstevel@tonic-gate fileptr->ar_flag |= F_MMAPED; 671*7c478bd9Sstevel@tonic-gate if ((fileptr->ar_contents = 672*7c478bd9Sstevel@tonic-gate (char *)mmap(0, stbuf.st_size, PROT_READ, 673*7c478bd9Sstevel@tonic-gate MAP_SHARED, fileno(f), 0)) == (char *)-1) { 674*7c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 675*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 676*7c478bd9Sstevel@tonic-gate exit(1); 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate (void) fclose(f); 680*7c478bd9Sstevel@tonic-gate (cmd_info->modified)++; 681*7c478bd9Sstevel@tonic-gate cmd_info->namv[i] = 0; 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate } 684*7c478bd9Sstevel@tonic-gate } 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate /* 687*7c478bd9Sstevel@tonic-gate * insert the file 'file' into the temporary file 688*7c478bd9Sstevel@tonic-gate */ 689*7c478bd9Sstevel@tonic-gate static void 690*7c478bd9Sstevel@tonic-gate movefil(ARFILE *fileptr, struct stat *stbuf) 691*7c478bd9Sstevel@tonic-gate { 692*7c478bd9Sstevel@tonic-gate fileptr->ar_size = stbuf->st_size; 693*7c478bd9Sstevel@tonic-gate fileptr->ar_date = stbuf->st_mtime; 694*7c478bd9Sstevel@tonic-gate fileptr->ar_mode = stbuf->st_mode; 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate /* 697*7c478bd9Sstevel@tonic-gate * The format of an 'ar' file includes a 6 character 698*7c478bd9Sstevel@tonic-gate * decimal string to contain the uid. 699*7c478bd9Sstevel@tonic-gate * 700*7c478bd9Sstevel@tonic-gate * If the uid or gid is too big to fit, then set it to 701*7c478bd9Sstevel@tonic-gate * nobody (for want of a better value). Clear the 702*7c478bd9Sstevel@tonic-gate * setuid/setgid bits in the mode to avoid setuid nobody 703*7c478bd9Sstevel@tonic-gate * or setgid nobody files unexpectedly coming into existence. 704*7c478bd9Sstevel@tonic-gate */ 705*7c478bd9Sstevel@tonic-gate if ((fileptr->ar_uid = stbuf->st_uid) > 999999) { 706*7c478bd9Sstevel@tonic-gate fileptr->ar_uid = UID_NOBODY; 707*7c478bd9Sstevel@tonic-gate if (S_ISREG(fileptr->ar_mode)) 708*7c478bd9Sstevel@tonic-gate fileptr->ar_mode &= ~S_ISUID; 709*7c478bd9Sstevel@tonic-gate } 710*7c478bd9Sstevel@tonic-gate if ((fileptr->ar_gid = stbuf->st_gid) > 999999) { 711*7c478bd9Sstevel@tonic-gate fileptr->ar_gid = GID_NOBODY; 712*7c478bd9Sstevel@tonic-gate if (S_ISREG(fileptr->ar_mode)) 713*7c478bd9Sstevel@tonic-gate fileptr->ar_mode &= ~S_ISGID; 714*7c478bd9Sstevel@tonic-gate } 715*7c478bd9Sstevel@tonic-gate } 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate static FILE * 718*7c478bd9Sstevel@tonic-gate stats(char *file, struct stat *stbuf) 719*7c478bd9Sstevel@tonic-gate { 720*7c478bd9Sstevel@tonic-gate register FILE *f; 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate f = fopen(file, "r"); 723*7c478bd9Sstevel@tonic-gate if (f == NULL) 724*7c478bd9Sstevel@tonic-gate return (f); 725*7c478bd9Sstevel@tonic-gate if (stat(file, stbuf) < 0) { 726*7c478bd9Sstevel@tonic-gate (void) fclose(f); 727*7c478bd9Sstevel@tonic-gate return (NULL); 728*7c478bd9Sstevel@tonic-gate } 729*7c478bd9Sstevel@tonic-gate return (f); 730*7c478bd9Sstevel@tonic-gate } 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate /* 733*7c478bd9Sstevel@tonic-gate * Used by xcmd() 734*7c478bd9Sstevel@tonic-gate */ 735*7c478bd9Sstevel@tonic-gate int 736*7c478bd9Sstevel@tonic-gate create_extract(ARFILE *a, int rawname, int f_len, Cmd_info *cmd_info) 737*7c478bd9Sstevel@tonic-gate { 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate int f; 740*7c478bd9Sstevel@tonic-gate char *f_name; 741*7c478bd9Sstevel@tonic-gate char *dup = NULL; 742*7c478bd9Sstevel@tonic-gate if (rawname) 743*7c478bd9Sstevel@tonic-gate f_name = a->ar_rawname; 744*7c478bd9Sstevel@tonic-gate else 745*7c478bd9Sstevel@tonic-gate f_name = a->ar_longname; 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate /* 748*7c478bd9Sstevel@tonic-gate * If -T is specified, check the file length. 749*7c478bd9Sstevel@tonic-gate */ 750*7c478bd9Sstevel@tonic-gate if (cmd_info->OPT_flgs & T_FLAG) { 751*7c478bd9Sstevel@tonic-gate int len; 752*7c478bd9Sstevel@tonic-gate len = strlen(f_name); 753*7c478bd9Sstevel@tonic-gate if (f_len <= len) { 754*7c478bd9Sstevel@tonic-gate dup = malloc(f_len+1); 755*7c478bd9Sstevel@tonic-gate if (dup == NULL) { 756*7c478bd9Sstevel@tonic-gate error_message(MALLOC_ERROR, 757*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0); 758*7c478bd9Sstevel@tonic-gate exit(1); 759*7c478bd9Sstevel@tonic-gate } 760*7c478bd9Sstevel@tonic-gate (void) strncpy(dup, f_name, f_len); 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate f_name = dup; 763*7c478bd9Sstevel@tonic-gate } 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate /* 766*7c478bd9Sstevel@tonic-gate * Bug 4052067 - If a file to be extracted has the same 767*7c478bd9Sstevel@tonic-gate * filename as the archive, the archive gets overwritten 768*7c478bd9Sstevel@tonic-gate * which can lead to a corrupted archive or worse, a ufs 769*7c478bd9Sstevel@tonic-gate * deadlock because libelf has mmap'ed the archive! We 770*7c478bd9Sstevel@tonic-gate * can't rely on strcmp() to test for this case because 771*7c478bd9Sstevel@tonic-gate * the archive could be prefixed with a partial or full 772*7c478bd9Sstevel@tonic-gate * path (and we could be using the rawname from the archive) 773*7c478bd9Sstevel@tonic-gate * This means we have to do the same thing we did for mv, 774*7c478bd9Sstevel@tonic-gate * which is to explicitly check if the file we would extract 775*7c478bd9Sstevel@tonic-gate * to is identical to the archive. Because part of this 776*7c478bd9Sstevel@tonic-gate * test is essentially what the -C flag does, I've merged 777*7c478bd9Sstevel@tonic-gate * the code together. 778*7c478bd9Sstevel@tonic-gate */ 779*7c478bd9Sstevel@tonic-gate if (access(f_name, F_OK) != -1) { 780*7c478bd9Sstevel@tonic-gate struct stat s1, s2; 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate /* 783*7c478bd9Sstevel@tonic-gate * If -C is specified, this is an error anyway 784*7c478bd9Sstevel@tonic-gate */ 785*7c478bd9Sstevel@tonic-gate if (cmd_info->OPT_flgs & C_FLAG) { 786*7c478bd9Sstevel@tonic-gate if (dup != NULL) 787*7c478bd9Sstevel@tonic-gate free(dup); 788*7c478bd9Sstevel@tonic-gate error_message(OVERRIDE_WARN_ERROR, 789*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, f_name); 790*7c478bd9Sstevel@tonic-gate return (-1); 791*7c478bd9Sstevel@tonic-gate } 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate /* 794*7c478bd9Sstevel@tonic-gate * Okay, -C wasn't specified. However, now we do 795*7c478bd9Sstevel@tonic-gate * the check to see if the archive would be overwritten 796*7c478bd9Sstevel@tonic-gate * by extracting this file. stat() both objects and 797*7c478bd9Sstevel@tonic-gate * test to see if their identical. 798*7c478bd9Sstevel@tonic-gate */ 799*7c478bd9Sstevel@tonic-gate if ((stat(f_name, &s1) == 0) && 800*7c478bd9Sstevel@tonic-gate (stat(cmd_info->arnam, &s2) == 0)) { 801*7c478bd9Sstevel@tonic-gate 802*7c478bd9Sstevel@tonic-gate if ((s1.st_dev == s2.st_dev) && 803*7c478bd9Sstevel@tonic-gate (s1.st_ino == s2.st_ino)) { 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate if (dup != NULL) 806*7c478bd9Sstevel@tonic-gate free(dup); 807*7c478bd9Sstevel@tonic-gate error_message(OVERRIDE_WARN_ERROR, 808*7c478bd9Sstevel@tonic-gate PLAIN_ERROR, (char *)0, f_name); 809*7c478bd9Sstevel@tonic-gate return (-1); 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate } 812*7c478bd9Sstevel@tonic-gate } 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate /* 815*7c478bd9Sstevel@tonic-gate * Okay to create extraction file... 816*7c478bd9Sstevel@tonic-gate */ 817*7c478bd9Sstevel@tonic-gate f = creat(f_name, (mode_t)a->ar_mode & 0777); 818*7c478bd9Sstevel@tonic-gate if (f < 0) { 819*7c478bd9Sstevel@tonic-gate error_message(SYS_CREATE_01_ERROR, 820*7c478bd9Sstevel@tonic-gate SYSTEM_ERROR, strerror(errno), f_name); 821*7c478bd9Sstevel@tonic-gate /* 822*7c478bd9Sstevel@tonic-gate * Created 823*7c478bd9Sstevel@tonic-gate */ 824*7c478bd9Sstevel@tonic-gate mesg('c', f_name, cmd_info); 825*7c478bd9Sstevel@tonic-gate } 826*7c478bd9Sstevel@tonic-gate if (dup) 827*7c478bd9Sstevel@tonic-gate free(dup); 828*7c478bd9Sstevel@tonic-gate return (f); 829*7c478bd9Sstevel@tonic-gate } 830*7c478bd9Sstevel@tonic-gate 831*7c478bd9Sstevel@tonic-gate static void 832*7c478bd9Sstevel@tonic-gate mesg(int c, char *file, Cmd_info *cmd_info) 833*7c478bd9Sstevel@tonic-gate { 834*7c478bd9Sstevel@tonic-gate #ifdef XPG4 835*7c478bd9Sstevel@tonic-gate /* 836*7c478bd9Sstevel@tonic-gate * XPG4 does not have any message defined for 837*7c478bd9Sstevel@tonic-gate * 'c' operation. 838*7c478bd9Sstevel@tonic-gate * In fact, XPG only defines messages for 839*7c478bd9Sstevel@tonic-gate * d, r, a and x at the present. (03/05/'96) 840*7c478bd9Sstevel@tonic-gate */ 841*7c478bd9Sstevel@tonic-gate if (c == 'c' || c == 'u' || c == 'm') 842*7c478bd9Sstevel@tonic-gate return; 843*7c478bd9Sstevel@tonic-gate #endif 844*7c478bd9Sstevel@tonic-gate /* 845*7c478bd9Sstevel@tonic-gate * If 'u' is passed, convert it to 'c'. 846*7c478bd9Sstevel@tonic-gate * 'u' makes more sense since the operation did not 847*7c478bd9Sstevel@tonic-gate * do anything, Unchanged, but 'c' has been used so 848*7c478bd9Sstevel@tonic-gate * I do no want to break the compatibility at this moment. 849*7c478bd9Sstevel@tonic-gate * (03/05/'96). 850*7c478bd9Sstevel@tonic-gate */ 851*7c478bd9Sstevel@tonic-gate if (c == 'u') 852*7c478bd9Sstevel@tonic-gate c = 'c'; 853*7c478bd9Sstevel@tonic-gate if (opt_FLAG(cmd_info, v_FLAG)) 854*7c478bd9Sstevel@tonic-gate if (c != 'c') 855*7c478bd9Sstevel@tonic-gate (void) fprintf(stdout, "%c - %s\n", c, file); 856*7c478bd9Sstevel@tonic-gate } 857*7c478bd9Sstevel@tonic-gate 858*7c478bd9Sstevel@tonic-gate static void 859*7c478bd9Sstevel@tonic-gate ar_select(int *pairp, unsigned long mode) 860*7c478bd9Sstevel@tonic-gate { 861*7c478bd9Sstevel@tonic-gate register int n, *ap; 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate ap = pairp; 864*7c478bd9Sstevel@tonic-gate n = *ap++; 865*7c478bd9Sstevel@tonic-gate while (--n >= 0 && (mode & *ap++) == 0) 866*7c478bd9Sstevel@tonic-gate ap++; 867*7c478bd9Sstevel@tonic-gate (void) putchar(*ap); 868*7c478bd9Sstevel@tonic-gate } 869