1 /* arsup.c - Archive support for MRI compatibility 2 Copyright (C) 1992-2020 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@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, FALSE); 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; 265 266 #if BFD_SUPPORTS_PLUGINS 267 abfd = bfd_openr (list->name, "plugin"); 268 #else 269 abfd = bfd_openr (list->name, NULL); 270 #endif 271 if (!abfd) 272 { 273 fprintf (stderr, _("%s: can't open file %s\n"), 274 program_name, list->name); 275 maybequit (); 276 } 277 else 278 { 279 abfd->archive_next = obfd->archive_head; 280 obfd->archive_head = abfd; 281 } 282 list = list->next; 283 } 284 } 285 } 286 287 288 void 289 ar_clear (void) 290 { 291 if (obfd) 292 obfd->archive_head = 0; 293 } 294 295 void 296 ar_delete (struct list *list) 297 { 298 if (!obfd) 299 { 300 fprintf (stderr, _("%s: no open output archive\n"), program_name); 301 maybequit (); 302 } 303 else 304 { 305 while (list) 306 { 307 /* Find this name in the archive. */ 308 bfd *member = obfd->archive_head; 309 bfd **prev = &(obfd->archive_head); 310 int found = 0; 311 312 while (member) 313 { 314 if (FILENAME_CMP(member->filename, list->name) == 0) 315 { 316 *prev = member->archive_next; 317 found = 1; 318 } 319 else 320 prev = &(member->archive_next); 321 322 member = member->archive_next; 323 } 324 325 if (!found) 326 { 327 fprintf (stderr, _("%s: can't find module file %s\n"), 328 program_name, list->name); 329 maybequit (); 330 } 331 332 list = list->next; 333 } 334 } 335 } 336 337 void 338 ar_save (void) 339 { 340 if (!obfd) 341 { 342 fprintf (stderr, _("%s: no open output archive\n"), program_name); 343 maybequit (); 344 } 345 else 346 { 347 char *ofilename = xstrdup (bfd_get_filename (obfd)); 348 349 if (deterministic > 0) 350 obfd->flags |= BFD_DETERMINISTIC_OUTPUT; 351 352 bfd_close (obfd); 353 354 smart_rename (ofilename, real_name, 0); 355 obfd = 0; 356 free (ofilename); 357 } 358 } 359 360 void 361 ar_replace (struct list *list) 362 { 363 if (!obfd) 364 { 365 fprintf (stderr, _("%s: no open output archive\n"), program_name); 366 maybequit (); 367 } 368 else 369 { 370 while (list) 371 { 372 /* Find this name in the archive. */ 373 bfd *member = obfd->archive_head; 374 bfd **prev = &(obfd->archive_head); 375 int found = 0; 376 377 while (member) 378 { 379 if (FILENAME_CMP (member->filename, list->name) == 0) 380 { 381 /* Found the one to replace. */ 382 bfd *abfd = bfd_openr (list->name, NULL); 383 384 if (!abfd) 385 { 386 fprintf (stderr, _("%s: can't open file %s\n"), 387 program_name, list->name); 388 maybequit (); 389 } 390 else 391 { 392 *prev = abfd; 393 abfd->archive_next = member->archive_next; 394 found = 1; 395 } 396 } 397 else 398 { 399 prev = &(member->archive_next); 400 } 401 member = member->archive_next; 402 } 403 404 if (!found) 405 { 406 bfd *abfd = bfd_openr (list->name, NULL); 407 408 fprintf (stderr,_("%s: can't find module file %s\n"), 409 program_name, list->name); 410 if (!abfd) 411 { 412 fprintf (stderr, _("%s: can't open file %s\n"), 413 program_name, list->name); 414 maybequit (); 415 } 416 else 417 *prev = abfd; 418 } 419 420 list = list->next; 421 } 422 } 423 } 424 425 /* And I added this one. */ 426 void 427 ar_list (void) 428 { 429 if (!obfd) 430 { 431 fprintf (stderr, _("%s: no open output archive\n"), program_name); 432 maybequit (); 433 } 434 else 435 { 436 bfd *abfd; 437 438 outfile = stdout; 439 verbose =1 ; 440 printf (_("Current open archive is %s\n"), bfd_get_filename (obfd)); 441 442 for (abfd = obfd->archive_head; 443 abfd != (bfd *)NULL; 444 abfd = abfd->archive_next) 445 ar_directory_doer (abfd, (bfd *) NULL); 446 } 447 } 448 449 void 450 ar_end (void) 451 { 452 if (obfd) 453 { 454 bfd_cache_close (obfd); 455 unlink (bfd_get_filename (obfd)); 456 } 457 } 458 459 void 460 ar_extract (struct list *list) 461 { 462 if (!obfd) 463 { 464 fprintf (stderr, _("%s: no open archive\n"), program_name); 465 maybequit (); 466 } 467 else 468 { 469 while (list) 470 { 471 /* Find this name in the archive. */ 472 bfd *member = obfd->archive_head; 473 int found = 0; 474 475 while (member && !found) 476 { 477 if (FILENAME_CMP (member->filename, list->name) == 0) 478 { 479 extract_file (member); 480 found = 1; 481 } 482 483 member = member->archive_next; 484 } 485 486 if (!found) 487 { 488 bfd_openr (list->name, NULL); 489 fprintf (stderr, _("%s: can't find module file %s\n"), 490 program_name, list->name); 491 } 492 493 list = list->next; 494 } 495 } 496 } 497