arsup.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /* arsup.c - Archive support for MRI compatibility
  2. Copyright (C) 1992-2022 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 char *temp_name;
  35. static int temp_fd;
  36. static FILE *outfile;
  37. static void
  38. map_over_list (bfd *arch, void (*function) (bfd *, bfd *), struct list *list)
  39. {
  40. bfd *head;
  41. if (list == NULL)
  42. {
  43. bfd *next;
  44. head = arch->archive_next;
  45. while (head != NULL)
  46. {
  47. next = head->archive_next;
  48. function (head, (bfd *) NULL);
  49. head = next;
  50. }
  51. }
  52. else
  53. {
  54. struct list *ptr;
  55. /* This may appear to be a baroque way of accomplishing what we
  56. want. however we have to iterate over the filenames in order
  57. to notice where a filename is requested but does not exist in
  58. the archive. Ditto mapping over each file each time -- we
  59. want to hack multiple references. */
  60. for (ptr = list; ptr; ptr = ptr->next)
  61. {
  62. bool found = false;
  63. bfd *prev = arch;
  64. for (head = arch->archive_next; head; head = head->archive_next)
  65. {
  66. if (bfd_get_filename (head) != NULL
  67. && FILENAME_CMP (ptr->name, bfd_get_filename (head)) == 0)
  68. {
  69. found = true;
  70. function (head, prev);
  71. }
  72. prev = head;
  73. }
  74. if (! found)
  75. fprintf (stderr, _("No entry %s in archive.\n"), ptr->name);
  76. }
  77. }
  78. }
  79. static void
  80. ar_directory_doer (bfd *abfd, bfd *ignore ATTRIBUTE_UNUSED)
  81. {
  82. print_arelt_descr(outfile, abfd, verbose, false);
  83. }
  84. void
  85. ar_directory (char *ar_name, struct list *list, char *output)
  86. {
  87. bfd *arch;
  88. arch = open_inarch (ar_name, (char *) NULL);
  89. if (output)
  90. {
  91. outfile = fopen(output,"w");
  92. if (outfile == 0)
  93. {
  94. outfile = stdout;
  95. fprintf (stderr,_("Can't open file %s\n"), output);
  96. output = 0;
  97. }
  98. }
  99. else
  100. outfile = stdout;
  101. map_over_list (arch, ar_directory_doer, list);
  102. bfd_close (arch);
  103. if (output)
  104. fclose (outfile);
  105. }
  106. void
  107. prompt (void)
  108. {
  109. extern int interactive;
  110. if (interactive)
  111. {
  112. printf ("AR >");
  113. fflush (stdout);
  114. }
  115. }
  116. void
  117. maybequit (void)
  118. {
  119. if (! interactive)
  120. xexit (9);
  121. }
  122. void
  123. ar_open (char *name, int t)
  124. {
  125. real_name = xstrdup (name);
  126. temp_name = make_tempname (real_name, &temp_fd);
  127. if (temp_name == NULL)
  128. {
  129. fprintf (stderr, _("%s: Can't open temporary file (%s)\n"),
  130. program_name, strerror(errno));
  131. maybequit ();
  132. return;
  133. }
  134. obfd = bfd_fdopenw (temp_name, NULL, temp_fd);
  135. if (!obfd)
  136. {
  137. fprintf (stderr,
  138. _("%s: Can't open output archive %s\n"),
  139. program_name, temp_name);
  140. maybequit ();
  141. }
  142. else
  143. {
  144. if (!t)
  145. {
  146. bfd **ptr;
  147. bfd *element;
  148. bfd *ibfd;
  149. #if BFD_SUPPORTS_PLUGINS
  150. ibfd = bfd_openr (name, "plugin");
  151. #else
  152. ibfd = bfd_openr (name, NULL);
  153. #endif
  154. if (!ibfd)
  155. {
  156. fprintf (stderr,_("%s: Can't open input archive %s\n"),
  157. program_name, name);
  158. maybequit ();
  159. return;
  160. }
  161. if (!bfd_check_format(ibfd, bfd_archive))
  162. {
  163. fprintf (stderr,
  164. _("%s: file %s is not an archive\n"),
  165. program_name, name);
  166. maybequit ();
  167. return;
  168. }
  169. ptr = &(obfd->archive_head);
  170. element = bfd_openr_next_archived_file (ibfd, NULL);
  171. while (element)
  172. {
  173. *ptr = element;
  174. ptr = &element->archive_next;
  175. element = bfd_openr_next_archived_file (ibfd, element);
  176. }
  177. }
  178. bfd_set_format (obfd, bfd_archive);
  179. obfd->has_armap = 1;
  180. obfd->is_thin_archive = 0;
  181. }
  182. }
  183. static void
  184. ar_addlib_doer (bfd *abfd, bfd *prev)
  185. {
  186. /* Add this module to the output bfd. */
  187. if (prev != NULL)
  188. prev->archive_next = abfd->archive_next;
  189. abfd->archive_next = obfd->archive_head;
  190. obfd->archive_head = abfd;
  191. }
  192. void
  193. ar_addlib (char *name, struct list *list)
  194. {
  195. if (obfd == NULL)
  196. {
  197. fprintf (stderr, _("%s: no output archive specified yet\n"), program_name);
  198. maybequit ();
  199. }
  200. else
  201. {
  202. bfd *arch;
  203. arch = open_inarch (name, (char *) NULL);
  204. if (arch != NULL)
  205. map_over_list (arch, ar_addlib_doer, list);
  206. /* Don't close the bfd, since it will make the elements disappear. */
  207. }
  208. }
  209. void
  210. ar_addmod (struct list *list)
  211. {
  212. if (!obfd)
  213. {
  214. fprintf (stderr, _("%s: no open output archive\n"), program_name);
  215. maybequit ();
  216. }
  217. else
  218. {
  219. while (list)
  220. {
  221. bfd *abfd;
  222. #if BFD_SUPPORTS_PLUGINS
  223. abfd = bfd_openr (list->name, "plugin");
  224. #else
  225. abfd = bfd_openr (list->name, NULL);
  226. #endif
  227. if (!abfd)
  228. {
  229. fprintf (stderr, _("%s: can't open file %s\n"),
  230. program_name, list->name);
  231. maybequit ();
  232. }
  233. else
  234. {
  235. abfd->archive_next = obfd->archive_head;
  236. obfd->archive_head = abfd;
  237. }
  238. list = list->next;
  239. }
  240. }
  241. }
  242. void
  243. ar_clear (void)
  244. {
  245. if (obfd)
  246. obfd->archive_head = 0;
  247. }
  248. void
  249. ar_delete (struct list *list)
  250. {
  251. if (!obfd)
  252. {
  253. fprintf (stderr, _("%s: no open output archive\n"), program_name);
  254. maybequit ();
  255. }
  256. else
  257. {
  258. while (list)
  259. {
  260. /* Find this name in the archive. */
  261. bfd *member = obfd->archive_head;
  262. bfd **prev = &(obfd->archive_head);
  263. int found = 0;
  264. while (member)
  265. {
  266. if (FILENAME_CMP (bfd_get_filename (member), list->name) == 0)
  267. {
  268. *prev = member->archive_next;
  269. found = 1;
  270. }
  271. else
  272. prev = &(member->archive_next);
  273. member = member->archive_next;
  274. }
  275. if (!found)
  276. {
  277. fprintf (stderr, _("%s: can't find module file %s\n"),
  278. program_name, list->name);
  279. maybequit ();
  280. }
  281. list = list->next;
  282. }
  283. }
  284. }
  285. void
  286. ar_save (void)
  287. {
  288. if (!obfd)
  289. {
  290. fprintf (stderr, _("%s: no open output archive\n"), program_name);
  291. maybequit ();
  292. }
  293. else
  294. {
  295. struct stat target_stat;
  296. if (deterministic > 0)
  297. obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
  298. temp_fd = dup (temp_fd);
  299. bfd_close (obfd);
  300. if (stat (real_name, &target_stat) != 0)
  301. {
  302. /* The temp file created in ar_open has mode 0600 as per mkstemp.
  303. Create the real empty output file here so smart_rename will
  304. update the mode according to the process umask. */
  305. obfd = bfd_openw (real_name, NULL);
  306. if (obfd != NULL)
  307. {
  308. bfd_set_format (obfd, bfd_archive);
  309. bfd_close (obfd);
  310. }
  311. }
  312. smart_rename (temp_name, real_name, temp_fd, NULL, false);
  313. obfd = 0;
  314. free (temp_name);
  315. free (real_name);
  316. }
  317. }
  318. void
  319. ar_replace (struct list *list)
  320. {
  321. if (!obfd)
  322. {
  323. fprintf (stderr, _("%s: no open output archive\n"), program_name);
  324. maybequit ();
  325. }
  326. else
  327. {
  328. while (list)
  329. {
  330. /* Find this name in the archive. */
  331. bfd *member = obfd->archive_head;
  332. bfd **prev = &(obfd->archive_head);
  333. int found = 0;
  334. while (member)
  335. {
  336. if (FILENAME_CMP (bfd_get_filename (member), list->name) == 0)
  337. {
  338. /* Found the one to replace. */
  339. bfd *abfd = bfd_openr (list->name, NULL);
  340. if (!abfd)
  341. {
  342. fprintf (stderr, _("%s: can't open file %s\n"),
  343. program_name, list->name);
  344. maybequit ();
  345. }
  346. else
  347. {
  348. *prev = abfd;
  349. abfd->archive_next = member->archive_next;
  350. found = 1;
  351. }
  352. }
  353. else
  354. {
  355. prev = &(member->archive_next);
  356. }
  357. member = member->archive_next;
  358. }
  359. if (!found)
  360. {
  361. bfd *abfd = bfd_openr (list->name, NULL);
  362. fprintf (stderr,_("%s: can't find module file %s\n"),
  363. program_name, list->name);
  364. if (!abfd)
  365. {
  366. fprintf (stderr, _("%s: can't open file %s\n"),
  367. program_name, list->name);
  368. maybequit ();
  369. }
  370. else
  371. *prev = abfd;
  372. }
  373. list = list->next;
  374. }
  375. }
  376. }
  377. /* And I added this one. */
  378. void
  379. ar_list (void)
  380. {
  381. if (!obfd)
  382. {
  383. fprintf (stderr, _("%s: no open output archive\n"), program_name);
  384. maybequit ();
  385. }
  386. else
  387. {
  388. bfd *abfd;
  389. outfile = stdout;
  390. verbose =1 ;
  391. printf (_("Current open archive is %s\n"), bfd_get_filename (obfd));
  392. for (abfd = obfd->archive_head;
  393. abfd != (bfd *)NULL;
  394. abfd = abfd->archive_next)
  395. ar_directory_doer (abfd, (bfd *) NULL);
  396. }
  397. }
  398. void
  399. ar_end (void)
  400. {
  401. if (obfd)
  402. {
  403. bfd_cache_close (obfd);
  404. unlink (bfd_get_filename (obfd));
  405. }
  406. }
  407. void
  408. ar_extract (struct list *list)
  409. {
  410. if (!obfd)
  411. {
  412. fprintf (stderr, _("%s: no open archive\n"), program_name);
  413. maybequit ();
  414. }
  415. else
  416. {
  417. while (list)
  418. {
  419. /* Find this name in the archive. */
  420. bfd *member = obfd->archive_head;
  421. int found = 0;
  422. while (member && !found)
  423. {
  424. if (FILENAME_CMP (bfd_get_filename (member), list->name) == 0)
  425. {
  426. extract_file (member);
  427. found = 1;
  428. }
  429. member = member->archive_next;
  430. }
  431. if (!found)
  432. {
  433. bfd_openr (list->name, NULL);
  434. fprintf (stderr, _("%s: can't find module file %s\n"),
  435. program_name, list->name);
  436. }
  437. list = list->next;
  438. }
  439. }
  440. }