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