arsup.c revision 218822
1/* arsup.c - Archive support for MRI compatibility 2 Copyright 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 3 2004, 2007 Free Software Foundation, Inc. 4 5 This file is part of GNU Binutils. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 20 21 22/* Contributed by Steve Chamberlain 23 sac@cygnus.com 24 25 This file looks after requests from arparse.y, to provide the MRI 26 style librarian command syntax + 1 word LIST. */ 27 28#include "sysdep.h" 29#include "bfd.h" 30#include "libiberty.h" 31#include "filenames.h" 32#include "bucomm.h" 33#include "arsup.h" 34 35static void map_over_list 36 (bfd *, void (*function) (bfd *, bfd *), struct list *); 37static void ar_directory_doer (bfd *, bfd *); 38static void ar_addlib_doer (bfd *, bfd *); 39 40extern int verbose; 41 42static bfd *obfd; 43static char *real_name; 44static FILE *outfile; 45 46static void 47map_over_list (bfd *arch, void (*function) (bfd *, bfd *), struct list *list) 48{ 49 bfd *head; 50 51 if (list == NULL) 52 { 53 bfd *next; 54 55 head = arch->archive_next; 56 while (head != NULL) 57 { 58 next = head->archive_next; 59 function (head, (bfd *) NULL); 60 head = next; 61 } 62 } 63 else 64 { 65 struct list *ptr; 66 67 /* This may appear to be a baroque way of accomplishing what we 68 want. however we have to iterate over the filenames in order 69 to notice where a filename is requested but does not exist in 70 the archive. Ditto mapping over each file each time -- we 71 want to hack multiple references. */ 72 for (ptr = list; ptr; ptr = ptr->next) 73 { 74 bfd_boolean found = FALSE; 75 bfd *prev = arch; 76 77 for (head = arch->archive_next; head; head = head->archive_next) 78 { 79 if (head->filename != NULL 80 && FILENAME_CMP (ptr->name, head->filename) == 0) 81 { 82 found = TRUE; 83 function (head, prev); 84 } 85 prev = head; 86 } 87 if (! found) 88 fprintf (stderr, _("No entry %s in archive.\n"), ptr->name); 89 } 90 } 91} 92 93 94 95static void 96ar_directory_doer (bfd *abfd, bfd *ignore ATTRIBUTE_UNUSED) 97{ 98 print_arelt_descr(outfile, abfd, verbose); 99} 100 101void 102ar_directory (char *ar_name, struct list *list, char *output) 103{ 104 bfd *arch; 105 106 arch = open_inarch (ar_name, (char *) NULL); 107 if (output) 108 { 109 outfile = fopen(output,"w"); 110 if (outfile == 0) 111 { 112 outfile = stdout; 113 fprintf (stderr,_("Can't open file %s\n"), output); 114 output = 0; 115 } 116 } 117 else 118 outfile = stdout; 119 120 map_over_list (arch, ar_directory_doer, list); 121 122 bfd_close (arch); 123 124 if (output) 125 fclose (outfile); 126} 127 128void 129prompt (void) 130{ 131 extern int interactive; 132 133 if (interactive) 134 { 135 printf ("AR >"); 136 fflush (stdout); 137 } 138} 139 140void 141maybequit (void) 142{ 143 if (! interactive) 144 xexit (9); 145} 146 147 148void 149ar_open (char *name, int t) 150{ 151 char *tname = (char *) xmalloc (strlen (name) + 10); 152 const char *bname = lbasename (name); 153 real_name = name; 154 155 /* Prepend tmp- to the beginning, to avoid file-name clashes after 156 truncation on filesystems with limited namespaces (DOS). */ 157 sprintf (tname, "%.*stmp-%s", (int) (bname - name), name, bname); 158 obfd = bfd_openw (tname, NULL); 159 160 if (!obfd) 161 { 162 fprintf (stderr, 163 _("%s: Can't open output archive %s\n"), 164 program_name, tname); 165 166 maybequit (); 167 } 168 else 169 { 170 if (!t) 171 { 172 bfd **ptr; 173 bfd *element; 174 bfd *ibfd; 175 176 ibfd = bfd_openr (name, NULL); 177 178 if (!ibfd) 179 { 180 fprintf (stderr,_("%s: Can't open input archive %s\n"), 181 program_name, name); 182 maybequit (); 183 return; 184 } 185 186 if (!bfd_check_format(ibfd, bfd_archive)) 187 { 188 fprintf (stderr, 189 _("%s: file %s is not an archive\n"), 190 program_name, name); 191 maybequit (); 192 return; 193 } 194 195 ptr = &(obfd->archive_head); 196 element = bfd_openr_next_archived_file (ibfd, NULL); 197 198 while (element) 199 { 200 *ptr = element; 201 ptr = &element->archive_next; 202 element = bfd_openr_next_archived_file (ibfd, element); 203 } 204 } 205 206 bfd_set_format (obfd, bfd_archive); 207 208 obfd->has_armap = 1; 209 } 210} 211 212static void 213ar_addlib_doer (bfd *abfd, bfd *prev) 214{ 215 /* Add this module to the output bfd. */ 216 if (prev != NULL) 217 prev->archive_next = abfd->archive_next; 218 219 abfd->archive_next = obfd->archive_head; 220 obfd->archive_head = abfd; 221} 222 223void 224ar_addlib (char *name, struct list *list) 225{ 226 if (obfd == NULL) 227 { 228 fprintf (stderr, _("%s: no output archive specified yet\n"), program_name); 229 maybequit (); 230 } 231 else 232 { 233 bfd *arch; 234 235 arch = open_inarch (name, (char *) NULL); 236 if (arch != NULL) 237 map_over_list (arch, ar_addlib_doer, list); 238 239 /* Don't close the bfd, since it will make the elements disappear. */ 240 } 241} 242 243void 244ar_addmod (struct list *list) 245{ 246 if (!obfd) 247 { 248 fprintf (stderr, _("%s: no open output archive\n"), program_name); 249 maybequit (); 250 } 251 else 252 { 253 while (list) 254 { 255 bfd *abfd = bfd_openr (list->name, NULL); 256 257 if (!abfd) 258 { 259 fprintf (stderr, _("%s: can't open file %s\n"), 260 program_name, list->name); 261 maybequit (); 262 } 263 else 264 { 265 abfd->archive_next = obfd->archive_head; 266 obfd->archive_head = abfd; 267 } 268 list = list->next; 269 } 270 } 271} 272 273 274void 275ar_clear (void) 276{ 277 if (obfd) 278 obfd->archive_head = 0; 279} 280 281void 282ar_delete (struct list *list) 283{ 284 if (!obfd) 285 { 286 fprintf (stderr, _("%s: no open output archive\n"), program_name); 287 maybequit (); 288 } 289 else 290 { 291 while (list) 292 { 293 /* Find this name in the archive. */ 294 bfd *member = obfd->archive_head; 295 bfd **prev = &(obfd->archive_head); 296 int found = 0; 297 298 while (member) 299 { 300 if (FILENAME_CMP(member->filename, list->name) == 0) 301 { 302 *prev = member->archive_next; 303 found = 1; 304 } 305 else 306 prev = &(member->archive_next); 307 308 member = member->archive_next; 309 } 310 311 if (!found) 312 { 313 fprintf (stderr, _("%s: can't find module file %s\n"), 314 program_name, list->name); 315 maybequit (); 316 } 317 318 list = list->next; 319 } 320 } 321} 322 323void 324ar_save (void) 325{ 326 if (!obfd) 327 { 328 fprintf (stderr, _("%s: no open output archive\n"), program_name); 329 maybequit (); 330 } 331 else 332 { 333 char *ofilename = xstrdup (bfd_get_filename (obfd)); 334 335 bfd_close (obfd); 336 337 smart_rename (ofilename, real_name, 0); 338 obfd = 0; 339 free (ofilename); 340 } 341} 342 343void 344ar_replace (struct list *list) 345{ 346 if (!obfd) 347 { 348 fprintf (stderr, _("%s: no open output archive\n"), program_name); 349 maybequit (); 350 } 351 else 352 { 353 while (list) 354 { 355 /* Find this name in the archive. */ 356 bfd *member = obfd->archive_head; 357 bfd **prev = &(obfd->archive_head); 358 int found = 0; 359 360 while (member) 361 { 362 if (FILENAME_CMP (member->filename, list->name) == 0) 363 { 364 /* Found the one to replace. */ 365 bfd *abfd = bfd_openr (list->name, 0); 366 367 if (!abfd) 368 { 369 fprintf (stderr, _("%s: can't open file %s\n"), 370 program_name, list->name); 371 maybequit (); 372 } 373 else 374 { 375 *prev = abfd; 376 abfd->archive_next = member->archive_next; 377 found = 1; 378 } 379 } 380 else 381 { 382 prev = &(member->archive_next); 383 } 384 member = member->archive_next; 385 } 386 387 if (!found) 388 { 389 bfd *abfd = bfd_openr (list->name, 0); 390 391 fprintf (stderr,_("%s: can't find module file %s\n"), 392 program_name, list->name); 393 if (!abfd) 394 { 395 fprintf (stderr, _("%s: can't open file %s\n"), 396 program_name, list->name); 397 maybequit (); 398 } 399 else 400 *prev = abfd; 401 } 402 403 list = list->next; 404 } 405 } 406} 407 408/* And I added this one. */ 409void 410ar_list (void) 411{ 412 if (!obfd) 413 { 414 fprintf (stderr, _("%s: no open output archive\n"), program_name); 415 maybequit (); 416 } 417 else 418 { 419 bfd *abfd; 420 421 outfile = stdout; 422 verbose =1 ; 423 printf (_("Current open archive is %s\n"), bfd_get_filename (obfd)); 424 425 for (abfd = obfd->archive_head; 426 abfd != (bfd *)NULL; 427 abfd = abfd->archive_next) 428 ar_directory_doer (abfd, (bfd *) NULL); 429 } 430} 431 432void 433ar_end (void) 434{ 435 if (obfd) 436 { 437 bfd_cache_close (obfd); 438 unlink (bfd_get_filename (obfd)); 439 } 440} 441 442void 443ar_extract (struct list *list) 444{ 445 if (!obfd) 446 { 447 fprintf (stderr, _("%s: no open archive\n"), program_name); 448 maybequit (); 449 } 450 else 451 { 452 while (list) 453 { 454 /* Find this name in the archive. */ 455 bfd *member = obfd->archive_head; 456 int found = 0; 457 458 while (member && !found) 459 { 460 if (FILENAME_CMP (member->filename, list->name) == 0) 461 { 462 extract_file (member); 463 found = 1; 464 } 465 466 member = member->archive_next; 467 } 468 469 if (!found) 470 { 471 bfd_openr (list->name, 0); 472 fprintf (stderr, _("%s: can't find module file %s\n"), 473 program_name, list->name); 474 } 475 476 list = list->next; 477 } 478 } 479} 480