arsup.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /* arsup.c - Archive support for MRI compatibility
  2. Copyright (C) 1992-2017 Free Software Foundation, Inc.
  3. This file is part of GNU Binutils.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  15. MA 02110-1301, USA. */
  16. /* Contributed by Steve Chamberlain
  17. sac@cygnus.com
  18. This file looks after requests from arparse.y, to provide the MRI
  19. style librarian command syntax + 1 word LIST. */
  20. #include "sysdep.h"
  21. #include "bfd.h"
  22. #include "libiberty.h"
  23. #include "filenames.h"
  24. #include "bucomm.h"
  25. #include "arsup.h"
  26. static void map_over_list
  27. (bfd *, void (*function) (bfd *, bfd *), struct list *);
  28. static void ar_directory_doer (bfd *, bfd *);
  29. static void ar_addlib_doer (bfd *, bfd *);
  30. extern int verbose;
  31. extern int deterministic;
  32. static bfd *obfd;
  33. static char *real_name;
  34. static FILE *outfile;
  35. static void
  36. map_over_list (bfd *arch, void (*function) (bfd *, bfd *), struct list *list)
  37. {
  38. bfd *head;
  39. if (list == NULL)
  40. {
  41. bfd *next;
  42. head = arch->archive_next;
  43. while (head != NULL)
  44. {
  45. next = head->archive_next;
  46. function (head, (bfd *) NULL);
  47. head = next;
  48. }
  49. }
  50. else
  51. {
  52. struct list *ptr;
  53. /* This may appear to be a baroque way of accomplishing what we
  54. want. however we have to iterate over the filenames in order
  55. to notice where a filename is requested but does not exist in
  56. the archive. Ditto mapping over each file each time -- we
  57. want to hack multiple references. */
  58. for (ptr = list; ptr; ptr = ptr->next)
  59. {
  60. bfd_boolean found = FALSE;
  61. bfd *prev = arch;
  62. for (head = arch->archive_next; head; head = head->archive_next)
  63. {
  64. if (head->filename != NULL
  65. && FILENAME_CMP (ptr->name, head->filename) == 0)
  66. {
  67. found = TRUE;
  68. function (head, prev);
  69. }
  70. prev = head;
  71. }
  72. if (! found)
  73. fprintf (stderr, _("No entry %s in archive.\n"), ptr->name);
  74. }
  75. }
  76. }
  77. static void
  78. ar_directory_doer (bfd *abfd, bfd *ignore ATTRIBUTE_UNUSED)
  79. {
  80. print_arelt_descr(outfile, abfd, verbose);
  81. }
  82. void
  83. ar_directory (char *ar_name, struct list *list, char *output)
  84. {
  85. bfd *arch;
  86. arch = open_inarch (ar_name, (char *) NULL);
  87. if (output)
  88. {
  89. outfile = fopen(output,"w");
  90. if (outfile == 0)
  91. {
  92. outfile = stdout;
  93. fprintf (stderr,_("Can't open file %s\n"), output);
  94. output = 0;
  95. }
  96. }
  97. else
  98. outfile = stdout;
  99. map_over_list (arch, ar_directory_doer, list);
  100. bfd_close (arch);
  101. if (output)
  102. fclose (outfile);
  103. }
  104. void
  105. prompt (void)
  106. {
  107. extern int interactive;
  108. if (interactive)
  109. {
  110. printf ("AR >");
  111. fflush (stdout);
  112. }
  113. }
  114. void
  115. maybequit (void)
  116. {
  117. if (! interactive)
  118. xexit (9);
  119. }
  120. void
  121. ar_open (char *name, int t)
  122. {
  123. char *tname = (char *) xmalloc (strlen (name) + 10);
  124. const char *bname = lbasename (name);
  125. real_name = name;
  126. /* Prepend tmp- to the beginning, to avoid file-name clashes after
  127. truncation on filesystems with limited namespaces (DOS). */
  128. sprintf (tname, "%.*stmp-%s", (int) (bname - name), name, bname);
  129. obfd = bfd_openw (tname, NULL);
  130. if (!obfd)
  131. {
  132. fprintf (stderr,
  133. _("%s: Can't open output archive %s\n"),
  134. program_name, tname);
  135. maybequit ();
  136. }
  137. else
  138. {
  139. if (!t)
  140. {
  141. bfd **ptr;
  142. bfd *element;
  143. bfd *ibfd;
  144. ibfd = bfd_openr (name, NULL);
  145. if (!ibfd)
  146. {
  147. fprintf (stderr,_("%s: Can't open input archive %s\n"),
  148. program_name, name);
  149. maybequit ();
  150. return;
  151. }
  152. if (!bfd_check_format(ibfd, bfd_archive))
  153. {
  154. fprintf (stderr,
  155. _("%s: file %s is not an archive\n"),
  156. program_name, name);
  157. maybequit ();
  158. return;
  159. }
  160. ptr = &(obfd->archive_head);
  161. element = bfd_openr_next_archived_file (ibfd, NULL);
  162. while (element)
  163. {
  164. *ptr = element;
  165. ptr = &element->archive_next;
  166. element = bfd_openr_next_archived_file (ibfd, element);
  167. }
  168. }
  169. bfd_set_format (obfd, bfd_archive);
  170. obfd->has_armap = 1;
  171. obfd->is_thin_archive = 0;
  172. }
  173. }
  174. static void
  175. ar_addlib_doer (bfd *abfd, bfd *prev)
  176. {
  177. /* Add this module to the output bfd. */
  178. if (prev != NULL)
  179. prev->archive_next = abfd->archive_next;
  180. abfd->archive_next = obfd->archive_head;
  181. obfd->archive_head = abfd;
  182. }
  183. void
  184. ar_addlib (char *name, struct list *list)
  185. {
  186. if (obfd == NULL)
  187. {
  188. fprintf (stderr, _("%s: no output archive specified yet\n"), program_name);
  189. maybequit ();
  190. }
  191. else
  192. {
  193. bfd *arch;
  194. arch = open_inarch (name, (char *) NULL);
  195. if (arch != NULL)
  196. map_over_list (arch, ar_addlib_doer, list);
  197. /* Don't close the bfd, since it will make the elements disappear. */
  198. }
  199. }
  200. void
  201. ar_addmod (struct list *list)
  202. {
  203. if (!obfd)
  204. {
  205. fprintf (stderr, _("%s: no open output archive\n"), program_name);
  206. maybequit ();
  207. }
  208. else
  209. {
  210. while (list)
  211. {
  212. bfd *abfd = bfd_openr (list->name, NULL);
  213. if (!abfd)
  214. {
  215. fprintf (stderr, _("%s: can't open file %s\n"),
  216. program_name, list->name);
  217. maybequit ();
  218. }
  219. else
  220. {
  221. abfd->archive_next = obfd->archive_head;
  222. obfd->archive_head = abfd;
  223. }
  224. list = list->next;
  225. }
  226. }
  227. }
  228. void
  229. ar_clear (void)
  230. {
  231. if (obfd)
  232. obfd->archive_head = 0;
  233. }
  234. void
  235. ar_delete (struct list *list)
  236. {
  237. if (!obfd)
  238. {
  239. fprintf (stderr, _("%s: no open output archive\n"), program_name);
  240. maybequit ();
  241. }
  242. else
  243. {
  244. while (list)
  245. {
  246. /* Find this name in the archive. */
  247. bfd *member = obfd->archive_head;
  248. bfd **prev = &(obfd->archive_head);
  249. int found = 0;
  250. while (member)
  251. {
  252. if (FILENAME_CMP(member->filename, list->name) == 0)
  253. {
  254. *prev = member->archive_next;
  255. found = 1;
  256. }
  257. else
  258. prev = &(member->archive_next);
  259. member = member->archive_next;
  260. }
  261. if (!found)
  262. {
  263. fprintf (stderr, _("%s: can't find module file %s\n"),
  264. program_name, list->name);
  265. maybequit ();
  266. }
  267. list = list->next;
  268. }
  269. }
  270. }
  271. void
  272. ar_save (void)
  273. {
  274. if (!obfd)
  275. {
  276. fprintf (stderr, _("%s: no open output archive\n"), program_name);
  277. maybequit ();
  278. }
  279. else
  280. {
  281. char *ofilename = xstrdup (bfd_get_filename (obfd));
  282. if (deterministic > 0)
  283. obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
  284. bfd_close (obfd);
  285. smart_rename (ofilename, real_name, 0);
  286. obfd = 0;
  287. free (ofilename);
  288. }
  289. }
  290. void
  291. ar_replace (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. while (member)
  307. {
  308. if (FILENAME_CMP (member->filename, list->name) == 0)
  309. {
  310. /* Found the one to replace. */
  311. bfd *abfd = bfd_openr (list->name, 0);
  312. if (!abfd)
  313. {
  314. fprintf (stderr, _("%s: can't open file %s\n"),
  315. program_name, list->name);
  316. maybequit ();
  317. }
  318. else
  319. {
  320. *prev = abfd;
  321. abfd->archive_next = member->archive_next;
  322. found = 1;
  323. }
  324. }
  325. else
  326. {
  327. prev = &(member->archive_next);
  328. }
  329. member = member->archive_next;
  330. }
  331. if (!found)
  332. {
  333. bfd *abfd = bfd_openr (list->name, 0);
  334. fprintf (stderr,_("%s: can't find module file %s\n"),
  335. program_name, list->name);
  336. if (!abfd)
  337. {
  338. fprintf (stderr, _("%s: can't open file %s\n"),
  339. program_name, list->name);
  340. maybequit ();
  341. }
  342. else
  343. *prev = abfd;
  344. }
  345. list = list->next;
  346. }
  347. }
  348. }
  349. /* And I added this one. */
  350. void
  351. ar_list (void)
  352. {
  353. if (!obfd)
  354. {
  355. fprintf (stderr, _("%s: no open output archive\n"), program_name);
  356. maybequit ();
  357. }
  358. else
  359. {
  360. bfd *abfd;
  361. outfile = stdout;
  362. verbose =1 ;
  363. printf (_("Current open archive is %s\n"), bfd_get_filename (obfd));
  364. for (abfd = obfd->archive_head;
  365. abfd != (bfd *)NULL;
  366. abfd = abfd->archive_next)
  367. ar_directory_doer (abfd, (bfd *) NULL);
  368. }
  369. }
  370. void
  371. ar_end (void)
  372. {
  373. if (obfd)
  374. {
  375. bfd_cache_close (obfd);
  376. unlink (bfd_get_filename (obfd));
  377. }
  378. }
  379. void
  380. ar_extract (struct list *list)
  381. {
  382. if (!obfd)
  383. {
  384. fprintf (stderr, _("%s: no open archive\n"), program_name);
  385. maybequit ();
  386. }
  387. else
  388. {
  389. while (list)
  390. {
  391. /* Find this name in the archive. */
  392. bfd *member = obfd->archive_head;
  393. int found = 0;
  394. while (member && !found)
  395. {
  396. if (FILENAME_CMP (member->filename, list->name) == 0)
  397. {
  398. extract_file (member);
  399. found = 1;
  400. }
  401. member = member->archive_next;
  402. }
  403. if (!found)
  404. {
  405. bfd_openr (list->name, 0);
  406. fprintf (stderr, _("%s: can't find module file %s\n"),
  407. program_name, list->name);
  408. }
  409. list = list->next;
  410. }
  411. }
  412. }