diff options
Diffstat (limited to 'usr.bin/ar')
-rw-r--r-- | usr.bin/ar/Makefile | 17 | ||||
-rw-r--r-- | usr.bin/ar/acplex.l | 78 | ||||
-rw-r--r-- | usr.bin/ar/acpyacc.y | 662 | ||||
-rw-r--r-- | usr.bin/ar/ar.1 | 406 | ||||
-rw-r--r-- | usr.bin/ar/ar.c | 387 | ||||
-rw-r--r-- | usr.bin/ar/ar.h | 125 | ||||
-rw-r--r-- | usr.bin/ar/read.c | 204 | ||||
-rw-r--r-- | usr.bin/ar/util.c | 86 | ||||
-rw-r--r-- | usr.bin/ar/write.c | 879 |
9 files changed, 0 insertions, 2844 deletions
diff --git a/usr.bin/ar/Makefile b/usr.bin/ar/Makefile deleted file mode 100644 index 533f931..0000000 --- a/usr.bin/ar/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# $FreeBSD$ - -PROG= ar -SRCS= ar.c acplex.l acpyacc.y read.c util.c write.c y.tab.h - -WARNS?= 5 - -DPADD= ${LIBARCHIVE} ${LIBBZ2} ${LIBZ} ${LIBELF} -LDADD= -larchive -lbz2 -lz -lelf - -CFLAGS+=-I. -I${.CURDIR} - -NO_SHARED?= yes -LINKS= ${BINDIR}/ar ${BINDIR}/ranlib -MLINKS= ar.1 ranlib.1 - -.include <bsd.prog.mk> diff --git a/usr.bin/ar/acplex.l b/usr.bin/ar/acplex.l deleted file mode 100644 index 3186d17..0000000 --- a/usr.bin/ar/acplex.l +++ /dev/null @@ -1,78 +0,0 @@ -%{ -/*- - * Copyright (c) 2008 Kai Wang - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <err.h> -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <sysexits.h> - -#include "y.tab.h" - -#define YY_NO_UNPUT -int lineno = 1; - -int yylex(void); - -%} - -%option noyywrap - -%% - -ADDLIB|addlib { return (ADDLIB); } -ADDMOD|addmod { return (ADDMOD); } -CLEAR|clear { return (CLEAR); } -CREATE|create { return (CREATE); } -DELETE|delete { return (DELETE); } -DIRECTORY|directory { return (DIRECTORY); } -END|end { return (END); } -EXTRACT|extract { return (EXTRACT); } -LIST|list { return (LIST); } -OPEN|open { return (OPEN); } -REPLACE|replace { return (REPLACE); } -VERBOSE|verbose { return (VERBOSE); } -SAVE|save { return (SAVE); } -"(" { return (LP); } -")" { return (RP); } -"," { return (COMMA); } - -[-_A-Za-z0-9/:$.\\]+ { - yylval.str = strdup(yytext); - if (yylval.str == NULL) - errc(EX_SOFTWARE, errno, "strdup failed"); - return (FNAME); -} - -[ \t] /* whitespace */ -"*".* /* comment */ -";".* /* comment */ -"+\n" { lineno++; /* '+' is line continuation char */ } -"\n" { lineno++; return (EOL); } diff --git a/usr.bin/ar/acpyacc.y b/usr.bin/ar/acpyacc.y deleted file mode 100644 index bc25b62..0000000 --- a/usr.bin/ar/acpyacc.y +++ /dev/null @@ -1,662 +0,0 @@ -%{ -/*- - * Copyright (c) 2008 Kai Wang - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/mman.h> -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/stat.h> -#include <archive.h> -#include <archive_entry.h> -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sysexits.h> -#include <unistd.h> - -#include "ar.h" - -#define TEMPLATE "arscp.XXXXXXXX" - -struct list { - char *str; - struct list *next; -}; - - -extern int yylex(void); -extern int yyparse(void); - -static void yyerror(const char *); -static void arscp_addlib(char *archive, struct list *list); -static void arscp_addmod(struct list *list); -static void arscp_clear(void); -static int arscp_copy(int ifd, int ofd); -static void arscp_create(char *in, char *out); -static void arscp_delete(struct list *list); -static void arscp_dir(char *archive, struct list *list, char *rlt); -static void arscp_end(int eval); -static void arscp_extract(struct list *list); -static void arscp_free_argv(void); -static void arscp_free_mlist(struct list *list); -static void arscp_list(void); -static struct list *arscp_mlist(struct list *list, char *str); -static void arscp_mlist2argv(struct list *list); -static int arscp_mlist_len(struct list *list); -static void arscp_open(char *fname); -static void arscp_prompt(void); -static void arscp_replace(struct list *list); -static void arscp_save(void); -static int arscp_target_exist(void); - -extern int lineno; - -static struct bsdar *bsdar; -static char *target; -static char *tmpac; -static int interactive; -static int verbose; - -%} - -%token ADDLIB -%token ADDMOD -%token CLEAR -%token CREATE -%token DELETE -%token DIRECTORY -%token END -%token EXTRACT -%token LIST -%token OPEN -%token REPLACE -%token VERBOSE -%token SAVE -%token LP -%token RP -%token COMMA -%token EOL -%token <str> FNAME -%type <list> mod_list - -%union { - char *str; - struct list *list; -} - -%% - -begin - : { arscp_prompt(); } ar_script - ; - -ar_script - : cmd_list - | - ; - -mod_list - : FNAME { $$ = arscp_mlist(NULL, $1); } - | mod_list separator FNAME { $$ = arscp_mlist($1, $3); } - ; - -separator - : COMMA - | - ; - -cmd_list - : rawcmd - | cmd_list rawcmd - ; - -rawcmd - : cmd EOL { arscp_prompt(); } - ; - -cmd - : addlib_cmd - | addmod_cmd - | clear_cmd - | create_cmd - | delete_cmd - | directory_cmd - | end_cmd - | extract_cmd - | list_cmd - | open_cmd - | replace_cmd - | verbose_cmd - | save_cmd - | invalid_cmd - | empty_cmd - | error - ; - -addlib_cmd - : ADDLIB FNAME LP mod_list RP { arscp_addlib($2, $4); } - | ADDLIB FNAME { arscp_addlib($2, NULL); } - ; - -addmod_cmd - : ADDMOD mod_list { arscp_addmod($2); } - ; - -clear_cmd - : CLEAR { arscp_clear(); } - ; - -create_cmd - : CREATE FNAME { arscp_create(NULL, $2); } - ; - -delete_cmd - : DELETE mod_list { arscp_delete($2); } - ; - -directory_cmd - : DIRECTORY FNAME { arscp_dir($2, NULL, NULL); } - | DIRECTORY FNAME LP mod_list RP { arscp_dir($2, $4, NULL); } - | DIRECTORY FNAME LP mod_list RP FNAME { arscp_dir($2, $4, $6); } - ; - -end_cmd - : END { arscp_end(EX_OK); } - ; - -extract_cmd - : EXTRACT mod_list { arscp_extract($2); } - ; - -list_cmd - : LIST { arscp_list(); } - ; - -open_cmd - : OPEN FNAME { arscp_open($2); } - ; - -replace_cmd - : REPLACE mod_list { arscp_replace($2); } - ; - -save_cmd - : SAVE { arscp_save(); } - ; - -verbose_cmd - : VERBOSE { verbose = !verbose; } - ; - -empty_cmd - : - ; - -invalid_cmd - : FNAME { yyerror(NULL); } - ; - -%% - -/* ARGSUSED */ -static void -yyerror(const char *s) -{ - - (void) s; - printf("Syntax error in archive script, line %d\n", lineno); -} - -/* - * arscp_open first open an archive and check its validity. If the archive - * format is valid, it calls arscp_create to create a temporary copy of - * the archive. - */ -static void -arscp_open(char *fname) -{ - struct archive *a; - struct archive_entry *entry; - int r; - - if ((a = archive_read_new()) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_read_new failed"); - archive_read_support_compression_all(a); - archive_read_support_format_all(a); - AC(archive_read_open_file(a, fname, DEF_BLKSZ)); - if ((r = archive_read_next_header(a, &entry))) - bsdar_warnc(bsdar, 0, "%s", archive_error_string(a)); - AC(archive_read_close(a)); - AC(archive_read_finish(a)); - if (r != ARCHIVE_OK) - return; - arscp_create(fname, fname); -} - -/* - * Create archive. in != NULL indicate it's a OPEN cmd, and resulting - * archive is based on modification of an existing one. If in == NULL, - * we are in CREATE cmd and a new empty archive will be created. - */ -static void -arscp_create(char *in, char *out) -{ - struct archive *a; - int ifd, ofd; - - /* Delete previously created temporary archive, if any. */ - if (tmpac) { - if (unlink(tmpac) < 0) - bsdar_errc(bsdar, EX_IOERR, errno, "unlink failed"); - free(tmpac); - } - - tmpac = strdup(TEMPLATE); - if (tmpac == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed"); - if ((ofd = mkstemp(tmpac)) < 0) - bsdar_errc(bsdar, EX_IOERR, errno, "mkstemp failed"); - - if (in) { - /* - * Command OPEN creates a temporary copy of the - * input archive. - */ - if ((ifd = open(in, O_RDONLY)) < 0) { - bsdar_warnc(bsdar, errno, "open failed"); - return; - } - if (arscp_copy(ifd, ofd)) { - bsdar_warnc(bsdar, 0, "arscp_copy failed"); - return; - } - close(ifd); - close(ofd); - } else { - /* - * Command CREATE creates an "empty" archive. - * (archive with only global header) - */ - if ((a = archive_write_new()) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, 0, - "archive_write_new failed"); - archive_write_set_format_ar_svr4(a); - AC(archive_write_open_fd(a, ofd)); - AC(archive_write_close(a)); - AC(archive_write_finish(a)); - } - - /* Override previous target, if any. */ - if (target) - free(target); - - target = out; - bsdar->filename = tmpac; -} - -/* A file copying implementation using mmap. */ -static int -arscp_copy(int ifd, int ofd) -{ - struct stat sb; - char *buf, *p; - ssize_t w; - size_t bytes; - - if (fstat(ifd, &sb) < 0) { - bsdar_warnc(bsdar, errno, "fstate failed"); - return (1); - } - if ((p = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, ifd, - (off_t)0)) == MAP_FAILED) { - bsdar_warnc(bsdar, errno, "mmap failed"); - return (1); - } - for (buf = p, bytes = sb.st_size; bytes > 0; bytes -= w) { - w = write(ofd, buf, bytes); - if (w <= 0) { - bsdar_warnc(bsdar, errno, "write failed"); - break; - } - } - if (munmap(p, sb.st_size) < 0) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "munmap failed"); - if (bytes > 0) - return (1); - - return (0); -} - -/* - * Add all modules of archive to current archive, if list != NULL, - * only those modules speicifed in 'list' will be added. - */ -static void -arscp_addlib(char *archive, struct list *list) -{ - - if (!arscp_target_exist()) - return; - arscp_mlist2argv(list); - bsdar->addlib = archive; - ar_mode_A(bsdar); - arscp_free_argv(); - arscp_free_mlist(list); -} - -/* Add modules into current archive. */ -static void -arscp_addmod(struct list *list) -{ - - if (!arscp_target_exist()) - return; - arscp_mlist2argv(list); - ar_mode_q(bsdar); - arscp_free_argv(); - arscp_free_mlist(list); -} - -/* Delete modules from current archive. */ -static void -arscp_delete(struct list *list) -{ - - if (!arscp_target_exist()) - return; - arscp_mlist2argv(list); - ar_mode_d(bsdar); - arscp_free_argv(); - arscp_free_mlist(list); -} - -/* Extract modules from current archive. */ -static void -arscp_extract(struct list *list) -{ - - if (!arscp_target_exist()) - return; - arscp_mlist2argv(list); - ar_mode_x(bsdar); - arscp_free_argv(); - arscp_free_mlist(list); -} - -/* List modules of archive. (Simple Mode) */ -static void -arscp_list() -{ - - if (!arscp_target_exist()) - return; - bsdar->argc = 0; - bsdar->argv = NULL; - /* Always verbose. */ - bsdar->options |= AR_V; - ar_mode_t(bsdar); - bsdar->options &= ~AR_V; -} - -/* List modules of archive. (Advance Mode) */ -static void -arscp_dir(char *archive, struct list *list, char *rlt) -{ - FILE *out; - - /* If rlt != NULL, redirect output to it */ - out = NULL; - if (rlt) { - out = stdout; - if ((stdout = fopen(rlt, "w")) == NULL) - bsdar_errc(bsdar, EX_IOERR, errno, - "fopen %s failed", rlt); - } - - bsdar->filename = archive; - if (list) - arscp_mlist2argv(list); - else { - bsdar->argc = 0; - bsdar->argv = NULL; - } - if (verbose) - bsdar->options |= AR_V; - ar_mode_t(bsdar); - bsdar->options &= ~AR_V; - - if (rlt) { - if (fclose(stdout) == EOF) - bsdar_errc(bsdar, EX_IOERR, errno, - "fclose %s failed", rlt); - stdout = out; - free(rlt); - } - free(archive); - bsdar->filename = tmpac; - arscp_free_argv(); - arscp_free_mlist(list); -} - - -/* Replace modules of current archive. */ -static void -arscp_replace(struct list *list) -{ - - if (!arscp_target_exist()) - return; - arscp_mlist2argv(list); - ar_mode_r(bsdar); - arscp_free_argv(); - arscp_free_mlist(list); -} - -/* Rename the temporary archive to the target archive. */ -static void -arscp_save() -{ - mode_t mask; - - if (target) { - if (rename(tmpac, target) < 0) - bsdar_errc(bsdar, EX_IOERR, errno, "rename failed"); - /* - * mkstemp creates temp files with mode 0600, here we - * set target archive mode per process umask. - */ - mask = umask(0); - umask(mask); - if (chmod(target, 0666 & ~mask) < 0) - bsdar_errc(bsdar, EX_IOERR, errno, "chmod failed"); - free(tmpac); - free(target); - tmpac = NULL; - target= NULL; - bsdar->filename = NULL; - } else - bsdar_warnc(bsdar, 0, "no open output archive"); -} - -/* - * Discard all the contents of current archive. This is achieved by - * invoking CREATE cmd on current archive. - */ -static void -arscp_clear() -{ - char *new_target; - - if (target) { - new_target = strdup(target); - if (new_target == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed"); - arscp_create(NULL, new_target); - } -} - -/* - * Quit ar(1). Note that END cmd will not SAVE current archive - * before exit. - */ -static void -arscp_end(int eval) -{ - - if (target) - free(target); - if (tmpac) { - if (unlink(tmpac) == -1) - bsdar_errc(bsdar, EX_IOERR, errno, "unlink %s failed", - tmpac); - free(tmpac); - } - - exit(eval); -} - -/* - * Check if target spcified, i.e, whether OPEN or CREATE has been - * issued by user. - */ -static int -arscp_target_exist() -{ - - if (target) - return (1); - - bsdar_warnc(bsdar, 0, "no open output archive"); - return (0); -} - -/* Construct module list. */ -static struct list * -arscp_mlist(struct list *list, char *str) -{ - struct list *l; - - l = malloc(sizeof(*l)); - if (l == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed"); - l->str = str; - l->next = list; - - return (l); -} - -/* Calculate the length of a mlist. */ -static int -arscp_mlist_len(struct list *list) -{ - int len; - - for(len = 0; list; list = list->next) - len++; - - return (len); -} - -/* Free the space allocated for mod_list. */ -static void -arscp_free_mlist(struct list *list) -{ - struct list *l; - - /* Note that list->str was freed in arscp_free_argv. */ - for(; list; list = l) { - l = list->next; - free(list); - } -} - -/* Convert mlist to argv array. */ -static void -arscp_mlist2argv(struct list *list) -{ - char **argv; - int i, n; - - n = arscp_mlist_len(list); - argv = malloc(n * sizeof(*argv)); - if (argv == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed"); - - /* Note that module names are stored in reverse order in mlist. */ - for(i = n - 1; i >= 0; i--, list = list->next) { - if (list == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "invalid mlist"); - argv[i] = list->str; - } - - bsdar->argc = n; - bsdar->argv = argv; -} - -/* Free space allocated for argv array and its elements. */ -static void -arscp_free_argv() -{ - int i; - - for(i = 0; i < bsdar->argc; i++) - free(bsdar->argv[i]); - - free(bsdar->argv); -} - -/* Show a prompt if we are in interactive mode */ -static void -arscp_prompt() -{ - - if (interactive) { - printf("AR >"); - fflush(stdout); - } -} - -/* Main function for ar script mode. */ -void -ar_mode_script(struct bsdar *ar) -{ - - bsdar = ar; - interactive = isatty(fileno(stdin)); - while(yyparse()) { - if (!interactive) - arscp_end(1); - } - - /* Script ends without END */ - arscp_end(EX_OK); -} diff --git a/usr.bin/ar/ar.1 b/usr.bin/ar/ar.1 deleted file mode 100644 index cb9414e..0000000 --- a/usr.bin/ar/ar.1 +++ /dev/null @@ -1,406 +0,0 @@ -.\" Copyright (c) 2007 Joseph Koshy. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" This software is provided by Joseph Koshy ``as is'' and -.\" any express or implied warranties, including, but not limited to, the -.\" implied warranties of merchantability and fitness for a particular purpose -.\" are disclaimed. in no event shall Joseph Koshy be liable -.\" for any direct, indirect, incidental, special, exemplary, or consequential -.\" damages (including, but not limited to, procurement of substitute goods -.\" or services; loss of use, data, or profits; or business interruption) -.\" however caused and on any theory of liability, whether in contract, strict -.\" liability, or tort (including negligence or otherwise) arising in any way -.\" out of the use of this software, even if advised of the possibility of -.\" such damage. -.\" -.\" $FreeBSD$ -.\" -.Dd August 31, 2007 -.Os -.Dt AR 1 -.Sh NAME -.Nm ar , -.Nm ranlib -.Nd manage archives -.Sh SYNOPSIS -.Nm -.Fl d -.Op Fl T -.Op Fl j -.Op Fl v -.Op Fl z -.Ar archive -.Ar files ... -.Nm -.Fl m -.Op Fl T -.Op Fl a Ar position-after -.Op Fl b Ar position-before -.Op Fl i Ar position-before -.Op Fl j -.Op Fl s -.Op Fl z -.Ar archive -.Ar files ... -.Nm -.Fl p -.Op Fl T -.Op Fl v -.Ar archive -.Op Ar files ... -.Nm -.Fl r -.Op Fl T -.Op Fl a Ar position-after -.Op Fl b Ar position-before -.Op Fl c -.Op Fl i Ar position-before -.Op Fl j -.Op Fl s -.Op Fl u -.Op Fl v -.Op Fl z -.Ar archive -.Ar files ... -.Nm -.Fl s -.Op Fl j -.Op Fl z -.Ar archive -.Nm -.Fl t -.Op Fl T -.Op Fl v -.Ar archive -.Op Ar files ... -.Nm -.Fl x -.Op Fl C -.Op Fl T -.Op Fl o -.Op Fl u -.Op Fl v -.Ar archive -.Op Ar files ... -.Nm ranlib -.Ar archive ... -.Sh DESCRIPTION -The -.Nm -utility creates and maintains groups of files combined into an -archive. -Once an archive has been created, new files can be added to it, and -existing files can be extracted, deleted or replaced. -.Pp -Files are named in the archive by their last file name component, -so if a file referenced by a path containing a -.Dq / -is archived, it will be named by the last component of the path. -Similarly when matching paths listed on the command line against -file names stored in the archive, only the last component of the -path will be compared. -.Pp -The normal use of -.Nm -is for the creation and maintenance of libraries suitable for use -with the link editor -.Xr ld 1 , -although it is not restricted to this purpose. -The -.Nm -utility can create and manage an archive symbol table (see -.Xr ar 5 ) -used to speed up link editing operations. -If a symbol table is present in an archive, it will be -kept up-to-date by subsequent operations on the archive (excepting -the quick update specified by the -.Fl q -option). -.Pp -The -.Nm ranlib -utility is used to add an archive symbol table -to an existing archive. -.Sh OPTIONS -The -.Nm -utility supports the following options: -.Bl -tag -width indent -.It Fl a Ar member-after -When used with option -.Fl m -this option specifies that the archive members specified by -arguments -.Ar files ... -are moved to after the archive member named by argument -.Ar member-after . -When used with option -.Fl r -this option specifies that the files specified by arguments -.Ar files ... -are added after the archive member named by argument -.Ar member-after . -.It Fl b Ar member-before -When used with option -.Fl m -this option specifies that the archive members specified by -arguments -.Ar files ... -are moved to before the archive member named by argument -.Ar member-before . -When used with option -.Fl r -this option specifies that the files specified by arguments -.Ar files ... -are added before the archive member named by argument -.Ar member-before . -.It Fl c -Suppress the informational message printed when a new archive is -created using the -.Fl r -and -.Fl q -options. -.It Fl C -Prevent extracted files from replacing like-named files -in the file system. -.It Fl d -Delete the members named by arguments -.Ar files ... -from the archive specified by argument -.Ar archive . -The archive's symbol table, if present, is updated to reflect -the new contents of the archive. -.It Fl f -Synonymous with option -.Fl T . -.It Fl i Ar member-before -Synonymous with option -.Fl b . -.It Fl j -Compress the resulting archive with -.Xr bzip2 1 . -.It Fl m -Move archive members specified by arguments -.Ar files ... -within the archive. -If a position has been specified by one of the -.Fl a , -.Fl b -or -.Fl i -options, the members are moved to before or after the specified -position. -If no position has been specified, the specified members are moved -to the end of the archive. -If the archive has a symbol table, it is updated to reflect the -new contents of the archive. -.It Fl o -Preserve the original modification times of members when extracting -them. -.It Fl p -Write the contents of the specified archive members named by -arguments -.Ar files ... -to standard output. -If no members were specified, the contents of all the files in the -archive are written in the order they appear in the archive. -.It Fl q -Append the files specified by arguments -.Ar files ... -to the archive specified by argument -.Ar archive -without checking if the files already exist in the archive and -without updating the archive's symbol table. -If the archive file -.Ar archive -does not already exist, a new archive is created. -However, to be compatible with GNU -.Nm , -option -.Fl q -will update the archive's symbol table. -.It Fl r -Replace (add) the files specified by arguments -.Ar files ... -in the archive specified by argument -.Ar archive , -creating the archive if necessary. -Files that replace existing files do not change the order of files -within the archive. -If a file named in arguments -.Ar files ... -does not exist, existing members in the archive that match that -name are not changed. -New files are added to the end of the archive unless one of the -positioning options -.Fl a , -.Fl b -or -.Fl i -is specified. -The archive symbol table, if it exists, is updated to reflect the -new state of the archive. -.It Fl s -Add an archive symbol table (see -.Xr ar 5 ) -to the archive specified by argument -.Ar archive . -Invoking -.Nm -with the -.Fl s -option alone is equivalent to invoking -.Nm ranlib . -.It Fl t -List the files specified by arguments -.Ar files ... -in the order in which they appear in the archive, one per line. -If no files are specified, all files in the archive are listed. -.It Fl T -Use only the first fifteen characters of the archive member name or -command line file name argument when naming archive members. -.It Fl u -Conditionally update the archive or extract members. -When used with the -.Fl r -option, files named by arguments -.Ar files ... -will be replaced in the archive if they are newer than their -archived versions. -When used with the -.Fl x -option, the members specified by arguments -.Ar files ... -will be extracted only if they are newer than the corresponding -files in the file system. -.It Fl v -Provide verbose output. -When used with the -.Fl d , -.Fl m , -.Fl q -or -.Fl x -options, -.Nm -gives a file-by-file description of the archive modification being -performed, which consists of three white-space seperated fields: -the option letter, a dash -.Dq "-" , -and the file name. -When used with the -.Fl r -option, -.Nm -displays the description as above, but the initial letter is an -.Dq a -if the file is added to the archive, or an -.Dq r -if the file replaces a file already in the archive. -When used with the -.Fl p -option, the name of the file enclosed in -.Dq < -and -.Dq > -characters is written to standard output preceded by a single newline -character and followed by two newline characters. -The contents of the named file follow the file name. -When used with the -.Fl t -option, -.Nm -displays eight whitespace separated fields: -the file permissions as displayed by -.Xr strmode 3 , -decimal user and group IDs separated by a slash ( -.Dq / Ns ) , -the file size in bytes, the file modification time in -.Xr strftime 3 -format -.Dq "%b %e %H:%M %Y" , -and the name of the file. -.It Fl x -Extract archive members specified by arguments -.Ar files ... -into the current directory. -If no members have been specified, extract all members of the archive. -If the file corresponding to an extracted member does not exist it -will be created. -If the file corresponding to an extracted member does exist, its owner -and group will not be changed while its contents will be overwritten -and its permissions will set to that entered in the archive. -The file's access and modification time would be that of the time -of extraction unless the -.Fl o -option was specified. -.It Fl z -Compress the resulting archive with -.Xr gzip 1 . -.El -.Sh EXAMPLES -To create a new archive -.Pa ex.a -containing three files -.Pa ex1.o , -.Pa ex2.o -and -.Pa ex3.o , -use: -.Dl "ar -rc ex.a ex1.o ex2.o ex3.o" -.Pp -To add an archive symbol table to an existing archive -.Pa ex.a , -use: -.Dl "ar -s ex.a" -.Pp -To delete file -.Pa ex1.o -from archive -.Pa ex.a , -use: -.D1 "ar -d ex.a ex1.o" -.Pp -To verbosely list the contents of archive -.Pa ex.a , -use: -.D1 "ar -tv ex.a" -.Sh DIAGNOSTICS -.Ex -std -.Sh SEE ALSO -.Xr ld 1 , -.Xr archive 3 , -.Xr elf 3 , -.Xr strftime 3 , -.Xr strmode 3 , -.Xr ar 5 -.\" .Sh COMPATIBILITY -.\" .Nm -.\" is expected to be compatible with GNU and SVR4 -.\" .Nm . -.\" .Sh STANDARDS -.\" Do the POSIX/SuSv3 standards have anything to say about AR(1)? -.Sh HISTORY -An -.Nm -command first appeared in AT&T UNIX Version 1. -In -.Fx 8.0 , -.An "Kai Wang" Aq kaiw@FreeBSD.org -reimplemented -.Nm -and -.Nm ranlib -using the -.Lb libarchive -and the -.Lb libelf . diff --git a/usr.bin/ar/ar.c b/usr.bin/ar/ar.c deleted file mode 100644 index e910e30..0000000 --- a/usr.bin/ar/ar.c +++ /dev/null @@ -1,387 +0,0 @@ -/*- - * Copyright (c) 2007 Kai Wang - * Copyright (c) 2007 Tim Kientzle - * Copyright (c) 2007 Joseph Koshy - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Hugh Smith at The University of Guelph. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/queue.h> -#include <sys/types.h> -#include <archive.h> -#include <errno.h> -#include <getopt.h> -#include <libgen.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sysexits.h> - -#include "ar.h" - -enum options -{ - OPTION_HELP -}; - -static struct option longopts[] = -{ - {"help", no_argument, NULL, OPTION_HELP}, - {"version", no_argument, NULL, 'V'}, - {NULL, 0, NULL, 0} -}; - -static void bsdar_usage(void); -static void ranlib_usage(void); -static void set_mode(struct bsdar *bsdar, char opt); -static void only_mode(struct bsdar *bsdar, const char *opt, - const char *valid_modes); -static void bsdar_version(void); -static void ranlib_version(void); - -int -main(int argc, char **argv) -{ - struct bsdar *bsdar, bsdar_storage; - char *p; - size_t len; - int i, opt; - - bsdar = &bsdar_storage; - memset(bsdar, 0, sizeof(*bsdar)); - - if ((bsdar->progname = getprogname()) == NULL) - bsdar->progname = "ar"; - - if (strcmp(bsdar->progname, "ranlib") == 0 || - strcmp(bsdar->progname, "bsdranlib") == 0) { - while ((opt = getopt_long(argc, argv, "tV", longopts, - NULL)) != -1) { - switch(opt) { - case 't': - /* Ignored. */ - break; - case 'V': - ranlib_version(); - break; - case OPTION_HELP: - ranlib_usage(); - default: - ranlib_usage(); - } - } - argv += optind; - argc -= optind; - - if (*argv == NULL) - ranlib_usage(); - - bsdar->options |= AR_S; - for (;(bsdar->filename = *argv++) != NULL;) - ar_mode_s(bsdar); - - exit(EX_OK); - } else { - if (argc < 2) - bsdar_usage(); - - if (*argv[1] != '-') { - len = strlen(argv[1]) + 2; - if ((p = malloc(len)) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, - "malloc failed"); - *p = '-'; - (void)strlcpy(p + 1, argv[1], len - 1); - argv[1] = p; - } - } - - while ((opt = getopt_long(argc, argv, "abCcdfijlMmopqrSsTtuVvxz", - longopts, NULL)) != -1) { - switch(opt) { - case 'a': - bsdar->options |= AR_A; - break; - case 'b': - case 'i': - bsdar->options |= AR_B; - break; - case 'C': - bsdar->options |= AR_CC; - break; - case 'c': - bsdar->options |= AR_C; - break; - case 'd': - set_mode(bsdar, opt); - break; - case 'f': - case 'T': - bsdar->options |= AR_TR; - break; - case 'j': - bsdar->options |= AR_J; - break; - case 'l': - /* ignored, for GNU ar comptibility */ - break; - case 'M': - set_mode(bsdar, opt); - break; - case 'm': - set_mode(bsdar, opt); - break; - case 'o': - bsdar->options |= AR_O; - break; - case 'p': - set_mode(bsdar, opt); - break; - case 'q': - set_mode(bsdar, opt); - break; - case 'r': - set_mode(bsdar, opt); - break; - case 'S': - bsdar->options |= AR_SS; - break; - case 's': - bsdar->options |= AR_S; - break; - case 't': - set_mode(bsdar, opt); - break; - case 'u': - bsdar->options |= AR_U; - break; - case 'V': - bsdar_version(); - break; - case 'v': - bsdar->options |= AR_V; - break; - case 'x': - set_mode(bsdar, opt); - break; - case 'z': - bsdar->options |= AR_Z; - break; - case OPTION_HELP: - bsdar_usage(); - default: - bsdar_usage(); - } - } - - argv += optind; - argc -= optind; - - if (*argv == NULL && bsdar->mode != 'M') - bsdar_usage(); - - if (bsdar->options & AR_A && bsdar->options & AR_B) - bsdar_errc(bsdar, EX_USAGE, 0, - "only one of -a and -[bi] options allowed"); - - if (bsdar->options & AR_J && bsdar->options & AR_Z) - bsdar_errc(bsdar, EX_USAGE, 0, - "only one of -j and -z options allowed"); - - if (bsdar->options & AR_S && bsdar->options & AR_SS) - bsdar_errc(bsdar, EX_USAGE, 0, - "only one of -s and -S options allowed"); - - if (bsdar->options & (AR_A | AR_B)) { - if ((bsdar->posarg = *argv) == NULL) - bsdar_errc(bsdar, EX_USAGE, 0, - "no position operand specified"); - if ((bsdar->posarg = basename(bsdar->posarg)) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, - "basename failed"); - argc--; - argv++; - } - - if (bsdar->options & AR_A) - only_mode(bsdar, "-a", "mqr"); - if (bsdar->options & AR_B) - only_mode(bsdar, "-b", "mqr"); - if (bsdar->options & AR_C) - only_mode(bsdar, "-c", "qr"); - if (bsdar->options & AR_CC) - only_mode(bsdar, "-C", "x"); - if (bsdar->options & AR_O) - only_mode(bsdar, "-o", "x"); - if (bsdar->options & AR_SS) - only_mode(bsdar, "-S", "mqr"); - if (bsdar->options & AR_U) - only_mode(bsdar, "-u", "qrx"); - - if (bsdar->mode == 'M') { - ar_mode_script(bsdar); - exit(EX_OK); - } - - if ((bsdar->filename = *argv) == NULL) - bsdar_usage(); - - bsdar->argc = --argc; - bsdar->argv = ++argv; - - if ((!bsdar->mode || strchr("ptx", bsdar->mode)) && - bsdar->options & AR_S) { - ar_mode_s(bsdar); - if (!bsdar->mode) - exit(EX_OK); - } - - switch(bsdar->mode) { - case 'd': - ar_mode_d(bsdar); - break; - case 'm': - ar_mode_m(bsdar); - break; - case 'p': - ar_mode_p(bsdar); - break; - case 'q': - ar_mode_q(bsdar); - break; - case 'r': - ar_mode_r(bsdar); - break; - case 't': - ar_mode_t(bsdar); - break; - case 'x': - ar_mode_x(bsdar); - break; - default: - bsdar_usage(); - /* NOTREACHED */ - } - - for (i = 0; i < bsdar->argc; i++) - if (bsdar->argv[i] != NULL) - bsdar_warnc(bsdar, 0, "%s: not found in archive", - bsdar->argv[i]); - - exit(EX_OK); -} - -static void -set_mode(struct bsdar *bsdar, char opt) -{ - - if (bsdar->mode != '\0' && bsdar->mode != opt) - bsdar_errc(bsdar, EX_USAGE, 0, - "Can't specify both -%c and -%c", opt, bsdar->mode); - bsdar->mode = opt; -} - -static void -only_mode(struct bsdar *bsdar, const char *opt, const char *valid_modes) -{ - - if (strchr(valid_modes, bsdar->mode) == NULL) - bsdar_errc(bsdar, EX_USAGE, 0, - "Option %s is not permitted in mode -%c", opt, bsdar->mode); -} - -static void -bsdar_usage() -{ - - (void)fprintf(stderr, "usage: ar -d [-Tjsvz] archive file ...\n"); - (void)fprintf(stderr, "\tar -m [-Tjsvz] archive file ...\n"); - (void)fprintf(stderr, "\tar -m [-Tabijsvz] position archive file ...\n"); - (void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n"); - (void)fprintf(stderr, "\tar -q [-Tcjsvz] archive file ...\n"); - (void)fprintf(stderr, "\tar -r [-Tcjsuvz] archive file ...\n"); - (void)fprintf(stderr, "\tar -r [-Tabcijsuvz] position archive file ...\n"); - (void)fprintf(stderr, "\tar -s [-jz] archive\n"); - (void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n"); - (void)fprintf(stderr, "\tar -x [-CTouv] archive [file ...]\n"); - (void)fprintf(stderr, "\tar -V\n"); - exit(EX_USAGE); -} - -static void -ranlib_usage() -{ - - (void)fprintf(stderr, "usage: ranlib [-t] archive ...\n"); - (void)fprintf(stderr, "\tranlib -V\n"); - exit(EX_USAGE); -} - -static void -bsdar_version() -{ - (void)printf("BSD ar %s - %s\n", BSDAR_VERSION, archive_version()); - exit(EX_OK); -} - -static void -ranlib_version() -{ - (void)printf("ranlib %s - %s\n", BSDAR_VERSION, archive_version()); - exit(EX_OK); -} diff --git a/usr.bin/ar/ar.h b/usr.bin/ar/ar.h deleted file mode 100644 index 111f944..0000000 --- a/usr.bin/ar/ar.h +++ /dev/null @@ -1,125 +0,0 @@ -/*- - * Copyright (c) 2007 Kai Wang - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#define BSDAR_VERSION "1.1.0" - -/* - * ar(1) options. - */ -#define AR_A 0x0001 /* position-after */ -#define AR_B 0x0002 /* position-before */ -#define AR_C 0x0004 /* creating new archive */ -#define AR_CC 0x0008 /* do not overwrite when extracting */ -#define AR_J 0x0010 /* bzip2 compression */ -#define AR_O 0x0020 /* preserve original mtime when extracting */ -#define AR_S 0x0040 /* write archive symbol table */ -#define AR_SS 0x0080 /* do not write archive symbol table */ -#define AR_TR 0x0100 /* only keep first 15 chars for member name */ -#define AR_U 0x0200 /* only extract or update newer members.*/ -#define AR_V 0x0400 /* verbose mode */ -#define AR_Z 0x0800 /* gzip compression */ - -#define DEF_BLKSZ 10240 /* default block size */ - -/* - * Convenient wrapper for general libarchive error handling. - */ -#define AC(CALL) do { \ - if ((CALL)) \ - bsdar_errc(bsdar, EX_SOFTWARE, 0, "%s", \ - archive_error_string(a)); \ -} while (0) - -/* - * In-memory representation of archive member(object). - */ -struct ar_obj { - char *name; /* member name */ - void *maddr; /* mmap start address */ - uid_t uid; /* user id */ - gid_t gid; /* group id */ - mode_t md; /* octal file permissions */ - size_t size; /* member size */ - time_t mtime; /* modification time */ - int fd; /* file descriptor */ - dev_t dev; /* inode's device */ - ino_t ino; /* inode's number */ - - TAILQ_ENTRY(ar_obj) objs; -}; - -/* - * Structure encapsulates the "global" data for "ar" program. - */ -struct bsdar { - const char *filename; /* archive name. */ - const char *addlib; /* target of ADDLIB. */ - const char *posarg; /* position arg for modifiers -a, -b. */ - char mode; /* program mode */ - char compression; /* compression mode */ - int options; /* command line options */ - - const char *progname; /* program name */ - int argc; - char **argv; - - /* - * Fields for the archive string table. - */ - char *as; /* buffer for archive string table. */ - size_t as_sz; /* current size of as table. */ - size_t as_cap; /* capacity of as table buffer. */ - - /* - * Fields for the archive symbol table. - */ - uint32_t s_cnt; /* current number of symbols. */ - uint32_t *s_so; /* symbol offset table. */ - size_t s_so_cap; /* capacity of so table buffer. */ - char *s_sn; /* symbol name table */ - size_t s_sn_cap; /* capacity of sn table buffer. */ - size_t s_sn_sz; /* current size of sn table. */ - /* Current member's offset (relative to the end of pseudo members.) */ - off_t rela_off; - - TAILQ_HEAD(, ar_obj) v_obj; /* object(member) list */ -}; - -void bsdar_errc(struct bsdar *, int _eval, int _code, - const char *fmt, ...); -void bsdar_warnc(struct bsdar *, int _code, const char *fmt, ...); -void ar_mode_d(struct bsdar *bsdar); -void ar_mode_m(struct bsdar *bsdar); -void ar_mode_p(struct bsdar *bsdar); -void ar_mode_q(struct bsdar *bsdar); -void ar_mode_r(struct bsdar *bsdar); -void ar_mode_s(struct bsdar *bsdar); -void ar_mode_t(struct bsdar *bsdar); -void ar_mode_x(struct bsdar *bsdar); -void ar_mode_A(struct bsdar *bsdar); -void ar_mode_script(struct bsdar *ar); diff --git a/usr.bin/ar/read.c b/usr.bin/ar/read.c deleted file mode 100644 index a9e2ed1..0000000 --- a/usr.bin/ar/read.c +++ /dev/null @@ -1,204 +0,0 @@ -/*- - * Copyright (c) 2007 Kai Wang - * Copyright (c) 2007 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/queue.h> -#include <sys/stat.h> -#include <archive.h> -#include <archive_entry.h> -#include <errno.h> -#include <libgen.h> -#include <stdio.h> -#include <string.h> -#include <sysexits.h> - -#include "ar.h" - -static void read_archive(struct bsdar *bsdar, char mode); - -void -ar_mode_p(struct bsdar *bsdar) -{ - - read_archive(bsdar, 'p'); -} - -void -ar_mode_t(struct bsdar *bsdar) -{ - - read_archive(bsdar, 't'); -} - -void -ar_mode_x(struct bsdar *bsdar) -{ - - read_archive(bsdar, 'x'); -} - -/* - * Handle read modes: 'x', 't' and 'p'. - */ -static void -read_archive(struct bsdar *bsdar, char mode) -{ - struct archive *a; - struct archive_entry *entry; - struct stat sb; - struct tm *tp; - const char *bname; - const char *name; - mode_t md; - size_t size; - time_t mtime; - uid_t uid; - gid_t gid; - char **av; - char buf[25]; - char find; - int flags, r, i; - - if ((a = archive_read_new()) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_read_new failed"); - archive_read_support_compression_all(a); - archive_read_support_format_all(a); - AC(archive_read_open_file(a, bsdar->filename, DEF_BLKSZ)); - - for (;;) { - r = archive_read_next_header(a, &entry); - if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY || - r == ARCHIVE_FATAL) - bsdar_warnc(bsdar, 0, "%s", archive_error_string(a)); - if (r == ARCHIVE_EOF || r == ARCHIVE_FATAL) - break; - if (r == ARCHIVE_RETRY) { - bsdar_warnc(bsdar, 0, "Retrying..."); - continue; - } - - name = archive_entry_pathname(entry); - - /* Skip pseudo members. */ - if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0) - continue; - - if (bsdar->argc > 0) { - find = 0; - for(i = 0; i < bsdar->argc; i++) { - av = &bsdar->argv[i]; - if (*av == NULL) - continue; - if ((bname = basename(*av)) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, - "basename failed"); - if (strcmp(bname, name) != 0) - continue; - - *av = NULL; - find = 1; - break; - } - if (!find) - continue; - } - - if (mode == 't') { - if (bsdar->options & AR_V) { - md = archive_entry_mode(entry); - uid = archive_entry_uid(entry); - gid = archive_entry_gid(entry); - size = archive_entry_size(entry); - mtime = archive_entry_mtime(entry); - (void)strmode(md, buf); - (void)fprintf(stdout, "%s %6d/%-6d %8ju ", - buf + 1, uid, gid, (uintmax_t)size); - tp = localtime(&mtime); - (void)strftime(buf, sizeof(buf), - "%b %e %H:%M %Y", tp); - (void)fprintf(stdout, "%s %s", buf, name); - } else - (void)fprintf(stdout, "%s", name); - r = archive_read_data_skip(a); - if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY || - r == ARCHIVE_FATAL) { - (void)fprintf(stdout, "\n"); - bsdar_warnc(bsdar, 0, "%s", - archive_error_string(a)); - } - - if (r == ARCHIVE_FATAL) - break; - - (void)fprintf(stdout, "\n"); - } else { - /* mode == 'x' || mode = 'p' */ - if (mode == 'p') { - if (bsdar->options & AR_V) { - (void)fprintf(stdout, "\n<%s>\n\n", - name); - fflush(stdout); - } - r = archive_read_data_into_fd(a, 1); - } else { - /* mode == 'x' */ - if (stat(name, &sb) != 0) { - if (errno != ENOENT) { - bsdar_warnc(bsdar, 0, - "stat %s failed", - bsdar->filename); - continue; - } - } else { - /* stat success, file exist */ - if (bsdar->options & AR_CC) - continue; - if (bsdar->options & AR_U && - archive_entry_mtime(entry) <= - sb.st_mtime) - continue; - } - - if (bsdar->options & AR_V) - (void)fprintf(stdout, "x - %s\n", name); - flags = 0; - if (bsdar->options & AR_O) - flags |= ARCHIVE_EXTRACT_TIME; - - r = archive_read_extract(a, entry, flags); - } - - if (r) - bsdar_warnc(bsdar, 0, "%s", - archive_error_string(a)); - } - } - AC(archive_read_close(a)); - AC(archive_read_finish(a)); -} diff --git a/usr.bin/ar/util.c b/usr.bin/ar/util.c deleted file mode 100644 index e1230e3..0000000 --- a/usr.bin/ar/util.c +++ /dev/null @@ -1,86 +0,0 @@ -/*- - * Copyright (c) 2003-2007 Tim Kientzle - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/queue.h> -#include <sys/types.h> -#include <errno.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "ar.h" - -static void bsdar_vwarnc(struct bsdar *, int code, - const char *fmt, va_list ap); -static void bsdar_verrc(struct bsdar *bsdar, int code, - const char *fmt, va_list ap); - -static void -bsdar_vwarnc(struct bsdar *bsdar, int code, const char *fmt, va_list ap) -{ - - fprintf(stderr, "%s: warning: ", bsdar->progname); - vfprintf(stderr, fmt, ap); - if (code != 0) - fprintf(stderr, ": %s", strerror(code)); - fprintf(stderr, "\n"); -} - -void -bsdar_warnc(struct bsdar *bsdar, int code, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - bsdar_vwarnc(bsdar, code, fmt, ap); - va_end(ap); -} - -static void -bsdar_verrc(struct bsdar *bsdar, int code, const char *fmt, va_list ap) -{ - - fprintf(stderr, "%s: fatal: ", bsdar->progname); - vfprintf(stderr, fmt, ap); - if (code != 0) - fprintf(stderr, ": %s", strerror(code)); - fprintf(stderr, "\n"); -} - -void -bsdar_errc(struct bsdar *bsdar, int eval, int code, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - bsdar_verrc(bsdar, code, fmt, ap); - va_end(ap); - exit(eval); -} diff --git a/usr.bin/ar/write.c b/usr.bin/ar/write.c deleted file mode 100644 index 3d4f93d..0000000 --- a/usr.bin/ar/write.c +++ /dev/null @@ -1,879 +0,0 @@ -/*- - * Copyright (c) 2007 Kai Wang - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer - * in this position and unchanged. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/endian.h> -#include <sys/mman.h> -#include <sys/queue.h> -#include <sys/stat.h> -#include <archive.h> -#include <archive_entry.h> -#include <errno.h> -#include <fcntl.h> -#include <gelf.h> -#include <libgen.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sysexits.h> - -#include "ar.h" - -#define _ARMAG_LEN 8 /* length of ar magic string */ -#define _ARHDR_LEN 60 /* length of ar header */ -#define _INIT_AS_CAP 128 /* initial archive string table size */ -#define _INIT_SYMOFF_CAP (256*(sizeof(uint32_t))) /* initial so table size */ -#define _INIT_SYMNAME_CAP 1024 /* initial sn table size */ -#define _MAXNAMELEN_SVR4 15 /* max member name length in svr4 variant */ -#define _TRUNCATE_LEN 15 /* number of bytes to keep for member name */ - -static void add_to_ar_str_table(struct bsdar *bsdar, const char *name); -static void add_to_ar_sym_table(struct bsdar *bsdar, const char *name); -static struct ar_obj *create_obj_from_file(struct bsdar *bsdar, - const char *name, time_t mtime); -static void create_symtab_entry(struct bsdar *bsdar, void *maddr, - size_t size); -static void insert_obj(struct bsdar *bsdar, struct ar_obj *obj, - struct ar_obj *pos); -static void read_objs(struct bsdar *bsdar, const char *archive, - int checkargv); -static void write_archive(struct bsdar *bsdar, char mode); -static void write_cleanup(struct bsdar *bsdar); -static void write_data(struct bsdar *bsdar, struct archive *a, - const void *buf, size_t s); -static void write_objs(struct bsdar *bsdar); - -void -ar_mode_d(struct bsdar *bsdar) -{ - - write_archive(bsdar, 'd'); -} - -void -ar_mode_m(struct bsdar *bsdar) -{ - - write_archive(bsdar, 'm'); -} - -void -ar_mode_q(struct bsdar *bsdar) -{ - - write_archive(bsdar, 'q'); -} - -void -ar_mode_r(struct bsdar *bsdar) -{ - - write_archive(bsdar, 'r'); -} - -void -ar_mode_s(struct bsdar *bsdar) -{ - - write_archive(bsdar, 's'); -} - -void -ar_mode_A(struct bsdar *bsdar) -{ - - write_archive(bsdar, 'A'); -} - -/* - * Create object from file, return created obj upon success, or NULL - * when an error occurs or the member is not newer than existing - * one while -u is specifed. - */ -static struct ar_obj * -create_obj_from_file(struct bsdar *bsdar, const char *name, time_t mtime) -{ - struct ar_obj *obj; - struct stat sb; - const char *bname; - - if (name == NULL) - return (NULL); - - obj = malloc(sizeof(struct ar_obj)); - if (obj == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed"); - if ((obj->fd = open(name, O_RDONLY, 0)) < 0) { - bsdar_warnc(bsdar, errno, "can't open file: %s", name); - free(obj); - return (NULL); - } - - if ((bname = basename(name)) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "basename failed"); - if (bsdar->options & AR_TR && strlen(bname) > _TRUNCATE_LEN) { - if ((obj->name = malloc(_TRUNCATE_LEN + 1)) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed"); - (void)strncpy(obj->name, bname, _TRUNCATE_LEN); - obj->name[_TRUNCATE_LEN] = '\0'; - } else - if ((obj->name = strdup(bname)) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed"); - - if (fstat(obj->fd, &sb) < 0) { - bsdar_warnc(bsdar, errno, "can't fstat file: %s", obj->name); - goto giveup; - } - if (!S_ISREG(sb.st_mode)) { - bsdar_warnc(bsdar, 0, "%s is not an ordinary file", obj->name); - goto giveup; - } - - /* - * When option '-u' is specified and member is not newer than the - * existing one, the replace will not happen. While if mtime == 0, - * which indicates that this is to "replace a none exist member", - * the replace will proceed regardless of '-u'. - */ - if (mtime != 0 && bsdar->options & AR_U && sb.st_mtime <= mtime) - goto giveup; - - obj->uid = sb.st_uid; - obj->gid = sb.st_gid; - obj->md = sb.st_mode; - obj->size = sb.st_size; - obj->mtime = sb.st_mtime; - obj->dev = sb.st_dev; - obj->ino = sb.st_ino; - - if (obj->size == 0) { - obj->maddr = NULL; - return (obj); - } - - if ((obj->maddr = mmap(NULL, obj->size, PROT_READ, - MAP_PRIVATE, obj->fd, (off_t)0)) == MAP_FAILED) { - bsdar_warnc(bsdar, errno, "can't mmap file: %s", obj->name); - goto giveup; - } - if (close(obj->fd) < 0) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "close failed: %s", - obj->name); - - return (obj); - -giveup: - if (close(obj->fd) < 0) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "close failed: %s", - obj->name); - free(obj->name); - free(obj); - return (NULL); -} - -/* - * Insert obj to the tail, or before/after the pos obj. - */ -static void -insert_obj(struct bsdar *bsdar, struct ar_obj *obj, struct ar_obj *pos) -{ - if (obj == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, 0, "try to insert a null obj"); - - if (pos == NULL || obj == pos) - /* - * If the object to move happens to be the posistion obj, - * or if there is not a pos obj, move it to tail. - */ - goto tail; - - if (bsdar->options & AR_B) { - TAILQ_INSERT_BEFORE(pos, obj, objs); - return; - } - if (bsdar->options & AR_A) { - TAILQ_INSERT_AFTER(&bsdar->v_obj, pos, obj, objs); - return; - } - -tail: - TAILQ_INSERT_TAIL(&bsdar->v_obj, obj, objs); - -} - -/* - * Read objects from archive into v_obj list. Note that checkargv is - * set when read_objs is used to read objects from the target of - * ADDLIB command (ar script mode), in this case argv array possibly - * specifies the members ADDLIB want. - */ -static void -read_objs(struct bsdar *bsdar, const char *archive, int checkargv) -{ - struct archive *a; - struct archive_entry *entry; - struct ar_obj *obj; - const char *name; - const char *bname; - char *buff; - char **av; - size_t size; - int i, r, find; - - if ((a = archive_read_new()) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_read_new failed"); - archive_read_support_compression_all(a); - archive_read_support_format_ar(a); - AC(archive_read_open_filename(a, archive, DEF_BLKSZ)); - for (;;) { - r = archive_read_next_header(a, &entry); - if (r == ARCHIVE_FATAL) - bsdar_errc(bsdar, EX_DATAERR, 0, "%s", - archive_error_string(a)); - if (r == ARCHIVE_EOF) - break; - if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY) - bsdar_warnc(bsdar, 0, "%s", archive_error_string(a)); - if (r == ARCHIVE_RETRY) { - bsdar_warnc(bsdar, 0, "Retrying..."); - continue; - } - - /* - * Remember the compression mode of existing archive. - * If neither -j nor -z is specified, this mode will - * be used for resulting archive. - */ - bsdar->compression = archive_compression(a); - - name = archive_entry_pathname(entry); - - /* - * skip pseudo members. - */ - if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0) - continue; - - /* - * If checkargv is set, only read those members specified - * in argv. - */ - if (checkargv && bsdar->argc > 0) { - find = 0; - for(i = 0; i < bsdar->argc; i++) { - av = &bsdar->argv[i]; - if (*av == NULL) - continue; - if ((bname = basename(*av)) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, - "basename failed"); - if (strcmp(bname, name) != 0) - continue; - - *av = NULL; - find = 1; - break; - } - if (!find) - continue; - } - - size = archive_entry_size(entry); - - if (size > 0) { - if ((buff = malloc(size)) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, - "malloc failed"); - if (archive_read_data(a, buff, size) != (ssize_t)size) { - bsdar_warnc(bsdar, 0, "%s", - archive_error_string(a)); - free(buff); - continue; - } - } else - buff = NULL; - - obj = malloc(sizeof(struct ar_obj)); - if (obj == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed"); - obj->maddr = buff; - if ((obj->name = strdup(name)) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "strdup failed"); - obj->size = size; - obj->uid = archive_entry_uid(entry); - obj->gid = archive_entry_gid(entry); - obj->md = archive_entry_mode(entry); - obj->mtime = archive_entry_mtime(entry); - obj->dev = 0; - obj->ino = 0; - - /* - * Objects from archive have obj->fd set to -1, - * for the ease of cleaning up. - */ - obj->fd = -1; - TAILQ_INSERT_TAIL(&bsdar->v_obj, obj, objs); - } - AC(archive_read_close(a)); - AC(archive_read_finish(a)); -} - -/* - * Determine the constitution of resulting archive. - */ -static void -write_archive(struct bsdar *bsdar, char mode) -{ - struct ar_obj *nobj, *obj, *obj_temp, *pos; - struct stat sb; - const char *bname; - char **av; - int i; - - TAILQ_INIT(&bsdar->v_obj); - nobj = NULL; - pos = NULL; - memset(&sb, 0, sizeof(sb)); - - /* By default, no compression is assumed. */ - bsdar->compression = ARCHIVE_COMPRESSION_NONE; - - /* - * Test if the specified archive exists, to figure out - * whether we are creating one here. - */ - if (stat(bsdar->filename, &sb) != 0) { - if (errno != ENOENT) { - bsdar_warnc(bsdar, 0, "stat %s failed", - bsdar->filename); - return; - } - - /* We do not create archive in mode 'd', 'm' and 's'. */ - if (mode != 'r' && mode != 'q') { - bsdar_warnc(bsdar, 0, "%s: no such file", - bsdar->filename); - return; - } - - /* Issue a warning if -c is not specified when creating. */ - if (!(bsdar->options & AR_C)) - bsdar_warnc(bsdar, 0, "creating %s", bsdar->filename); - goto new_archive; - } - - /* - * First read members from existing archive. - */ - read_objs(bsdar, bsdar->filename, 0); - - /* - * For mode 's', no member will be moved, deleted or replaced. - */ - if (mode == 's') - goto write_objs; - - /* - * For mode 'q', we don't need to adjust existing members either. - * Also, -a, -b and -i are ignored in this mode. New members are - * always inserted at tail. - */ - if (mode == 'q') - goto new_archive; - - /* - * Mode 'A' adds the contents of another archive to the tail of - * current archive. Note that mode 'A' is a special mode for the - * ADDLIB command of the ar script mode. Currently there is no - * access to this function from the ar command line mode. - */ - if (mode == 'A') { - /* - * Read objects from the target archive of ADDLIB command. - * If there are members spcified in argv, read those members - * only, otherwise the entire archive will be read. - */ - read_objs(bsdar, bsdar->addlib, 1); - goto write_objs; - } - - /* - * Try to find the position member specified by user. - */ - if (bsdar->options & AR_A || bsdar->options & AR_B) { - TAILQ_FOREACH(obj, &bsdar->v_obj, objs) { - if (strcmp(obj->name, bsdar->posarg) == 0) { - pos = obj; - break; - } - } - - /* - * If can't find `pos' specified by user, - * sliently insert objects at tail. - */ - if (pos == NULL) - bsdar->options &= ~(AR_A | AR_B); - } - - for (i = 0; i < bsdar->argc; i++) { - av = &bsdar->argv[i]; - - TAILQ_FOREACH_SAFE(obj, &bsdar->v_obj, objs, obj_temp) { - if ((bname = basename(*av)) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, - "basename failed"); - if (bsdar->options & AR_TR) { - if (strncmp(bname, obj->name, _TRUNCATE_LEN)) - continue; - } else - if (strcmp(bname, obj->name) != 0) - continue; - - if (mode == 'r') { - /* - * if the new member is not qualified - * to replace the old one, skip it. - */ - nobj = create_obj_from_file(bsdar, *av, - obj->mtime); - if (nobj == NULL) - goto skip_obj; - } - - if (bsdar->options & AR_V) - (void)fprintf(stdout, "%c - %s\n", mode, - *av); - - TAILQ_REMOVE(&bsdar->v_obj, obj, objs); - if (mode == 'd' || mode == 'r') { - free(obj->maddr); - free(obj->name); - free(obj); - } - - if (mode == 'm') - insert_obj(bsdar, obj, pos); - if (mode == 'r') - insert_obj(bsdar, nobj, pos); - - skip_obj: - *av = NULL; - break; - } - - } - -new_archive: - /* - * When operating in mode 'r', directly add those user specified - * objects which do not exist in current archive. When operating - * in mode 'q', all objects specified in command line args are - * appended to the archive, without comparing with existing ones. - */ - for (i = 0; i < bsdar->argc; i++) { - av = &bsdar->argv[i]; - if (*av != NULL && (mode == 'r' || mode == 'q')) { - nobj = create_obj_from_file(bsdar, *av, 0); - if (nobj != NULL) - insert_obj(bsdar, nobj, pos); - if (bsdar->options & AR_V && nobj != NULL) - (void)fprintf(stdout, "a - %s\n", *av); - *av = NULL; - } - } - -write_objs: - write_objs(bsdar); - write_cleanup(bsdar); -} - -/* - * Memory cleaning up. - */ -static void -write_cleanup(struct bsdar *bsdar) -{ - struct ar_obj *obj, *obj_temp; - - TAILQ_FOREACH_SAFE(obj, &bsdar->v_obj, objs, obj_temp) { - if (obj->fd == -1) - free(obj->maddr); - else - if (obj->maddr != NULL && munmap(obj->maddr, obj->size)) - bsdar_warnc(bsdar, errno, - "can't munmap file: %s", obj->name); - TAILQ_REMOVE(&bsdar->v_obj, obj, objs); - free(obj->name); - free(obj); - } - - free(bsdar->as); - free(bsdar->s_so); - free(bsdar->s_sn); - bsdar->as = NULL; - bsdar->s_so = NULL; - bsdar->s_sn = NULL; -} - -/* - * Wrapper for archive_write_data(). - */ -static void -write_data(struct bsdar *bsdar, struct archive *a, const void *buf, size_t s) -{ - if (archive_write_data(a, buf, s) != (ssize_t)s) - bsdar_errc(bsdar, EX_SOFTWARE, 0, "%s", - archive_error_string(a)); -} - -/* - * Write the resulting archive members. - */ -static void -write_objs(struct bsdar *bsdar) -{ - struct ar_obj *obj; - struct archive *a; - struct archive_entry *entry; - size_t s_sz; /* size of archive symbol table. */ - size_t pm_sz; /* size of pseudo members */ - int i, nr; - - if (elf_version(EV_CURRENT) == EV_NONE) - bsdar_errc(bsdar, EX_SOFTWARE, 0, - "ELF library initialization failed: %s", elf_errmsg(-1)); - - bsdar->rela_off = 0; - - /* Create archive symbol table and archive string table, if need. */ - TAILQ_FOREACH(obj, &bsdar->v_obj, objs) { - if (!(bsdar->options & AR_SS) && obj->maddr != NULL) - create_symtab_entry(bsdar, obj->maddr, obj->size); - if (strlen(obj->name) > _MAXNAMELEN_SVR4) - add_to_ar_str_table(bsdar, obj->name); - bsdar->rela_off += _ARHDR_LEN + obj->size + obj->size % 2; - } - - /* - * Pad the symbol name string table. It is treated specially because - * symbol name table should be padded by a '\0', not the common '\n' - * for other members. The size of sn table includes the pad bit. - */ - if (bsdar->s_cnt != 0 && bsdar->s_sn_sz % 2 != 0) - bsdar->s_sn[bsdar->s_sn_sz++] = '\0'; - - /* - * Archive string table is padded by a "\n" as the normal members. - * The difference is that the size of archive string table counts - * in the pad bit, while normal members' size fileds do not. - */ - if (bsdar->as != NULL && bsdar->as_sz % 2 != 0) - bsdar->as[bsdar->as_sz++] = '\n'; - - /* - * If there is a symbol table, calculate the size of pseudo members, - * convert previously stored relative offsets to absolute ones, and - * then make them Big Endian. - * - * absolute_offset = htobe32(relative_offset + size_of_pseudo_members) - */ - - if (bsdar->s_cnt != 0) { - s_sz = (bsdar->s_cnt + 1) * sizeof(uint32_t) + bsdar->s_sn_sz; - pm_sz = _ARMAG_LEN + (_ARHDR_LEN + s_sz); - if (bsdar->as != NULL) - pm_sz += _ARHDR_LEN + bsdar->as_sz; - for (i = 0; (size_t)i < bsdar->s_cnt; i++) - *(bsdar->s_so + i) = htobe32(*(bsdar->s_so + i) + - pm_sz); - } - - if ((a = archive_write_new()) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, 0, "archive_write_new failed"); - - archive_write_set_format_ar_svr4(a); - - /* The compression mode of the existing archive is used - * for the result archive or if creating a new archive, we - * do not compress archive by default. This default behavior can - * be overrided by compression mode specified explicitly - * through command line option `-j' or `-z'. - */ - if (bsdar->options & AR_J) - bsdar->compression = ARCHIVE_COMPRESSION_BZIP2; - if (bsdar->options & AR_Z) - bsdar->compression = ARCHIVE_COMPRESSION_GZIP; - if (bsdar->compression == ARCHIVE_COMPRESSION_BZIP2) - archive_write_set_compression_bzip2(a); - else if (bsdar->compression == ARCHIVE_COMPRESSION_GZIP) - archive_write_set_compression_gzip(a); - else - archive_write_set_compression_none(a); - - AC(archive_write_open_filename(a, bsdar->filename)); - - /* - * write the archive symbol table, if there is one. - * If options -s is explicitly specified or we are invoked - * as ranlib, write the symbol table even if it is empty. - */ - if ((bsdar->s_cnt != 0 && !(bsdar->options & AR_SS)) || - bsdar->options & AR_S) { - entry = archive_entry_new(); - archive_entry_copy_pathname(entry, "/"); - archive_entry_set_mtime(entry, time(NULL), 0); - archive_entry_set_size(entry, (bsdar->s_cnt + 1) * - sizeof(uint32_t) + bsdar->s_sn_sz); - AC(archive_write_header(a, entry)); - nr = htobe32(bsdar->s_cnt); - write_data(bsdar, a, &nr, sizeof(uint32_t)); - write_data(bsdar, a, bsdar->s_so, sizeof(uint32_t) * - bsdar->s_cnt); - write_data(bsdar, a, bsdar->s_sn, bsdar->s_sn_sz); - archive_entry_free(entry); - } - - /* write the archive string table, if any. */ - if (bsdar->as != NULL) { - entry = archive_entry_new(); - archive_entry_copy_pathname(entry, "//"); - archive_entry_set_size(entry, bsdar->as_sz); - AC(archive_write_header(a, entry)); - write_data(bsdar, a, bsdar->as, bsdar->as_sz); - archive_entry_free(entry); - } - - /* write normal members. */ - TAILQ_FOREACH(obj, &bsdar->v_obj, objs) { - entry = archive_entry_new(); - archive_entry_copy_pathname(entry, obj->name); - archive_entry_set_uid(entry, obj->uid); - archive_entry_set_gid(entry, obj->gid); - archive_entry_set_mode(entry, obj->md); - archive_entry_set_size(entry, obj->size); - archive_entry_set_mtime(entry, obj->mtime, 0); - archive_entry_set_dev(entry, obj->dev); - archive_entry_set_ino(entry, obj->ino); - archive_entry_set_filetype(entry, AE_IFREG); - AC(archive_write_header(a, entry)); - write_data(bsdar, a, obj->maddr, obj->size); - archive_entry_free(entry); - } - - AC(archive_write_close(a)); - AC(archive_write_finish(a)); -} - -/* - * Extract global symbols from ELF binary members. - */ -static void -create_symtab_entry(struct bsdar *bsdar, void *maddr, size_t size) -{ - Elf *e; - Elf_Scn *scn; - GElf_Shdr shdr; - GElf_Sym sym; - Elf_Data *data; - char *name; - size_t n, shstrndx; - int elferr, tabndx, len, i; - - if ((e = elf_memory(maddr, size)) == NULL) { - bsdar_warnc(bsdar, 0, "elf_memory() failed: %s", - elf_errmsg(-1)); - return; - } - if (elf_kind(e) != ELF_K_ELF) { - /* Sliently ignore non-elf member. */ - elf_end(e); - return; - } - if (elf_getshstrndx(e, &shstrndx) == 0) { - bsdar_warnc(bsdar, EX_SOFTWARE, 0, "elf_getshstrndx failed: %s", - elf_errmsg(-1)); - elf_end(e); - return; - } - - tabndx = -1; - scn = NULL; - while ((scn = elf_nextscn(e, scn)) != NULL) { - if (gelf_getshdr(scn, &shdr) != &shdr) { - bsdar_warnc(bsdar, 0, - "elf_getshdr failed: %s", elf_errmsg(-1)); - continue; - } - if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL) { - bsdar_warnc(bsdar, 0, - "elf_strptr failed: %s", elf_errmsg(-1)); - continue; - } - if (strcmp(name, ".strtab") == 0) { - tabndx = elf_ndxscn(scn); - break; - } - } - elferr = elf_errno(); - if (elferr != 0) - bsdar_warnc(bsdar, 0, "elf_nextscn failed: %s", - elf_errmsg(elferr)); - if (tabndx == -1) { - bsdar_warnc(bsdar, 0, "can't find .strtab section"); - elf_end(e); - return; - } - - scn = NULL; - while ((scn = elf_nextscn(e, scn)) != NULL) { - if (gelf_getshdr(scn, &shdr) != &shdr) { - bsdar_warnc(bsdar, EX_SOFTWARE, 0, - "elf_getshdr failed: %s", elf_errmsg(-1)); - continue; - } - if (shdr.sh_type != SHT_SYMTAB) - continue; - - data = NULL; - n = 0; - while (n < shdr.sh_size && - (data = elf_getdata(scn, data)) != NULL) { - len = data->d_size / shdr.sh_entsize; - for (i = 0; i < len; i++) { - if (gelf_getsym(data, i, &sym) != &sym) { - bsdar_warnc(bsdar, EX_SOFTWARE, 0, - "gelf_getsym failed: %s", - elf_errmsg(-1)); - continue; - } - - /* keep only global or weak symbols */ - if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL && - GELF_ST_BIND(sym.st_info) != STB_WEAK) - continue; - - /* keep only defined symbols */ - if (sym.st_shndx == SHN_UNDEF) - continue; - - if ((name = elf_strptr(e, tabndx, - sym.st_name)) == NULL) { - bsdar_warnc(bsdar, EX_SOFTWARE, 0, - "elf_strptr failed: %s", - elf_errmsg(-1)); - continue; - } - - add_to_ar_sym_table(bsdar, name); - } - } - } - elferr = elf_errno(); - if (elferr != 0) - bsdar_warnc(bsdar, EX_SOFTWARE, 0, "elf_nextscn failed: %s", - elf_errmsg(elferr)); - - elf_end(e); -} - -/* - * Append to the archive string table buffer. - */ -static void -add_to_ar_str_table(struct bsdar *bsdar, const char *name) -{ - - if (bsdar->as == NULL) { - bsdar->as_cap = _INIT_AS_CAP; - bsdar->as_sz = 0; - if ((bsdar->as = malloc(bsdar->as_cap)) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed"); - } - - /* - * The space required for holding one member name in as table includes: - * strlen(name) + (1 for '/') + (1 for '\n') + (possibly 1 for padding). - */ - while (bsdar->as_sz + strlen(name) + 3 > bsdar->as_cap) { - bsdar->as_cap *= 2; - bsdar->as = realloc(bsdar->as, bsdar->as_cap); - if (bsdar->as == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "realloc failed"); - } - strncpy(&bsdar->as[bsdar->as_sz], name, strlen(name)); - bsdar->as_sz += strlen(name); - bsdar->as[bsdar->as_sz++] = '/'; - bsdar->as[bsdar->as_sz++] = '\n'; -} - -/* - * Append to the archive symbol table buffer. - */ -static void -add_to_ar_sym_table(struct bsdar *bsdar, const char *name) -{ - - if (bsdar->s_so == NULL) { - if ((bsdar->s_so = malloc(_INIT_SYMOFF_CAP)) == - NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed"); - bsdar->s_so_cap = _INIT_SYMOFF_CAP; - bsdar->s_cnt = 0; - } - - if (bsdar->s_sn == NULL) { - if ((bsdar->s_sn = malloc(_INIT_SYMNAME_CAP)) == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "malloc failed"); - bsdar->s_sn_cap = _INIT_SYMNAME_CAP; - bsdar->s_sn_sz = 0; - } - - if (bsdar->s_cnt * sizeof(uint32_t) >= bsdar->s_so_cap) { - bsdar->s_so_cap *= 2; - bsdar->s_so = realloc(bsdar->s_so, bsdar->s_so_cap); - if (bsdar->s_so == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "realloc failed"); - } - bsdar->s_so[bsdar->s_cnt] = bsdar->rela_off; - bsdar->s_cnt++; - - /* - * The space required for holding one symbol name in sn table includes: - * strlen(name) + (1 for '\n') + (possibly 1 for padding). - */ - while (bsdar->s_sn_sz + strlen(name) + 2 > bsdar->s_sn_cap) { - bsdar->s_sn_cap *= 2; - bsdar->s_sn = realloc(bsdar->s_sn, bsdar->s_sn_cap); - if (bsdar->s_sn == NULL) - bsdar_errc(bsdar, EX_SOFTWARE, errno, "realloc failed"); - } - strncpy(&bsdar->s_sn[bsdar->s_sn_sz], name, strlen(name)); - bsdar->s_sn_sz += strlen(name); - bsdar->s_sn[bsdar->s_sn_sz++] = '\0'; -} |