📄 ar.c
字号:
if (stat (archive_filename, &sbuf) != 0) {#if !defined(__GO32__) || defined(__DJGPP__) /* FIXME: I don't understand why this fragment was ifndef'ed away for __GO32__; perhaps it was in the days of DJGPP v1.x. stat() works just fine in v2.x, so I think this should be removed. For now, I enable it for DJGPP v2. (And yes, I know this is all unused, but somebody, someday, might wish to resurrect this again... -- EZ. *//* KLUDGE ALERT! Temporary fix until I figger why stat() is wrong ... think it's buried in GO32's IDT - Jax */ if (errno != ENOENT) bfd_fatal (archive_filename);#endif newfile = true; } ofile = fopen (archive_filename, FOPEN_AUB); if (ofile == NULL) { perror (program_name); xexit (1); } temp = bfd_openr (archive_filename, NULL); if (temp == NULL) { bfd_fatal (archive_filename); } if (newfile == false) { if (bfd_check_format (temp, bfd_archive) != true) /* xgettext:c-format */ fatal (_("%s is not an archive"), archive_filename); } else { fwrite (ARMAG, 1, SARMAG, ofile); if (!silent_create) /* xgettext:c-format */ non_fatal (_("creating %s"), archive_filename); } if (ar_truncate) temp->flags |= BFD_TRADITIONAL_FORMAT; /* assume it's an achive, go straight to the end, sans $200 */ fseek (ofile, 0, 2); for (; files_to_append && *files_to_append; ++files_to_append) { struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append); if (hdr == NULL) { bfd_fatal (*files_to_append); } BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr)); ifile = fopen (*files_to_append, FOPEN_RB); if (ifile == NULL) { bfd_nonfatal (*files_to_append); } if (stat (*files_to_append, &sbuf) != 0) { bfd_nonfatal (*files_to_append); } tocopy = sbuf.st_size; /* XXX should do error-checking! */ fwrite (hdr, 1, sizeof (struct ar_hdr), ofile); while (tocopy > 0) { thistime = tocopy; if (thistime > BUFSIZE) thistime = BUFSIZE; fread (buf, 1, thistime, ifile); fwrite (buf, 1, thistime, ofile); tocopy -= thistime; } fclose (ifile); if ((sbuf.st_size % 2) == 1) putc ('\012', ofile); } fclose (ofile); bfd_close (temp); free (buf);}#endif /* 0 */static voidwrite_archive (iarch) bfd *iarch;{ bfd *obfd; char *old_name, *new_name; bfd *contents_head = iarch->next; old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1); strcpy (old_name, bfd_get_filename (iarch)); new_name = make_tempname (old_name); output_filename = new_name; obfd = bfd_openw (new_name, bfd_get_target (iarch)); if (obfd == NULL) bfd_fatal (old_name); output_bfd = obfd; bfd_set_format (obfd, bfd_archive); /* Request writing the archive symbol table unless we've been explicitly requested not to. */ obfd->has_armap = write_armap >= 0; if (ar_truncate) { /* This should really use bfd_set_file_flags, but that rejects archives. */ obfd->flags |= BFD_TRADITIONAL_FORMAT; } if (bfd_set_archive_head (obfd, contents_head) != true) bfd_fatal (old_name); if (!bfd_close (obfd)) bfd_fatal (old_name); output_bfd = NULL; output_filename = NULL; /* We don't care if this fails; we might be creating the archive. */ bfd_close (iarch); if (smart_rename (new_name, old_name, 0) != 0) xexit (1);}/* Return a pointer to the pointer to the entry which should be rplacd'd into when altering. DEFAULT_POS should be how to interpret pos_default, and should be a pos value. */static bfd **get_pos_bfd (contents, default_pos, default_posname) bfd **contents; enum pos default_pos; const char *default_posname;{ bfd **after_bfd = contents; enum pos realpos; const char *realposname; if (postype == pos_default) { realpos = default_pos; realposname = default_posname; } else { realpos = postype; realposname = posname; } if (realpos == pos_end) { while (*after_bfd) after_bfd = &((*after_bfd)->next); } else { for (; *after_bfd; after_bfd = &(*after_bfd)->next) if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0) { if (realpos == pos_after) after_bfd = &(*after_bfd)->next; break; } } return after_bfd;}static voiddelete_members (arch, files_to_delete) bfd *arch; char **files_to_delete;{ bfd **current_ptr_ptr; boolean found; boolean something_changed = false; int match_count; for (; *files_to_delete != NULL; ++files_to_delete) { /* In a.out systems, the armap is optional. It's also called __.SYMDEF. So if the user asked to delete it, we should remember that fact. This isn't quite right for COFF systems (where __.SYMDEF might be regular member), but it's very unlikely to be a problem. FIXME */ if (!strcmp (*files_to_delete, "__.SYMDEF")) { arch->has_armap = false; write_armap = -1; continue; } found = false; match_count = 0; current_ptr_ptr = &(arch->next); while (*current_ptr_ptr) { if (FILENAME_CMP (normalize (*files_to_delete, arch), (*current_ptr_ptr)->filename) == 0) { ++match_count; if (counted_name_mode && match_count != counted_name_counter) { /* Counting, and didn't match on count; go on to the next one. */ } else { found = true; something_changed = true; if (verbose) printf ("d - %s\n", *files_to_delete); *current_ptr_ptr = ((*current_ptr_ptr)->next); goto next_file; } } current_ptr_ptr = &((*current_ptr_ptr)->next); } if (verbose && found == false) { /* xgettext:c-format */ printf (_("No member named `%s'\n"), *files_to_delete); } next_file: ; } if (something_changed == true) write_archive (arch); else output_filename = NULL;}/* Reposition existing members within an archive */static voidmove_members (arch, files_to_move) bfd *arch; char **files_to_move;{ bfd **after_bfd; /* New entries go after this one */ bfd **current_ptr_ptr; /* cdr pointer into contents */ for (; *files_to_move; ++files_to_move) { current_ptr_ptr = &(arch->next); while (*current_ptr_ptr) { bfd *current_ptr = *current_ptr_ptr; if (FILENAME_CMP (normalize (*files_to_move, arch), current_ptr->filename) == 0) { /* Move this file to the end of the list - first cut from where it is. */ bfd *link; *current_ptr_ptr = current_ptr->next; /* Now glue to end */ after_bfd = get_pos_bfd (&arch->next, pos_end, NULL); link = *after_bfd; *after_bfd = current_ptr; current_ptr->next = link; if (verbose) printf ("m - %s\n", *files_to_move); goto next_file; } current_ptr_ptr = &((*current_ptr_ptr)->next); } /* xgettext:c-format */ fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename); next_file:; } write_archive (arch);}/* Ought to default to replacing in place, but this is existing practice! */static voidreplace_members (arch, files_to_move, quick) bfd *arch; char **files_to_move; boolean quick;{ boolean changed = false; bfd **after_bfd; /* New entries go after this one */ bfd *current; bfd **current_ptr; bfd *temp; while (files_to_move && *files_to_move) { if (! quick) { current_ptr = &arch->next; while (*current_ptr) { current = *current_ptr; /* For compatibility with existing ar programs, we permit the same file to be added multiple times. */ if (FILENAME_CMP (normalize (*files_to_move, arch), normalize (current->filename, arch)) == 0 && current->arelt_data != NULL) { if (newer_only) { struct stat fsbuf, asbuf; if (stat (*files_to_move, &fsbuf) != 0) { if (errno != ENOENT) bfd_fatal (*files_to_move); goto next_file; } if (bfd_stat_arch_elt (current, &asbuf) != 0) /* xgettext:c-format */ fatal (_("internal stat error on %s"), current->filename); if (fsbuf.st_mtime <= asbuf.st_mtime) goto next_file; } after_bfd = get_pos_bfd (&arch->next, pos_after, current->filename); temp = *after_bfd; *after_bfd = bfd_openr (*files_to_move, NULL); if (*after_bfd == (bfd *) NULL) { bfd_fatal (*files_to_move); } (*after_bfd)->next = temp; /* snip out this entry from the chain */ *current_ptr = (*current_ptr)->next; if (verbose) { printf ("r - %s\n", *files_to_move); } changed = true; goto next_file; } current_ptr = &(current->next); } } /* Add to the end of the archive. */ after_bfd = get_pos_bfd (&arch->next, pos_end, NULL); temp = *after_bfd; *after_bfd = bfd_openr (*files_to_move, NULL); if (*after_bfd == (bfd *) NULL) { bfd_fatal (*files_to_move); } if (verbose) { printf ("a - %s\n", *files_to_move); } (*after_bfd)->next = temp; changed = true; next_file:; files_to_move++; } if (changed) write_archive (arch); else output_filename = NULL;}static voidranlib_only (archname) const char *archname;{ bfd *arch; write_armap = 1; arch = open_inarch (archname, (char *) NULL); if (arch == NULL) xexit (1); write_archive (arch);}/* Update the timestamp of the symbol map of an archive. */static voidranlib_touch (archname) const char *archname;{#ifdef __GO32__ /* I don't think updating works on go32. */ ranlib_only (archname);#else int f; bfd *arch; char **matching; f = open (archname, O_RDWR | O_BINARY, 0); if (f < 0) { bfd_set_error (bfd_error_system_call); bfd_fatal (archname); } arch = bfd_fdopenr (archname, (const char *) NULL, f); if (arch == NULL) bfd_fatal (archname); if (! bfd_check_format_matches (arch, bfd_archive, &matching)) { bfd_nonfatal (archname); if (bfd_get_error () == bfd_error_file_ambiguously_recognized) { list_matching_formats (matching); free (matching); } xexit (1); } if (! bfd_has_map (arch)) /* xgettext:c-format */ fatal (_("%s: no archive map to update"), archname); bfd_update_armap_timestamp (arch); if (! bfd_close (arch)) bfd_fatal (archname);#endif}/* Things which are interesting to map over all or some of the files: */static voidprint_descr (abfd) bfd *abfd;{ print_arelt_descr (stdout, abfd, verbose);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -