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