summaryrefslogtreecommitdiffstats
path: root/src/ar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ar.c')
-rw-r--r--src/ar.c181
1 files changed, 92 insertions, 89 deletions
diff --git a/src/ar.c b/src/ar.c
index ec32cee5..6ad12ca8 100644
--- a/src/ar.c
+++ b/src/ar.c
@@ -393,14 +393,14 @@ open_archive (const char *arfname, int flags, int mode, Elf **elf,
if (elf != NULL)
{
- Elf_Cmd cmd = flags == O_RDONLY ? ELF_C_READ_MMAP : ELF_C_RDWR_MMAP;
+ Elf_Cmd cmd = flags == (O_RDONLY | O_BINARY) ? ELF_C_READ_MMAP : ELF_C_RDWR_MMAP;
*elf = elf_begin (fd, cmd, NULL);
if (*elf == NULL)
error (EXIT_FAILURE, 0, gettext ("cannot open archive '%s': %s"),
arfname, elf_errmsg (-1));
- if (flags == O_RDONLY && elf_kind (*elf) != ELF_K_AR)
+ if (flags == (O_RDONLY | O_BINARY) && elf_kind (*elf) != ELF_K_AR)
error (EXIT_FAILURE, 0, gettext ("%s: not an archive file"), arfname);
}
@@ -439,6 +439,20 @@ copy_content (Elf *elf, int newfd, off_t off, size_t n)
static int
+string_compare (const void *a, const void *b)
+{
+ return strcmp((const char *)a, (const char *)b);
+}
+
+
+void
+free_node (void *node)
+{
+ (void) node;
+}
+
+
+static int
do_oper_extract (int oper, const char *arfname, char **argv, int argc,
long int instance)
{
@@ -448,16 +462,6 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
size_t name_max = 0;
inline bool should_truncate_fname (void)
{
- if (errno == ENAMETOOLONG && allow_truncate_fname)
- {
- if (name_max == 0)
- {
- long int len = pathconf (".", _PC_NAME_MAX);
- if (len > 0)
- name_max = len;
- }
- return name_max != 0;
- }
return false;
}
@@ -467,15 +471,13 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
int status = 0;
Elf *elf;
- int fd = open_archive (arfname, O_RDONLY, 0, &elf, NULL, false);
+ int fd = open_archive (arfname, O_RDONLY | O_BINARY, 0, &elf, NULL, false);
- if (hcreate (2 * argc) == 0)
- error (EXIT_FAILURE, errno, gettext ("cannot create hash table"));
+ void *root = NULL;
for (int cnt = 0; cnt < argc; ++cnt)
{
- ENTRY entry = { .key = argv[cnt], .data = &argv[cnt] };
- if (hsearch (entry, ENTER) == NULL)
+ if (tsearch (argv[cnt], &root, &string_compare) == NULL)
error (EXIT_FAILURE, errno,
gettext ("cannot insert into hash table"));
}
@@ -517,12 +519,10 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
bool do_extract = argc <= 0;
if (!do_extract)
{
- ENTRY entry;
- entry.key = arhdr->ar_name;
- ENTRY *res = hsearch (entry, FIND);
+ void *res = tfind (arhdr->ar_name, &root, &string_compare);
if (res != NULL && (instance < 0 || instance-- == 0)
- && !found[(char **) res->data - argv])
- found[(char **) res->data - argv] = do_extract = true;
+ && !found[(char **) res - argv])
+ found[(char **) res - argv] = do_extract = true;
}
if (do_extract)
@@ -540,7 +540,7 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
else if (oper == oper_list)
{
char datestr[100];
- strftime (datestr, sizeof (datestr), "%b %e %H:%M %Y",
+ strftime (datestr, sizeof (datestr), "%b %d %H:%M %Y",
localtime (&arhdr->ar_date));
printf ("%c%c%c%c%c%c%c%c%c %u/%u %6ju %s %s\n",
@@ -600,7 +600,7 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
{
/* We cannot create a temporary file. Try to overwrite
the file or create it if it does not exist. */
- int flags = O_WRONLY | O_CREAT;
+ int flags = O_WRONLY | O_BINARY | O_CREAT;
if (dont_replace_existing)
flags |= O_EXCL;
else
@@ -655,6 +655,7 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
if (oper != oper_print)
{
+#if HAVE_DECL_FCHMOD
/* Fix up the mode. */
if (unlikely (fchmod (xfd, arhdr->ar_mode) != 0))
{
@@ -662,23 +663,7 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
arhdr->ar_name);
status = 0;
}
-
- if (preserve_dates)
- {
- struct timespec tv[2];
- tv[0].tv_sec = arhdr->ar_date;
- tv[0].tv_nsec = 0;
- tv[1].tv_sec = arhdr->ar_date;
- tv[1].tv_nsec = 0;
-
- if (unlikely (futimens (xfd, tv) != 0))
- {
- error (0, errno,
- gettext ("cannot change modification time of %s"),
- arhdr->ar_name);
- status = 1;
- }
- }
+#endif
/* If we used a temporary file, move it do the right
name now. */
@@ -739,7 +724,8 @@ cannot rename temporary file to %.*s"),
error (1, 0, "%s: %s", arfname, elf_errmsg (-1));
}
- hdestroy ();
+ tdestroy(root, &free_node);
+ root = NULL;
if (force_symtab)
{
@@ -788,20 +774,25 @@ cannot rename temporary file to %.*s"),
!= (ssize_t) symtab.symsofflen)
|| (write_retry (newfd, symtab.symsname,
symtab.symsnamelen)
- != (ssize_t) symtab.symsnamelen)))
+ != (ssize_t) symtab.symsnamelen))) ||
/* Even if the original file had content before the
symbol table, we write it in the correct order. */
- || (index_off != SARMAG
- && copy_content (elf, newfd, SARMAG, index_off - SARMAG))
- || copy_content (elf, newfd, rest_off, st.st_size - rest_off)
+ (index_off != SARMAG
+ && copy_content (elf, newfd, SARMAG, index_off - SARMAG)) ||
+ copy_content (elf, newfd, rest_off, st.st_size - rest_off) ||
+#if HAVE_DECL_FCHMOD
/* Set the mode of the new file to the same values the
original file has. */
- || fchmod (newfd, st.st_mode & ALLPERMS) != 0
+ fchmod (newfd, st.st_mode & 07777) != 0 ||
+#endif
+ (
+#if HAVE_DECL_FCHOWN
/* Never complain about fchown failing. */
- || (({asm ("" :: "r" (fchown (newfd, st.st_uid,
+ ({asm ("" :: "r" (fchown (newfd, st.st_uid,
st.st_gid))); }),
- close (newfd) != 0)
- || (newfd = -1, rename (tmpfname, arfname) != 0))
+#endif
+ close (newfd) != 0) ||
+ (newfd = -1, rename (tmpfname, arfname) != 0))
goto nonew_unlink;
}
}
@@ -912,15 +903,13 @@ do_oper_delete (const char *arfname, char **argv, int argc,
int status = 0;
Elf *elf;
struct stat st;
- int fd = open_archive (arfname, O_RDONLY, 0, &elf, &st, false);
+ int fd = open_archive (arfname, O_RDONLY | O_BINARY, 0, &elf, &st, false);
- if (hcreate (2 * argc) == 0)
- error (EXIT_FAILURE, errno, gettext ("cannot create hash table"));
+ void *root = NULL;
for (int cnt = 0; cnt < argc; ++cnt)
{
- ENTRY entry = { .key = argv[cnt], .data = &argv[cnt] };
- if (hsearch (entry, ENTER) == NULL)
+ if (tsearch (argv[cnt], &root, &string_compare) == NULL)
error (EXIT_FAILURE, errno,
gettext ("cannot insert into hash table"));
}
@@ -942,12 +931,10 @@ do_oper_delete (const char *arfname, char **argv, int argc,
bool do_delete = argc <= 0;
if (!do_delete)
{
- ENTRY entry;
- entry.key = arhdr->ar_name;
- ENTRY *res = hsearch (entry, FIND);
+ void *res = tfind (arhdr->ar_name, &root, &string_compare);
if (res != NULL && (instance < 0 || instance-- == 0)
- && !found[(char **) res->data - argv])
- found[(char **) res->data - argv] = do_delete = true;
+ && !found[(char **) res - argv])
+ found[(char **) res - argv] = do_delete = true;
}
if (do_delete)
@@ -988,7 +975,8 @@ do_oper_delete (const char *arfname, char **argv, int argc,
arlib_finalize ();
- hdestroy ();
+ tdestroy (root, &free_node);
+ root = NULL;
/* Create a new, temporary file in the same directory as the
original file. */
@@ -1046,13 +1034,19 @@ do_oper_delete (const char *arfname, char **argv, int argc,
goto nonew_unlink;
}
- /* Set the mode of the new file to the same values the original file
- has. */
- if (fchmod (newfd, st.st_mode & ALLPERMS) != 0
+ if (
+#if HAVE_DECL_FCHMOD
+ /* Set the mode of the new file to the same values the original file
+ has. */
+ fchmod (newfd, st.st_mode & 07777) != 0 ||
+#endif
+ (
+#if HAVE_DECL_FCHOWN
/* Never complain about fchown failing. */
- || (({asm ("" :: "r" (fchown (newfd, st.st_uid, st.st_gid))); }),
- close (newfd) != 0)
- || (newfd = -1, rename (tmpfname, arfname) != 0))
+ ({asm ("" :: "r" (fchown (newfd, st.st_uid, st.st_gid))); }),
+#endif
+ close (newfd) != 0) ||
+ (newfd = -1, rename (tmpfname, arfname) != 0))
goto nonew_unlink;
errout:
@@ -1080,13 +1074,21 @@ no0print (bool ofmt, char *buf, int bufsize, long int val)
static int
+basename_compare(const void *a, const void *b)
+{
+ return strcmp(basename((const char *)a), basename((const char *)b));
+}
+
+
+static int
do_oper_insert (int oper, const char *arfname, char **argv, int argc,
const char *member)
{
int status = 0;
Elf *elf;
struct stat st;
- int fd = open_archive (arfname, O_RDONLY, 0, &elf, &st, oper != oper_move);
+ int fd = open_archive (arfname, O_RDONLY | O_BINARY, 0, &elf, &st, oper != oper_move);
+ void *root = NULL;
/* List of the files we keep. */
struct armem *all = NULL;
@@ -1114,15 +1116,9 @@ do_oper_insert (int oper, const char *arfname, char **argv, int argc,
index. */
if (oper != oper_qappend)
{
- if (hcreate (2 * argc) == 0)
- error (EXIT_FAILURE, errno, gettext ("cannot create hash table"));
-
for (int cnt = 0; cnt < argc; ++cnt)
{
- ENTRY entry;
- entry.key = full_path ? argv[cnt] : basename (argv[cnt]);
- entry.data = &argv[cnt];
- if (hsearch (entry, ENTER) == NULL)
+ if (tsearch (argv[cnt], &root, full_path ? &basename_compare : &string_compare) == NULL)
error (EXIT_FAILURE, errno,
gettext ("cannot insert into hash table"));
}
@@ -1165,12 +1161,10 @@ do_oper_insert (int oper, const char *arfname, char **argv, int argc,
member = NULL;
}
- ENTRY entry;
- entry.key = arhdr->ar_name;
- ENTRY *res = hsearch (entry, FIND);
- if (res != NULL && found[(char **) res->data - argv] == NULL)
+ void *res = tfind(arhdr->ar_name, &root, full_path ? &basename_compare : &string_compare);
+ if (res != NULL && found[(char **) res - argv] == NULL)
{
- found[(char **) res->data - argv] = newp;
+ found[(char **) res - argv] = newp;
/* If we insert before or after a certain element move
all files to a special list. */
@@ -1202,7 +1196,10 @@ do_oper_insert (int oper, const char *arfname, char **argv, int argc,
}
if (oper != oper_qappend)
- hdestroy ();
+ {
+ tdestroy(root, &free_node);
+ root = NULL;
+ }
no_old:
if (member != NULL)
@@ -1242,7 +1239,7 @@ do_oper_insert (int oper, const char *arfname, char **argv, int argc,
struct stat newst;
Elf *newelf;
- int newfd = open (argv[cnt], O_RDONLY);
+ int newfd = open (argv[cnt], O_RDONLY | O_BINARY);
if (newfd == -1)
{
error (0, errno, gettext ("cannot open %s"), argv[cnt]);
@@ -1386,7 +1383,7 @@ do_oper_insert (int oper, const char *arfname, char **argv, int argc,
newfd = mkstemp (tmpfname);
else
{
- newfd = open (arfname, O_RDWR | O_CREAT | O_EXCL, DEFFILEMODE);
+ newfd = open (arfname, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0666);
if (newfd == -1 && errno == EEXIST)
/* Bah, first the file did not exist, now it does. Restart. */
return do_oper_insert (oper, arfname, argv, argc, member);
@@ -1503,14 +1500,20 @@ do_oper_insert (int oper, const char *arfname, char **argv, int argc,
goto nonew_unlink;
}
- /* Set the mode of the new file to the same values the original file
- has. */
if (fd != -1
- && (fchmod (newfd, st.st_mode & ALLPERMS) != 0
+ && (
+#if HAVE_DECL_FCHMOD
+ /* Set the mode of the new file to the same values the original file
+ has. */
+ fchmod (newfd, st.st_mode & 07777) != 0 ||
+#endif
+ (
+#if HAVE_DECL_FCHOWN
/* Never complain about fchown failing. */
- || (({asm ("" :: "r" (fchown (newfd, st.st_uid, st.st_gid))); }),
- close (newfd) != 0)
- || (newfd = -1, rename (tmpfname, arfname) != 0)))
+ ({asm ("" :: "r" (fchown (newfd, st.st_uid, st.st_gid))); }),
+#endif
+ close (newfd) != 0) ||
+ (newfd = -1, rename (tmpfname, arfname) != 0)))
goto nonew_unlink;
errout: