diff options
Diffstat (limited to 'src/ar.c')
| -rw-r--r-- | src/ar.c | 181 |
1 files changed, 92 insertions, 89 deletions
@@ -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: |
