1 /* arsup.c - Archive support for MRI compatibility 2 Copyright 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 3 2004 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., 51 Franklin Street - Fifth Floor, Boston, 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 "bfd.h" 29 #include "arsup.h" 30 #include "libiberty.h" 31 #include "bucomm.h" 32 #include "filenames.h" 33 34 static void map_over_list 35 (bfd *, void (*function) (bfd *, bfd *), struct list *); 36 static void ar_directory_doer (bfd *, bfd *); 37 static void ar_addlib_doer (bfd *, bfd *); 38 39 extern int verbose; 40 41 static bfd *obfd; 42 static char *real_name; 43 static FILE *outfile; 44 45 static void 46 map_over_list (bfd *arch, void (*function) (bfd *, bfd *), struct list *list) 47 { 48 bfd *head; 49 50 if (list == NULL) 51 { 52 bfd *next; 53 54 head = arch->next; 55 while (head != NULL) 56 { 57 next = head->next; 58 function (head, (bfd *) NULL); 59 head = next; 60 } 61 } 62 else 63 { 64 struct list *ptr; 65 66 /* This may appear to be a baroque way of accomplishing what we 67 want. however we have to iterate over the filenames in order 68 to notice where a filename is requested but does not exist in 69 the archive. Ditto mapping over each file each time -- we 70 want to hack multiple references. */ 71 for (ptr = list; ptr; ptr = ptr->next) 72 { 73 bfd_boolean found = FALSE; 74 bfd *prev = arch; 75 76 for (head = arch->next; head; head = head->next) 77 { 78 if (head->filename != NULL 79 && FILENAME_CMP (ptr->name, head->filename) == 0) 80 { 81 found = TRUE; 82 function (head, prev); 83 } 84 prev = head; 85 } 86 if (! found) 87 fprintf (stderr, _("No entry %s in archive.\n"), ptr->name); 88 } 89 } 90 } 91 92 93 94 static void 95 ar_directory_doer (bfd *abfd, bfd *ignore ATTRIBUTE_UNUSED) 96 { 97 print_arelt_descr(outfile, abfd, verbose); 98 } 99 100 void 101 ar_directory (char *ar_name, struct list *list, char *output) 102 { 103 bfd *arch; 104 105 arch = open_inarch (ar_name, (char *) NULL); 106 if (output) 107 { 108 outfile = fopen(output,"w"); 109 if (outfile == 0) 110 { 111 outfile = stdout; 112 fprintf (stderr,_("Can't open file %s\n"), output); 113 output = 0; 114 } 115 } 116 else 117 outfile = stdout; 118 119 map_over_list (arch, ar_directory_doer, list); 120 121 bfd_close (arch); 122 123 if (output) 124 fclose (outfile); 125 } 126 127 void 128 prompt (void) 129 { 130 extern int interactive; 131 132 if (interactive) 133 { 134 printf ("AR >"); 135 fflush (stdout); 136 } 137 } 138 139 void 140 maybequit (void) 141 { 142 if (! interactive) 143 xexit (9); 144 } 145 146 147 void 148 ar_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 211 static void 212 ar_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 222 void 223 ar_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 242 void 243 ar_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 273 void 274 ar_clear (void) 275 { 276 if (obfd) 277 obfd->archive_head = 0; 278 } 279 280 void 281 ar_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 322 void 323 ar_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 342 void 343 ar_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. */ 408 void 409 ar_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 431 void 432 ar_end (void) 433 { 434 if (obfd) 435 { 436 bfd_cache_close (obfd); 437 unlink (bfd_get_filename (obfd)); 438 } 439 } 440 441 void 442 ar_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