📄 ar.c
字号:
++arg_ptr; /* compatibility */ while ((c = *arg_ptr++) != '\0') { switch (c) { case 'd': case 'm': case 'p': case 'q': case 'r': case 't': case 'x': if (operation != none) fatal (_("two different operation options specified")); switch (c) { case 'd': operation = delete; operation_alters_arch = true; break; case 'm': operation = move; operation_alters_arch = true; break; case 'p': operation = print_files; break; case 'q': operation = quick_append; operation_alters_arch = true; break; case 'r': operation = replace; operation_alters_arch = true; break; case 't': operation = print_table; break; case 'x': operation = extract; break; } case 'l': break; case 'c': silent_create = 1; break; case 'o': preserve_dates = 1; break; case 'V': show_version = true; break; case 's': write_armap = 1; break; case 'S': write_armap = -1; break; case 'u': newer_only = 1; break; case 'v': verbose = 1; break; case 'a': postype = pos_after; break; case 'b': postype = pos_before; break; case 'i': postype = pos_before; break; case 'M': mri_mode = 1; break; case 'N': counted_name_mode = true; break; case 'f': ar_truncate = true; break; case 'P': full_pathname = true; break; default: /* xgettext:c-format */ non_fatal (_("illegal option -- %c"), c); usage (0); } } if (show_version) print_version ("ar"); if (argc < 3) usage (0); if (mri_mode) { mri_emul (); } else { bfd *arch; /* We can't write an armap when using ar q, so just do ar r instead. */ if (operation == quick_append && write_armap) operation = replace; if ((operation == none || operation == print_table) && write_armap == 1) { ranlib_only (argv[2]); xexit (0); } if (operation == none) fatal (_("no operation specified")); if (newer_only && operation != replace) fatal (_("`u' is only meaningful with the `r' option.")); arg_index = 2; if (postype != pos_default) posname = argv[arg_index++]; if (counted_name_mode) { if (operation != extract && operation != delete) fatal (_("`N' is only meaningful with the `x' and `d' options.")); counted_name_counter = atoi (argv[arg_index++]); if (counted_name_counter <= 0) fatal (_("Value for `N' must be positive.")); } inarch_filename = argv[arg_index++]; files = arg_index < argc ? argv + arg_index : NULL; file_count = argc - arg_index;#if 0 /* We don't use do_quick_append any more. Too many systems expect ar to always rebuild the symbol table even when q is used. */ /* We can't do a quick append if we need to construct an extended name table, because do_quick_append won't be able to rebuild the name table. Unfortunately, at this point we don't actually know the maximum name length permitted by this object file format. So, we guess. FIXME. */ if (operation == quick_append && ! ar_truncate) { char **chk; for (chk = files; chk != NULL && *chk != '\0'; chk++) { if (strlen (normalize (*chk, (bfd *) NULL)) > 14) { operation = replace; break; } } } if (operation == quick_append) { /* Note that quick appending to a non-existent archive creates it, even if there are no files to append. */ do_quick_append (inarch_filename, files); xexit (0); }#endif arch = open_inarch (inarch_filename, files == NULL ? (char *) NULL : files[0]); switch (operation) { case print_table: map_over_members (arch, print_descr, files, file_count); break; case print_files: map_over_members (arch, print_contents, files, file_count); break; case extract: map_over_members (arch, extract_file, files, file_count); break; case delete: if (files != NULL) delete_members (arch, files); else output_filename = NULL; break; case move: if (files != NULL) move_members (arch, files); else output_filename = NULL; break; case replace: case quick_append: if (files != NULL || write_armap > 0) replace_members (arch, files, operation == quick_append); else output_filename = NULL; break; /* Shouldn't happen! */ default: /* xgettext:c-format */ fatal (_("internal error -- this option not implemented")); } } END_PROGRESS (program_name); xexit (0); return 0;}bfd *open_inarch (archive_filename, file) const char *archive_filename; const char *file;{ const char *target; bfd **last_one; bfd *next_one; struct stat sbuf; bfd *arch; char **matching; bfd_set_error (bfd_error_no_error); target = NULL; 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. -- 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 if (!operation_alters_arch) { fprintf (stderr, "%s: ", program_name); perror (archive_filename); maybequit (); return NULL; } /* Try to figure out the target to use for the archive from the first object on the list. */ if (file != NULL) { bfd *obj; obj = bfd_openr (file, NULL); if (obj != NULL) { if (bfd_check_format (obj, bfd_object)) target = bfd_get_target (obj); (void) bfd_close (obj); } } /* Create an empty archive. */ arch = bfd_openw (archive_filename, target); if (arch == NULL || ! bfd_set_format (arch, bfd_archive) || ! bfd_close (arch)) bfd_fatal (archive_filename); /* If we die creating a new archive, don't leave it around. */ output_filename = archive_filename; } arch = bfd_openr (archive_filename, target); if (arch == NULL) { bloser: bfd_fatal (archive_filename); } if (! bfd_check_format_matches (arch, bfd_archive, &matching)) { bfd_nonfatal (archive_filename); if (bfd_get_error () == bfd_error_file_ambiguously_recognized) { list_matching_formats (matching); free (matching); } xexit (1); } last_one = &(arch->next); /* Read all the contents right away, regardless. */ for (next_one = bfd_openr_next_archived_file (arch, NULL); next_one; next_one = bfd_openr_next_archived_file (arch, next_one)) { PROGRESS (1); *last_one = next_one; last_one = &next_one->next; } *last_one = (bfd *) NULL; if (bfd_get_error () != bfd_error_no_more_archived_files) goto bloser; return arch;}static voidprint_contents (abfd) bfd *abfd;{ int ncopied = 0; char *cbuf = xmalloc (BUFSIZE); struct stat buf; long size; if (bfd_stat_arch_elt (abfd, &buf) != 0) /* xgettext:c-format */ fatal (_("internal stat error on %s"), bfd_get_filename (abfd)); if (verbose) /* xgettext:c-format */ printf (_("\n<member %s>\n\n"), bfd_get_filename (abfd)); bfd_seek (abfd, 0, SEEK_SET); size = buf.st_size; while (ncopied < size) { int nread; int tocopy = size - ncopied; if (tocopy > BUFSIZE) tocopy = BUFSIZE; nread = bfd_read (cbuf, 1, tocopy, abfd); /* oops -- broke abstraction! */ if (nread != tocopy) /* xgettext:c-format */ fatal (_("%s is not a valid archive"), bfd_get_filename (bfd_my_archive (abfd))); fwrite (cbuf, 1, nread, stdout); ncopied += tocopy; } free (cbuf);}/* Extract a member of the archive into its own file. We defer opening the new file until after we have read a BUFSIZ chunk of the old one, since we know we have just read the archive header for the old one. Since most members are shorter than BUFSIZ, this means we will read the old header, read the old data, write a new inode for the new file, and write the new data, and be done. This 'optimization' is what comes from sitting next to a bare disk and hearing it every time it seeks. -- Gnu Gilmore */voidextract_file (abfd) bfd *abfd;{ FILE *ostream; char *cbuf = xmalloc (BUFSIZE); int nread, tocopy; long ncopied = 0; long size; struct stat buf; if (bfd_stat_arch_elt (abfd, &buf) != 0) /* xgettext:c-format */ fatal (_("internal stat error on %s"), bfd_get_filename (abfd)); size = buf.st_size; if (size < 0) /* xgettext:c-format */ fatal (_("stat returns negative size for %s"), bfd_get_filename (abfd)); if (verbose) printf ("x - %s\n", bfd_get_filename (abfd)); bfd_seek (abfd, 0, SEEK_SET); ostream = NULL; if (size == 0) { /* Seems like an abstraction violation, eh? Well it's OK! */ output_filename = bfd_get_filename (abfd); ostream = fopen (bfd_get_filename (abfd), FOPEN_WB); if (ostream == NULL) { perror (bfd_get_filename (abfd)); xexit (1); } output_file = ostream; } else while (ncopied < size) { tocopy = size - ncopied; if (tocopy > BUFSIZE) tocopy = BUFSIZE; nread = bfd_read (cbuf, 1, tocopy, abfd); if (nread != tocopy) /* xgettext:c-format */ fatal (_("%s is not a valid archive"), bfd_get_filename (bfd_my_archive (abfd))); /* See comment above; this saves disk arm motion */ if (ostream == NULL) { /* Seems like an abstraction violation, eh? Well it's OK! */ output_filename = bfd_get_filename (abfd); ostream = fopen (bfd_get_filename (abfd), FOPEN_WB); if (ostream == NULL) { perror (bfd_get_filename (abfd)); xexit (1); } output_file = ostream; } fwrite (cbuf, 1, nread, ostream); ncopied += tocopy; } if (ostream != NULL) fclose (ostream); output_file = NULL; output_filename = NULL; chmod (bfd_get_filename (abfd), buf.st_mode); if (preserve_dates) set_times (bfd_get_filename (abfd), &buf); free (cbuf);}#if 0/* We don't use this anymore. Too many systems expect ar to rebuild the symbol table even when q is used. *//* Just do it quickly; don't worry about dups, armap, or anything like that */static voiddo_quick_append (archive_filename, files_to_append) const char *archive_filename; char **files_to_append;{ FILE *ofile, *ifile; char *buf = xmalloc (BUFSIZE); long tocopy, thistime; bfd *temp; struct stat sbuf; boolean newfile = false; bfd_set_error (bfd_error_no_error);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -