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