1 /* arsup.c - Archive support for MRI compatibility 2 Copyright (C) 1992-2016 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); 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 if (deterministic > 0) 345 obfd->flags |= BFD_DETERMINISTIC_OUTPUT; 346 347 bfd_close (obfd); 348 349 smart_rename (ofilename, real_name, 0); 350 obfd = 0; 351 free (ofilename); 352 } 353 } 354 355 void 356 ar_replace (struct list *list) 357 { 358 if (!obfd) 359 { 360 fprintf (stderr, _("%s: no open output archive\n"), program_name); 361 maybequit (); 362 } 363 else 364 { 365 while (list) 366 { 367 /* Find this name in the archive. */ 368 bfd *member = obfd->archive_head; 369 bfd **prev = &(obfd->archive_head); 370 int found = 0; 371 372 while (member) 373 { 374 if (FILENAME_CMP (member->filename, list->name) == 0) 375 { 376 /* Found the one to replace. */ 377 bfd *abfd = bfd_openr (list->name, 0); 378 379 if (!abfd) 380 { 381 fprintf (stderr, _("%s: can't open file %s\n"), 382 program_name, list->name); 383 maybequit (); 384 } 385 else 386 { 387 *prev = abfd; 388 abfd->archive_next = member->archive_next; 389 found = 1; 390 } 391 } 392 else 393 { 394 prev = &(member->archive_next); 395 } 396 member = member->archive_next; 397 } 398 399 if (!found) 400 { 401 bfd *abfd = bfd_openr (list->name, 0); 402 403 fprintf (stderr,_("%s: can't find module file %s\n"), 404 program_name, list->name); 405 if (!abfd) 406 { 407 fprintf (stderr, _("%s: can't open file %s\n"), 408 program_name, list->name); 409 maybequit (); 410 } 411 else 412 *prev = abfd; 413 } 414 415 list = list->next; 416 } 417 } 418 } 419 420 /* And I added this one. */ 421 void 422 ar_list (void) 423 { 424 if (!obfd) 425 { 426 fprintf (stderr, _("%s: no open output archive\n"), program_name); 427 maybequit (); 428 } 429 else 430 { 431 bfd *abfd; 432 433 outfile = stdout; 434 verbose =1 ; 435 printf (_("Current open archive is %s\n"), bfd_get_filename (obfd)); 436 437 for (abfd = obfd->archive_head; 438 abfd != (bfd *)NULL; 439 abfd = abfd->archive_next) 440 ar_directory_doer (abfd, (bfd *) NULL); 441 } 442 } 443 444 void 445 ar_end (void) 446 { 447 if (obfd) 448 { 449 bfd_cache_close (obfd); 450 unlink (bfd_get_filename (obfd)); 451 } 452 } 453 454 void 455 ar_extract (struct list *list) 456 { 457 if (!obfd) 458 { 459 fprintf (stderr, _("%s: no open archive\n"), program_name); 460 maybequit (); 461 } 462 else 463 { 464 while (list) 465 { 466 /* Find this name in the archive. */ 467 bfd *member = obfd->archive_head; 468 int found = 0; 469 470 while (member && !found) 471 { 472 if (FILENAME_CMP (member->filename, list->name) == 0) 473 { 474 extract_file (member); 475 found = 1; 476 } 477 478 member = member->archive_next; 479 } 480 481 if (!found) 482 { 483 bfd_openr (list->name, 0); 484 fprintf (stderr, _("%s: can't find module file %s\n"), 485 program_name, list->name); 486 } 487 488 list = list->next; 489 } 490 } 491 } 492