diff options
| author | Ali Bahrami <Ali.Bahrami@Oracle.COM> | 2010-07-08 09:23:43 -0600 |
|---|---|---|
| committer | Ali Bahrami <Ali.Bahrami@Oracle.COM> | 2010-07-08 09:23:43 -0600 |
| commit | ba7866cd2cbdf574f47d4e38a1301b90744dd677 (patch) | |
| tree | 61774e774c951296df1a185c9b8004a5ba75739f /usr/src | |
| parent | 65e70c04884b95e29d10e9933a3d55f0ec5af3be (diff) | |
| download | illumos-joyent-ba7866cd2cbdf574f47d4e38a1301b90744dd677.tar.gz | |
6952219 ld support for archives larger than 2 GB
PSARC/2010/224 Support for archives larger than 2 GB
Diffstat (limited to 'usr/src')
38 files changed, 1754 insertions, 1791 deletions
diff --git a/usr/src/cmd/sgs/Makefile b/usr/src/cmd/sgs/Makefile index 10483bb9f2..25c5486d0a 100644 --- a/usr/src/cmd/sgs/Makefile +++ b/usr/src/cmd/sgs/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved. # include $(SRC)/cmd/Makefile.cmd @@ -84,8 +83,7 @@ SUBDIRS= $(SUBDIRS-common) $(SUBDIRS-$(MACH)) # Messaging support # -POSUBDIRS= ar m4 nm \ - tsort yacc +POSUBDIRS= m4 nm tsort yacc POFILE= sgs.po POFILES= $(POSUBDIRS:%=%/%.po) @@ -93,7 +91,7 @@ MSGSUBDIRS= ld ldd libld liblddbg \ libldstab librtld rtld libelf \ ldprof libcrle pvs elfdump \ elfedit crle moe lari \ - librtld_db elfwrap + librtld_db elfwrap ar MSGDIR= messages diff --git a/usr/src/cmd/sgs/ar/Makefile.com b/usr/src/cmd/sgs/ar/Makefile.com index e37d825ad4..2670d05404 100644 --- a/usr/src/cmd/sgs/ar/Makefile.com +++ b/usr/src/cmd/sgs/ar/Makefile.com @@ -19,44 +19,47 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. # PROG= ar XPG4PROG= ar include $(SRC)/cmd/Makefile.cmd +include $(SRC)/cmd/sgs/Makefile.com -COMOBJS= main.o file.o cmd.o global.o \ - message.o +COMOBJ= main.o file.o cmd.o -POFILE= ../ar.po +BLTOBJ = msg.o -OBJS= $(COMOBJS:%=objs/%) -XPG4OBJS= $(COMOBJS:%=objs.xpg4/%) +OBJS= $(BLTOBJ:%=objs/%) $(COMOBJ:%=objs/%) +XPG4OBJS= $(BLTOBJ:%=objs.xpg4/%) $(COMOBJ:%=objs.xpg4/%) LLDFLAGS = '-R$$ORIGIN/../../lib' -CPPFLAGS= -I../../include $(CPPFLAGS.master) +LLDFLAGS64 = '-R$$ORIGIN/../../../lib/$(MACH64)' +CPPFLAGS= -I. -I../../include $(CPPFLAGS.master) -I$(ELFCAP) CFLAGS += $(CCVERBOSE) C99MODE= $(C99_ENABLE) -LDLIBS += -lelf -LINTFLAGS= -mx -LINTFLAGS64= -mx -m64 - -SED= sed +LDLIBS += -lelf $(CONVLIBDIR) $(CONV_LIB) -lsendfile +LINTFLAGS= -x +LINTFLAGS64= -x $(XPG4) := CPPFLAGS += -DXPG4 -SRCS= $(COMOBJS:%.o=../common/%.c) -LINTSRCS= $(SRCS) +BLTDEFS = msg.h +BLTDATA = msg.c +BLTMESG = $(SGSMSGDIR)/ar + +BLTFILES = $(BLTDEFS) $(BLTDATA) $(BLTMESG) -CLEANFILES += $(OBJS) $(XPG4OBJS) $(LINTOUT) +SGSMSGCOM = ../common/ar.msg +SGSMSGTARG = $(SGSMSGCOM) +SGSMSGALL = $(SGSMSGCOM) +SGSMSGFLAGS += -h $(BLTDEFS) -d $(BLTDATA) -m $(BLTMESG) -n ar_msg -# Building SUNWonld results in a call to the `package' target. Requirements -# needed to run this application on older releases are established: -# i18n support requires libintl.so.1 prior to 2.6 +SRCS= $(COMOBJ:%.o=../common/%.c) $(BLTDATA:%.o=$(SGSTOOLS)/common/%.c) +LINTSRCS= $(SRCS) ../common/lintsup.c -package := LDLIBS += /usr/lib/libintl.so.1 +CLEANFILES += $(LINTOUTS) $(BLTFILES) diff --git a/usr/src/cmd/sgs/ar/Makefile.targ b/usr/src/cmd/sgs/ar/Makefile.targ index 9a272b0de2..6d28736736 100644 --- a/usr/src/cmd/sgs/ar/Makefile.targ +++ b/usr/src/cmd/sgs/ar/Makefile.targ @@ -19,30 +19,29 @@ # CDDL HEADER END # # -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. objs/%.o \ objs.xpg4/%.o: ../common/%.c $(COMPILE.c) -o $@ $< $(POST_PROCESS_O) -all: $(PROG) $(XPG4) +objs/%.o \ +objs.xpg4/%.o: %.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) clean: - $(RM) $(CLEANFILES) + $(RM) $(OBJS) $(XPG4OBJS) $(CLEANFILES) delete: $(RM) $(PROG) -install \ -package: all $(ROOTPROG) $(ROOTXPG4PROG) $(ROOTCCSBINLINK) +catalog: $(BLTMESG) -catalog: $(POFILE) +.PARALLEL: $(LINTOUT32) $(LINTOUT64) -lint: $(LINTOUT) +lint: $(LINTOUT32) $(SGSLINTOUT) $(PROG): $(OBJS) $(LINK.c) -o $@ $(LLDFLAGS) $(OBJS) $(LDLIBS) @@ -52,14 +51,6 @@ $(XPG4): $(XPG4OBJS) $(LINK.c) -o $@ $(XPG4OBJS) $(LDLIBS) $(POST_PROCESS) -$(POFILE): - $(RM) $@ - $(XGETTEXT) $(XGETFLAGS) ../common/main.c - $(SED) "/^domain/d" < messages.po > $@ - $(XGETTEXT) -a $(XGETFLAGS) ../common/message.c - $(SED) "/^domain/d" < messages.po >> $@ - $(RM) messages.po - $(OBJS): objs $(XPG4OBJS): objs.xpg4 @@ -67,8 +58,17 @@ $(XPG4OBJS): objs.xpg4 objs objs.xpg4: -@ mkdir -p $@ -$(LINTOUT): $(SRCS) - perl ../../tools/lint_hdr.pl $(PROG) > $(LINTOUT) - $(LINT.c) $(SRCS) $(LDLIBS) 2>&1 | tee -a $(LINTOUT) - include $(SRC)/cmd/Makefile.targ +include $(SRC)/cmd/sgs/Makefile.targ + +# Derived source and header files (messaging). + +catalog: $(BLTMESG) + +chkmsg: $(SRCS) + sh $(CHKMSG) $(CHKMSGFLAGS) $(SRCS) + +$(BLTDEFS) + \ +$(BLTDATA) + \ +$(BLTMESG): $(SGSMSGALL) + $(SGSMSG) $(SGSMSGFLAGS) $(SGSMSGALL) diff --git a/usr/src/cmd/sgs/packages/common/admin b/usr/src/cmd/sgs/ar/amd64/Makefile index 2d57427f83..4077158a06 100644 --- a/usr/src/cmd/sgs/packages/common/admin +++ b/usr/src/cmd/sgs/ar/amd64/Makefile @@ -1,7 +1,4 @@ # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# # CDDL HEADER START # # The contents of this file are subject to the terms of the @@ -22,24 +19,27 @@ # CDDL HEADER END # -# This admin file can be used to force the installation of the -# SUNWonld package on a system that already has it installed, without -# having to first uninstall the existing instance. This is a generally -# undesirable thing to do, but can be handy if you forget to uninstall -# SUNWonld before BFUing the system. In that state, removing the -# package can break your system, and the only safe route forward is -# to install on top of the existing package. # -# # pkgadd -a admin -d SUNWonld +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # -mail= -instance=overwrite -partial=ask -runlevel=nocheck -idepend=nocheck -rdepend=ask -space=nocheck -setuid=nocheck -conflict=nocheck -action=nocheck +include ../Makefile.com + +.KEEP_STATE: + +LLDFLAGS = $(LLDFLAGS64) +CONVLIBDIR = $(CONVLIBDIR64) +ELFLIBDIR = $(ELFLIBDIR64) +LDDBGLIBDIR = $(LDDBGLIBDIR64) +LINTFLAGS64 += $(VAR_LINTFLAGS64) + +ROOTPROG = $(ROOTPROG64) + +all: $(PROG) + +install \ +package: all $(ROOTPROG64) $(ROOTCCSBINLINK64) + + +include ../Makefile.targ +include ../../Makefile.sub.64 diff --git a/usr/src/cmd/sgs/ar/common/ar.msg b/usr/src/cmd/sgs/ar/common/ar.msg new file mode 100644 index 0000000000..f82a689966 --- /dev/null +++ b/usr/src/cmd/sgs/ar/common/ar.msg @@ -0,0 +1,134 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +@ _START_ + +# Message file for cmd/sgs/ar. + +@ MSG_ID_AR + +@ MSG_USAGE "usage: ar -d[-SvV] archive file ...\n \ + ar -m[-abiSvV] [posname] archive file ...\n \ + ar -p[-vV][-sS] archive [file ...]\n \ + ar -q[-cuvSV] [-abi] [posname] [file ...]\n \ + ar -r[-cuvSV] [-abi] [posname] [file ...]\n \ + ar -t[-vV][-sS] archive [file ...]\n \ + ar -x[-vV][-sSCT] archive [file ...]\n" + +@ MSG_MALLOC "ar: could not allocate memory: %s\n" +@ MSG_TOOBIG4G "ar: archive size exceeds capabilities of 32-bit \ + process\n" + +@ MSG_USAGE_01 "ar: one of [drqtpmx] must be specified\n" +@ MSG_USAGE_02 "ar: -%c requires an operand\n" +@ MSG_USAGE_03 "ar: bad option: -%c\n" +@ MSG_USAGE_04 "ar: only one of [drqtpmx] allowed\n" +@ MSG_USAGE_05 "ar: abi not allowed with q\n" +@ MSG_USAGE_06 "ar: %s taken as mandatory 'posname' with keys 'abi'\n" + +@ MSG_INTERNAL_01 "ar: internal error: cannot tell whether file is \ + included in archive or not\n" +@ MSG_INTERNAL_02 "ar: internal header generation error\n" + +@ MSG_SYS_OPEN "ar: cannot open %s: %s\n" +@ MSG_SYS_CLOSE "ar: cannot close %s: %s\n" +@ MSG_SYS_WRITE "ar: %s: cannot write: %s\n" +@ MSG_SYS_STAT "ar: cannot stat %s: %s\n" +@ MSG_SYS_RENAME "ar: cannot rename %s to %s: %s\n" + +@ MSG_NOT_FOUND_AR "ar: archive %s not found\n" +@ MSG_NOT_FOUND_POSNAM "ar: posname %s: not found\n" +@ MSG_NOT_FOUND_FILE "ar: %s not found\n" + +@ MSG_ELF_LIB_FILE "ar: %s caused libelf error: %s\n" +@ MSG_ELF_LIB_AR "ar: %s(%s) libelf error: %s\n" +@ MSG_ELF_BEGIN_FILE "ar: cannot elf_begin() %s: %s\n" +@ MSG_ELF_GETDATA_FILE "ar: %s has bad elf format: %s\n" +@ MSG_ELF_GETDATA_AR "ar: %s(%s) has bad elf format: %s\n" +@ MSG_ELF_GETSCN_FILE "ar: %s has no section header or bad elf format: %s\n" +@ MSG_ELF_GETSCN_AR "ar: %s(%s) has no section header or bad elf \ + format: %s\n" +@ MSG_ELF_MALARCHIVE "ar: %s: offset %lld: malformed archive: %s\n" +@ MSG_ELF_RAWFILE "ar: elf_rawfile() failed: %s\n" +@ MSG_ELF_VERSION "ar: libelf.a out of date: %s\n" +@ MSG_W_ELF_NODATA_FILE "ar: %s has no data in section header table\n" +@ MSG_W_ELF_NODATA_AR "ar: %s(%s) has no data in section header table\n" + +@ MSG_BER_MES_CREATE "ar: creating %s\n" +@ MSG_BER_MES_WRITE "ar: writing %s\n" + +@ MSG_SYMTAB_01 "ar: symbol table entry size is 0\n" +@ MSG_SYMTAB_NOSTR_FILE "ar: %s has no string table for symbol names\n" +@ MSG_SYMTAB_NOSTR_AR "ar: %s(%s) has no string table for symbol names\n" +@ MSG_SYMTAB_NODAT_FILE "ar: %s has no data in string table\n" +@ MSG_SYMTAB_NODAT_AR "ar: %s(%s) no data in string table\n" +@ MSG_SYMTAB_ZDAT_FILE "ar: %s has no data in string table: size is 0\n" +@ MSG_SYMTAB_ZDAT_AR "ar: %s(%s) no data in string table: size is 0\n" + + +@ MSG_PATHCONF "ar: -T failed to calculate file name length: %s\n" +@ MSG_LOCALTIME "ar: don't have enough space to store the date\n" +@ MSG_NOT_ARCHIVE "ar: %s not in archive format\n" +@ MSG_OVERRIDE_WARN "ar: %s already exists. Will not be extracted\n" + +@ MSG_ERR_LONGSTRTBLSZ "ar: archive format limit: long name string table \ + would exceed 4GB\n" +@ MSG_ERR_MEMBER4G "ar: archive format limit: individual archive \ + members are limited to 4GB: %s\n" + +@ _END_ + +# The following strings represent reserved words, files, pathnames and symbols. +# Reference to this strings is via the MSG_ORIG() macro, and thus no message +# translation is required. + +@ MSG_STR_OPTIONS ":a:b:i:vucsrdxtplmqVCTzMS" +@ MSG_SUNW_OST_SGS "SUNW_OST_SGS" + +@ MSG_STR_EMPTY "" +@ MSG_STR_HYPHEN "-" +@ MSG_STR_PERIOD "." +@ MSG_STR_LCR "r" +@ MSG_STR_SLASH "/" +@ MSG_STR_DSLASH "//" +@ MSG_STR_SYM64 "/SYM64/" + +# Format for full member header +# +@ MSG_MH_FORMAT "%-16s%-12d%-6u%-6u%-8o%-10lld%-2s" + +@ MSG_FMT_VERSION "ar: %s %s\n" +@ MSG_FMT_P_TITLE "\n<%s>\n\n" +@ MSG_FMT_T_IDSZ "%6d/%6d%7lld" +@ MSG_FMT_T_DATE "%b %e %H:%M %Y" +@ MSG_FMT_SPSTRSP " %s " +@ MSG_FMT_STRNL "%s\n" +@ MSG_FMT_FILE "%c - %s\n" +@ MSG_FMT_LLINT "/%lld" + +@ MSG_CMD_SWAP "/usr/sbin/swap -s" + +# Template for use with mktemp() +@ MSG_STR_MKTEMP "arXXXXXX" diff --git a/usr/src/cmd/sgs/ar/common/cmd.c b/usr/src/cmd/sgs/ar/common/cmd.c index d7ea1875ac..4ed18765f6 100644 --- a/usr/src/cmd/sgs/ar/common/cmd.c +++ b/usr/src/cmd/sgs/ar/common/cmd.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -30,8 +28,6 @@ * */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Incompatible Archive Header * @@ -70,38 +66,34 @@ */ #include "inc.h" -#include "extern.h" /* - * Function prototypes + * Forward Declarations */ -static char *match(char *, Cmd_info *); - -static void cleanup(Cmd_info *); -static void movefil(ARFILE *, struct stat *); -static void mesg(int, char *, Cmd_info *); -static void ar_select(int *, unsigned long); - -static FILE *stats(char *, struct stat *); - -static int create_extract(ARFILE *, int, int, Cmd_info *); +static void ar_select(int *, unsigned long); +static void cleanup(Cmd_info *); +static int create_extract(ARFILE *, int, int, Cmd_info *); +static char *match(char *, Cmd_info *); +static void mesg(int, char *, Cmd_info *); +static void movefil(ARFILE *, struct stat *); +static FILE *stats(char *, struct stat *); /* * Commands */ -int +void rcmd(Cmd_info *cmd_info) { - FILE *f; - ARFILE *fileptr; - ARFILE *abifile = NULL; - ARFILE *backptr = NULL; - ARFILE *endptr; - ARFILE *moved_files; - ARFILE *prev_entry, *new_listhead, *new_listend; - int deleted; - struct stat stbuf; - char *gfile; + FILE *f; + ARFILE *fileptr; + ARFILE *abifile = NULL; + ARFILE *backptr = NULL; + ARFILE *endptr; + ARFILE *moved_files; + ARFILE *prev_entry, *new_listhead, *new_listend; + int deleted; + struct stat stbuf; + char *gfile; new_listhead = NULL; new_listend = NULL; @@ -110,7 +102,7 @@ rcmd(Cmd_info *cmd_info) for (fileptr = getfile(cmd_info); fileptr; fileptr = getfile(cmd_info)) { deleted = 0; - if (!abifile && cmd_info-> ponam && + if (!abifile && cmd_info->ponam && strcmp(fileptr->ar_longname, cmd_info->ponam) == 0) abifile = fileptr; else if (!abifile) @@ -125,16 +117,18 @@ rcmd(Cmd_info *cmd_info) */ f = stats(gfile, &stbuf); /* gfile is set by match */ if (f == NULL) { - if (cmd_info->namc) - error_message(SYS_OPEN_ERROR, - SYSTEM_ERROR, strerror(errno), - gfile); + if (cmd_info->namc) { + int err = errno; + (void) fprintf(stderr, + MSG_INTL(MSG_SYS_OPEN), + gfile, strerror(err)); + } /* * Created */ mesg('c', gfile, cmd_info); } else { - if (opt_FLAG(cmd_info, u_FLAG) && + if ((cmd_info->opt_flgs & u_FLAG) && stbuf.st_mtime <= fileptr->ar_date) { (void) fclose(f); continue; @@ -147,9 +141,7 @@ rcmd(Cmd_info *cmd_info) /* * Clear the previous contents. */ - if (fileptr->ar_flag & F_MALLOCED) - free(fileptr->ar_contents); - else if (fileptr->ar_flag & F_ELFRAW) { + if (fileptr->ar_flag & F_ELFRAW) { /* * clear ar_elf */ @@ -157,59 +149,23 @@ rcmd(Cmd_info *cmd_info) fileptr->ar_elf = 0; } /* clear 'ar_flag' */ - fileptr->ar_flag &= - ~(F_ELFRAW | F_MMAPED | F_MALLOCED); - if ((cmd_info->OPT_flgs & M_FLAG) == 0) { - if ((cmd_info->bytes_in_mem + - stbuf.st_size) - < AR_MAX_BYTES_IN_MEM) { - if ((fileptr->ar_contents = - malloc(ROUNDUP( - stbuf.st_size))) == NULL) { - error_message( - MALLOC_ERROR, - PLAIN_ERROR, - (char *)0); - exit(1); - } - fileptr->ar_flag &= - ~(F_ELFRAW | F_MMAPED); - fileptr->ar_flag |= F_MALLOCED; - if (fread(fileptr->ar_contents, - sizeof (char), - stbuf.st_size, f) != - stbuf.st_size) { - error_message( - SYS_READ_ERROR, - SYSTEM_ERROR, - strerror(errno), - fileptr-> - ar_longname); - exit(1); - } - cmd_info->bytes_in_mem += - stbuf.st_size; - } - } else { - if ((fileptr->ar_contents = (char *) - mmap(0, stbuf.st_size, - PROT_READ, - MAP_SHARED, - fileno(f), 0)) == (char *)-1) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); - exit(1); - } - fileptr->ar_flag &= - ~(F_ELFRAW | F_MALLOCED); - fileptr->ar_flag |= F_MMAPED; - } + fileptr->ar_flag &= ~F_ELFRAW; + + /* + * Defer reading contents until needed, and + * then use an in-kernel file-to-file transfer + * to avoid excessive in-process memory use. + */ + fileptr->ar_contents = NULL; + if (fileptr->ar_pathname != NULL) free(fileptr->ar_pathname); if ((fileptr->ar_pathname = malloc(strlen(gfile) + 1)) == NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); + int err = errno; + (void) fprintf(stderr, + MSG_INTL(MSG_MALLOC), + strerror(err)); exit(1); } @@ -252,8 +208,8 @@ rcmd(Cmd_info *cmd_info) if (cmd_info->ponam && endptr && (((moved_files = endptr->ar_next) != NULL) || new_listhead)) { if (!abifile) { - error_message(NOT_FOUND_02_ERROR, - PLAIN_ERROR, (char *)0, cmd_info->ponam); + (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_POSNAM), + cmd_info->ponam); exit(2); } endptr->ar_next = NULL; @@ -269,7 +225,7 @@ rcmd(Cmd_info *cmd_info) moved_files = new_listhead; } /* 2: insert at appropriate position... */ - if (opt_FLAG(cmd_info, b_FLAG)) + if (cmd_info->opt_flgs & b_FLAG) abifile = backptr; if (abifile) { listend->ar_next = abifile->ar_next; @@ -280,12 +236,11 @@ rcmd(Cmd_info *cmd_info) } listend = endptr; } else if (cmd_info->ponam && !abifile) - error_message(NOT_FOUND_02_ERROR, - PLAIN_ERROR, (char *)0, cmd_info->ponam); - return (0); + (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_POSNAM), + cmd_info->ponam); } -int +void dcmd(Cmd_info *cmd_info) { ARFILE *fptr; @@ -319,25 +274,25 @@ dcmd(Cmd_info *cmd_info) backptr = fptr; } } - return (0); } -int +void xcmd(Cmd_info *cmd_info) { - int f; - ARFILE *next; - int rawname = 0; - int f_len = 0; + int f; + ARFILE *next; + int rawname = 0; + long f_len = 0; /* * If -T is specified, get the maximum file name length. */ - if (cmd_info->OPT_flgs & T_FLAG) { - f_len = pathconf(".", _PC_NAME_MAX); + if (cmd_info->opt_flgs & T_FLAG) { + f_len = pathconf(MSG_ORIG(MSG_STR_PERIOD), _PC_NAME_MAX); if (f_len == -1) { - error_message(PATHCONF_ERROR, - SYSTEM_ERROR, strerror(errno)); + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_PATHCONF), + strerror(err)); exit(1); } } @@ -362,10 +317,11 @@ xcmd(Cmd_info *cmd_info) if (write(f, next->ar_contents, (unsigned)next->ar_size) != next->ar_size) { - error_message(SYS_WRITE_ERROR, - SYSTEM_ERROR, - strerror(errno), - next->ar_rawname); + int err = errno; + (void) fprintf(stderr, + MSG_INTL(MSG_SYS_WRITE), + next->ar_rawname, + strerror(err)); exit(1); } } else { @@ -376,10 +332,11 @@ xcmd(Cmd_info *cmd_info) if (write(f, next->ar_contents, (unsigned)next->ar_size) != next->ar_size) { - error_message(SYS_WRITE_ERROR, - SYSTEM_ERROR, - strerror(errno), - next->ar_longname); + int err = errno; + (void) fprintf(stderr, + MSG_INTL(MSG_SYS_WRITE), + next->ar_longname, + strerror(err)); exit(1); } } @@ -389,10 +346,9 @@ xcmd(Cmd_info *cmd_info) } rawname = 0; } /* for */ - return (0); } -int +void pcmd(Cmd_info *cmd_info) { ARFILE *next; @@ -406,19 +362,19 @@ pcmd(Cmd_info *cmd_info) * Refer to "Incompatible Archive Header" * blocked comment at the beginning of this file. */ - if (opt_FLAG(cmd_info, v_FLAG)) { + if (cmd_info->opt_flgs & v_FLAG) { (void) fprintf(stdout, - "\n<%s>\n\n", next->ar_longname); + MSG_ORIG(MSG_FMT_P_TITLE), + next->ar_longname); (void) fflush(stdout); } (void) fwrite(next->ar_contents, sizeof (char), next->ar_size, stdout); } } - return (0); } -int +void mcmd(Cmd_info *cmd_info) { ARFILE *fileptr; @@ -462,17 +418,17 @@ mcmd(Cmd_info *cmd_info) } if (!tmphead) - return (1); + return; if (!cmd_info->ponam) listend->ar_next = tmphead; else { if (!abifile) { - error_message(NOT_FOUND_02_ERROR, - PLAIN_ERROR, (char *)0, cmd_info->ponam); + (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_POSNAM), + cmd_info->ponam); exit(2); } - if (opt_FLAG(cmd_info, b_FLAG)) + if (cmd_info->opt_flgs & b_FLAG) abifile = backptr2; if (abifile) { tmpend->ar_next = abifile->ar_next; @@ -483,24 +439,23 @@ mcmd(Cmd_info *cmd_info) } } (cmd_info->modified)++; - return (0); } -int +void tcmd(Cmd_info *cmd_info) { ARFILE *next; int **mp; char buf[DATESIZE]; - int m1[] = {1, ROWN, 'r', '-'}; - int m2[] = {1, WOWN, 'w', '-'}; - int m3[] = {2, SUID, 's', XOWN, 'x', '-'}; - int m4[] = {1, RGRP, 'r', '-'}; - int m5[] = {1, WGRP, 'w', '-'}; - int m6[] = {2, SGID, 's', XGRP, 'x', '-'}; - int m7[] = {1, ROTH, 'r', '-'}; - int m8[] = {1, WOTH, 'w', '-'}; - int m9[] = {2, STXT, 't', XOTH, 'x', '-'}; + int m1[] = {1, S_IRUSR, 'r', '-'}; + int m2[] = {1, S_IWUSR, 'w', '-'}; + int m3[] = {2, S_ISUID, 's', S_IXUSR, 'x', '-'}; + int m4[] = {1, S_IRGRP, 'r', '-'}; + int m5[] = {1, S_IWGRP, 'w', '-'}; + int m6[] = {2, S_ISGID, 's', S_IXGRP, 'x', '-'}; + int m7[] = {1, S_IROTH, 'r', '-'}; + int m8[] = {1, S_IWOTH, 'w', '-'}; + int m9[] = {2, S_ISVTX, 't', S_IXOTH, 'x', '-'}; int *m[10]; m[0] = m1; @@ -523,49 +478,48 @@ tcmd(Cmd_info *cmd_info) * Refer to "Incompatible Archive Header" * blocked comment at the beginning of this file. */ - if (opt_FLAG(cmd_info, v_FLAG)) { + if (cmd_info->opt_flgs & v_FLAG) { for (mp = &m[0]; mp < &m[9]; ) ar_select(*mp++, next->ar_mode); - (void) fprintf(stdout, "%6d/%6d", next->ar_uid, - next->ar_gid); - (void) fprintf(stdout, "%7ld", next->ar_size); + (void) fprintf(stdout, MSG_ORIG(MSG_FMT_T_IDSZ), + next->ar_uid, next->ar_gid, + EC_XWORD(next->ar_size)); if ((strftime(buf, - DATESIZE, - "%b %e %H:%M %Y", + DATESIZE, MSG_ORIG(MSG_FMT_T_DATE), localtime(&(next->ar_date)))) == 0) { - error_message(LOCALTIME_ERROR, - PLAIN_ERROR, (char *)0); + (void) fprintf(stderr, + MSG_INTL(MSG_LOCALTIME)); exit(1); } - (void) fprintf(stdout, " %s ", buf); + (void) fprintf(stdout, + MSG_ORIG(MSG_FMT_SPSTRSP), buf); } if ((next->ar_longname[0] == 0) && (next->ar_rawname[0] != 0)) (void) fprintf(stdout, - "%s\n", trim(next->ar_rawname)); + MSG_ORIG(MSG_FMT_STRNL), + trim(next->ar_rawname)); else (void) fprintf(stdout, - "%s\n", trim(next->ar_longname)); + MSG_ORIG(MSG_FMT_STRNL), + trim(next->ar_longname)); } } /* for */ - return (0); } -int +void qcmd(Cmd_info *cmd_info) { ARFILE *fptr; - if (opt_FLAG(cmd_info, a_FLAG) || opt_FLAG(cmd_info, b_FLAG)) { - error_message(USAGE_05_ERROR, - PLAIN_ERROR, (char *)0); + if (cmd_info->opt_flgs & (a_FLAG | b_FLAG)) { + (void) fprintf(stderr, MSG_INTL(MSG_USAGE_05)); exit(1); } for (fptr = getfile(cmd_info); fptr; fptr = getfile(cmd_info)) ; cleanup(cmd_info); - return (0); } /* @@ -607,10 +561,11 @@ cleanup(Cmd_info *cmd_info) */ mesg('a', cmd_info->namv[i], cmd_info); f = stats(cmd_info->namv[i], &stbuf); - if (f == NULL) - error_message(SYS_OPEN_ERROR, - SYSTEM_ERROR, strerror(errno), cmd_info->namv[i]); - else { + if (f == NULL) { + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), + cmd_info->namv[i], strerror(err)); + } else { fileptr = newfile(); /* if short name */ (void) strncpy(fileptr->ar_name, @@ -619,8 +574,9 @@ cleanup(Cmd_info *cmd_info) if ((fileptr->ar_longname = malloc(strlen(trim(cmd_info->namv[i])) + 1)) == NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), + strerror(err)); exit(1); } @@ -629,8 +585,9 @@ cleanup(Cmd_info *cmd_info) if ((fileptr->ar_pathname = malloc(strlen(cmd_info->namv[i]) + 1)) == NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), + strerror(err)); exit(1); } @@ -639,43 +596,15 @@ cleanup(Cmd_info *cmd_info) movefil(fileptr, &stbuf); /* clear 'ar_flag' */ - fileptr->ar_flag &= ~(F_ELFRAW | F_MMAPED | F_MALLOCED); - - if ((cmd_info->OPT_flgs & M_FLAG) == 0) { - if ((cmd_info->bytes_in_mem + stbuf.st_size) < - AR_MAX_BYTES_IN_MEM) { - fileptr->ar_flag &= - ~(F_ELFRAW | F_MMAPED); - fileptr->ar_flag |= F_MALLOCED; - if ((fileptr->ar_contents = - malloc(ROUNDUP(stbuf.st_size))) == - NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); - exit(1); - } - if (fread(fileptr->ar_contents, - sizeof (char), stbuf.st_size, - f) != stbuf.st_size) { - error_message(SYS_READ_ERROR, - SYSTEM_ERROR, - strerror(errno), - fileptr->ar_longname); - exit(1); - } - cmd_info->bytes_in_mem += stbuf.st_size; - } - } else { - fileptr->ar_flag &= ~(F_ELFRAW | F_MALLOCED); - fileptr->ar_flag |= F_MMAPED; - if ((fileptr->ar_contents = - (char *)mmap(0, stbuf.st_size, PROT_READ, - MAP_SHARED, fileno(f), 0)) == (char *)-1) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); - exit(1); - } - } + fileptr->ar_flag &= ~F_ELFRAW; + + /* + * Defer reading contents until needed, and then use + * an in-kernel file-to-file transfer to avoid + * excessive in-process memory use. + */ + fileptr->ar_contents = NULL; + (void) fclose(f); (cmd_info->modified)++; cmd_info->namv[i] = 0; @@ -719,7 +648,7 @@ stats(char *file, struct stat *stbuf) { FILE *f; - f = fopen(file, "r"); + f = fopen(file, MSG_ORIG(MSG_STR_LCR)); if (f == NULL) return (f); if (stat(file, stbuf) < 0) { @@ -747,14 +676,15 @@ create_extract(ARFILE *a, int rawname, int f_len, Cmd_info *cmd_info) /* * If -T is specified, check the file length. */ - if (cmd_info->OPT_flgs & T_FLAG) { + if (cmd_info->opt_flgs & T_FLAG) { int len; len = strlen(f_name); if (f_len <= len) { dup = malloc(f_len+1); if (dup == NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), + strerror(err)); exit(1); } (void) strncpy(dup, f_name, f_len); @@ -782,11 +712,11 @@ create_extract(ARFILE *a, int rawname, int f_len, Cmd_info *cmd_info) /* * If -C is specified, this is an error anyway */ - if (cmd_info->OPT_flgs & C_FLAG) { + if (cmd_info->opt_flgs & C_FLAG) { + (void) fprintf(stderr, MSG_INTL(MSG_OVERRIDE_WARN), + f_name); if (dup != NULL) free(dup); - error_message(OVERRIDE_WARN_ERROR, - PLAIN_ERROR, (char *)0, f_name); return (-1); } @@ -802,10 +732,10 @@ create_extract(ARFILE *a, int rawname, int f_len, Cmd_info *cmd_info) if ((s1.st_dev == s2.st_dev) && (s1.st_ino == s2.st_ino)) { + (void) fprintf(stderr, + MSG_INTL(MSG_OVERRIDE_WARN), f_name); if (dup != NULL) free(dup); - error_message(OVERRIDE_WARN_ERROR, - PLAIN_ERROR, (char *)0, f_name); return (-1); } } @@ -816,8 +746,9 @@ create_extract(ARFILE *a, int rawname, int f_len, Cmd_info *cmd_info) */ f = creat(f_name, (mode_t)a->ar_mode & 0777); if (f < 0) { - error_message(SYS_CREATE_01_ERROR, - SYSTEM_ERROR, strerror(errno), f_name); + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), f_name, + strerror(err)); /* * Created */ @@ -850,9 +781,9 @@ mesg(int c, char *file, Cmd_info *cmd_info) */ if (c == 'u') c = 'c'; - if (opt_FLAG(cmd_info, v_FLAG)) + if (cmd_info->opt_flgs & v_FLAG) if (c != 'c') - (void) fprintf(stdout, "%c - %s\n", c, file); + (void) fprintf(stdout, MSG_ORIG(MSG_FMT_FILE), c, file); } static void diff --git a/usr/src/cmd/sgs/ar/common/file.c b/usr/src/cmd/sgs/ar/common/file.c index 7457d2e39f..0c48b9f622 100644 --- a/usr/src/cmd/sgs/ar/common/file.c +++ b/usr/src/cmd/sgs/ar/common/file.c @@ -18,9 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -29,26 +29,57 @@ * */ -#include "gelf.h" +#include <sys/sendfile.h> #include "inc.h" -#include "extern.h" +#include "gelf.h" + +/* + * List of archive members, accessed globally by cmd and file. + */ +ARFILE *listhead, *listend; + +/* + * Type used to manage string tables. Archives can have two of these: + * + * sym_strtbl: String table included at the end of the symbol table + * archive member, following the offset array. + * + * long_strtbl: String table used to hold member names that exceed 15 + * characters in length, found in the long names archive member. + */ +typedef struct { + char *base; /* Base of string table memory */ + size_t used; /* # bytes used from allocation */ + size_t size; /* Size of allocation */ +} ARSTRTBL; -static char *str_base; /* start of string table for names */ -static char *str_top; /* pointer to next available location */ -static char *str_base1, *str_top1; -static int pad_symtab; /* # of bytes by which to pad symbol table */ +static ARSTRTBL sym_strtbl; +static ARSTRTBL long_strtbl; /* + * Name and file descriptor used when creating a new archive. + * If this variable references an open file when exit_cleanup() + * executes, it will close and remove the file, preventing incomplete + * temporary files from being left behind in the case of a failure + * or interruption. + */ +static struct { + int fd; /* -1, or open file descriptor */ + const char *path; /* Path to open file */ +} ar_outfile; + +/* * The ar file format requires objects to be padded to an even size. * We do that, but it turns out to be beneficial to go farther. * * ld(1) accesses archives by mmapping them into memory. If the mapped - * objects have the proper alignment, we can access them directly. If the - * alignment is wrong, libelf "slides" them so that they are also accessible. - * This is expensive in time (to copy memory) and space (it causes swap - * to be allocated by the system to back the now-modified pages). Hence, we - * really want to ensure that the alignment is right. + * objects (member data) have the proper alignment, we can access them + * directly. If the data alignment is wrong, libelf "slides" them over the + * archive header to correct the misalignment. This is expensive in time + * (to copy memory) and space (it causes swap to be allocated by the system + * to back the now-modified pages). Hence, we really want to ensure that + * the alignment is right. * * We used to align 32-bit objects at 4-byte boundaries, and 64-bit objects * at 8-byte. More recently, an elf section type has appeared that has @@ -67,28 +98,42 @@ static int pad_symtab; /* # of bytes by which to pad symbol table */ #define PADSZ 8 /* - * Function Prototypes + * Forward Declarations */ -static long mklong_tab(int *); -static char *trimslash(char *s); +static void arwrite(const char *, int, const char *, size_t); +static size_t mklong_tab(); +static size_t mksymtab(const char *, ARFILEP **, int *); +static const char *make_tmpname(const char *); +static size_t sizeof_symtbl(size_t, int, size_t); +static void savelongname(ARFILE *); +static void savename(char *); +static int search_sym_tab(const char *, ARFILE *, Elf *, + Elf_Scn *, size_t *, ARFILEP **, size_t *); +static size_t sizeofmembers(size_t); +static char *sputl32(uint32_t, char *); +static char *sputl64(uint64_t, char *); +static void strtbl_pad(ARSTRTBL *, size_t, int); +static char *trimslash(char *s); +static void writesymtab(const char *, int fd, size_t, ARFILEP *, + size_t); -static long mksymtab(ARFILEP **, int *); -static int writesymtab(char *, long, ARFILEP *); -static void savename(char *); -static void savelongname(ARFILE *, char *); -static void sputl(long, char *); - -static char *writelargefile(Cmd_info *cmd_info, long long_tab_size, - int longnames, ARFILEP *symlist, long nsyms, int found_obj, - int new_archive); - -static int sizeofmembers(); -static int sizeofnewarchive(int, int); - -static int search_sym_tab(ARFILE *, Elf *, Elf_Scn *, - long *, ARFILEP **, int *); +/* + * Function to be called on exit to clean up incomplete new archive. + */ +static void +exit_cleanup(void) +{ + if (ar_outfile.fd != -1) { + /* Both of these system calls are Async-Signal-Safe */ + (void) close(ar_outfile.fd); + (void) unlink(ar_outfile.path); + } +} +/* + * Open an existing archive. + */ int getaf(Cmd_info *cmd_info) { @@ -97,19 +142,21 @@ getaf(Cmd_info *cmd_info) char *arnam = cmd_info->arnam; if (elf_version(EV_CURRENT) == EV_NONE) { - error_message(ELF_VERSION_ERROR, - LIBELF_ERROR, elf_errmsg(-1)); + (void) fprintf(stderr, MSG_INTL(MSG_ELF_VERSION), + elf_errmsg(-1)); exit(1); } if ((cmd_info->afd = fd = open(arnam, O_RDONLY)) == -1) { - if (errno == ENOENT) { + int err = errno; + + if (err == ENOENT) { /* archive does not exist yet, may have to create one */ return (fd); } else { /* problem other than "does not exist" */ - error_message(SYS_OPEN_ERROR, - SYSTEM_ERROR, strerror(errno), arnam); + (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), + arnam, strerror(err)); exit(1); } } @@ -118,37 +165,36 @@ getaf(Cmd_info *cmd_info) cmd_info->arf = elf_begin(fd, cmd, (Elf *)0); if (elf_kind(cmd_info->arf) != ELF_K_AR) { - error_message(NOT_ARCHIVE_ERROR, - PLAIN_ERROR, (char *)0, arnam); - if (opt_FLAG(cmd_info, a_FLAG) || opt_FLAG(cmd_info, b_FLAG)) - error_message(USAGE_06_ERROR, - PLAIN_ERROR, (char *)0, cmd_info->ponam); + (void) fprintf(stderr, MSG_INTL(MSG_NOT_ARCHIVE), arnam); + if (cmd_info->opt_flgs & (a_FLAG | b_FLAG)) + (void) fprintf(stderr, MSG_INTL(MSG_USAGE_06), + cmd_info->ponam); exit(1); } return (fd); } /* - * Given a size, return the number of bytes required to round it - * up to the next PADSZ boundary. + * Given a value, and a pad alignment, return the number of bytes + * required to pad the value to the next alignment boundary. */ -static int -pad(int n) +static size_t +pad(size_t n, size_t align) { - int r; + size_t r; - r = n % PADSZ; + r = n % align; if (r) - r = PADSZ - r; + r = align - r; return (r); } /* - * If the current archive item is an object, then ar(1) may have added + * If the current archive item is an ELF object, then ar(1) may have added * newline padding at the end in order to bring the following object * into PADSZ alignment within the file. This padding cannot be - * distinguished from data using the information kept in the ar headers. + * distinguished from data using the information kept in the member header. * This routine examines the objects, using knowledge of * ELF and how our tools lay out objects to determine whether padding was * added to an archive item. If so, it adjusts the st_size and @@ -157,9 +203,9 @@ pad(int n) static void recover_padding(Elf *elf, ARFILE *file) { - long extent; - long padding; - GElf_Ehdr ehdr; + size_t extent; + size_t padding; + GElf_Ehdr ehdr; /* ar(1) only pads objects, so bail if not looking at one */ @@ -178,16 +224,24 @@ recover_padding(Elf *elf, ARFILE *file) */ extent = gelf_getehdr(elf, &ehdr) ? (ehdr.e_shoff + (ehdr.e_shnum * ehdr.e_shentsize)) : 0; - padding = file->ar_size - extent; - if ((padding < 0) || (padding >= PADSZ)) { + /* + * If the extent exceeds the end of the archive member + * (negative padding), then we don't know what is going on + * and simply leave things alone. + */ + if (extent > file->ar_size) + return; + + padding = file->ar_size - extent; + if (padding >= PADSZ) { /* * The section header array is not at the end of the object. * Traverse the section headers and look for the one with * the highest used address. If this address is within * PADSZ bytes of ar_size, then this is the end of the object. */ - Elf_Scn *scn = 0; + Elf_Scn *scn = NULL; do { scn = elf_nextscn(elf, scn); @@ -195,12 +249,18 @@ recover_padding(Elf *elf, ARFILE *file) GElf_Shdr shdr; if (gelf_getshdr(scn, &shdr)) { - long t = shdr.sh_offset + shdr.sh_size; + size_t t; + + t = shdr.sh_offset + shdr.sh_size; if (t > extent) extent = t; } } } while (scn); + + if (extent > file->ar_size) + return; + padding = file->ar_size - extent; } /* @@ -216,9 +276,9 @@ recover_padding(Elf *elf, ARFILE *file) * characters. If anything else is seen, it is not padding so * leave it alone. */ - if ((padding > 0) && (padding < PADSZ)) { + if (padding < PADSZ) { if (file->ar_contents) { - long cnt = padding; + size_t cnt = padding; char *p = file->ar_contents + extent; while (cnt--) { @@ -235,10 +295,15 @@ recover_padding(Elf *elf, ARFILE *file) } } +/* + * Each call to getfile() returns the next unread archive member + * from the archive opened by getaf(). Returns NULL if no more + * archive members are left. + */ ARFILE * getfile(Cmd_info *cmd_info) { - Elf_Arhdr *mem_header; + Elf_Arhdr *mem_header = NULL; ARFILE *file; char *tmp_rawname, *file_rawname; Elf *elf; @@ -249,30 +314,21 @@ getfile(Cmd_info *cmd_info) if (fd == -1) return (NULL); /* the archive doesn't exist */ - if ((elf = elf_begin(fd, ELF_C_READ, arf)) == 0) - return (NULL); /* the archive is empty or have hit the end */ - - if ((mem_header = elf_getarhdr(elf)) == NULL) { - error_message(ELF_MALARCHIVE_ERROR, - LIBELF_ERROR, elf_errmsg(-1), - arnam, elf_getbase(elf)); - exit(1); - } - - /* zip past special members like the symbol and string table members */ - - while (strncmp(mem_header->ar_name, "/", 1) == 0 || - strncmp(mem_header->ar_name, "//", 2) == 0) { - (void) elf_next(elf); - (void) elf_end(elf); + while (mem_header == NULL) { if ((elf = elf_begin(fd, ELF_C_READ, arf)) == 0) - return (NULL); - /* the archive is empty or have hit the end */ + return (NULL); /* archive is empty or have hit end */ + if ((mem_header = elf_getarhdr(elf)) == NULL) { - error_message(ELF_MALARCHIVE_ERROR, - LIBELF_ERROR, elf_errmsg(-1), - arnam, elf_getbase(elf)); - exit(0); + (void) fprintf(stderr, MSG_INTL(MSG_ELF_MALARCHIVE), + arnam, EC_XWORD(elf_getbase(elf)), elf_errmsg(-1)); + exit(1); + } + + /* Ignore special members like the symbol and string tables */ + if (mem_header->ar_name[0] == '/') { + (void) elf_next(elf); + (void) elf_end(elf); + mem_header = NULL; } } @@ -288,19 +344,17 @@ getfile(Cmd_info *cmd_info) file = newfile(); (void) strncpy(file->ar_name, mem_header->ar_name, SNAME); - if ((file->ar_longname - = malloc(strlen(mem_header->ar_name) + 1)) + if ((file->ar_longname = malloc(strlen(mem_header->ar_name) + 1)) == NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err)); exit(1); } (void) strcpy(file->ar_longname, mem_header->ar_name); - if ((file->ar_rawname - = malloc(strlen(mem_header->ar_rawname) + 1)) + if ((file->ar_rawname = malloc(strlen(mem_header->ar_rawname) + 1)) == NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err)); exit(1); } tmp_rawname = mem_header->ar_rawname; @@ -320,14 +374,14 @@ getfile(Cmd_info *cmd_info) file->ar_size = mem_header->ar_size; /* reverse logic */ - if (!(opt_FLAG(cmd_info, t_FLAG) && !opt_FLAG(cmd_info, s_FLAG))) { + if ((cmd_info->opt_flgs & (t_FLAG | s_FLAG)) != t_FLAG) { size_t ptr; file->ar_flag = F_ELFRAW; if ((file->ar_contents = elf_rawfile(elf, &ptr)) == NULL) { if (ptr != 0) { - error_message(ELF_RAWFILE_ERROR, - LIBELF_ERROR, elf_errmsg(-1)); + (void) fprintf(stderr, + MSG_INTL(MSG_ELF_RAWFILE), elf_errmsg(-1)); exit(1); } } @@ -340,18 +394,22 @@ getfile(Cmd_info *cmd_info) return (file); } +/* + * Allocate a new archive member descriptor and add it to the list. + */ ARFILE * newfile(void) { static ARFILE *buffer = NULL; - static int count = 0; - ARFILE *fileptr; + static size_t count = 0; + ARFILE *fileptr; if (count == 0) { if ((buffer = (ARFILE *) calloc(CHUNK, sizeof (ARFILE))) == NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), + strerror(err)); exit(1); } count = CHUNK; @@ -374,7 +432,7 @@ trimslash(char *s) (void) strncpy(buf, trim(s), SNAME - 2); buf[SNAME - 2] = '\0'; - return (strcat(buf, "/")); + return (strcat(buf, MSG_ORIG(MSG_STR_SLASH))); } char * @@ -397,61 +455,91 @@ trim(char *s) } -static long -mksymtab(ARFILEP **symlist, int *found_obj) +/* + * Find all the global symbols exported by ELF archive members, and + * build a list associating each one with the archive member that + * provides it. + * + * exit: + * *symlist is set to the list of symbols. If any ELF object was + * found, *found_obj is set to TRUE (1). Returns the number of symbols + * located. + */ +static size_t +mksymtab(const char *arname, ARFILEP **symlist, int *found_obj) { - ARFILE *fptr; - long mem_offset = 0; - Elf *elf; - Elf_Scn *scn; - GElf_Ehdr ehdr; - int newfd; - long nsyms = 0; - int class = 0; - Elf_Data *data; - int num_errs = 0; + ARFILE *fptr; + size_t mem_offset = 0; + Elf *elf; + Elf_Scn *scn; + GElf_Ehdr ehdr; + int newfd; + size_t nsyms = 0; + int class = 0; + Elf_Data *data; + size_t num_errs = 0; newfd = 0; for (fptr = listhead; fptr; fptr = fptr->ar_next) { /* determine if file is coming from the archive or not */ - if ((fptr->ar_elf != 0) && (fptr->ar_pathname == NULL)) { + if ((fptr->ar_elf != NULL) && (fptr->ar_pathname == NULL)) { /* * I can use the saved elf descriptor. */ elf = fptr->ar_elf; - } else if ((fptr->ar_elf == 0) && + } else if ((fptr->ar_elf == NULL) && (fptr->ar_pathname != NULL)) { +#ifdef _LP64 + /* + * The archive member header ar_size field is 10 + * decimal digits, sufficient to represent a 32-bit + * value, but not a 64-bit one. Hence, we reject + * attempts to insert a member larger than 4GB. + * + * One obvious way to extend the format without altering + * the ar_hdr struct is to use the same mechanism used + * for ar_name: Put the size string into the long name + * string table and write a string /xxx into ar_size, + * where xxx is the string table offset. + * + * At the time of this writing (June 2010), the largest + * relocatable objects are measured in 10s or 100s + * of megabytes, so we still have many years to go + * before this becomes limiting. By that time, it may + * turn out that a completely new archive format is + * a better solution, as the current format has many + * warts and inefficiencies. In the meantime, we + * won't burden the current implementation with support + * for a bandaid feature that will have little use. + */ + if (fptr->ar_size > 0xffffffff) { + (void) fprintf(stderr, + MSG_INTL(MSG_ERR_MEMBER4G), + fptr->ar_pathname); + num_errs++; + continue; + } +#endif if ((newfd = open(fptr->ar_pathname, O_RDONLY)) == -1) { - error_message(SYS_OPEN_ERROR, - SYSTEM_ERROR, strerror(errno), - fptr->ar_pathname); + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), + fptr->ar_pathname, strerror(err)); num_errs++; continue; } if ((elf = elf_begin(newfd, ELF_C_READ, (Elf *)0)) == 0) { - if (fptr->ar_pathname != NULL) - error_message(ELF_BEGIN_02_ERROR, - LIBELF_ERROR, elf_errmsg(-1), - fptr->ar_pathname); - else - error_message(ELF_BEGIN_03_ERROR, - LIBELF_ERROR, elf_errmsg(-1)); + (void) fprintf(stderr, + MSG_INTL(MSG_ELF_BEGIN_FILE), + fptr->ar_pathname, elf_errmsg(-1)); (void) close(newfd); newfd = 0; num_errs++; continue; } if (elf_kind(elf) == ELF_K_AR) { - if (fptr->ar_pathname != NULL) - error_message(ARCHIVE_IN_ARCHIVE_ERROR, - PLAIN_ERROR, (char *)0, - fptr->ar_pathname); - else - error_message(ARCHIVE_USAGE_ERROR, - PLAIN_ERROR, (char *)0); if (newfd) { (void) close(newfd); newfd = 0; @@ -460,8 +548,7 @@ mksymtab(ARFILEP **symlist, int *found_obj) continue; } } else { - error_message(INTERNAL_01_ERROR, - PLAIN_ERROR, (char *)0); + (void) fprintf(stderr, MSG_INTL(MSG_INTERNAL_01)); exit(1); } if (gelf_getehdr(elf, &ehdr) != 0) { @@ -472,12 +559,14 @@ mksymtab(ARFILEP **symlist, int *found_obj) scn = elf_getscn(elf, ehdr.e_shstrndx); if (scn == NULL) { if (fptr->ar_pathname != NULL) - error_message(ELF_GETSCN_01_ERROR, - LIBELF_ERROR, elf_errmsg(-1), - fptr->ar_pathname); + (void) fprintf(stderr, + MSG_INTL(MSG_ELF_GETSCN_FILE), + fptr->ar_pathname, elf_errmsg(-1)); else - error_message(ELF_GETSCN_02_ERROR, - LIBELF_ERROR, elf_errmsg(-1)); + (void) fprintf(stderr, + MSG_INTL(MSG_ELF_GETSCN_AR), + arname, fptr->ar_longname, + elf_errmsg(-1)); num_errs++; if (newfd) { (void) close(newfd); @@ -491,12 +580,14 @@ mksymtab(ARFILEP **symlist, int *found_obj) data = elf_getdata(scn, data); if (data == NULL) { if (fptr->ar_pathname != NULL) - error_message(ELF_GETDATA_01_ERROR, - LIBELF_ERROR, elf_errmsg(-1), - fptr->ar_pathname); + (void) fprintf(stderr, + MSG_INTL(MSG_ELF_GETDATA_FILE), + fptr->ar_pathname, elf_errmsg(-1)); else - error_message(ELF_GETDATA_02_ERROR, - LIBELF_ERROR, elf_errmsg(-1)); + (void) fprintf(stderr, + MSG_INTL(MSG_ELF_GETDATA_AR), + arname, fptr->ar_longname, + elf_errmsg(-1)); num_errs++; if (newfd) { (void) close(newfd); @@ -507,12 +598,13 @@ mksymtab(ARFILEP **symlist, int *found_obj) } if (data->d_size == 0) { if (fptr->ar_pathname != NULL) - error_message(W_ELF_NO_DATA_01_ERROR, - PLAIN_ERROR, (char *)0, + (void) fprintf(stderr, + MSG_INTL(MSG_W_ELF_NODATA_FILE), fptr->ar_pathname); else - error_message(W_ELF_NO_DATA_02_ERROR, - PLAIN_ERROR, (char *)0); + (void) fprintf(stderr, + MSG_INTL(MSG_W_ELF_NODATA_AR), + arname, fptr->ar_longname); if (newfd) { (void) close(newfd); newfd = 0; @@ -527,17 +619,18 @@ mksymtab(ARFILEP **symlist, int *found_obj) while ((scn = elf_nextscn(elf, scn)) != 0) { GElf_Shdr shdr; if (gelf_getshdr(scn, &shdr) == NULL) { + /* BEGIN CSTYLED */ if (fptr->ar_pathname != NULL) - error_message( - ELF_GETDATA_01_ERROR, - LIBELF_ERROR, - elf_errmsg(-1), - fptr->ar_pathname); + (void) fprintf(stderr, + MSG_INTL(MSG_ELF_GETDATA_FILE), + fptr->ar_pathname, + elf_errmsg(-1)); else - error_message( - ELF_GETDATA_02_ERROR, - LIBELF_ERROR, - elf_errmsg(-1)); + (void) fprintf(stderr, + MSG_INTL(MSG_ELF_GETDATA_AR), + arname, fptr->ar_longname, + elf_errmsg(-1)); + /* END CSTYLED */ if (newfd) { (void) close(newfd); newfd = 0; @@ -548,7 +641,7 @@ mksymtab(ARFILEP **symlist, int *found_obj) } *found_obj = 1; if (shdr.sh_type == SHT_SYMTAB) - if (search_sym_tab(fptr, elf, + if (search_sym_tab(arname, fptr, elf, scn, &nsyms, symlist, &num_errs) == -1) { if (newfd) { @@ -567,448 +660,736 @@ mksymtab(ARFILEP **symlist, int *found_obj) (void) close(newfd); newfd = 0; } - } /* for */ + } if (num_errs) exit(1); + + if (found_obj) { + if (nsyms == 0) { + /* + * It is possible, though rare, to have ELF objects + * that do not export any global symbols. Presumably + * such objects operate via their .init/.fini + * sections. In this case, we produce an empty + * symbol table, so that applications that rely + * on a successful call to elf_getarsym() to determine + * if ELF objects are present will succeed. To do this, + * we require a small empty symbol string table. + */ + strtbl_pad(&sym_strtbl, 4, '\0'); + } else { + /* + * Historical behavior is to pad string tables + * to a multiple of 4. + */ + strtbl_pad(&sym_strtbl, pad(sym_strtbl.used, 4), '\0'); + } + + } + return (nsyms); } /* - * This routine writes an archive symbol table for the - * output archive file. The symbol table is built if - * there was at least one object file specified. - * In rare case, there could be no symbol. - * In this case, str_top and str_base can not be used to - * make the string table. So the routine adjust the size - * and make a dummy string table. String table is needed - * by elf_getarsym(). + * Output a member header. */ -static int -writesymtab(char *dst, long nsyms, ARFILEP *symlist) +/*ARGSUSED*/ +static void +write_member_header(const char *filename, int fd, int is_elf, + const char *name, time_t timestamp, uid_t uid, gid_t gid, mode_t mode, + size_t size) { - char buf1[sizeof (struct ar_hdr) + 1]; - char *buf2, *bptr; - int i, j; - ARFILEP *ptr; - long sym_tab_size = 0; - int sum = 0; + char buf[sizeof (struct ar_hdr) + 1]; + int len; + + len = snprintf(buf, sizeof (buf), MSG_ORIG(MSG_MH_FORMAT), name, + EC_WORD(timestamp), EC_WORD(uid), EC_WORD(gid), EC_WORD(mode), + EC_XWORD(size), ARFMAG); /* - * patch up archive pointers and write the symbol entries + * If snprintf() reports that it needed more space than we gave + * it, it means that the caller fed us a long name, which is a + * fatal internal error. */ - while ((str_top - str_base) & 03) /* round up string table */ - *str_top++ = '\0'; - sym_tab_size = (nsyms +1) * 4 + sizeof (char) * (str_top - str_base); - if (nsyms == 0) - sym_tab_size += 4; - sym_tab_size += pad_symtab; - - (void) sprintf(buf1, FORMAT, SYMDIRNAME, time(0), (unsigned)0, - (unsigned)0, (unsigned)0, (long)sym_tab_size, ARFMAG); - - if (strlen(buf1) != sizeof (struct ar_hdr)) { - error_message(INTERNAL_02_ERROR); + if (len != sizeof (struct ar_hdr)) { + (void) fprintf(stderr, MSG_INTL(MSG_INTERNAL_02)); exit(1); } - if ((buf2 = malloc(4 * (nsyms + 1))) == NULL) { - error_message(MALLOC_ERROR); - error_message(DIAG_01_ERROR, errno); + arwrite(filename, fd, buf, len); + + /* + * We inject inter-member padding to ensure that ELF object + * member data is aligned on PADSZ. If this is a debug build, + * verify that the computations were right. + */ + assert(!is_elf || (pad(lseek(fd, 0, SEEK_CUR), PADSZ) == 0)); +} + +/* + * Write the archive symbol table member to the output archive file. + * + * note: + * sizeofmembers() must have been called to establish member offset + * and padding values before writesymtab() is used. + */ +static void +writesymtab(const char *filename, int fd, size_t nsyms, ARFILEP *symlist, + size_t eltsize) +{ + size_t i, j; + ARFILEP *ptr; + size_t tblsize; + char *buf, *dst; + int is64 = (eltsize == 8); + + /* + * We require a buffer large enough to hold a symbol table count, + * plus one offset for each symbol. + */ + tblsize = (nsyms + 1) * eltsize; + if ((buf = dst = malloc(tblsize)) == NULL) { + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err)); exit(1); } - sputl(nsyms, buf2); - bptr = buf2 + 4; + + write_member_header(filename, fd, 0, + (is64 ? MSG_ORIG(MSG_STR_SYM64) : MSG_ORIG(MSG_STR_SLASH)), + time(0), 0, 0, 0, tblsize + sym_strtbl.used); + + dst = is64 ? sputl64(nsyms, dst) : sputl32(nsyms, dst); for (i = 0, j = SYMCHUNK, ptr = symlist; i < nsyms; i++, j--, ptr++) { if (!j) { j = SYMCHUNK; ptr = (ARFILEP *)*ptr; } - sputl((*ptr)->ar_offset, bptr); - bptr += 4; - } - (void) memcpy(dst, buf1, sizeof (struct ar_hdr)); - dst += sizeof (struct ar_hdr); - sum += sizeof (struct ar_hdr); - - (void) memcpy(dst, buf2, (nsyms + 1) * 4); - dst += (nsyms + 1)*4; - sum += (nsyms + 1)*4; - - if (nsyms != 0) { - (void) memcpy(dst, str_base, (str_top - str_base)); - dst += str_top - str_base; - sum += str_top - str_base; - } else { - /* - * Writing a dummy string table. - */ - int i; - for (i = 0; i < 4; i++) - *dst++ = 0; - sum += 4; + dst = is64 ? sputl64((*ptr)->ar_offset, dst) : + sputl32((*ptr)->ar_offset, dst); } + arwrite(filename, fd, buf, tblsize); + free(buf); + arwrite(filename, fd, sym_strtbl.base, sym_strtbl.used); +} + +/* + * Grow the size of the given string table so that there is room + * for at least need bytes. + * + * entry: + * strtbl - String table to grow + * need - Amount of space required by caller + */ +static void +strtbl_alloc(ARSTRTBL *strtbl, size_t need) +{ +#define STRTBL_INITSZ 8196 + + /* + * On 32-bit systems, we require a larger integer type in order + * to avoid overflow and wraparound when doing our computations. + */ + uint64_t need64 = need; + uint64_t used64 = strtbl->used; + uint64_t size64 = strtbl->size; + uint64_t target = need64 + used64; + + int sys32, tbl32; + + if (target <= size64) + return; + + /* + * Detect 32-bit system. We might usually do this with the preprocessor, + * but it can serve as a predicate in tests that also apply to 64-bit + * systems. + */ + sys32 = (sizeof (size_t) == 4); + + /* + * The symbol string table can be larger than 32-bits on a 64-bit + * system. However, the long name table must stay below that limit. + * The reason for this is that there is not enough room in the ar_name + * field of the member header to represent 64-bit offsets. + */ + tbl32 = (strtbl == &long_strtbl); /* - * The first member file is an ELF object. We need to make - * sure it will be placed at the PADSZ byte boundary. + * If request is larger than 4GB and we can't do it because we + * are a 32-bit program, or because the table is format limited, + * we can go no further. */ - if (pad_symtab) { - int i; - for (i = 0; i < pad_symtab; i++) - *dst++ = 0; - sum += pad_symtab; + if ((target > 0xffffffff) && (sys32 || tbl32)) + goto limit_fail; + + /* Default starting size */ + if (strtbl->base == NULL) + size64 = STRTBL_INITSZ; + + /* + * Our strategy is to double the size until we find a size that + * exceeds the request. However, if this table cannot exceed 4GB, + * then once we exceed 2GB, we switch to a strategy of taking the + * current request and rounding it up to STRTBL_INITSZ. + */ + while (target > size64) { + if ((target > 0x7fffffff) && (sys32 || tbl32)) { + size64 = ((target + STRTBL_INITSZ) / STRTBL_INITSZ) * + STRTBL_INITSZ; + + /* + * If we are so close to the line that this small + * increment exceeds 4GB, give it up. + */ + if ((size64 > 0xffffffff) && (sys32 || tbl32)) + goto limit_fail; + + break; + } + + size64 *= 2; } - free(buf2); - return (sum); + strtbl->base = realloc(strtbl->base, size64); + if (strtbl->base == NULL) { + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err)); + exit(1); + } + strtbl->size = (size_t)size64; + return; + +limit_fail: + /* + * Control comes here if we are unable to allocate more than 4GB of + * memory for the string table due to one of the following reasons: + * + * - A 32-bit process is attempting to be larger than 4GB + * + * - A 64-bit process is attempting to grow the long names string + * table beyond the ar format limit of 32-bits. + */ + if (sys32) + (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(ENOMEM)); + else + (void) fprintf(stderr, MSG_INTL(MSG_ERR_LONGSTRTBLSZ)); + exit(1); + +#undef STRTBL_INITSZ } +/* + * Add the specified number of pad characters to the end of the + * given string table. + * + * entry: + * strtbl - String table to pad + * n - # of pad characters to add + * ch - Pad character to use + */ static void -savename(char *symbol) +strtbl_pad(ARSTRTBL *strtbl, size_t n, int ch) { - static int str_length = BUFSIZ * 5; - char *p, *s; - unsigned int i; - int diff; - - diff = 0; - if (str_base == (char *)0) { - /* no space allocated yet */ - if ((str_base = malloc((unsigned)str_length)) == NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); - exit(1); - } - str_top = str_base; - } + if (n == 0) + return; - p = str_top; - str_top += strlen(symbol) + 1; + if ((n + strtbl->used) > strtbl->size) + strtbl_alloc(strtbl, n); - if (str_top > str_base + str_length) { - char *old_base = str_base; + while (n--) + strtbl->base[strtbl->used++] = ch; +} - do - str_length += BUFSIZ * 2; - while (str_top > str_base + str_length) - ; - if ((str_base = (char *)realloc(str_base, str_length)) == - NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); - exit(1); - } - /* - * Re-adjust other pointers - */ - diff = str_base - old_base; - p += diff; - } - for (i = 0, s = symbol; i < strlen(symbol) && *s != '\0'; i++) { - *p++ = *s++; - } - *p++ = '\0'; - str_top = p; +/* + * Enter a symbol name into the symbol string table. + */ +static void +savename(char *symbol) +{ + size_t need; + + need = strlen(symbol) + 1; + if ((need + sym_strtbl.used) > sym_strtbl.size) + strtbl_alloc(&sym_strtbl, need); + + (void) strcpy(sym_strtbl.base + sym_strtbl.used, symbol); + sym_strtbl.used += need; } +/* + * Prepare an archive member with a long (>15 characters) name for + * the output archive. + * + * entry: + * fptr - pointer to archive member with long name + * + * exit: + * The long name is entered into the long name string table, + * and fptr->ar_name has been replaced with the special /xxx + * name used to indicate that the real name is in the string table + * at offset xxx. + */ static void -savelongname(ARFILE *fptr, char *ptr_index) +savelongname(ARFILE *fptr) { - static int str_length = BUFSIZ * 5; - char *p, *s; - unsigned int i; - int diff; - static int bytes_used; - int index; - char ptr_index1[SNAME-1]; - - diff = 0; - if (str_base1 == (char *)0) { - /* no space allocated yet */ - if ((str_base1 = malloc((unsigned)str_length)) - == NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); - exit(1); - } - str_top1 = str_base1; - } + size_t len, need; + char *p; - p = str_top1; - str_top1 += strlen(fptr->ar_longname) + 2; - - index = bytes_used; - (void) sprintf(ptr_index1, "%d", index); /* holds digits */ - (void) sprintf(ptr_index, FNFORMAT, SYMDIRNAME); - ptr_index[1] = '\0'; - (void) strcat(ptr_index, ptr_index1); - (void) strcpy(fptr->ar_name, ptr_index); - bytes_used += strlen(fptr->ar_longname) + 2; - - if (str_top1 > str_base1 + str_length) { - char *old_base = str_base1; - - do - str_length += BUFSIZ * 2; - while (str_top1 > str_base1 + str_length) - ; - if ((str_base1 = (char *)realloc(str_base1, str_length)) - == NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); - exit(1); - } - /* - * Re-adjust other pointers - */ - diff = str_base1 - old_base; - p += diff; - } - for (i = 0, s = fptr->ar_longname; - i < strlen(fptr->ar_longname) && *s != '\0'; i++) { - *p++ = *s++; - } + /* Size of new item to add */ + len = strlen(fptr->ar_longname); + need = len + 2; + + /* Ensure there's room */ + if ((need + long_strtbl.used) > long_strtbl.size) + strtbl_alloc(&long_strtbl, need); + + /* + * Generate the index string to be written into the member header + * + * This will not overflow the ar_name field because that field is + * 16 characters in size, and a 32-bit unsigned value can be formatted + * in 10 characters. Allowing a character for the leading '/', and one + * for the NULL termination, that leaves us with 4 extra spaces. + */ + (void) snprintf(fptr->ar_name, sizeof (fptr->ar_name), + MSG_ORIG(MSG_FMT_LLINT), EC_XWORD(long_strtbl.used)); + + /* + * Enter long name into reserved spot, terminated with a slash + * and a newline character. + */ + p = long_strtbl.base + long_strtbl.used; + long_strtbl.used += need; + (void) strcpy(p, fptr->ar_longname); + p += len; *p++ = '/'; *p++ = '\n'; - str_top1 = p; } -char * +/* + * Determine if the archive we're about to write will exceed the + * 32-bit limit of 4GB. + * + * entry: + * mksymtab() and mklong_tab() have been called to set up + * the string tables. + * + * exit: + * Returns TRUE (1) if the 64-bit symbol table is needed, and + * FALSE (0) otherwise. + * + */ +static int +require64(size_t nsyms, int found_obj, size_t longnames) +{ + ARFILE *fptr; + uint64_t size; + + /* + * If there are more than 4GB symbols, we have to use + * the 64-bit form. Note that longnames cannot exceed 4GB + * because that symbol table is limited to a length of 4GB by + * the archive format. + */ + if (nsyms > 0xffffffff) + return (1); + + /* + * Make a worst case estimate for the size of the resulting + * archive by assuming full padding between members. + */ + size = SARMAG; + if (longnames) + size += sizeof (struct ar_hdr) + long_strtbl.used + PADSZ; + + if (found_obj) + size += sizeof_symtbl(nsyms, found_obj, 4) + PADSZ; + + if (size > 0xffffffff) + return (1); + + for (fptr = listhead; fptr; fptr = fptr->ar_next) { + size += sizeof (struct ar_hdr) + fptr->ar_size + PADSZ; + + if (size > 0xffffffff) + return (1); + } + + /* 32-bit symbol table will suffice */ + return (0); +} + +void writefile(Cmd_info *cmd_info) { - ARFILE * fptr; - ARFILEP *symlist = 0; - int i; - int longnames = 0; - long long_tab_size = 0; - long nsyms; - int new_archive = 0; - char *name = cmd_info->arnam; - int arsize; - char *dst; - char *tmp_dst; - int nfd; - int found_obj = 0; - - long_tab_size = mklong_tab(&longnames); - nsyms = mksymtab(&symlist, &found_obj); - - for (i = 0; signum[i]; i++) - /* started writing, cannot interrupt */ - (void) signal(signum[i], SIG_IGN); - - - /* Is this a new archive? */ - if ((access(cmd_info->arnam, 0) < 0) && (errno == ENOENT)) { - new_archive = 1; - if (!opt_FLAG(cmd_info, c_FLAG)) { - error_message(BER_MES_CREATE_ERROR, - PLAIN_ERROR, (char *)0, cmd_info->arnam); + ARFILE *fptr; + ARFILEP *symlist = 0; + size_t longnames; + size_t nsyms; + int new_archive = 0; + char *name = cmd_info->arnam; + size_t arsize; /* Size of magic # and special members */ + size_t symtbl_eltsize = 4; + int found_obj = 0; + int fd; + off_t off; + struct stat stbuf, ar_stbuf; + char pad_bytes[PADSZ]; + size_t pad_cnt; + int is_elf; + + /* + * Gather the list of symbols and associate each one to the + * ARFILE descriptor of the object it belongs to. At the same + * time, tag each ELF object with the appropriate F_CLASSxx + * flag. + */ + nsyms = mksymtab(name, &symlist, &found_obj); + + /* Generate the string table for long member names */ + longnames = mklong_tab(); + + /* + * Will this archive exceed 4GB? If we're a 32-bit process, we can't + * do it. If we're a 64-bit process, then we'll have to use a + * 64-bit symbol table. + */ + if (require64(nsyms, found_obj, longnames)) { +#ifdef _LP64 + symtbl_eltsize = 8; +#else + (void) fprintf(stderr, MSG_INTL(MSG_TOOBIG4G)); + exit(1); +#endif + } + + /* + * If the user requested it, use the 64-bit symbol table even if + * a 32-bit one would suffice. 32-bit tables are more portable and + * take up less room, so this feature is primarily for testing. + */ + if (cmd_info->opt_flgs & S_FLAG) + symtbl_eltsize = 8; + + /* + * If the first non-special archive member is an ELF object, then we + * need to arrange for its data to have an alignment of PADSZ. The + * preceeding special member will be the symbol table, or the long + * name string table. We pad the string table that precedes the + * ELF member in order to achive the desired alignment. + */ + is_elf = listhead && (listhead->ar_flag & (F_CLASS32 | F_CLASS64)); + arsize = SARMAG; + if (found_obj) { + arsize += sizeof_symtbl(nsyms, found_obj, symtbl_eltsize); + if (is_elf && (longnames == 0)) { + pad_cnt = pad(arsize + sizeof (struct ar_hdr), PADSZ); + strtbl_pad(&sym_strtbl, pad_cnt, '\0'); + arsize += pad_cnt; } - } else - new_archive = 0; + } + if (longnames > 0) { + arsize += sizeof (struct ar_hdr) + long_strtbl.used; + if (is_elf) { + pad_cnt = pad(arsize + sizeof (struct ar_hdr), PADSZ); + strtbl_pad(&long_strtbl, pad_cnt, '\0'); + arsize += pad_cnt; + } + } /* - * Calculate the size of the new archive + * For each user visible (non-special) archive member, determine + * the header offset, and the size of any required padding. */ - arsize = sizeofnewarchive(nsyms, longnames); + (void) sizeofmembers(arsize); /* - * Dummy symtab ? + * Is this a new archive, or are we updating an existing one? + * + * A subtlety here is that POSIX says we are not supposed + * to replace a non-writable file. The only 100% reliable test + * against this is to open the file for non-destructive + * write access. If the open succeeds, we are clear to + * replace it, and if not, then the error generated is + * the error we need to report. */ - if (nsyms == 0 && found_obj != 0) - /* - * 4 + 4 = First 4 bytes to keep the number of symbols. - * The second 4 bytes for string table. - */ - arsize += sizeof (struct ar_hdr) + 4 + 4; + if ((fd = open(name, O_RDWR)) < 0) { + int err = errno; - if (arsize > AR_MAX_BYTES_IN_MEM) { - tmp_dst = dst = NULL; + if (err != ENOENT) { + (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), + name, strerror(err)); + exit(1); + } + new_archive = 1; + if ((cmd_info->opt_flgs & c_FLAG) == 0) { + (void) fprintf(stderr, MSG_INTL(MSG_BER_MES_CREATE), + cmd_info->arnam); + } } else { - tmp_dst = dst = malloc(arsize); - } - if (dst == NULL) { - return writelargefile(cmd_info, long_tab_size, - longnames, symlist, nsyms, found_obj, new_archive); + /* Capture mode and owner information to apply to replacement */ + if (fstat(fd, &ar_stbuf) < 0) { + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_SYS_STAT), + name, strerror(err)); + (void) close(fd); + exit(1); + } + (void) close(fd); + new_archive = 0; } - (void) memcpy(tmp_dst, ARMAG, SARMAG); - tmp_dst += SARMAG; - if (nsyms || found_obj != 0) { - int diff; - diff = writesymtab(tmp_dst, nsyms, symlist); - tmp_dst += diff; + /* + * Register exit handler function to clean up after us if we exit + * before completing the new archive. atexit() is defined as + * only being able to fail due to memory exhaustion. + */ + if (atexit(exit_cleanup) != 0) { + (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(ENOMEM)); + exit(1); + } + + /* + * If a new archive, create it in place. If updating an archive, + * create the replacement under a temporary name and then rename it + * into place. + */ + ar_outfile.path = new_archive ? name : make_tmpname(name); + ar_outfile.fd = open(ar_outfile.path, O_RDWR|O_CREAT|O_LARGEFILE, 0666); + if (ar_outfile.fd == -1) { + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), + ar_outfile.path, strerror(err)); + exit(1); } + /* Output magic string */ + arwrite(name, ar_outfile.fd, ARMAG, SARMAG); + + /* + * The symbol table member is always first if present. Note that + * writesymtab() uses the member offsets computed by sizeofmembers() + * above. + */ + if (found_obj) + writesymtab(name, ar_outfile.fd, nsyms, symlist, + symtbl_eltsize); + if (longnames) { - (void) sprintf(tmp_dst, FORMAT, LONGDIRNAME, time(0), - (unsigned)0, (unsigned)0, (unsigned)0, - (long)long_tab_size, ARFMAG); - tmp_dst += sizeof (struct ar_hdr); - (void) memcpy(tmp_dst, str_base1, str_top1 - str_base1); - tmp_dst += str_top1 - str_base1; + write_member_header(name, ar_outfile.fd, 0, + MSG_ORIG(MSG_STR_DSLASH), time(0), 0, 0, 0, + long_strtbl.used); + arwrite(name, ar_outfile.fd, long_strtbl.base, + long_strtbl.used); } - for (fptr = listhead; fptr; fptr = fptr->ar_next) { /* - * NOTE: - * The mem_header->ar_name[] is set to a NULL string - * if the archive member header has some error. - * (See elf_getarhdr() man page.) - * It is set to NULL for example, the ar command reads - * the archive files created by SunOS 4.1 system. - * See c block comment in cmd.c, "Incompatible Archive Header". + * The accuracy of the symbol table depends on our having calculated + * the size of the archive accurately to this point. If this is a + * debug build, verify it. */ + assert(arsize == lseek(ar_outfile.fd, 0, SEEK_CUR)); + +#ifndef XPG4 + if (cmd_info->opt_flgs & v_FLAG) { + (void) fprintf(stderr, MSG_INTL(MSG_BER_MES_WRITE), + cmd_info->arnam); + } +#endif + + /* + * Fill pad_bytes array with newline characters. This array + * is used to supply padding bytes at the end of ELF objects. + * There can never be more tha PADSZ such bytes, so this number + * will always suffice. + */ + for (pad_cnt = 0; pad_cnt < PADSZ; pad_cnt++) + pad_bytes[pad_cnt] = '\n'; + + for (fptr = listhead; fptr; fptr = fptr->ar_next) { + /* + * We computed the expected offset for each ELF member and + * used those offsets to fill the symbol table. If this is + * a debug build, verify that the computed offset was right. + */ + is_elf = (fptr->ar_flag & (F_CLASS32 | F_CLASS64)) != 0; + assert(!is_elf || + (fptr->ar_offset == lseek(ar_outfile.fd, 0, SEEK_CUR))); + + /* + * NOTE: + * The mem_header->ar_name[] is set to a NULL string + * if the archive member header has some error. + * (See elf_getarhdr() man page.) + * It is set to NULL for example, the ar command reads + * the archive files created by SunOS 4.1 system. + * See c block comment in cmd.c, "Incompatible Archive Header". + */ if (fptr->ar_name[0] == 0) { fptr->ar_longname = fptr->ar_rawname; (void) strncpy(fptr->ar_name, fptr->ar_rawname, SNAME); } - if (strlen(fptr->ar_longname) <= (unsigned)SNAME-2) - (void) sprintf(tmp_dst, FNFORMAT, - trimslash(fptr->ar_longname)); - else - (void) sprintf(tmp_dst, FNFORMAT, fptr->ar_name); - (void) sprintf(tmp_dst+16, TLFORMAT, fptr->ar_date, - (unsigned)fptr->ar_uid, (unsigned)fptr->ar_gid, - (unsigned)fptr->ar_mode, fptr->ar_size + fptr->ar_padding, - ARFMAG); - - tmp_dst += sizeof (struct ar_hdr); - - if (!(fptr->ar_flag & F_MALLOCED) && - !(fptr->ar_flag & F_MMAPED) && - !(fptr->ar_flag & F_ELFRAW)) { - /* file was not read in fptr->ar_contents during 'cmd' */ - /* do it now */ - FILE *f; - f = fopen(fptr->ar_pathname, "r"); - if (f == NULL) { - error_message(SYS_OPEN_ERROR, - SYSTEM_ERROR, strerror(errno), - fptr->ar_longname); + write_member_header(name, ar_outfile.fd, is_elf, + (strlen(fptr->ar_longname) <= (unsigned)SNAME-2) ? + trimslash(fptr->ar_longname) : fptr->ar_name, + EC_WORD(fptr->ar_date), fptr->ar_uid, fptr->ar_gid, + fptr->ar_mode, fptr->ar_size + fptr->ar_padding); + + + if ((fptr->ar_flag & F_ELFRAW) == 0) { + /* + * The file doesn't come from the archive, and is + * therefore not already in memory(fptr->ar_contents) + * so open it and do a direct file-to-file transfer of + * its contents. We use the sendfile() system call + * to make the kernel do the transfer, so we don't have + * to buffer data in process, and we trust that the + * kernel will use an optimal transfer strategy. + */ + if ((fd = open(fptr->ar_pathname, O_RDONLY)) == -1) { + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), + fptr->ar_longname, strerror(err)); + exit(1); + } + if (stat(fptr->ar_pathname, &stbuf) < 0) { + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), + fptr->ar_longname, strerror(err)); + (void) close(fd); exit(1); - } else { - if (fread(tmp_dst, sizeof (char), - fptr->ar_size, f) != fptr->ar_size) { - error_message(SYS_READ_ERROR, - SYSTEM_ERROR, strerror(errno), - fptr->ar_longname); - exit(1); - } } - (void) fclose(f); + off = 0; + if (sendfile(ar_outfile.fd, fd, &off, + stbuf.st_size) != stbuf.st_size) { + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_SYS_WRITE), + name, strerror(err)); + exit(2); + } + (void) close(fd); } else { - (void) memcpy(tmp_dst, fptr->ar_contents, + /* Archive member is in memory. Write it out */ + arwrite(name, ar_outfile.fd, fptr->ar_contents, fptr->ar_size); - if (fptr->ar_flag & F_MALLOCED) { - (void) free(fptr->ar_contents); - fptr->ar_flag &= ~(F_MALLOCED); - } } - tmp_dst += fptr->ar_size; - if (fptr->ar_size & 0x1) { - (void) memcpy(tmp_dst, "\n", 1); - tmp_dst++; - } - - if (fptr->ar_padding) { - int i = fptr->ar_padding; - while (i) { - *tmp_dst++ = '\n'; - --i; - } - } + /* + * All archive members are padded to at least a boundary of 2. + * The expression ((fptr->ar_size & 0x1) != 0) yields 1 for + * odd boundaries, and 0 for even ones. To this, we add + * whatever padding is needed for ELF objects. + */ + pad_cnt = ((fptr->ar_size & 0x1) != 0) + fptr->ar_padding; + if (pad_cnt > 0) + arwrite(name, ar_outfile.fd, pad_bytes, pad_cnt); } /* - * All preparation for writing is done. + * All archive output is done. */ + if (close(ar_outfile.fd) < 0) { + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_SYS_CLOSE), ar_outfile.path, + strerror(err)); + exit(1); + } + ar_outfile.fd = -1; /* Prevent removal on exit */ (void) elf_end(cmd_info->arf); (void) close(cmd_info->afd); /* - * Write out to the file + * If updating an existing archive, rename the new version on + * top of the original. */ - if (new_archive) { - /* - * create a new file - */ - nfd = creat(name, 0666); - if (nfd == -1) { - error_message(SYS_CREATE_01_ERROR, - SYSTEM_ERROR, strerror(errno), name); - exit(1); - } - } else { + if (!new_archive) { /* - * Open the new file + * Prevent the replacement of the original archive from + * being interrupted, to lower the possibility of an + * interrupt destroying a pre-existing archive. */ - nfd = open(name, O_RDWR|O_TRUNC); - if (nfd == -1) { - error_message(SYS_WRITE_02_ERROR, - SYSTEM_ERROR, strerror(errno), name); + establish_sighandler(SIG_IGN); + + if (rename(ar_outfile.path, name) < 0) { + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_SYS_RENAME), + ar_outfile.path, name, strerror(err)); + (void) unlink(ar_outfile.path); exit(1); } + (void) chmod(name, ar_stbuf.st_mode & 0777); + if (chown(name, ar_stbuf.st_uid, ar_stbuf.st_gid) >= 0) + (void) chmod(name, ar_stbuf.st_mode & 07777); + } -#ifndef XPG4 - if (opt_FLAG(cmd_info, v_FLAG)) { - error_message(BER_MES_WRITE_ERROR, - PLAIN_ERROR, (char *)0, cmd_info->arnam); - } -#endif - if (write(nfd, dst, arsize) != arsize) { - error_message(SYS_WRITE_04_ERROR, - SYSTEM_ERROR, strerror(errno), name); - if (!new_archive) - error_message(WARN_USER_ERROR, - PLAIN_ERROR, (char *)0); - exit(2); - } - return (dst); } -static long -mklong_tab(int *longnames) +/* + * Examine all the archive members, enter any member names longer than + * 15 characters into the long name string table, and count the number + * of names found. + * + * Returns the size of the resulting archive member, including the + * member header. + */ +static size_t +mklong_tab(void) { ARFILE *fptr; - char ptr_index[SNAME+1]; - long ret = 0; + size_t longnames = 0; for (fptr = listhead; fptr; fptr = fptr->ar_next) { if (strlen(fptr->ar_longname) >= (unsigned)SNAME-1) { - (*longnames)++; - savelongname(fptr, ptr_index); - (void) strcpy(fptr->ar_name, ptr_index); + longnames++; + savelongname(fptr); } } - if (*longnames) { - /* round up table that keeps the long filenames */ - while ((str_top1 - str_base1) & 03) - *str_top1++ = '\n'; - ret = sizeof (char) * (str_top1 - str_base1); - } - return (ret); + + /* round up table that keeps the long filenames */ + if (longnames > 0) + strtbl_pad(&long_strtbl, pad(long_strtbl.used, 4), '\n'); + + return (longnames); } -/* Put bytes in archive header in machine independent order. */ +/* + * Write 32/64-bit words into buffer in archive symbol table + * standard byte order (MSB). + */ +static char * +sputl32(uint32_t n, char *cp) +{ + *cp++ = n >> 24; + *cp++ = n >> 16; + *cp++ = n >> 8; -static void -sputl(long n, char *cp) + *cp++ = n & 255; + + return (cp); +} + +static char * +sputl64(uint64_t n, char *cp) { + *cp++ = n >> 56; + *cp++ = n >> 48; + *cp++ = n >> 40; + *cp++ = n >> 32; + *cp++ = n >> 24; *cp++ = n >> 16; *cp++ = n >> 8; *cp++ = n & 255; + + return (cp); } static int -search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn, - long *nsyms, ARFILEP **symlist, int *num_errs) +search_sym_tab(const char *arname, ARFILE *fptr, Elf *elf, Elf_Scn *scn, + size_t *nsyms, ARFILEP **symlist, size_t *num_errs) { Elf_Data *str_data, *sym_data; /* string table, symbol table */ Elf_Scn *str_scn; @@ -1026,20 +1407,18 @@ search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn, str_scn = elf_getscn(elf, shdr.sh_link); /* index for string table */ if (str_scn == NULL) { if (fname != NULL) - error_message(ELF_GETDATA_01_ERROR, - LIBELF_ERROR, elf_errmsg(-1), - fname); + (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_FILE), + fname, elf_errmsg(-1)); else - error_message(ELF_GETDATA_02_ERROR, - LIBELF_ERROR, elf_errmsg(-1)); + (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_AR), + arname, fptr->ar_longname, elf_errmsg(-1)); (*num_errs)++; return (-1); } no_of_symbols = shdr.sh_size / shdr.sh_entsize; if (no_of_symbols == -1) { - error_message(SYMTAB_01_ERROR, - PLAIN_ERROR, (char *)0); + (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_01)); return (-1); } @@ -1047,11 +1426,11 @@ search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn, str_shtype = shdr.sh_type; if (str_shtype == -1) { if (fname != NULL) - error_message(ELF_GETDATA_01_ERROR, - LIBELF_ERROR, elf_errmsg(-1), fname); + (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_FILE), + fname, elf_errmsg(-1)); else - error_message(ELF_GETDATA_02_ERROR, - LIBELF_ERROR, elf_errmsg(-1)); + (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA_AR), + arname, fptr->ar_longname, elf_errmsg(-1)); (*num_errs)++; return (-1); } @@ -1062,45 +1441,40 @@ search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn, if (str_shtype != SHT_STRTAB) { if (fname != NULL) - error_message(SYMTAB_02_ERROR, - PLAIN_ERROR, (char *)0, + (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NOSTR_FILE), fname); else - error_message(SYMTAB_03_ERROR, - PLAIN_ERROR, (char *)0); + (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NOSTR_AR), + arname, fptr->ar_longname); return (0); } str_data = 0; if ((str_data = elf_getdata(str_scn, str_data)) == 0) { if (fname != NULL) - error_message(SYMTAB_04_ERROR, - PLAIN_ERROR, (char *)0, + (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NODAT_FILE), fname); else - error_message(SYMTAB_05_ERROR, - PLAIN_ERROR, (char *)0); + (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_NODAT_AR), + arname, fptr->ar_longname); return (0); } if (str_data->d_size == 0) { if (fname != NULL) - error_message(SYMTAB_06_ERROR, - PLAIN_ERROR, (char *)0, + (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_ZDAT_FILE), fname); else - error_message(SYMTAB_07_ERROR, - PLAIN_ERROR, (char *)0); + (void) fprintf(stderr, MSG_INTL(MSG_SYMTAB_ZDAT_AR), + arname, fptr->ar_longname); return (0); } sym_data = 0; if ((sym_data = elf_getdata(scn, sym_data)) == NULL) { if (fname != NULL) - error_message(ELF_01_ERROR, - LIBELF_ERROR, elf_errmsg(-1), + (void) fprintf(stderr, MSG_INTL(MSG_ELF_LIB_FILE), fname, elf_errmsg(-1)); else - error_message(ELF_02_ERROR, - LIBELF_ERROR, elf_errmsg(-1), - elf_errmsg(-1)); + (void) fprintf(stderr, MSG_INTL(MSG_ELF_LIB_AR), + arname, fptr->ar_longname, elf_errmsg(-1)); return (0); } @@ -1118,8 +1492,10 @@ search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn, sym_ptr = malloc((SYMCHUNK+1) * sizeof (ARFILEP)); if (sym_ptr == NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); + int err = errno; + (void) fprintf(stderr, + MSG_INTL(MSG_MALLOC), + strerror(err)); exit(1); } syms_left = SYMCHUNK; @@ -1144,12 +1520,12 @@ search_sym_tab(ARFILE *fptr, Elf *elf, Elf_Scn *scn, /* * Get the output file size */ -static int -sizeofmembers(int psum) +static size_t +sizeofmembers(size_t psum) { - int sum = 0; - ARFILE *fptr; - int hdrsize = sizeof (struct ar_hdr); + size_t sum = 0; + ARFILE *fptr; + size_t hdrsize = sizeof (struct ar_hdr); for (fptr = listhead; fptr; fptr = fptr->ar_next) { fptr->ar_offset = psum + sum; @@ -1161,7 +1537,7 @@ sizeofmembers(int psum) /* * If the current item, and the next item are both ELF * objects, then add padding to current item so that the - * next item will have PADSZ alignment. + * data in the next item will have PADSZ alignment. * * In any other case, set the padding to 0. If the * item comes from another archive, it may be carrying @@ -1171,7 +1547,7 @@ sizeofmembers(int psum) if ((fptr->ar_flag & (F_CLASS32 | F_CLASS64)) && fptr->ar_next && (fptr->ar_next->ar_flag & (F_CLASS32 | F_CLASS64))) { - fptr->ar_padding = pad(psum + sum + hdrsize); + fptr->ar_padding = pad(psum + sum + hdrsize, PADSZ); sum += fptr->ar_padding; } else { fptr->ar_padding = 0; @@ -1180,292 +1556,63 @@ sizeofmembers(int psum) return (sum); } -static int -sizeofnewarchiveheader(int nsyms, int longnames) +/* + * Compute the size of the symbol table archive member. + * + * entry: + * nsyms - # of symbols in the table + * found_obj - TRUE if the archive contains any ELF objects + * eltsize - Size of the integer type to use for the symbol + * table. 4 for 32-bit tables, and 8 for 64-bit tables. + */ +static size_t +sizeof_symtbl(size_t nsyms, int found_obj, size_t eltsize) { - int sum = 0; - - sum += SARMAG; + size_t sum = 0; - if (nsyms) { - char *top = (char *)str_top; - char *base = (char *)str_base; - - while ((top - base) & 03) - top++; - sum += sizeof (struct ar_hdr); - sum += (nsyms + 1) * 4; - sum += top - base; + if (found_obj) { + /* Member header, symbol count, and one slot per symbol */ + sum += sizeof (struct ar_hdr) + ((nsyms + 1) * eltsize); + sum += sym_strtbl.used; } - if (longnames) { - sum += sizeof (struct ar_hdr); - sum += str_top1 - str_base1; - } - - /* - * If the first member file is an ELF object, - * we have to ensure the member contents will align - * on PADSZ byte boundary. - */ - if (listhead && (listhead->ar_flag & (F_CLASS32 | F_CLASS64))) { - pad_symtab = pad(sum + sizeof (struct ar_hdr)); - sum += pad_symtab; - } - - return (sum); -} - -static int -sizeofnewarchive(int nsyms, int longnames) -{ - int sum; - - sum = sizeofnewarchiveheader(nsyms, longnames); - sum += sizeofmembers(sum); return (sum); } static void -arwrite(char *name, int nfd, char *dst, int size) { +arwrite(const char *name, int nfd, const char *dst, size_t size) { if (write(nfd, dst, size) != size) { - error_message(SYS_WRITE_04_ERROR, - SYSTEM_ERROR, strerror(errno), name); + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_SYS_WRITE), + name, strerror(err)); exit(2); } } -static char * -make_tmpname(char *filename) { - static char template[] = "arXXXXXX"; - char *tmpname; - char *slash = strrchr(filename, '/'); - - if (slash != (char *)NULL) { - char c; - - c = *slash; - *slash = 0; - tmpname = (char *)malloc(strlen(filename) + - sizeof (template) + 2); - (void) strcpy(tmpname, filename); - (void) strcat(tmpname, "/"); - (void) strcat(tmpname, template); - (void) mktemp(tmpname); - *slash = c; - } else { - tmpname = malloc(sizeof (template)); - (void) strcpy(tmpname, template); - (void) mktemp(tmpname); - } - return (tmpname); -} - -static int -ar_copy(char *from, char *to) { - int fromfd, tofd, nread; - int saved; - char buf[8192]; - - fromfd = open(from, O_RDONLY); - if (fromfd < 0) - return (-1); - tofd = open(to, O_CREAT | O_WRONLY | O_TRUNC, 0777); - if (tofd < 0) { - saved = errno; - (void) close(fromfd); - errno = saved; - return (-1); - } - while ((nread = read(fromfd, buf, sizeof (buf))) > 0) { - if (write(tofd, buf, nread) != nread) { - saved = errno; - (void) close(fromfd); - (void) close(tofd); - errno = saved; - return (-1); - } - } - saved = errno; - (void) close(fromfd); - (void) close(tofd); - if (nread < 0) { - errno = saved; - return (-1); - } - return (0); -} - -static int -ar_rename(char *from, char *to) -{ - int exists; - struct stat s; - int ret = 0; - - exists = lstat(to, &s) == 0; - - if (! exists || (!S_ISLNK(s.st_mode) && s.st_nlink == 1)) { - ret = rename(from, to); - if (ret == 0) { - if (exists) { - (void) chmod(to, s.st_mode & 0777); - if (chown(to, s.st_uid, s.st_gid) >= 0) - (void) chmod(to, s.st_mode & 07777); - } - } else { - (void) unlink(from); - } - } else { - ret = ar_copy(from, to); - (void) unlink(from); - } - return (ret); -} - -static char * -writelargefile(Cmd_info *cmd_info, long long_tab_size, int longnames, - ARFILEP *symlist, long nsyms, int found_obj, int new_archive) -{ - ARFILE * fptr; - char *name = cmd_info->arnam; - int arsize; - char *dst; - char *tmp_dst; - int nfd; - char *new_name; - FILE *f; - struct stat stbuf; - - new_name = make_tmpname(name); - - if (new_archive) { - nfd = open(name, O_RDWR|O_CREAT|O_LARGEFILE, 0666); - if (nfd == -1) { - error_message(SYS_CREATE_01_ERROR, - SYSTEM_ERROR, strerror(errno), name); - exit(1); - } - } else { - nfd = open(new_name, O_RDWR|O_CREAT|O_LARGEFILE, 0666); - if (nfd == -1) { - error_message(SYS_WRITE_02_ERROR, - SYSTEM_ERROR, strerror(errno), name); - exit(1); - } - } - - arsize = sizeofnewarchiveheader(nsyms, longnames); - if (nsyms == 0 && found_obj != 0) - arsize += sizeof (struct ar_hdr) + 4 + 4; - if (arsize < 2048) { - arsize = 2048; - } - dst = tmp_dst = (char *)malloc(arsize); - (void) memcpy(tmp_dst, ARMAG, SARMAG); - tmp_dst += SARMAG; - - if (nsyms || found_obj != 0) { - int diff; - diff = writesymtab(tmp_dst, nsyms, symlist); - tmp_dst += diff; - } - - if (longnames) { - (void) sprintf(tmp_dst, FORMAT, LONGDIRNAME, time(0), - (unsigned)0, (unsigned)0, (unsigned)0, - (long)long_tab_size, ARFMAG); - tmp_dst += sizeof (struct ar_hdr); - (void) memcpy(tmp_dst, str_base1, str_top1 - str_base1); - tmp_dst += str_top1 - str_base1; - } -#ifndef XPG4 - if (opt_FLAG(cmd_info, v_FLAG)) { - error_message(BER_MES_WRITE_ERROR, - PLAIN_ERROR, (char *)0, - cmd_info->arnam); - } -#endif - arwrite(name, nfd, dst, (int)(tmp_dst - dst)); - - for (fptr = listhead; fptr; fptr = fptr->ar_next) { - if (fptr->ar_name[0] == 0) { - fptr->ar_longname = fptr->ar_rawname; - (void) strncpy(fptr->ar_name, fptr->ar_rawname, SNAME); - } - if (strlen(fptr->ar_longname) <= (unsigned)SNAME-2) - (void) sprintf(dst, FNFORMAT, - trimslash(fptr->ar_longname)); - else - (void) sprintf(dst, FNFORMAT, fptr->ar_name); - (void) sprintf(dst+16, TLFORMAT, fptr->ar_date, - (unsigned)fptr->ar_uid, (unsigned)fptr->ar_gid, - (unsigned)fptr->ar_mode, fptr->ar_size + fptr->ar_padding, - ARFMAG); - arwrite(name, nfd, dst, sizeof (struct ar_hdr)); - - if (!(fptr->ar_flag & F_MALLOCED) && - !(fptr->ar_flag & F_MMAPED) && - !(fptr->ar_flag & F_ELFRAW)) { - f = fopen(fptr->ar_pathname, "r"); - if (stat(fptr->ar_pathname, &stbuf) < 0) { - (void) fclose(f); - f = NULL; - } - if (f == NULL) { - error_message(SYS_OPEN_ERROR, - SYSTEM_ERROR, strerror(errno), - fptr->ar_longname); - exit(1); - } else { - if ((fptr->ar_contents = (char *) - malloc(ROUNDUP(stbuf.st_size))) == NULL) { - error_message(MALLOC_ERROR, - PLAIN_ERROR, (char *)0); - exit(1); - } - if (fread(fptr->ar_contents, - sizeof (char), - stbuf.st_size, f) != stbuf.st_size) { - error_message(SYS_READ_ERROR, - SYSTEM_ERROR, strerror(errno), - fptr->ar_longname); - exit(1); - } - } - arwrite(name, nfd, fptr->ar_contents, fptr->ar_size); - (void) fclose(f); - free(fptr->ar_contents); - } else { - arwrite(name, nfd, fptr->ar_contents, fptr->ar_size); - if (fptr->ar_flag & F_MALLOCED) { - (void) free(fptr->ar_contents); - fptr->ar_flag &= ~(F_MALLOCED); - } - } - - if (fptr->ar_size & 0x1) { - arwrite(name, nfd, "\n", 1); - } - - if (fptr->ar_padding) { - int i = fptr->ar_padding; - while (i) { - arwrite(name, nfd, "\n", 1); - --i; - } - } - } +static const char * +make_tmpname(const char *filename) { + char *slash, *tmpname; + size_t prefix_cnt = 0; /* - * All preparation for writing is done. + * If there is a path prefix in front of the filename, we + * want to put the temporary file in the same directory. + * Determine the length of the path. */ - (void) elf_end(cmd_info->arf); - (void) close(cmd_info->afd); - - if (!new_archive) { - (void) ar_rename(new_name, name); + slash = strrchr(filename, '/'); + if (slash != NULL) + prefix_cnt = slash - filename + 1; + tmpname = malloc(prefix_cnt + MSG_STR_MKTEMP_SIZE + 1); + if (tmpname == NULL) { + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err)); + exit(1); } - return (dst); + if (prefix_cnt > 0) + (void) strncpy(tmpname, filename, prefix_cnt); + (void) strcpy(tmpname + prefix_cnt, MSG_ORIG(MSG_STR_MKTEMP)); + (void) mktemp(tmpname); + + return (tmpname); } diff --git a/usr/src/cmd/sgs/ar/common/global.c b/usr/src/cmd/sgs/ar/common/global.c deleted file mode 100644 index bff4ca37b8..0000000000 --- a/usr/src/cmd/sgs/ar/common/global.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* Copyright (c) 1988 AT&T */ -/* All Rights Reserved */ - - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "inc.h" - -ARFILE *listhead, *listend; - -int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0}; diff --git a/usr/src/cmd/sgs/ar/common/inc.h b/usr/src/cmd/sgs/ar/common/inc.h index e7d14df1cd..9ef5735924 100644 --- a/usr/src/cmd/sgs/ar/common/inc.h +++ b/usr/src/cmd/sgs/ar/common/inc.h @@ -18,9 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -33,219 +33,123 @@ #define _INC_H #include <stdio.h> -#include <sys/param.h> -#include <ar.h> +#include <stdarg.h> +#include <stdlib.h> #include <errno.h> #include <ctype.h> #include <unistd.h> -#include "sgs.h" -#include <stdarg.h> -#include <sys/mman.h> - -#ifndef UID_NOBODY -#define UID_NOBODY 60001 -#endif - -#ifndef GID_NOBODY -#define GID_NOBODY 60001 -#endif - -#include <stdlib.h> - -#include "libelf.h" - #include <signal.h> #include <sys/stat.h> #include <errno.h> #include <string.h> #include <fcntl.h> - +#include <sys/types.h> +#include <sys/param.h> #include <time.h> #include <locale.h> +#include <ar.h> +#include <libelf.h> +#include "sgs.h" +#include "msg.h" -#define SUID 04000 -#define SGID 02000 -#define ROWN 0400 -#define WOWN 0200 -#define XOWN 0100 -#define RGRP 040 -#define WGRP 020 -#define XGRP 010 -#define ROTH 04 -#define WOTH 02 -#define XOTH 01 -#define STXT 01000 - -#define opt_FLAG(_x, ch) ((_x->opt_flgs & ch)) #define CHUNK 500 #define SYMCHUNK 1000 #define SNAME 16 #define ROUNDUP(x) (((x) + 1) & ~1) -#define LONGDIRNAME "// " -#define SYMDIRNAME "/ " /* symbol directory filename */ -#define FNFORMAT "%-16s" /* filename format */ -#define TLFORMAT "%-12ld%-6u%-6u%-8o%-10ld%-2s" /* trailer format */ -#define FORMAT FNFORMAT TLFORMAT #define DATESIZE 60 /* sizeof (struct ar_hdr) */ -#define PLAIN_ERROR 0 -#define LIBELF_ERROR 1 -#define SYSTEM_ERROR 2 - typedef struct arfile ARFILE; -typedef ARFILE * ARFILEP; - -#define AR_MAX_BYTES_IN_MEM 0x20000000 /* 512 Mb */ +typedef ARFILE *ARFILEP; -struct arfile -{ - char ar_name[SNAME]; /* info from archive member header */ - time_t ar_date; - int ar_uid; - int ar_gid; +/* + * Per-member state, help on listhead/listend list. + */ +struct arfile { + char ar_name[SNAME]; /* info from archive member header */ + time_t ar_date; + int ar_uid; + int ar_gid; unsigned long ar_mode; - long ar_size; - char *ar_longname; - char *ar_rawname; - Elf *ar_elf; /* My elf descriptor */ - char *ar_pathname; - char *ar_contents; - long ar_offset; /* The member offset */ - unsigned char ar_flag; - unsigned char ar_padding; /* padding for CLASS64 */ - ARFILE *ar_next; + size_t ar_size; + char *ar_longname; + char *ar_rawname; + Elf *ar_elf; /* My elf descriptor */ + char *ar_pathname; + char *ar_contents; + size_t ar_offset; /* The member offset */ + unsigned char ar_flag; + unsigned char ar_padding; /* # padding bytes following data */ + ARFILE *ar_next; /* Next member in linked list or NULL */ }; +/* + * Command function. There is one of these for each operation + * ar can perform (r, x, etc). + */ +struct cmd_info; +typedef void Cmd_func(struct cmd_info *); + +/* Command information block */ typedef struct cmd_info { - char *arnam; /* Archive file name */ - int afd; /* fd for the archive file */ - Elf *arf; /* Elf descriptor for the archive */ - char *ponam; - char **namv; - int namc; - int opt_flgs; /* lower case options */ - int OPT_flgs; /* upper case options */ - int (*comfun)(); - int modified; - unsigned long bytes_in_mem; + char *arnam; /* Archive file name */ + int afd; /* fd for the archive file */ + Elf *arf; /* Elf descriptor for the archive */ + char *ponam; /* Position Name (-a, -b/-i) */ + char **namv; /* Member names from command line */ + int namc; /* # of member names in namv */ + int opt_flgs; /* options */ + Cmd_func *comfun; /* function to carry out command */ + int modified; /* Set if need to write archive */ } Cmd_info; /* - * options + * options (Cmd_info opt_flgs) */ -#define a_FLAG 0x0001 -#define b_FLAG 0x0002 -#define c_FLAG 0x0004 -#define d_FLAG 0x0008 -#define l_FLAG 0x0020 -#define m_FLAG 0x0040 -#define p_FLAG 0x0080 -#define q_FLAG 0x0100 -#define r_FLAG 0x0200 -#define s_FLAG 0x0400 -#define t_FLAG 0x0800 -#define u_FLAG 0x1000 -#define v_FLAG 0x2000 -#define x_FLAG 0x4000 -#define z_FLAG 0x8000 - -#define C_FLAG 0x0001 -#define M_FLAG 0x0002 -#define T_FLAG 0x0004 +#define a_FLAG 0x00000001 +#define b_FLAG 0x00000002 +#define c_FLAG 0x00000004 +#define C_FLAG 0x00000008 +#define d_FLAG 0x00000010 +#define m_FLAG 0x00000020 +#define p_FLAG 0x00000040 +#define q_FLAG 0x00000080 +#define r_FLAG 0x00000100 +#define s_FLAG 0x00000200 +#define S_FLAG 0x00000400 +#define t_FLAG 0x00000800 +#define T_FLAG 0x00001000 +#define u_FLAG 0x00002000 +#define v_FLAG 0x00004000 +#define x_FLAG 0x00008000 +#define z_FLAG 0x00010000 /* - * Where is the file contents from ? + * Member flags (ARFILE ar_flag) */ -#define F_ELFRAW 0x01 /* Mmaped via elf_raw() */ -#define F_MMAPED 0x02 /* Mmaped file contents */ -#define F_MALLOCED 0x04 /* Malloced file contents */ -#define F_CLASS32 0x08 /* This is ELFCLASS32 */ -#define F_CLASS64 0x10 /* This is ELFCLASS64 */ +#define F_ELFRAW 0x01 /* ar_contents data via elf_rawfile */ +#define F_CLASS32 0x02 /* ELFCLASS32 */ +#define F_CLASS64 0x04 /* ELFCLASS64 */ /* * Function prototypes */ -int qcmd(Cmd_info *); -int rcmd(Cmd_info *); -int dcmd(Cmd_info *); -int xcmd(Cmd_info *); -int pcmd(Cmd_info *); -int mcmd(Cmd_info *); -int tcmd(Cmd_info *); - -int getaf(Cmd_info *); -char *writefile(Cmd_info *cmd_info); -void error_message(int, ...); - -ARFILE *getfile(Cmd_info *); -ARFILE *newfile(); +Cmd_func qcmd; +Cmd_func rcmd; +Cmd_func dcmd; +Cmd_func xcmd; +Cmd_func pcmd; +Cmd_func mcmd; +Cmd_func tcmd; + +extern ARFILE *listhead, *listend; + +extern void establish_sighandler(void (*)()); +extern int getaf(Cmd_info *); +extern ARFILE *getfile(Cmd_info *); +extern ARFILE *newfile(void); +extern char *trim(char *); +extern void writefile(Cmd_info *cmd_info); -char *trim(char *); - -/* - * Error definitions - */ -#define MALLOC_ERROR 0 -#define USAGE_01_ERROR 1 -#define NOT_FOUND_01_ERROR 2 -#define USAGE_02_ERROR 3 -#define USAGE_03_ERROR 4 -#define USAGE_04_ERROR 5 -#define SYS_OPEN_ERROR 6 -#define SYS_READ_ERROR 7 -#define NOT_FOUND_02_ERROR 8 -#define PATHCONF_ERROR 9 -#define SYS_WRITE_ERROR 10 -#define LOCALTIME_ERROR 11 -#define USAGE_05_ERROR 12 -#define ELF_VERSION_ERROR 13 -#define NOT_ARCHIVE_ERROR 14 -#define USAGE_06_ERROR 15 -#define ELF_MALARCHIVE_ERROR 16 -#define SYS_LSEEK_ERROR 17 -#define NOT_FOUND_03_ERROR 18 -#define SYS_LSEEK_02_ERROR 19 -#define SYS_LSEEK_03_ERROR 20 -#define SYS_LSEEK_04_ERROR 21 -#define DEBUG_INFO_01_ERROR 22 -#define DEBUG_INFO_02_ERROR 23 -#define ELF_INTERNAL_RAND_ERROR 24 -#define ELF_BEGIN_01_ERROR 25 -#define DEBUG_INFO_03_ERROR 26 -#define ELF_BEGIN_02_ERROR 27 -#define ELF_BEGIN_03_ERROR 28 -#define ARCHIVE_IN_ARCHIVE_ERROR 29 -#define ARCHIVE_USAGE_ERROR 30 -#define INTERNAL_01_ERROR 31 -#define ELF_GETSCN_01_ERROR 32 -#define ELF_GETSCN_02_ERROR 33 -#define ELF_GETDATA_01_ERROR 34 -#define ELF_GETDATA_02_ERROR 35 -#define W_ELF_NO_DATA_01_ERROR 36 -#define W_ELF_NO_DATA_02_ERROR 37 -#define INTERNAL_02_ERROR 38 -#define DIAG_01_ERROR 39 -#define BER_MES_CREATE_ERROR 40 -#define SYS_CREATE_01_ERROR 41 -#define SYS_WRITE_02_ERROR 42 -#define BER_MES_WRITE_ERROR 43 -#define SYS_WRITE_03_ERROR 44 -#define SBROW_01_ERROR 45 -#define SBROW_02_ERROR 46 -#define SBROW_03_ERROR 47 -#define SYMTAB_01_ERROR 48 -#define SYMTAB_02_ERROR 49 -#define SYMTAB_03_ERROR 50 -#define SYMTAB_04_ERROR 51 -#define SYMTAB_05_ERROR 52 -#define SYMTAB_06_ERROR 53 -#define SYMTAB_07_ERROR 54 -#define ELF_01_ERROR 55 -#define ELF_02_ERROR 56 -#define OVERRIDE_WARN_ERROR 57 -#define SYS_WRITE_04_ERROR 58 -#define WARN_USER_ERROR 59 -#define ELF_RAWFILE_ERROR 60 #endif /* _INC_H */ diff --git a/usr/src/cmd/sgs/ar/common/extern.h b/usr/src/cmd/sgs/ar/common/lintsup.c index 4b1de6efd3..e456077e2e 100644 --- a/usr/src/cmd/sgs/ar/common/extern.h +++ b/usr/src/cmd/sgs/ar/common/lintsup.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,11 +18,20 @@ * * CDDL HEADER END */ -/* Copyright (c) 1988 AT&T */ -/* All Rights Reserved */ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + */ + +/* + * Supplemental Pseudo-code to get lint to consider these symbols used. + */ +#include <msg.h> -#pragma ident "%Z%%M% %I% %E% SMI" +#pragma error_messages(off, E_STATIC_UNUSED) -extern ARFILE *listhead, *listend; -extern int signum[]; +static void +foo(void) +{ + (void) _ar_msg((Msg)&__ar_msg[0]); +} diff --git a/usr/src/cmd/sgs/ar/common/main.c b/usr/src/cmd/sgs/ar/common/main.c index c5c94d062c..a452d403ff 100644 --- a/usr/src/cmd/sgs/ar/common/main.c +++ b/usr/src/cmd/sgs/ar/common/main.c @@ -22,52 +22,82 @@ /* All Rights Reserved */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. */ #include "inc.h" -#include "extern.h" - -static char *arnam; +#include "conv.h" /* - * Function prototypes + * Forward declarations */ static void setup(int, char **, Cmd_info *); -static void setcom(Cmd_info *, int (*)()); +static void setcom(Cmd_info *, Cmd_func); static void usage(void); static void sigexit(int sig); static int notfound(Cmd_info *); static void check_swap(); -#define OPTSTR ":a:b:i:vucsrdxtplmqVCTzM" +const char * +_ar_msg(Msg mid) +{ + return (gettext(MSG_ORIG(mid))); +} + -int -main(int argc, char **argv) +void +establish_sighandler(void (*handler)()) { + static const int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0}; int i; + + if (handler == SIG_IGN) { + /* Ignore all the specified signals */ + for (i = 0; signum[i]; i++) + (void) signal(signum[i], SIG_IGN); + + } else { + /* + * Set any signal that doesn't default to being ignored + * to our signal handler. + */ + for (i = 0; signum[i]; i++) + if (signal(signum[i], SIG_IGN) != SIG_IGN) + (void) signal(signum[i], handler); + } +} + +int +main(int argc, char **argv, char *envp[]) +{ int fd; Cmd_info *cmd_info; int ret; char *new = NULL; - char *data = NULL; - (void) setlocale(LC_ALL, ""); -#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ -#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ +#ifndef XPG4 + /* + * Check for a binary that better fits this architecture. + */ + (void) conv_check_native(argv, envp); #endif - (void) textdomain(TEXT_DOMAIN); - for (i = 0; signum[i]; i++) - if (signal(signum[i], SIG_IGN) != SIG_IGN) - (void) signal(signum[i], sigexit); + /* + * Establish locale. + */ + (void) setlocale(LC_ALL, MSG_ORIG(MSG_STR_EMPTY)); + (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS)); + + /* Allow a graceful exit up until we start to write an archive */ + establish_sighandler(sigexit); + /* * Initialize cmd_info */ cmd_info = (Cmd_info *)calloc(1, sizeof (Cmd_info)); if (cmd_info == NULL) { - error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0); + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), strerror(err)); exit(1); } @@ -80,10 +110,12 @@ main(int argc, char **argv) if (argv[1][0] != '-') { new = (char *)malloc(strlen(argv[1]) + 2); if (new == NULL) { - error_message(MALLOC_ERROR, PLAIN_ERROR, (char *)0); + int err = errno; + (void) fprintf(stderr, MSG_INTL(MSG_MALLOC), + strerror(err)); exit(1); } - (void) strcpy(new, "-"); + (void) strcpy(new, MSG_ORIG(MSG_STR_HYPHEN)); (void) strcat(new, argv[1]); argv[1] = new; } @@ -92,37 +124,33 @@ main(int argc, char **argv) /* * Check SWAP */ - if (opt_FLAG((cmd_info), z_FLAG)) + if (cmd_info->opt_flgs & z_FLAG) check_swap(); - if (cmd_info->comfun == 0) { - if (!(opt_FLAG((cmd_info), d_FLAG) || - opt_FLAG(cmd_info, r_FLAG) || - opt_FLAG(cmd_info, q_FLAG) || opt_FLAG(cmd_info, t_FLAG) || - opt_FLAG(cmd_info, p_FLAG) || opt_FLAG(cmd_info, m_FLAG) || - opt_FLAG(cmd_info, x_FLAG))) { - error_message(USAGE_01_ERROR, PLAIN_ERROR, (char *)0); + if (cmd_info->comfun == NULL) { + if ((cmd_info->opt_flgs & (d_FLAG | r_FLAG | q_FLAG | + t_FLAG | p_FLAG | m_FLAG | x_FLAG)) == 0) { + (void) fprintf(stderr, MSG_INTL(MSG_USAGE_01)); exit(1); } } - cmd_info->modified = opt_FLAG(cmd_info, s_FLAG); + cmd_info->modified = (cmd_info->opt_flgs & s_FLAG); fd = getaf(cmd_info); if ((fd == -1) && - (opt_FLAG(cmd_info, d_FLAG) || opt_FLAG(cmd_info, t_FLAG) || - opt_FLAG(cmd_info, p_FLAG) || opt_FLAG(cmd_info, m_FLAG) || - opt_FLAG(cmd_info, x_FLAG) || - (opt_FLAG(cmd_info, r_FLAG) && (opt_FLAG(cmd_info, a_FLAG) || - opt_FLAG(cmd_info, b_FLAG))))) { - error_message(NOT_FOUND_01_ERROR, - PLAIN_ERROR, (char *)0, arnam); + (cmd_info->opt_flgs & + (d_FLAG | m_FLAG | p_FLAG | t_FLAG | x_FLAG)) || + ((cmd_info->opt_flgs & r_FLAG) && + (cmd_info->opt_flgs & (a_FLAG | b_FLAG)))) { + (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_AR), + cmd_info->arnam); exit(1); } (*cmd_info->comfun)(cmd_info); if (cmd_info->modified) { - data = writefile(cmd_info); + writefile(cmd_info); } else (void) close(fd); @@ -131,10 +159,9 @@ main(int argc, char **argv) /* * Check SWAP */ - if (opt_FLAG((cmd_info), z_FLAG)) + if (cmd_info->opt_flgs & z_FLAG) check_swap(); - free(data); free(new); free(cmd_info); return (ret); @@ -142,7 +169,7 @@ main(int argc, char **argv) } /* - * Option hadning function. + * Option handing function. * Using getopt(), following xcu4 convention. */ static void @@ -152,7 +179,7 @@ setup(int argc, char *argv[], Cmd_info *cmd_info) int c; int usage_err = 0; - while ((c = getopt(argc, argv, OPTSTR)) != -1) { + while ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) { switch (c) { case 'a': /* position after named archive member file */ cmd_info->opt_flgs |= a_FLAG; @@ -174,8 +201,7 @@ setup(int argc, char *argv[], Cmd_info *cmd_info) setcom(cmd_info, dcmd); cmd_info->opt_flgs |= d_FLAG; break; - case 'l': /* temporary directory */ - cmd_info->opt_flgs |= l_FLAG; + case 'l': /* ignored */ break; case 'm': /* @@ -213,6 +239,9 @@ setup(int argc, char *argv[], Cmd_info *cmd_info) case 's': /* force symbol table regeneration */ cmd_info->opt_flgs |= s_FLAG; break; + case 'S': /* Build SYM64 symbol table */ + cmd_info->opt_flgs |= S_FLAG; + break; case 't': /* * key operation: @@ -244,29 +273,33 @@ setup(int argc, char *argv[], Cmd_info *cmd_info) * adjust command line access accounting */ if (Vflag == 0) { - (void) fprintf(stderr, "ar: %s %s\n", + (void) fprintf(stderr, + MSG_ORIG(MSG_FMT_VERSION), (const char *)SGU_PKG, (const char *)SGU_REL); Vflag++; } break; case 'C': - cmd_info->OPT_flgs |= C_FLAG; + cmd_info->opt_flgs |= C_FLAG; break; case 'M': - cmd_info->OPT_flgs |= M_FLAG; + /* + * -M was an original undocumented AT&T feature that + * would force the use of mmap() instead of read() + * for pulling file data into the process before + * writing it to the archive. Ignored. + */ break; case 'T': - cmd_info->OPT_flgs |= T_FLAG; + cmd_info->opt_flgs |= T_FLAG; break; case ':': - error_message(USAGE_02_ERROR, - PLAIN_ERROR, (char *)0, optopt); + (void) fprintf(stderr, MSG_INTL(MSG_USAGE_02), optopt); usage_err++; break; case '?': - error_message(USAGE_03_ERROR, - PLAIN_ERROR, (char *)0, optopt); + (void) fprintf(stderr, MSG_INTL(MSG_USAGE_03), optopt); usage_err++; break; } @@ -275,7 +308,7 @@ setup(int argc, char *argv[], Cmd_info *cmd_info) if (usage_err || argc - optind < 1) usage(); - cmd_info->arnam = arnam = argv[optind]; + cmd_info->arnam = argv[optind]; cmd_info->namv = &argv[optind+1]; cmd_info->namc = argc - optind - 1; } @@ -286,10 +319,10 @@ setup(int argc, char *argv[], Cmd_info *cmd_info) * Check that only one key is indicated. */ static void -setcom(Cmd_info *cmd_info, int (*fun)()) +setcom(Cmd_info *cmd_info, Cmd_func *fun) { if (cmd_info->comfun != 0) { - error_message(USAGE_04_ERROR, PLAIN_ERROR, (char *)0); + (void) fprintf(stderr, MSG_INTL(MSG_USAGE_04)); exit(1); } cmd_info->comfun = fun; @@ -298,14 +331,7 @@ setcom(Cmd_info *cmd_info, int (*fun)()) static void usage(void) { - (void) fprintf(stderr, gettext( -"usage: ar -d[-vV] archive file ...\n" -" ar -m[-abivV] [posname] archive file ...\n" -" ar -p[-vV][-s] archive [file ...]\n" -" ar -q[-cuvV] [-abi] [posname] [file ...]\n" -" ar -r[-cuvV] [-abi] [posname] [file ...]\n" -" ar -t[-vV][-s] archive [file ...]\n" -" ar -x[-vV][-sCT] archive [file ...]\n")); + (void) fprintf(stderr, MSG_INTL(MSG_USAGE)); exit(1); } @@ -326,8 +352,8 @@ notfound(Cmd_info *cmd_info) n = 0; for (i = 0; i < cmd_info->namc; i++) if (cmd_info->namv[i]) { - error_message(NOT_FOUND_03_ERROR, - PLAIN_ERROR, (char *)0, cmd_info->namv[i]); + (void) fprintf(stderr, MSG_INTL(MSG_NOT_FOUND_FILE), + cmd_info->namv[i]); n++; } return (n); @@ -339,5 +365,5 @@ notfound(Cmd_info *cmd_info) static void check_swap(void) { - (void) system("/usr/sbin/swap -s"); + (void) system(MSG_ORIG(MSG_CMD_SWAP)); } diff --git a/usr/src/cmd/sgs/ar/common/message.c b/usr/src/cmd/sgs/ar/common/message.c deleted file mode 100644 index 38232e45f9..0000000000 --- a/usr/src/cmd/sgs/ar/common/message.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "inc.h" - -static const char *msg[] = { -/* MALLOC_ERROR */ -"ar: could not allocate memory.\n", -/* USAGE_01_ERROR */ -"ar: one of [drqtpmx] must be specified\n", -/* NOT_FOUND_01_ERROR */ -"ar: archive, %s, not found\n", -/* USAGE_02_ERROR */ -"ar: -%c requires an operand\n", -/* USAGE_03_ERROR */ -"ar: bad option `%c'\n", -/* USAGE_04_ERROR */ -"ar: only one of [drqtpmx] allowed\n", -/* SYS_OPEN_ERROR */ -"ar: cannot open %s\n", -/* SYS_READ_ERROR */ -"ar: cannot read %s\n", -/* NOT_FOUND_02_ERROR */ -"ar: posname, %s, not found\n", -/* PATHCONF_ERROR */ -"ar: -T failed to calculate file name length.\n", -/* SYS_WRITE_ERROR */ -"ar: %s: cannot write\n", -/* LOCALTIME_ERROR */ -"ar: don't have enough space to store the date\n", -/* USAGE_05_ERROR */ -"ar: abi not allowed with q\n", -/* ELF_VERSION_ERROR */ -"ar: libelf.a out of date\n", -/* NOT_ARCHIVE_ERROR */ -"ar: %s not in archive format\n", -/* USAGE_06_ERROR */ -"ar: %s taken as mandatory 'posname' with keys 'abi'\n", -/* ELF_MALARCHIVE_ERROR */ -"ar: %s: malformed archive (at %ld)\n", -/* SYS_LSEEK_ERROR */ -"ar: cannot lseek\n", -/* NOT_FOUND_03_ERROR */ -"ar: %s not found\n", -/* SYS_LSEEK_02_ERROR */ -"ar: lseek(current) errno=%d\n", -/* SYS_LSEEK_03_ERROR */ -"ar: lseek(f->offset) errno=%d\n", -/* SYS_LSEEK_04_ERROR */ -"ar: Problem seeking\n", -/* DEBUG_INFO_01_ERROR */ -"ar: currentloc %d intendedloc %d resultingloc %d\n", -/* DEBUG_INFO_02_ERROR */ -"ar: ar_name '%s' longname '%s'\n", -/* ELF_INTERNAL_RAND_ERROR */ -"ar: internal or system error; archive file has been scribbled\n", -/* ELF_BEGIN_01_ERROR */ -"ar: archive is corrupted/possible end-of-archive\n", -/* DEBUG_INFO_03_ERROR */ -"ar: can not find member'%s' at offset 0x%x\n", -/* ELF_BEGIN_02_ERROR */ -"ar: cannot elf_begin() %s.\n", -/* ELF_BEGIN_03_ERROR */ -"ar: cannot elf_begin().\n", -/* ARCHIVE_IN_ARCHIVE_ERROR */ -"ar: %s is in archive format - embedded archives are not allowed\n", -/* ARCHIVE_USAGE_ERROR */ -"ar: embedded archives are not allowed.\n", -/* INTERNAL_01_ERROR */ -"ar: internal error - cannot tell whether file is included in archive or not\n", -/* ELF_GETSCN_01_ERROR */ -"ar: %s has no section header or bad elf format.\n", -/* ELF_GETSCN_02_ERROR */ -"ar: no section header or bad elf format.\n", -/* ELF_GETDATA_01_ERROR */ -"ar: %s has bad elf format.\n", -/* ELF_GETDATA_02_ERROR */ -"ar: bad elf format.\n", -/* W_ELF_NO_DATA_01_ERROR */ -"ar: %s has no data in section header table.\n", -/* W_ELF_NO_DATA_02_ERROR */ -"ar: No data in section header table.\n", -/* INTERNAL_02_ERROR */ -"ar: internal header generation error\n", -/* DIAG_01_ERROR */ -"ar: diagnosis: ERRNO=%d\n", -/* BER_MES_CREATE_ERROR */ -"ar: creating %s\n", -/* SYS_CREATE_01_ERROR */ -"ar: cannot create %s\n", -/* SYS_WRITE_02_ERROR */ -"ar: cannot write %s\n", -/* BER_MES_WRITE_ERROR */ -"ar: writing %s\n", -/* SYS_WRITE_03_ERROR */ -"ar: cannot write archive\n", -/* SBROW_01_ERROR */ -"ar: No data in stab table.\n", -/* SBROW_02_ERROR */ -"ar: No data in stab string table.\n", -/* SBROW_03_ERROR */ -"ar: No data in stab table - size is 0\n", -/* SYMTAB_01_ERROR */ -"ar: Symbol table entry size is 0!\n", -/* SYMTAB_02_ERROR */ -"ar: %s has no string table for symbol names\n", -/* SYMTAB_03_ERROR */ -"ar: No string table for symbol names\n", -/* SYMTAB_04_ERROR */ -"ar: %s has no data in string table\n", -/* SYMTAB_05_ERROR */ -"ar: No data in string table\n", -/* SYMTAB_06_ERROR */ -"ar: %s has no data in string table - size is 0\n", -/* SYMTAB_07_ERROR */ -"ar: No data in string table - size is 0\n", -/* ELF_01_ERROR */ -"ar: %s caused libelf error: %s\n", -/* ELF_02_ERROR */ -"ar: libelf error: %s\n", -/* OVERRIDE_WARN_ERROR */ -"ar: %s already exists. Will not be extracted\n", -/* SYS_WRITE_04_ERROR */ -"ar: writing to %s failed.\n", -/* WARN_USER_ERROR */ -"\tThe original archive is destroyed.\n", -/* ELF_RAWFILE_ERROR */ -"ar: elf_rawfile() failed.\n", -}; - -void -error_message(int args, ...) -{ - int mes = args; - char *message = gettext((char *)msg[mes]); - int flag; - char *sys_mes; - va_list ap; - va_start(ap, args); - - flag = va_arg(ap, int); - sys_mes = va_arg(ap, char *); - - switch (mes) { - case MALLOC_ERROR: - case USAGE_01_ERROR: - case USAGE_04_ERROR: - case PATHCONF_ERROR: - case LOCALTIME_ERROR: - case USAGE_05_ERROR: - case ARCHIVE_USAGE_ERROR: - case INTERNAL_01_ERROR: - case INTERNAL_02_ERROR: - case SBROW_01_ERROR: - case SBROW_02_ERROR: - case SBROW_03_ERROR: - case SYMTAB_01_ERROR: - case SYMTAB_03_ERROR: - case SYMTAB_05_ERROR: - case SYMTAB_07_ERROR: - /* LINTED: variable format */ - (void) fprintf(stderr, message); - break; - case ARCHIVE_IN_ARCHIVE_ERROR: - case NOT_FOUND_01_ERROR: - case NOT_FOUND_02_ERROR: - case NOT_FOUND_03_ERROR: - case NOT_ARCHIVE_ERROR: - case USAGE_06_ERROR: - case BER_MES_CREATE_ERROR: - case BER_MES_WRITE_ERROR: - case SYMTAB_02_ERROR: - case SYMTAB_04_ERROR: - case SYMTAB_06_ERROR: - case OVERRIDE_WARN_ERROR: - /* LINTED: variable format */ - (void) fprintf(stderr, message, va_arg(ap, char *)); - break; - case USAGE_02_ERROR: - case USAGE_03_ERROR: - /* LINTED: variable format */ - (void) fprintf(stderr, message, va_arg(ap, int)); - break; - case DIAG_01_ERROR: - /* LINTED: variable format */ - (void) fprintf(stderr, message, va_arg(ap, int)); - break; - case DEBUG_INFO_01_ERROR: { - int a1, a2, a3; - - a1 = va_arg(ap, int); - a2 = va_arg(ap, int); - a3 = va_arg(ap, int); - /* LINTED: variable format */ - (void) fprintf(stderr, message, a1, a2, a3); - break; - } - case DEBUG_INFO_02_ERROR: { - char *a1, *a2; - - a1 = va_arg(ap, char *); - a2 = va_arg(ap, char *); - /* LINTED: variable format */ - (void) fprintf(stderr, message, a1, a2); - break; - } - case DEBUG_INFO_03_ERROR: { - char *a1; - int a2; - - a1 = va_arg(ap, char *); - a2 = va_arg(ap, int); - /* LINTED: variable format */ - (void) fprintf(stderr, message, a1, a2); - break; - } - /* - * system call failure - */ - case SYS_LSEEK_ERROR: - case SYS_LSEEK_04_ERROR: - case SYS_WRITE_03_ERROR: - /* LINTED: variable format */ - (void) fprintf(stderr, message); - break; - case SYS_OPEN_ERROR: - case SYS_READ_ERROR: - case SYS_WRITE_ERROR: - case SYS_WRITE_02_ERROR: - case SYS_CREATE_01_ERROR: - /* LINTED: variable format */ - (void) fprintf(stderr, message, va_arg(ap, char *)); - break; - case SYS_LSEEK_02_ERROR: - case SYS_LSEEK_03_ERROR: - /* LINTED: variable format */ - (void) fprintf(stderr, message, va_arg(ap, int)); - break; - /* - * Elf related errors - */ - case ELF_VERSION_ERROR: - case ELF_INTERNAL_RAND_ERROR: - case ELF_BEGIN_02_ERROR: - case ELF_GETSCN_02_ERROR: - case ELF_GETDATA_02_ERROR: - case W_ELF_NO_DATA_02_ERROR: - case ELF_RAWFILE_ERROR: - /* LINTED: variable format */ - (void) fprintf(stderr, message); - break; - case ELF_BEGIN_01_ERROR: - case ELF_GETSCN_01_ERROR: - case ELF_GETDATA_01_ERROR: - case W_ELF_NO_DATA_01_ERROR: - case ELF_02_ERROR: - /* LINTED: variable format */ - (void) fprintf(stderr, message, va_arg(ap, char *)); - break; - case ELF_01_ERROR: { - char *a1, *a2; - - a1 = va_arg(ap, char *); - a2 = va_arg(ap, char *); - /* LINTED: variable format */ - (void) fprintf(stderr, message, a1, a2); - break; - } - case ELF_MALARCHIVE_ERROR: { - char *a1; - long a2; - - a1 = va_arg(ap, char *); - a2 = va_arg(ap, long); - /* LINTED: variable format */ - (void) fprintf(stderr, message, a1, a2); - break; - } - default: - (void) fprintf(stderr, "internal error: error_message(%d)\n", - mes); - exit(100); - } - - if (flag != PLAIN_ERROR) - (void) fprintf(stderr, "\t%s\n", sys_mes); - va_end(ap); -} diff --git a/usr/src/cmd/sgs/ar/i386/Makefile b/usr/src/cmd/sgs/ar/i386/Makefile index 0955bc546b..65c061d3b8 100644 --- a/usr/src/cmd/sgs/ar/i386/Makefile +++ b/usr/src/cmd/sgs/ar/i386/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,13 +19,17 @@ # CDDL HEADER END # # -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright (c) 1996 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. include ../Makefile.com .KEEP_STATE: +all: $(PROG) $(XPG4) + +install \ +package: all $(ROOTPROG) $(ROOTXPG4PROG) $(ROOTCCSBINLINK) + + + include ../Makefile.targ diff --git a/usr/src/cmd/sgs/ar/sparc/Makefile b/usr/src/cmd/sgs/ar/sparc/Makefile index 0955bc546b..eed82bcded 100644 --- a/usr/src/cmd/sgs/ar/sparc/Makefile +++ b/usr/src/cmd/sgs/ar/sparc/Makefile @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -20,13 +19,15 @@ # CDDL HEADER END # # -#ident "%Z%%M% %I% %E% SMI" -# -# Copyright (c) 1996 by Sun Microsystems, Inc. -# All rights reserved. +# Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. include ../Makefile.com .KEEP_STATE: +all: $(PROG) $(XPG4) + +install \ +package: all $(ROOTPROG) $(ROOTXPG4PROG) $(ROOTCCSBINLINK) + include ../Makefile.targ diff --git a/usr/src/cmd/sgs/ar/sparcv9/Makefile b/usr/src/cmd/sgs/ar/sparcv9/Makefile new file mode 100644 index 0000000000..dc3747cacb --- /dev/null +++ b/usr/src/cmd/sgs/ar/sparcv9/Makefile @@ -0,0 +1,43 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# + +include ../Makefile.com + +.KEEP_STATE: + +LLDFLAGS = $(LLDFLAGS64) +CONVLIBDIR = $(CONVLIBDIR64) +ELFLIBDIR = $(ELFLIBDIR64) +LDDBGLIBDIR = $(LDDBGLIBDIR64) +LINTFLAGS64 += $(VAR_LINTFLAGS64) + +ROOTPROG = $(ROOTPROG64) + +all: $(PROG) + +package \ +install: all $(ROOTPROG64) $(ROOTCCSBINLINK64) + +include ../Makefile.targ +include ../../Makefile.sub.64 diff --git a/usr/src/cmd/sgs/dump/common/dump.c b/usr/src/cmd/sgs/dump/common/dump.c index c542ed8171..665ee85e49 100644 --- a/usr/src/cmd/sgs/dump/common/dump.c +++ b/usr/src/cmd/sgs/dump/common/dump.c @@ -23,8 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. */ /* Get definitions for the relocation types supported. */ @@ -1808,7 +1807,8 @@ dump_ar_hdr(int fd, Elf *elf_file, char *filename) elf_errmsg(-1)); continue; } - if (strcmp(p_ar->ar_name, "/") == 0) { + if ((strcmp(p_ar->ar_name, "/") == 0) || + (strcmp(p_ar->ar_name, "/SYM64/") == 0)) { if (g_flag) ar_sym_read(elf_file, filename); } else if (strcmp(p_ar->ar_name, "//") == 0) { @@ -1893,8 +1893,7 @@ dump_ar_files(int fd, Elf *elf_file, char *filename) prog_name, filename, elf_errmsg(-1)); return; } - if ((strcmp(p_ar->ar_name, "/") == 0) || - (strcmp(p_ar->ar_name, "//") == 0)) { + if (p_ar->ar_name[0] == '/') { cmd = elf_next(arf); (void) elf_end(arf); continue; diff --git a/usr/src/cmd/sgs/dump/common/fcns.c b/usr/src/cmd/sgs/dump/common/fcns.c index 6d3a933991..2ce89728e3 100644 --- a/usr/src/cmd/sgs/dump/common/fcns.c +++ b/usr/src/cmd/sgs/dump/common/fcns.c @@ -23,15 +23,14 @@ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> -#include <libelf.h> +#include <_libelf.h> #include <limits.h> #include "conv.h" #include "dump.h" @@ -47,7 +46,8 @@ void ar_sym_read(Elf *elf, char *filename) { Elf_Arsym * arsym; - size_t cnt, ptr; + size_t cnt, ptr, is64; + const char *fmt; if ((arsym = elf_getarsym(elf, &ptr)) == NULL) { (void) fprintf(stderr, "%s: %s: no archive symbol table\n", @@ -55,18 +55,23 @@ ar_sym_read(Elf *elf, char *filename) return; } + is64 = (_elf_getarsymwordsize(elf) == 8); (void) printf("%s:\n", filename); if (!p_flag) { (void) printf(" **** ARCHIVE SYMBOL TABLE ****\n"); - (void) printf("%-8s %s\n\n", "Offset", "Name"); + if (is64) { + (void) printf("%-8s %s\n\n", "Offset", "Name"); + fmt = "%-16.16llx %s\n"; + } else { + (void) printf("%-8s %s\n\n", "Offset", "Name"); + fmt = "%-8.8llx %s\n"; + } } for (cnt = 0; cnt < ptr; cnt++, arsym++) { - if (arsym->as_off) { - /* LINTED */ - (void) printf("%-8.8x %s\n", (int)arsym->as_off, + if (arsym->as_off) + (void) printf(fmt, EC_XWORD(arsym->as_off), (arsym->as_name ? arsym->as_name : "")); - } } } diff --git a/usr/src/cmd/sgs/elfdump/common/elfdump.msg b/usr/src/cmd/sgs/elfdump/common/elfdump.msg index 5735d19b53..aada7e8e9f 100644 --- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg @@ -243,8 +243,10 @@ @ MSG_ELF_ERR_DATA "\tunable to obtain section data: shstrtab[%lld]\n" @ MSG_ELF_ERR_SCN "\tunable to obtain section header: section[%d]\n" @ MSG_ELF_ERR_SCNDATA "\tunable to obtain section data: section[%d]\n" -@ MSG_ARCHIVE_SYMTAB "\nSymbol Table: (archive)" -@ MSG_ARCHIVE_FIELDS " index offset member name and symbol" +@ MSG_ARCHIVE_SYMTAB_32 "\nSymbol Table: (archive, 32-bit offsets)" +@ MSG_ARCHIVE_SYMTAB_64 "\nSymbol Table: (archive, 64-bit offsets)" +@ MSG_ARCHIVE_FIELDS_32 " index offset member name and symbol" +@ MSG_ARCHIVE_FIELDS_64 " index offset member name and symbol" @ MSG_GOT_MULTIPLE "%s: multiple relocations against \ the same GOT entry ndx: %d addr: 0x%llx\n" @@ -356,8 +358,10 @@ @ MSG_FMT_INTEGER " %d" @ MSG_FMT_HASH_INFO "%10.10s %-10s %s" @ MSG_FMT_CHAIN_INFO "%10.10s %-10s %s" -@ MSG_FMT_ARSYM1 "%10.10s 0x%8.8x (%s):%s" -@ MSG_FMT_ARSYM2 "%10.10s 0x%8.8x" +@ MSG_FMT_ARSYM1_32 "%10.10s 0x%8.8llx (%s):%s" +@ MSG_FMT_ARSYM2_32 "%10.10s 0x%8.8llx" +@ MSG_FMT_ARSYM1_64 "%10.10s 0x%16.16llx (%s):%s" +@ MSG_FMT_ARSYM2_64 "%10.10s 0x%16.16llx" @ MSG_FMT_ARNAME "%s(%s)" @ MSG_FMT_NLSTR "\n%s:" @ MSG_FMT_NLSTRNL "\n%s:\n" diff --git a/usr/src/cmd/sgs/elfdump/common/main.c b/usr/src/cmd/sgs/elfdump/common/main.c index 76b6b02d5f..b35da26ecc 100644 --- a/usr/src/cmd/sgs/elfdump/common/main.c +++ b/usr/src/cmd/sgs/elfdump/common/main.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -32,7 +31,7 @@ #include <stdio.h> #include <stdlib.h> #include <ctype.h> -#include <libelf.h> +#include <_libelf.h> #include <link.h> #include <stdarg.h> #include <unistd.h> @@ -595,12 +594,29 @@ archive(const char *file, int fd, Elf *elf, uint_t flags, size_t cnt; char index[MAXNDXSIZE]; size_t offset = 0, _offset = 0; + const char *fmt_arsym1, *fmt_arsym2; /* - * Print out all the symbol entries. + * Print out all the symbol entries. The format width used + * corresponds to whether the archive symbol table is 32 + * or 64-bit. We see them via Elf_Arhdr as size_t values + * in either case with no information loss (see the comments + * in libelf/getarsym.c) so this is done simply to improve + * the user presentation. */ - dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB)); - dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS)); + if (_elf_getarsymwordsize(elf) == 8) { + dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_64)); + dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_64)); + + fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_64); + fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_64); + } else { + dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_32)); + dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_32)); + + fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_32); + fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_32); + } for (cnt = 0; cnt < ptr; cnt++, arsym++) { /* @@ -637,16 +653,15 @@ archive(const char *file, int fd, Elf *elf, uint_t flags, (void) snprintf(index, MAXNDXSIZE, MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt)); if (arsym->as_off) - dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM1), index, - /* LINTED */ - (int)arsym->as_off, arhdr ? arhdr->ar_name : + dbg_print(0, fmt_arsym1, index, + EC_XWORD(arsym->as_off), + arhdr ? arhdr->ar_name : MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ? demangle(arsym->as_name, flags) : MSG_INTL(MSG_STR_NULL))); else - dbg_print(0, MSG_ORIG(MSG_FMT_ARSYM2), index, - /* LINTED */ - (int)arsym->as_off); + dbg_print(0, fmt_arsym2, index, + EC_XWORD(arsym->as_off)); } if (_elf) diff --git a/usr/src/cmd/sgs/include/_libelf.h b/usr/src/cmd/sgs/include/_libelf.h index d7e8446721..790cc03627 100644 --- a/usr/src/cmd/sgs/include/_libelf.h +++ b/usr/src/cmd/sgs/include/_libelf.h @@ -44,6 +44,7 @@ typedef void _elf_execfill_func_t(void *, off_t, size_t); extern void _elf_execfill(_elf_execfill_func_t *); extern size_t _elf_getnextoff(Elf *); extern off_t _elf_getarhdrbase(Elf *); +extern size_t _elf_getarsymwordsize(Elf *); extern Elf64_Off _elf_getxoff(Elf_Data *); extern GElf_Xword _gelf_getdyndtflags_1(Elf *); extern int _elf_swap_wrimage(Elf *); diff --git a/usr/src/cmd/sgs/libelf/common/ar.c b/usr/src/cmd/sgs/libelf/common/ar.c index 9cfa68ad4f..38836fd1c7 100644 --- a/usr/src/cmd/sgs/libelf/common/ar.c +++ b/usr/src/cmd/sgs/libelf/common/ar.c @@ -20,8 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ /* @@ -29,8 +28,6 @@ * All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <ar.h> #include <stdlib.h> #include <memory.h> @@ -214,6 +211,11 @@ _elf_armem(Elf *elf, char *file, size_t fsz) m->m_name[1] = '\0'; else if (f->ar_name[1] == '/' && f->ar_name[2] == ' ') /* "//" */ m->m_name[2] = '\0'; + else if (f->ar_name[1] == 'S' && f->ar_name[2] == 'Y' && + f->ar_name[3] == 'M' && f->ar_name[4] == '6' && + f->ar_name[5] == '4' && f->ar_name[6] == '/' && + f->ar_name[7] == ' ') /* "/SYM64/" */ + m->m_name[7] = '\0'; else { /* "/?" */ m->m_hdr.ar_name = 0; /*LINTED*/ /* MSG_INTL(EFMT_ARUNKNM) */ @@ -241,8 +243,16 @@ _elf_armem(Elf *elf, char *file, size_t fsz) /* * Initial archive processing * An archive may have two special members. - * A symbol table, named /, must be first if it is present. - * A string table, named //, must precede all "normal" members. + * + * A symbol table, named / or /SYM64/, must be first if it is present. + * Both forms use the same layout differing in the width of the + * integer type used (32 or 64-bit respectively). + * + * A long name string table, named //, must precede all "normal" + * members. This string table is used to hold the names of archive + * members with names that are longer than 15 characters. It should not + * be confused with the string table found at the end of the symbol + * table, which is used to hold symbol names. * * This code "peeks" at headers but doesn't change them. * Later processing wants original headers. @@ -284,11 +294,12 @@ _elf_arinit(Elf * elf) } hdr = mem + sz; - if (a->ar_name[1] == ' ') { + if (a->ar_name[1] == ' ') { /* 32-bit symbol table */ elf->ed_arsym = mem; elf->ed_arsymsz = sz; elf->ed_arsymoff = (char *)a - base; } else if (a->ar_name[1] == '/' && a->ar_name[2] == ' ') { + /* Long name string table */ int k; if (_elf_vm(elf, (size_t)(mem - elf->ed_ident), @@ -314,6 +325,15 @@ _elf_arinit(Elf * elf) ++mem; } *(mem - 1) = '\0'; + } else if (a->ar_name[1] == 'S' && a->ar_name[2] == 'Y' && + a->ar_name[3] == 'M' && a->ar_name[4] == '6' && + a->ar_name[5] == '4' && a->ar_name[6] == '/' && + a->ar_name[7] == ' ') { + /* 64-bit symbol table */ + elf->ed_arsym = mem; + elf->ed_arsymsz = sz; + elf->ed_arsymoff = (char *)a - base; + elf->ed_myflags |= EDF_ARSYM64; } else { return; } diff --git a/usr/src/cmd/sgs/libelf/common/decl.h b/usr/src/cmd/sgs/libelf/common/decl.h index f293b14c42..613bfbba41 100644 --- a/usr/src/cmd/sgs/libelf/common/decl.h +++ b/usr/src/cmd/sgs/libelf/common/decl.h @@ -23,8 +23,7 @@ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _DECL_H @@ -391,6 +390,7 @@ NOTE(RWLOCK_COVERS_LOCKS(Elf::ed_rwlock, Elf_Scn::s_mutex)) #define EDF_MPROTECT 0x400 /* applies to slideable archives */ #define EDF_IMALLOC 0x800 /* wrimage dynamically allocated */ #define EDF_WRALLOC 0x1000 /* wrimage is to by dyn allocated */ +#define EDF_ARSYM64 0x2000 /* archive symbol table is 64-bit format */ typedef enum diff --git a/usr/src/cmd/sgs/libelf/common/getarsym.c b/usr/src/cmd/sgs/libelf/common/getarsym.c index 0163ef06ae..9431d75aa1 100644 --- a/usr/src/cmd/sgs/libelf/common/getarsym.c +++ b/usr/src/cmd/sgs/libelf/common/getarsym.c @@ -20,15 +20,12 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdlib.h> #include <errno.h> #include <libelf.h> @@ -38,40 +35,86 @@ /* * Convert archive symbol table to memory format - * This takes a pointer to file's archive symbol table, - * alignment unconstrained. Returns null terminated - * vector of Elf_Arsym structures. * - * Symbol table is the following: - * # offsets 4-byte word - * offset[0...] 4-byte word each + * This takes a pointer to file's archive symbol table, alignment + * unconstrained. Returns null terminated vector of Elf_Arsym + * structures. Elf_Arsym uses size_t to represent offsets, which + * will be 32-bit in 32-bit versions, and 64-bits otherwise. + * + * There are two forms of archive symbol table, the original 32-bit + * form, and a 64-bit form originally found in IRIX64. The two formats + * differ only in the width of the integer word: + * + * # offsets 4/8-byte word + * offset[0...] 4/8-byte word each * strings null-terminated, for offset[x] + * + * By default, the 64-bit form is only used when the archive exceeds + * the limits of 32-bits (4GB) in size. However, this is not required, + * and the ar -S option can be used to create a 64-bit symbol table in + * an archive that is under 4GB. + * + * Both 32 and 64-bit versions of libelf can read the 32-bit format + * without loss of information. Similarly, a 64-bit version of libelf + * will have no problem reading a 64-bit symbol table. This leaves the + * case where a 32-bit libelf reads a 64-bit symbol table, which requires + * some explanation. The offsets in a 64-bit symbol table will have zeros + * in the upper half of the words until the size of the archive exceeds 4GB. + * However, 32-bit libelf is unable to read any files larger than 2GB + * (see comments in update.c). As such, any archive that the 32-bit version + * of this code will encounter will be under 4GB in size. The upper 4 + * bytes of each word will be zero, and can be safely ignored. */ -#define get4(p) ((((((p[0]<<8)+p[1])<<8)+p[2])<<8)+p[3]) - +/* + * Offsets in archive headers are written in MSB (large endian) order + * on all platforms, regardless of native byte order. These macros read + * 4 and 8 byte values from unaligned memory. + * + * note: + * - The get8() macro for 32-bit code can ignore the first 4 bytes of + * of the word, because they are known to be 0. + * + * - The inner most value in these macros is cast to an unsigned integer + * of the final width in order to prevent the C comilier from doing + * unwanted sign extension when the topmost bit of a byte is set. + */ +#define get4(p) (((((((uint32_t)p[0]<<8)+p[1])<<8)+p[2])<<8)+p[3]) -static Elf_Void *arsym _((Byte *, size_t, size_t *)); +#ifdef _LP64 +#define get8(p) (((((((((((((((uint64_t)p[0]<<8)+p[1])<<8)+p[2])<<8)+ \ + p[3])<<8)+p[4])<<8)+p[5])<<8)+p[6])<<8)+p[7]) +#else +#define get8(p) (((((((uint64_t)p[4]<<8)+p[5])<<8)+p[6])<<8)+p[7]) +#endif -Elf_Void * -arsym(Byte *off, size_t sz, size_t *e) +static Elf_Void * +arsym(Byte *off, size_t sz, size_t *e, int is64) { char *endstr = (char *)off + sz; register char *str; Byte *endoff; Elf_Void *oas; + size_t eltsize = is64 ? 8 : 4; { register size_t n; - if (sz < 4 || (sz - 4) / 4 < (n = get4(off))) { - _elf_seterr(EFMT_ARSYMSZ, 0); - return (0); + if (is64) { + if (sz < 8 || (sz - 8) / 8 < (n = get8(off))) { + _elf_seterr(EFMT_ARSYMSZ, 0); + return (0); + } + } else { + if (sz < 4 || (sz - 4) / 4 < (n = get4(off))) { + _elf_seterr(EFMT_ARSYMSZ, 0); + return (0); + } } - off += 4; - endoff = off + n * 4; + off += eltsize; + endoff = off + n * eltsize; /* * string table must be present, null terminated @@ -103,11 +146,14 @@ arsym(Byte *off, size_t sz, size_t *e) free(oas); return (0); } - as->as_off = get4(off); + if (is64) + as->as_off = get8(off); + else + as->as_off = get4(off); as->as_name = str; as->as_hash = elf_hash(str); ++as; - off += 4; + off += eltsize; while (*str++ != '\0') /* LINTED */ ; @@ -126,10 +172,11 @@ elf_getarsym(Elf *elf, size_t *ptr) Byte *as; size_t sz; Elf_Arsym *rc; + int is64; if (ptr != 0) *ptr = 0; - if (elf == 0) + if (elf == NULL) return (0); ELFRLOCK(elf); if (elf->ed_kind != ELF_K_AR) { @@ -148,6 +195,8 @@ elf_getarsym(Elf *elf, size_t *ptr) /* LINTED */ return ((Elf_Arsym *)as); } + is64 = (elf->ed_myflags & EDF_ARSYM64) != 0; + /* * We're gonna need a write lock. */ @@ -159,7 +208,7 @@ elf_getarsym(Elf *elf, size_t *ptr) ELFUNLOCK(elf); return (0); } - if ((elf->ed_arsym = arsym(as, sz, &elf->ed_arsymsz)) == 0) { + if ((elf->ed_arsym = arsym(as, sz, &elf->ed_arsymsz, is64)) == 0) { ELFUNLOCK(elf); return (0); } @@ -170,3 +219,32 @@ elf_getarsym(Elf *elf, size_t *ptr) ELFUNLOCK(elf); return (rc); } + +/* + * Private function to obtain the value sizeof() would return + * for a word from the symbol table from the given archive. Normally, + * this is an unimportant implementation detail hidden within + * elf_getarsym(). However, it is useful to elfdump for formatting the + * output correctly, and for the file command. + * + * exit: + * Returns 4 (32-bit) or 8 (64-bit) if a symbol table is present. + * Returns 0 in all other cases. + */ +size_t +_elf_getarsymwordsize(Elf *elf) +{ + size_t size; + + if (elf == NULL) + return (0); + + ELFRLOCK(elf); + if ((elf->ed_kind == ELF_K_AR) && (elf->ed_arsym != 0)) + size = (elf->ed_myflags & EDF_ARSYM64) ? 8 : 4; + else + size = 0; + ELFUNLOCK(elf); + + return (size); +} diff --git a/usr/src/cmd/sgs/libelf/common/llib-lelf b/usr/src/cmd/sgs/libelf/common/llib-lelf index 19f99fcc47..f525dde839 100644 --- a/usr/src/cmd/sgs/libelf/common/llib-lelf +++ b/usr/src/cmd/sgs/libelf/common/llib-lelf @@ -143,6 +143,7 @@ int nlist(const char *, struct nlist *); */ extern void _elf_execfill(_elf_execfill_func_t *); extern off_t _elf_getarhdrbase(Elf *); +extern size_t _elf_getarsymwordsize(Elf *); extern size_t _elf_getnextoff(Elf *); Elf64_Off _elf_getxoff(Elf_Data *); int _elf_swap_wrimage(Elf *); diff --git a/usr/src/cmd/sgs/libelf/common/mapfile-vers b/usr/src/cmd/sgs/libelf/common/mapfile-vers index 6c46234e31..35f397f126 100644 --- a/usr/src/cmd/sgs/libelf/common/mapfile-vers +++ b/usr/src/cmd/sgs/libelf/common/mapfile-vers @@ -163,6 +163,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { global: _elf_execfill; _elf_getarhdrbase; + _elf_getarsymwordsize; _elf_getnextoff; _elf_getxoff; _elf_outsync; diff --git a/usr/src/cmd/sgs/mcs/common/file.c b/usr/src/cmd/sgs/mcs/common/file.c index 2d9eca56b9..7fbf0af943 100644 --- a/usr/src/cmd/sgs/mcs/common/file.c +++ b/usr/src/cmd/sgs/mcs/common/file.c @@ -23,8 +23,7 @@ * Copyright (c) 1988 AT&T * All Rights Reserved * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <errno.h> @@ -1338,7 +1337,8 @@ copy_non_elf_to_temp_ar( char mem_header_buf[sizeof (struct ar_hdr) + 1]; char *file_buf; - if (strcmp(mem_header->ar_name, "/") != 0) { + if ((strcmp(mem_header->ar_name, "/") != 0) && + (strcmp(mem_header->ar_name, "/SYM64/") != 0)) { (void) sprintf(mem_header_buf, FORMAT, mem_header->ar_rawname, mem_header->ar_date, (unsigned)mem_header->ar_uid, (unsigned)mem_header->ar_gid, (unsigned)mem_header->ar_mode, diff --git a/usr/src/cmd/sgs/messages/Makefile.com b/usr/src/cmd/sgs/messages/Makefile.com index 97b2c0c7e3..8a57a7094b 100644 --- a/usr/src/cmd/sgs/messages/Makefile.com +++ b/usr/src/cmd/sgs/messages/Makefile.com @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. # # cmd/sgs/messages/Makefile.com @@ -44,7 +43,8 @@ MSGFMT= msgfmt POFILES= ld ldd libld liblddbg \ librtld rtld libelf ldprof \ libcrle crle moe pvs \ - elfdump elfedit elfwrap lari + elfdump elfedit elfwrap lari \ + ar # These message files are generated as a side effect of generating the # elfedit messages. Otherwise they are the same thing as POFILES diff --git a/usr/src/cmd/sgs/messages/sgs.ident b/usr/src/cmd/sgs/messages/sgs.ident index eaee78733e..9aa369693f 100644 --- a/usr/src/cmd/sgs/messages/sgs.ident +++ b/usr/src/cmd/sgs/messages/sgs.ident @@ -1,6 +1,5 @@ # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. # # CDDL HEADER START # @@ -58,3 +57,4 @@ MSG_ID_ELFEDIT_STR 27 SUNW_OST_SGS /* str: */ MSG_ID_ELFEDIT_SYM 27 SUNW_OST_SGS /* sym: */ MSG_ID_ELFEDIT_SYMINFO 27 SUNW_OST_SGS /* syminfo: */ MSG_ID_ELFWRAP 28 SUNW_OST_SGS /* sgs/elfwrap */ +MSG_ID_AR 29 SUNW_OST_SGS /* sgs/ar */ diff --git a/usr/src/cmd/sgs/nm/common/nm.c b/usr/src/cmd/sgs/nm/common/nm.c index d8d1c7cddd..258bd9fd67 100644 --- a/usr/src/cmd/sgs/nm/common/nm.c +++ b/usr/src/cmd/sgs/nm/common/nm.c @@ -609,7 +609,7 @@ print_ar_files(int fd, Elf * elf_file, char *filename) prog_name, filename, elf_errmsg(-1)); return; } - if ((int)strncmp(p_ar->ar_name, "/", 1) == 0) { + if (p_ar->ar_name[0] == '/') { cmd = elf_next(arf); (void) elf_end(arf); continue; diff --git a/usr/src/cmd/sgs/nm/i386/Makefile b/usr/src/cmd/sgs/nm/i386/Makefile index 3a4112fb12..6653481253 100644 --- a/usr/src/cmd/sgs/nm/i386/Makefile +++ b/usr/src/cmd/sgs/nm/i386/Makefile @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. # # cmd/sgs/nm/i386/Makefile # @@ -53,13 +52,6 @@ objs.xpg4/%.o := CPPFLAGS += -DXPG4 $(DEMOBJS):= DEFLIST = -DELF_OBJ -# Building SUNWonld results in a call to the `package' target. Requirements -# needed to run this application on older releases are established: -# i18n support requires libintl.so.1 prior to 2.6 - -package := LDLIBS += /usr/lib/libintl.so.1 - - objs.xpg4/%.o: ../common/%.c $(COMPILE.c) -o $@ $< diff --git a/usr/src/cmd/sgs/packages/Makefile b/usr/src/cmd/sgs/packages/Makefile index f990d328a9..2a70f64d62 100644 --- a/usr/src/cmd/sgs/packages/Makefile +++ b/usr/src/cmd/sgs/packages/Makefile @@ -20,8 +20,7 @@ # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. # include $(SRC)/Makefile.master @@ -76,6 +75,7 @@ PKGDIRS= ../libcrle \ ../elfedit \ ../elfedit/modules \ ../elfwrap \ + ../ar \ ../crle \ ../dump \ ../lari \ diff --git a/usr/src/cmd/sgs/packages/Makefile.com b/usr/src/cmd/sgs/packages/Makefile.com index 4512a20777..714a8f010f 100644 --- a/usr/src/cmd/sgs/packages/Makefile.com +++ b/usr/src/cmd/sgs/packages/Makefile.com @@ -19,8 +19,7 @@ # CDDL HEADER END # # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. # include $(SRC)/Makefile.master @@ -28,7 +27,7 @@ include $(SRC)/Makefile.master LINTLOG= ../lint.$(MACH).log PKGARCHIVE= . -DATAFILES= admin copyright prototype_com prototype_$(MACH) postinstall \ +DATAFILES= copyright prototype_com prototype_$(MACH) postinstall \ preremove depend checkinstall README= SUNWonld-README FILES= $(DATAFILES) pkginfo diff --git a/usr/src/cmd/sgs/packages/Makefile.lint b/usr/src/cmd/sgs/packages/Makefile.lint index a5122dc95a..09db2eb0ed 100644 --- a/usr/src/cmd/sgs/packages/Makefile.lint +++ b/usr/src/cmd/sgs/packages/Makefile.lint @@ -20,10 +20,7 @@ # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" +# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. # # cmd/sgs/packages/Makefile.lint @@ -60,6 +57,7 @@ LINTLDIRS= ../libld \ ../elfedit \ ../elfedit/modules \ ../elfwrap \ + ../ar \ ../crle \ ../dump \ ../ld \ diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README index eaeb3372ff..74e1fb4c7a 100644 --- a/usr/src/cmd/sgs/packages/common/SUNWonld-README +++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README @@ -1601,3 +1601,5 @@ Bugid Risk Synopsis 6962343 sgsmsg should use mkstemp() for temporary file creation 6965723 libsoftcrypto symbol capabilities rely on compiler generated capabilities - gcc failure (link-editor components only) +6952219 ld support for archives larger than 2 GB (D, P) + PSARC/2010/224 Support for archives larger than 2 GB diff --git a/usr/src/cmd/sgs/packages/common/prototype_com b/usr/src/cmd/sgs/packages/common/prototype_com index 76bda331a6..b16d52eba4 100644 --- a/usr/src/cmd/sgs/packages/common/prototype_com +++ b/usr/src/cmd/sgs/packages/common/prototype_com @@ -20,10 +20,7 @@ # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" +# Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. # # This required package information file contains a list of package contents. # The 'pkgmk' command uses this file to identify the contents of a package @@ -62,6 +59,9 @@ f none $SGSDIR/lib/librtld.so.1=lib/librtld.so.1 755 root bin s none $SGSDIR/lib/librtld_db.so=librtld_db.so.1 f none $SGSDIR/lib/librtld_db.so.1=lib/librtld_db.so.1 755 root bin d none $SGSDIR/usr/bin 755 root bin +f none $SGSDIR/usr/bin/ar=usr/bin/ar 555 root bin +s none $SGSDIR/usr/ccs/bin/ar=../../bin/ar +f none $SGSDIR/usr/xpg4/bin/ar=usr/xpg4/bin/ar 0555 root bin f none $SGSDIR/usr/bin/crle=usr/bin/crle 555 root bin f none $SGSDIR/usr/bin/ldd=usr/bin/ldd 555 root bin f none $SGSDIR/usr/bin/moe=usr/bin/moe 555 root bin @@ -247,10 +247,6 @@ f none opt/SUNWonld/man/man1l/sgsmsg.1l 444 root bin #d none $SGSDIR/usr/share/lib 755 root bin #d none $SGSDIR/usr/share/lib/ccs 755 root bin -#f none $SGSDIR/usr/bin/ar=usr/bin/ar 555 root bin -#s none $SGSDIR/usr/ccs/bin/ar=../../bin/ar -#f none $SGSDIR/usr/xpg4/bin/ar=usr/xpg4/bin/ar 0555 root bin - #f none $SGSDIR/usr/bin/error=usr/bin/error 555 root bin #s none $SGSDIR/usr/ccs/bin/error=../../bin/error diff --git a/usr/src/cmd/sgs/packages/common/prototype_i386 b/usr/src/cmd/sgs/packages/common/prototype_i386 index 52b1ed359c..b17f7b4a46 100644 --- a/usr/src/cmd/sgs/packages/common/prototype_i386 +++ b/usr/src/cmd/sgs/packages/common/prototype_i386 @@ -20,10 +20,7 @@ # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" +# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. # # This required package information file contains a list of package contents. # The 'pkgmk' command uses this file to identify the contents of a package @@ -50,6 +47,8 @@ f none $SGSDIR/lib/amd64/librtld.so.1=lib/amd64/librtld.so.1 755 root bin f none $SGSDIR/lib/amd64/librtld_db.so.1=lib/amd64/librtld_db.so.1 755 root bin s none $SGSDIR/lib/amd64/librtld_db.so=librtld_db.so.1 d none $SGSDIR/usr/bin/amd64 755 root bin +f none $SGSDIR/usr/bin/amd64/ar=usr/bin/amd64/ar 555 root bin +s none $SGSDIR/usr/ccs/bin/amd64/ar=../../bin/amd64/ar f none $SGSDIR/usr/bin/amd64/crle=usr/bin/amd64/crle 555 root bin f none $SGSDIR/usr/bin/amd64/ldd=usr/bin/amd64/ldd 555 root bin f none $SGSDIR/usr/bin/amd64/moe=usr/bin/amd64/moe 555 root bin diff --git a/usr/src/cmd/sgs/packages/common/prototype_sparc b/usr/src/cmd/sgs/packages/common/prototype_sparc index cd676819c6..6f6e6f317c 100644 --- a/usr/src/cmd/sgs/packages/common/prototype_sparc +++ b/usr/src/cmd/sgs/packages/common/prototype_sparc @@ -20,10 +20,7 @@ # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" +# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. # # This required package information file contains a list of package contents. # The 'pkgmk' command uses this file to identify the contents of a package @@ -50,6 +47,8 @@ f none $SGSDIR/lib/sparcv9/librtld.so.1=lib/sparcv9/librtld.so.1 755 root bin f none $SGSDIR/lib/sparcv9/librtld_db.so.1=lib/sparcv9/librtld_db.so.1 755 root bin s none $SGSDIR/lib/sparcv9/librtld_db.so=librtld_db.so.1 d none $SGSDIR/usr/bin/sparcv9 755 root bin +f none $SGSDIR/usr/bin/sparcv9/ar=usr/bin/sparcv9/ar 555 root bin +s none $SGSDIR/usr/ccs/bin/sparcv9/ar=../../bin/sparcv9/ar f none $SGSDIR/usr/bin/sparcv9/crle=usr/bin/sparcv9/crle 555 root bin f none $SGSDIR/usr/bin/sparcv9/ldd=usr/bin/sparcv9/ldd 555 root bin f none $SGSDIR/usr/bin/sparcv9/moe=usr/bin/sparcv9/moe 555 root bin diff --git a/usr/src/pkg/manifests/developer-object-file.mf b/usr/src/pkg/manifests/developer-object-file.mf index 4b662ee421..a9d010062b 100644 --- a/usr/src/pkg/manifests/developer-object-file.mf +++ b/usr/src/pkg/manifests/developer-object-file.mf @@ -43,6 +43,7 @@ dir path=usr/lib/elfedit/$(ARCH64) dir path=usr/share group=sys dir path=usr/share/lib group=sys dir path=usr/share/lib/ccs +file path=usr/bin/$(ARCH64)/ar mode=0555 file path=usr/bin/$(ARCH64)/dump mode=0555 file path=usr/bin/$(ARCH64)/elfdump mode=0555 file path=usr/bin/$(ARCH64)/elfedit mode=0555 @@ -108,6 +109,7 @@ license cmd/backup/dump/THIRDPARTYLICENSE \ license=cmd/backup/dump/THIRDPARTYLICENSE license cr_Sun license=cr_Sun license lic_CDDL license=lic_CDDL +link path=usr/ccs/bin/$(ARCH64)/ar target=../../../bin/$(ARCH64)/ar link path=usr/ccs/bin/$(ARCH64)/dump target=../../../bin/$(ARCH64)/dump link path=usr/ccs/bin/$(ARCH64)/elfdump target=../../../bin/$(ARCH64)/elfdump link path=usr/ccs/bin/$(ARCH64)/mcs target=../../../bin/$(ARCH64)/mcs |
