summaryrefslogtreecommitdiffstats
path: root/src/ar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ar.c')
-rw-r--r--src/ar.c250
1 files changed, 105 insertions, 145 deletions
diff --git a/src/ar.c b/src/ar.c
index d70f1f46..7634d318 100644
--- a/src/ar.c
+++ b/src/ar.c
@@ -27,7 +27,6 @@
#include <libintl.h>
#include <limits.h>
#include <locale.h>
-#include <search.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
@@ -392,14 +391,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);
}
@@ -436,7 +435,6 @@ copy_content (Elf *elf, int newfd, off_t off, size_t n)
return write_retry (newfd, rawfile + off, n) != (ssize_t) n;
}
-
static int
do_oper_extract (int oper, const char *arfname, char **argv, int argc,
long int instance)
@@ -447,16 +445,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;
}
@@ -466,18 +454,7 @@ 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);
-
- if (hcreate (2 * argc) == 0)
- error (EXIT_FAILURE, errno, gettext ("cannot create hash table"));
-
- for (int cnt = 0; cnt < argc; ++cnt)
- {
- ENTRY entry = { .key = argv[cnt], .data = &argv[cnt] };
- if (hsearch (entry, ENTER) == NULL)
- error (EXIT_FAILURE, errno,
- gettext ("cannot insert into hash table"));
- }
+ int fd = open_archive (arfname, O_RDONLY | O_BINARY, 0, &elf, NULL, false);
struct stat st;
if (force_symtab)
@@ -516,12 +493,15 @@ 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);
- if (res != NULL && (instance < 0 || instance-- == 0)
- && !found[(char **) res->data - argv])
- found[(char **) res->data - argv] = do_extract = true;
+ for (int cnt = 0; cnt < argc; ++cnt)
+ {
+ if (!strcmp (arhdr->ar_name, argv[cnt]))
+ {
+ if ((instance < 0 || instance-- == 0) && !found[cnt])
+ found[cnt] = do_extract = true;
+ break;
+ }
+ }
}
if (do_extract)
@@ -546,7 +526,7 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
tp = localtime (&time);
}
- strftime (datestr, sizeof (datestr), "%b %e %H:%M %Y", tp);
+ strftime (datestr, sizeof (datestr), "%b %d %H:%M %Y", tp);
printf ("%c%c%c%c%c%c%c%c%c %u/%u %6ju %s %s\n",
(arhdr->ar_mode & S_IRUSR) ? 'r' : '-',
@@ -605,7 +585,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
@@ -653,13 +633,14 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
{
error (0, errno, gettext ("failed to write %s"), arhdr->ar_name);
status = 1;
- unlink (tempfname);
close (xfd);
+ unlink (tempfname);
goto next;
}
if (oper != oper_print)
{
+#if HAVE_DECL_FCHMOD
/* Fix up the mode. */
if (unlikely (fchmod (xfd, arhdr->ar_mode) != 0))
{
@@ -667,26 +648,11 @@ 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. */
+ close (xfd);
if (use_mkstemp)
{
int r;
@@ -698,7 +664,10 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
unlink (tempfname);
}
else
- r = rename (tempfname, arhdr->ar_name);
+ {
+ unlink (arhdr->ar_name);
+ r = rename (tempfname, arhdr->ar_name);
+ }
if (unlikely (r) != 0)
{
@@ -720,7 +689,10 @@ do_oper_extract (int oper, const char *arfname, char **argv, int argc,
unlink (tempfname);
}
else
- r = rename (tempfname, truncfname);
+ {
+ unlink (truncfname);
+ r = rename (tempfname, truncfname);
+ }
}
if (r != 0)
@@ -733,8 +705,6 @@ cannot rename temporary file to %.*s"),
}
}
}
-
- close (xfd);
}
}
@@ -744,8 +714,6 @@ cannot rename temporary file to %.*s"),
error (1, 0, "%s: %s", arfname, elf_errmsg (-1));
}
- hdestroy ();
-
if (force_symtab)
{
arlib_finalize ();
@@ -771,9 +739,9 @@ cannot rename temporary file to %.*s"),
{
// XXX Use /prof/self/fd/%d ???
nonew_unlink:
- unlink (tmpfname);
if (newfd != -1)
close (newfd);
+ unlink (tmpfname);
goto nonew;
}
@@ -793,20 +761,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, close (fd) != 0) ||
+ (fd = -1, unlink (arfname), rename (tmpfname, arfname) != 0))
goto nonew_unlink;
}
}
@@ -814,7 +787,8 @@ cannot rename temporary file to %.*s"),
elf_end (elf);
- close (fd);
+ if (fd != -1)
+ close (fd);
not_found (argc, argv, found);
@@ -917,18 +891,7 @@ 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);
-
- if (hcreate (2 * argc) == 0)
- error (EXIT_FAILURE, errno, gettext ("cannot create hash table"));
-
- for (int cnt = 0; cnt < argc; ++cnt)
- {
- ENTRY entry = { .key = argv[cnt], .data = &argv[cnt] };
- if (hsearch (entry, ENTER) == NULL)
- error (EXIT_FAILURE, errno,
- gettext ("cannot insert into hash table"));
- }
+ int fd = open_archive (arfname, O_RDONLY | O_BINARY, 0, &elf, &st, false);
arlib_init ();
@@ -947,12 +910,15 @@ 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);
- if (res != NULL && (instance < 0 || instance-- == 0)
- && !found[(char **) res->data - argv])
- found[(char **) res->data - argv] = do_delete = true;
+ for (int cnt = 0; cnt < argc; ++cnt)
+ {
+ if (!strcmp (arhdr->ar_name, argv[cnt]))
+ {
+ if ((instance < 0 || instance-- == 0) && !found[cnt])
+ found[cnt] = do_delete = true;
+ break;
+ }
+ }
}
if (do_delete)
@@ -993,8 +959,6 @@ do_oper_delete (const char *arfname, char **argv, int argc,
arlib_finalize ();
- hdestroy ();
-
/* Create a new, temporary file in the same directory as the
original file. */
char tmpfname[strlen (arfname) + 7];
@@ -1051,13 +1015,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, close (fd) != 0) ||
+ (fd = -1, unlink (arfname), rename (tmpfname, arfname) != 0))
goto nonew_unlink;
errout:
@@ -1065,7 +1035,8 @@ do_oper_delete (const char *arfname, char **argv, int argc,
arlib_fini ();
- close (fd);
+ if (fd != -1)
+ close (fd);
not_found (argc, argv, found);
@@ -1087,7 +1058,6 @@ no0print (bool ofmt, char *buf, int bufsize, long int val)
return true;
}
-
static int
do_oper_insert (int oper, const char *arfname, char **argv, int argc,
const char *member)
@@ -1095,7 +1065,7 @@ do_oper_insert (int oper, const char *arfname, char **argv, int argc,
int status = 0;
Elf *elf = NULL;
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);
/* List of the files we keep. */
struct armem *all = NULL;
@@ -1117,26 +1087,6 @@ do_oper_insert (int oper, const char *arfname, char **argv, int argc,
goto no_old;
}
- /* Store the names of all files from the command line in a hash
- table so that we can match it. Note that when no file name is
- given we are basically doing nothing except recreating the
- 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)
- error (EXIT_FAILURE, errno,
- gettext ("cannot insert into hash table"));
- }
- }
-
/* While iterating over the current content of the archive we must
determine a number of things: which archive members to keep,
which are replaced, and where to insert the new members. */
@@ -1174,25 +1124,32 @@ 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)
+ const char *arhdr_basename = basename (arhdr->ar_name);
+ for (int cnt = 0; cnt < argc; ++cnt)
{
- found[(char **) res->data - argv] = newp;
-
- /* If we insert before or after a certain element move
- all files to a special list. */
- if (unlikely (ipos != ipos_none || oper == oper_move))
- {
- if (after_memberelem == newp)
- /* Since we remove this element even though we should
- insert everything after it, we in fact insert
- everything after the previous element. */
- after_memberelem = all;
+ if (full_path && strcmp (arhdr_basename, basename (argv[cnt])))
+ continue;
+ else if (!full_path && strcmp (arhdr->ar_name, argv[cnt]))
+ continue;
+
+ if (found[cnt] == NULL)
+ {
+ found[cnt] = newp;
+
+ /* If we insert before or after a certain element move
+ all files to a special list. */
+ if (unlikely (ipos != ipos_none || oper == oper_move))
+ {
+ if (after_memberelem == newp)
+ /* Since we remove this element even though we should
+ insert everything after it, we in fact insert
+ everything after the previous element. */
+ after_memberelem = all;
- goto next;
+ goto next;
+ }
}
+ break;
}
}
@@ -1210,9 +1167,6 @@ do_oper_insert (int oper, const char *arfname, char **argv, int argc,
error (EXIT_FAILURE, 0, "%s: %s", arfname, elf_errmsg (-1));
}
- if (oper != oper_qappend)
- hdestroy ();
-
no_old:
if (member != NULL)
error (EXIT_FAILURE, 0, gettext ("position member %s not found"),
@@ -1251,7 +1205,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]);
@@ -1393,7 +1347,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);
@@ -1408,9 +1362,9 @@ do_oper_insert (int oper, const char *arfname, char **argv, int argc,
if (fd != -1)
{
// XXX Use /prof/self/fd/%d ???
- unlink (tmpfname);
if (newfd != -1)
close (newfd);
+ unlink (tmpfname);
}
nonew:
error (0, errno, gettext ("cannot create new file"));
@@ -1532,14 +1486,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, close(fd) != 0) ||
+ (fd = -1, unlink (arfname), rename (tmpfname, arfname) != 0)))
goto nonew_unlink;
errout: