1 /* arsup.c - Archive support for MRI compatibility 2 Copyright (C) 1992-2014 Free Software Foundation, Inc. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21 22 /* Contributed by Steve Chamberlain 23 sac (at) 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 35 static void map_over_list 36 (bfd *, void (*function) (bfd *, bfd *), struct list *); 37 static void ar_directory_doer (bfd *, bfd *); 38 static void ar_addlib_doer (bfd *, bfd *); 39 40 extern int verbose; 41 extern int deterministic; 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 = (char *) xmalloc (strlen (name) + 10); 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 sprintf (tname, "%.*stmp-%s", (int) (bname - name), name, bname); 159 obfd = bfd_openw (tname, NULL); 160 161 if (!obfd) 162 { 163 fprintf (stderr, 164 _("%s: Can't open output archive %s\n"), 165 program_name, tname); 166 167 maybequit (); 168 } 169 else 170 { 171 if (!t) 172 { 173 bfd **ptr; 174 bfd *element; 175 bfd *ibfd; 176 177 ibfd = bfd_openr (name, NULL); 178 179 if (!ibfd) 180 { 181 fprintf (stderr,_("%s: Can't open input archive %s\n"), 182 program_name, name); 183 maybequit (); 184 return; 185 } 186 187 if (!bfd_check_format(ibfd, bfd_archive)) 188 { 189 fprintf (stderr, 190 _("%s: file %s is not an archive\n"), 191 program_name, name); 192 maybequit (); 193 return; 194 } 195 196 ptr = &(obfd->archive_head); 197 element = bfd_openr_next_archived_file (ibfd, NULL); 198 199 while (element) 200 { 201 *ptr = element; 202 ptr = &element->archive_next; 203 element = bfd_openr_next_archived_file (ibfd, element); 204 } 205 } 206 207 bfd_set_format (obfd, bfd_archive); 208 209 obfd->has_armap = 1; 210 obfd->is_thin_archive = 0; 211 } 212 } 213 214 static void 215 ar_addlib_doer (bfd *abfd, bfd *prev) 216 { 217 /* Add this module to the output bfd. */ 218 if (prev != NULL) 219 prev->archive_next = abfd->archive_next; 220 221 abfd->archive_next = obfd->archive_head; 222 obfd->archive_head = abfd; 223 } 224 225 void 226 ar_addlib (char *name, struct list *list) 227 { 228 if (obfd == NULL) 229 { 230 fprintf (stderr, _("%s: no output archive specified yet\n"), program_name); 231 maybequit (); 232 } 233 else 234 { 235 bfd *arch; 236 237 arch = open_inarch (name, (char *) NULL); 238 if (arch != NULL) 239 map_over_list (arch, ar_addlib_doer, list); 240 241 /* Don't close the bfd, since it will make the elements disappear. */ 242 } 243 } 244 245 void 246 ar_addmod (struct list *list) 247 { 248 if (!obfd) 249 { 250 fprintf (stderr, _("%s: no open output archive\n"), program_name); 251 maybequit (); 252 } 253 else 254 { 255 while (list) 256 { 257 bfd *abfd = bfd_openr (list->name, NULL); 258 259 if (!abfd) 260 { 261 fprintf (stderr, _("%s: can't open file %s\n"), 262 program_name, list->name); 263 maybequit (); 264 } 265 else 266 { 267 abfd->archive_next = obfd->archive_head; 268 obfd->archive_head = abfd; 269 } 270 list = list->next; 271 } 272 } 273 } 274 275 276 void 277 ar_clear (void) 278 { 279 if (obfd) 280 obfd->archive_head = 0; 281 } 282 283 void 284 ar_delete (struct list *list) 285 { 286 if (!obfd) 287 { 288 fprintf (stderr, _("%s: no open output archive\n"), program_name); 289 maybequit (); 290 } 291 else 292 { 293 while (list) 294 { 295 /* Find this name in the archive. */ 296 bfd *member = obfd->archive_head; 297 bfd **prev = &(obfd->archive_head); 298 int found = 0; 299 300 while (member) 301 { 302 if (FILENAME_CMP(member->filename, list->name) == 0) 303 { 304 *prev = member->archive_next; 305 found = 1; 306 } 307 else 308 prev = &(member->archive_next); 309 310 member = member->archive_next; 311 } 312 313 if (!found) 314 { 315 fprintf (stderr, _("%s: can't find module file %s\n"), 316 program_name, list->name); 317 maybequit (); 318 } 319 320 list = list->next; 321 } 322 } 323 } 324 325 void 326 ar_save (void) 327 { 328 if (!obfd) 329 { 330 fprintf (stderr, _("%s: no open output archive\n"), program_name); 331 maybequit (); 332 } 333 else 334 { 335 char *ofilename = xstrdup (bfd_get_filename (obfd)); 336 337 if (deterministic > 0) 338 obfd->flags |= BFD_DETERMINISTIC_OUTPUT; 339 340 bfd_close (obfd); 341 342 smart_rename (ofilename, real_name, 0); 343 obfd = 0; 344 free (ofilename); 345 } 346 } 347 348 void 349 ar_replace (struct list *list) 350 { 351 if (!obfd) 352 { 353 fprintf (stderr, _("%s: no open output archive\n"), program_name); 354 maybequit (); 355 } 356 else 357 { 358 while (list) 359 { 360 /* Find this name in the archive. */ 361 bfd *member = obfd->archive_head; 362 bfd **prev = &(obfd->archive_head); 363 int found = 0; 364 365 while (member) 366 { 367 if (FILENAME_CMP (member->filename, list->name) == 0) 368 { 369 /* Found the one to replace. */ 370 bfd *abfd = bfd_openr (list->name, 0); 371 372 if (!abfd) 373 { 374 fprintf (stderr, _("%s: can't open file %s\n"), 375 program_name, list->name); 376 maybequit (); 377 } 378 else 379 { 380 *prev = abfd; 381 abfd->archive_next = member->archive_next; 382 found = 1; 383 } 384 } 385 else 386 { 387 prev = &(member->archive_next); 388 } 389 member = member->archive_next; 390 } 391 392 if (!found) 393 { 394 bfd *abfd = bfd_openr (list->name, 0); 395 396 fprintf (stderr,_("%s: can't find module file %s\n"), 397 program_name, list->name); 398 if (!abfd) 399 { 400 fprintf (stderr, _("%s: can't open file %s\n"), 401 program_name, list->name); 402 maybequit (); 403 } 404 else 405 *prev = abfd; 406 } 407 408 list = list->next; 409 } 410 } 411 } 412 413 /* And I added this one. */ 414 void 415 ar_list (void) 416 { 417 if (!obfd) 418 { 419 fprintf (stderr, _("%s: no open output archive\n"), program_name); 420 maybequit (); 421 } 422 else 423 { 424 bfd *abfd; 425 426 outfile = stdout; 427 verbose =1 ; 428 printf (_("Current open archive is %s\n"), bfd_get_filename (obfd)); 429 430 for (abfd = obfd->archive_head; 431 abfd != (bfd *)NULL; 432 abfd = abfd->archive_next) 433 ar_directory_doer (abfd, (bfd *) NULL); 434 } 435 } 436 437 void 438 ar_end (void) 439 { 440 if (obfd) 441 { 442 bfd_cache_close (obfd); 443 unlink (bfd_get_filename (obfd)); 444 } 445 } 446 447 void 448 ar_extract (struct list *list) 449 { 450 if (!obfd) 451 { 452 fprintf (stderr, _("%s: no open archive\n"), program_name); 453 maybequit (); 454 } 455 else 456 { 457 while (list) 458 { 459 /* Find this name in the archive. */ 460 bfd *member = obfd->archive_head; 461 int found = 0; 462 463 while (member && !found) 464 { 465 if (FILENAME_CMP (member->filename, list->name) == 0) 466 { 467 extract_file (member); 468 found = 1; 469 } 470 471 member = member->archive_next; 472 } 473 474 if (!found) 475 { 476 bfd_openr (list->name, 0); 477 fprintf (stderr, _("%s: can't find module file %s\n"), 478 program_name, list->name); 479 } 480 481 list = list->next; 482 } 483 } 484 } 485