ar.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805
  1. /* ar.c - Archive modify and extract.
  2. Copyright (C) 1988 Free Software Foundation, Inc.
  3. NO WARRANTY
  4. BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
  5. NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
  6. WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC,
  7. RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS"
  8. WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
  9. BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  10. FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
  11. AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
  12. DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
  13. CORRECTION.
  14. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
  15. STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY
  16. WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE
  17. LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR
  18. OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
  19. USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR
  20. DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR
  21. A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS
  22. PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
  23. DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
  24. GENERAL PUBLIC LICENSE TO COPY
  25. 1. You may copy and distribute verbatim copies of this source file
  26. as you receive it, in any medium, provided that you conspicuously
  27. and appropriately publish on each copy a valid copyright notice
  28. "Copyright (C) 1987 Free Software Foundation, Inc.", and include
  29. following the copyright notice a verbatim copy of the above disclaimer
  30. of warranty and of this License.
  31. 2. You may modify your copy or copies of this source file or
  32. any portion of it, and copy and distribute such modifications under
  33. the terms of Paragraph 1 above, provided that you also do the following:
  34. a) cause the modified files to carry prominent notices stating
  35. that you changed the files and the date of any change; and
  36. b) cause the whole of any work that you distribute or publish,
  37. that in whole or in part contains or is a derivative of this
  38. program or any part thereof, to be licensed at no charge to all
  39. third parties on terms identical to those contained in this
  40. License Agreement (except that you may choose to grant more
  41. extensive warranty protection to third parties, at your option).
  42. c) You may charge a distribution fee for the physical act of
  43. transferring a copy, and you may at your option offer warranty
  44. protection in exchange for a fee.
  45. 3. You may copy and distribute this program or any portion of it in
  46. compiled, executable or object code form under the terms of Paragraphs
  47. 1 and 2 above provided that you do the following:
  48. a) cause each such copy to be accompanied by the
  49. corresponding machine-readable source code, which must
  50. be distributed under the terms of Paragraphs 1 and 2 above; or,
  51. b) cause each such copy to be accompanied by a
  52. written offer, with no time limit, to give any third party
  53. free (except for a nominal shipping charge) a machine readable
  54. copy of the corresponding source code, to be distributed
  55. under the terms of Paragraphs 1 and 2 above; or,
  56. c) in the case of a recipient of this program in compiled, executable
  57. or object code form (without the corresponding source code) you
  58. shall cause copies you distribute to be accompanied by a copy
  59. of the written offer of source code which you received along
  60. with the copy you received.
  61. 4. You may not copy, sublicense, distribute or transfer this program
  62. except as expressly provided under this License Agreement. Any attempt
  63. otherwise to copy, sublicense, distribute or transfer this program is void and
  64. your rights to use the program under this License agreement shall be
  65. automatically terminated. However, parties who have received computer
  66. software programs from you with this License Agreement will not have
  67. their licenses terminated so long as such parties remain in full compliance.
  68. 5. If you wish to incorporate parts of this program into other free
  69. programs whose distribution conditions are different, write to the Free
  70. Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet
  71. worked out a simple rule that can be stated here, but we will often permit
  72. this. We will be guided by the two goals of preserving the free status of
  73. all derivatives of our free software and of promoting the sharing and reuse of
  74. software.
  75. In other words, you are welcome to use, share and improve this program.
  76. You are forbidden to forbid anyone else to use, share and improve
  77. what you give them. Help stamp out software-hoarding! */
  78. #include <stdio.h>
  79. #include <ar.h>
  80. #include <errno.h>
  81. #include <sys/types.h>
  82. #include <sys/stat.h>
  83. #ifdef COFF_ENCAPSULATE
  84. #include "a.out.encap.h"
  85. #else
  86. #include <a.out.h>
  87. #endif
  88. #ifdef USG
  89. #include <time.h>
  90. #include <fcntl.h>
  91. #else
  92. #include <sys/file.h>
  93. #include <sys/time.h>
  94. #endif
  95. /* Locking is normally disabled because fcntl hangs on the Sun
  96. and it isn't supported properly across NFS anyhow. */
  97. #ifdef LOCKS
  98. #include <sys/fcntl.h>
  99. #endif
  100. /* Define a name for the length of member name an archive can store. */
  101. struct ar_hdr foo;
  102. #define ARNAMESIZE sizeof(foo.ar_name)
  103. /* This structure is used internally to represent the info
  104. on a member of an archive. This is to make it easier to change format. */
  105. struct member_desc
  106. {
  107. char *name; /* Name of member */
  108. /* The following fields are stored in the member header
  109. as decimal or octal numerals,
  110. but in this structure they are stored as machine numbers. */
  111. int mode; /* Protection mode from member header */
  112. int date; /* Last modify date as stored in member header */
  113. int size; /* size of member's data in bytes, from member header */
  114. int uid, gid; /* uid and gid fields copied from member header */
  115. int offset; /* Offset in archive of the header of this member */
  116. int data_offset; /* Offset of first data byte of the member */
  117. /* The next field does not describe where the member was in the old archive,
  118. but rather where it will be in the modified archive.
  119. It is set up by write_archive. */
  120. int new_offset; /* Offset of this member in new archive */
  121. struct symdef *symdefs; /* Symdef data for member.
  122. Used only for files being inserted. */
  123. int nsymdefs; /* Number of entries of symdef data */
  124. int string_size; /* Size of strings needed by symdef data */
  125. };
  126. /* Each symbol is recorded by something like this. */
  127. struct symdef
  128. {
  129. union
  130. {
  131. long stringoffset;
  132. char *name;
  133. } s;
  134. long offset;
  135. };
  136. /* Nonzero means it's the name of an existing member;
  137. position new or moved files with respect to this one. */
  138. char *posname;
  139. /* How to use `posname':
  140. POS_BEFORE means position before that member.
  141. POS_AFTER means position after that member.
  142. POS_DEFAULT if position by default; then `posname' should also be zero. */
  143. enum { POS_DEFAULT, POS_BEFORE, POS_AFTER } postype;
  144. /* Nonzero means describe each action performed. */
  145. int verbose;
  146. /* Nonzero means don't warn about creating the archive file if necessary. */
  147. int silent_create;
  148. /* Nonzero means don't replace existing members
  149. whose dates are more recent than the corresponding files. */
  150. int newer_only;
  151. /* Nonzero means preserve dates of members when extracting them. */
  152. int preserve_dates;
  153. /* Operation to be performed. */
  154. #define DELETE 1
  155. #define REPLACE 2
  156. #define PRINT_TABLE 3
  157. #define PRINT_FILES 4
  158. #define EXTRACT 5
  159. #define MOVE 6
  160. #define QUICK_APPEND 7
  161. int operation;
  162. /* Name of archive file. */
  163. char *archive;
  164. /* Descriptor on which we have locked the original archive file,
  165. or -1 if this has not been done. */
  166. int lock_indesc;
  167. /* Pointer to tail of `argv', at first subfile name argument,
  168. or zero if no such were specified. */
  169. char **files;
  170. /* Nonzero means write a __.SYMDEF member into the modified archive. */
  171. int symdef_flag;
  172. /* Nonzero means __.SYMDEF member exists in old archive. */
  173. int symdef_exists;
  174. /* Total number of symdef entries we will have. */
  175. long nsymdefs;
  176. /* Symdef data from old archive (set up only if we need it) */
  177. struct symdef *old_symdefs;
  178. /* Number of symdefs in remaining in old_symdefs. */
  179. int num_old_symdefs;
  180. /* Number of symdefs old_symdefs had when it was read in. */
  181. long original_num_symdefs;
  182. /* String table from old __.SYMDEF member. */
  183. char *old_strings;
  184. /* Size of old_strings */
  185. long old_strings_size;
  186. /* String table to be written into __.SYMDEF member. */
  187. char *new_strings;
  188. /* Size of new_strings */
  189. long new_strings_size;
  190. /* An archive map is a chain of these structures.
  191. Each structure describes one member of the archive.
  192. The chain is in the same order as the members are. */
  193. struct mapelt
  194. {
  195. struct member_desc info;
  196. struct mapelt *next;
  197. };
  198. struct mapelt *maplast;
  199. /* If nonzero, this is the map-element for the __.SYMDEF member
  200. and we should update the time of that member just before finishing. */
  201. struct mapelt *symdef_mapelt;
  202. /* Header that we wrote for the __.SYMDEF member. */
  203. struct ar_hdr symdef_header;
  204. void add_to_map ();
  205. void print_descr ();
  206. char *concat ();
  207. void scan ();
  208. char *requestedp ();
  209. void extract_member ();
  210. void print_contents ();
  211. void write_symdef_member ();
  212. void read_old_symdefs ();
  213. main (argc, argv)
  214. int argc;
  215. char **argv;
  216. {
  217. int i;
  218. operation = 0;
  219. verbose = 0;
  220. newer_only = 0;
  221. silent_create = 0;
  222. posname = 0;
  223. postype = POS_DEFAULT;
  224. preserve_dates = 0;
  225. symdef_flag = 0;
  226. symdef_exists = 0;
  227. symdef_mapelt = 0;
  228. files = 0;
  229. lock_indesc = -1;
  230. if (argc < 2)
  231. fatal ("too few command arguments", 0);
  232. {
  233. char *key = argv[1];
  234. char *p = key;
  235. char c;
  236. while (c = *p++)
  237. {
  238. switch (c)
  239. {
  240. case 'a':
  241. postype = POS_AFTER;
  242. break;
  243. case 'b':
  244. postype = POS_BEFORE;
  245. break;
  246. case 'c':
  247. silent_create = 1;
  248. break;
  249. case 'd':
  250. if (operation)
  251. two_operations ();
  252. operation = DELETE;
  253. break;
  254. case 'i':
  255. postype = POS_BEFORE;
  256. break;
  257. case 'l':
  258. break;
  259. case 'm':
  260. if (operation) two_operations ();
  261. operation = MOVE;
  262. break;
  263. case 'o':
  264. preserve_dates = 1;
  265. break;
  266. case 'p':
  267. if (operation) two_operations ();
  268. operation = PRINT_FILES;
  269. break;
  270. case 'q':
  271. if (operation) two_operations ();
  272. operation = QUICK_APPEND;
  273. break;
  274. case 'r':
  275. if (operation) two_operations ();;
  276. operation = REPLACE;
  277. break;
  278. case 's':
  279. symdef_flag = 1;
  280. break;
  281. case 't':
  282. if (operation) two_operations ();
  283. operation = PRINT_TABLE;
  284. break;
  285. case 'u':
  286. newer_only = 1;
  287. break;
  288. case 'v':
  289. verbose = 1;
  290. break;
  291. case 'x':
  292. if (operation) two_operations ();
  293. operation = EXTRACT;
  294. break;
  295. }
  296. }
  297. }
  298. if (!operation && symdef_flag)
  299. operation = REPLACE;
  300. if (!operation)
  301. fatal ("no operation specified", 0);
  302. i = 2;
  303. if (postype != POS_DEFAULT)
  304. posname = argv[i++];
  305. archive = argv[i++];
  306. if (i < argc)
  307. files = &argv[i];
  308. switch (operation)
  309. {
  310. case EXTRACT:
  311. extract_members (extract_member);
  312. break;
  313. case PRINT_TABLE:
  314. extract_members (print_descr);
  315. break;
  316. case PRINT_FILES:
  317. extract_members (print_contents);
  318. break;
  319. case DELETE:
  320. if (!files) break;
  321. delete_members ();
  322. break;
  323. case MOVE:
  324. if (!files) break;
  325. move_members ();
  326. break;
  327. case REPLACE:
  328. if (!files && !symdef_flag) break;
  329. replace_members ();
  330. break;
  331. case QUICK_APPEND:
  332. if (!files) break;
  333. quick_append ();
  334. break;
  335. default:
  336. fatal ("operation not implemented yet", 0);
  337. }
  338. }
  339. two_operations ()
  340. {
  341. fatal ("two different operation switches specified", 0);
  342. }
  343. void
  344. scan (function, crflag)
  345. void (*function) ();
  346. int crflag;
  347. {
  348. int desc = open (archive, 0, 0);
  349. if (desc < 0 && crflag)
  350. /* Creation-warning, if desired, will happen later. */
  351. return;
  352. if (desc < 0)
  353. {
  354. perror_with_name (archive);
  355. exit (1);
  356. }
  357. {
  358. char buf[SARMAG];
  359. int nread = read (desc, buf, SARMAG);
  360. if (nread != SARMAG || bcmp (buf, ARMAG, SARMAG))
  361. fatal ("file %s not a valid archive", archive);
  362. }
  363. /* Now find the members one by one. */
  364. {
  365. int member_offset = SARMAG;
  366. while (1)
  367. {
  368. int nread;
  369. struct ar_hdr member_header;
  370. struct member_desc member_desc;
  371. char name [1 + sizeof member_header.ar_name];
  372. if (lseek (desc, member_offset, 0) < 0)
  373. perror_with_name (archive);
  374. nread = read (desc, &member_header, sizeof (struct ar_hdr));
  375. if (!nread) break; /* No data left means end of file; that is ok */
  376. if (nread != sizeof (member_header)
  377. || bcmp (member_header.ar_fmag, ARFMAG, 2))
  378. fatal ("file %s not a valid archive", archive);
  379. bcopy (member_header.ar_name, name, sizeof member_header.ar_name);
  380. {
  381. char *p = name + sizeof member_header.ar_name;
  382. while (p > name && *--p == ' ') *p = 0;
  383. }
  384. member_desc.name = name;
  385. member_desc.date = atoi (member_header.ar_date);
  386. member_desc.size = atoi (member_header.ar_size);
  387. sscanf (member_header.ar_mode, "%o", &member_desc.mode);
  388. member_desc.uid = atoi (member_header.ar_uid);
  389. member_desc.gid = atoi (member_header.ar_gid);
  390. member_desc.offset = member_offset;
  391. member_desc.data_offset = member_offset + sizeof (member_header);
  392. if (!strcmp (name, "__.SYMDEF"))
  393. symdef_exists = 1;
  394. function (member_desc, desc);
  395. member_offset += sizeof (member_header) + member_desc.size;
  396. if (member_offset & 1) member_offset++;
  397. }
  398. }
  399. close (desc);
  400. }
  401. /* If the string `name' matches one of the member-name arguments
  402. from the command line, return nonzero. Otherwise return 0.
  403. Only the first `len' characters of `name' need to match. */
  404. /* In fact, the value is the command argument that `name' matched. */
  405. char *
  406. requestedp (name, len)
  407. char *name;
  408. int len;
  409. {
  410. char **fp = files;
  411. char *fn;
  412. if (fp == 0)
  413. return 0;
  414. while (fn = *fp++)
  415. if (!strncmp (name, fn, len))
  416. return fn;
  417. return 0;
  418. }
  419. void
  420. print_descr (member)
  421. struct member_desc member;
  422. {
  423. char *timestring;
  424. if (!verbose)
  425. {
  426. printf ("%s\n", member.name);
  427. return;
  428. }
  429. print_modes (member.mode);
  430. timestring = ctime (&member.date);
  431. printf (" %2d/%2d %6d %12.12s %4.4s %s\n",
  432. member.uid, member.gid,
  433. member.size, timestring + 4, timestring + 20,
  434. member.name);
  435. }
  436. print_modes (modes)
  437. int modes;
  438. {
  439. putchar (modes & 0400 ? 'r' : '-');
  440. putchar (modes & 0200 ? 'w' : '-');
  441. putchar (modes & 0100 ? 'x' : '-');
  442. putchar (modes & 040 ? 'r' : '-');
  443. putchar (modes & 020 ? 'w' : '-');
  444. putchar (modes & 010 ? 'x' : '-');
  445. putchar (modes & 04 ? 'r' : '-');
  446. putchar (modes & 02 ? 'w' : '-');
  447. putchar (modes & 01 ? 'x' : '-');
  448. }
  449. #define BUFSIZE 1024
  450. void
  451. extract_member (member, arcdesc)
  452. struct member_desc member;
  453. int arcdesc;
  454. {
  455. int ncopied = 0;
  456. FILE *istream, *ostream;
  457. lseek (arcdesc, member.data_offset, 0);
  458. istream = fdopen (arcdesc, "r");
  459. ostream = fopen (member.name, "w");
  460. if (!ostream)
  461. {
  462. perror_with_name (member.name);
  463. return;
  464. }
  465. if (verbose)
  466. printf ("extracting %s\n", member.name);
  467. while (ncopied < member.size)
  468. {
  469. char buf [BUFSIZE];
  470. int tocopy = member.size - ncopied;
  471. int nread;
  472. if (tocopy > BUFSIZE) tocopy = BUFSIZE;
  473. nread = fread (buf, 1, tocopy, istream);
  474. if (nread != tocopy)
  475. fatal ("file %s not a valid archive", archive);
  476. fwrite (buf, 1, nread, ostream);
  477. ncopied += tocopy;
  478. }
  479. #ifdef USG
  480. chmod (member.name, member.mode);
  481. #else
  482. fchmod (fileno (ostream), member.mode);
  483. #endif
  484. fclose (ostream);
  485. if (preserve_dates)
  486. {
  487. #ifdef USG
  488. long tv[2];
  489. tv[0] = member.date;
  490. tv[1] = member.date;
  491. utime (member.name, tv);
  492. #else
  493. struct timeval tv[2];
  494. tv[0].tv_sec = member.date;
  495. tv[0].tv_usec = 0;
  496. tv[1].tv_sec = member.date;
  497. tv[1].tv_usec = 0;
  498. utimes (member.name, tv);
  499. #endif
  500. }
  501. }
  502. void
  503. print_contents (member, arcdesc)
  504. struct member_desc member;
  505. int arcdesc;
  506. {
  507. int ncopied = 0;
  508. FILE *istream;
  509. lseek (arcdesc, member.data_offset, 0);
  510. istream = fdopen (arcdesc, "r");
  511. if (verbose)
  512. printf ("\n<member %s>\n\n", member.name);
  513. while (ncopied < member.size)
  514. {
  515. char buf [BUFSIZE];
  516. int tocopy = member.size - ncopied;
  517. int nread;
  518. if (tocopy > BUFSIZE) tocopy = BUFSIZE;
  519. nread = fread (buf, 1, tocopy, istream);
  520. if (nread != tocopy)
  521. fatal ("file %s not a valid archive", archive);
  522. fwrite (buf, 1, nread, stdout);
  523. ncopied += tocopy;
  524. }
  525. }
  526. /* Make a map of the existing members of the archive: their names,
  527. positions and sizes. */
  528. /* If `nonexistent_ok' is nonzero,
  529. just return 0 for an archive that does not exist.
  530. This will cause the ordinary supersede procedure to
  531. create a new archive. */
  532. struct mapelt *
  533. make_map (nonexistent_ok)
  534. int nonexistent_ok;
  535. {
  536. struct mapelt mapstart;
  537. mapstart.next = 0;
  538. maplast = &mapstart;
  539. scan (add_to_map, nonexistent_ok);
  540. return mapstart.next;
  541. }
  542. void
  543. add_to_map (member)
  544. struct member_desc member;
  545. {
  546. struct mapelt *mapelt = (struct mapelt *) xmalloc (sizeof (struct mapelt));
  547. mapelt->info = member;
  548. mapelt->info.name = concat (mapelt->info.name, "", "");
  549. maplast->next = mapelt;
  550. mapelt->next = 0;
  551. maplast = mapelt;
  552. }
  553. /* Return the last element of the specified map. */
  554. struct mapelt *
  555. last_mapelt (map)
  556. struct mapelt *map;
  557. {
  558. struct mapelt *tail = map;
  559. while (tail->next) tail = tail->next;
  560. return tail;
  561. }
  562. /* Return the element of the specified map which precedes elt. */
  563. struct mapelt *
  564. prev_mapelt (map, elt)
  565. struct mapelt *map, *elt;
  566. {
  567. struct mapelt *tail = map;
  568. while (tail->next && tail->next != elt)
  569. tail = tail->next;
  570. if (tail->next) return tail;
  571. return 0;
  572. }
  573. /* Return the element of the specified map which has the specified name. */
  574. struct mapelt *
  575. find_mapelt (map, name)
  576. struct mapelt *map;
  577. char *name;
  578. {
  579. struct mapelt *tail = map;
  580. for (;tail; tail = tail->next)
  581. if (tail->info.name && !strcmp (tail->info.name, name))
  582. return tail;
  583. error ("no member named %s", name);
  584. return 0;
  585. }
  586. struct mapelt *
  587. find_mapelt_noerror (map, name)
  588. struct mapelt *map;
  589. char *name;
  590. {
  591. struct mapelt *tail = map;
  592. for (;tail; tail = tail->next)
  593. if (tail->info.name && !strcmp (tail->info.name, name))
  594. return tail;
  595. return 0;
  596. }
  597. /* Before looking at the archive, if we are going to update it
  598. based on looking at its current contents, make an exclusive lock on it.
  599. The lock is released when `write_archive' is called. */
  600. void
  601. lock_for_update ()
  602. {
  603. /* Open the existing archive file; if that fails, create an empty one. */
  604. lock_indesc = open (archive, O_RDWR, 0);
  605. if (lock_indesc < 0)
  606. {
  607. int outdesc;
  608. if (!silent_create)
  609. printf ("Creating archive file `%s'\n", archive);
  610. outdesc = open (archive, O_WRONLY | O_APPEND | O_CREAT, 0666);
  611. if (outdesc < 0)
  612. pfatal_with_name (archive);
  613. write (outdesc, ARMAG, SARMAG);
  614. close (outdesc);
  615. /* Now we had better be able to open for update! */
  616. lock_indesc = open (archive, O_RDWR, 0);
  617. if (lock_indesc < 0)
  618. pfatal_with_name (archive);
  619. }
  620. #ifdef LOCKS
  621. /* Lock the old file so that it won't be updated by two programs at once.
  622. This uses the fcntl locking facility found on Sun systems
  623. which is also in POSIX. (Perhaps it comes from sysV.)
  624. Note that merely reading an archive does not require a lock,
  625. because we use `rename' to update the whole file atomically. */
  626. {
  627. struct flock lock;
  628. lock.l_type = F_WRLCK;
  629. lock.l_whence = 0;
  630. lock.l_start = 0;
  631. lock.l_len = 0;
  632. while (1)
  633. {
  634. int value = fcntl (lock_indesc, F_SETLKW, &lock);
  635. if (value >= 0)
  636. break;
  637. else if (errno == EINTR)
  638. continue;
  639. else
  640. pfatal_with_name ("locking archive");
  641. }
  642. }
  643. #endif
  644. }
  645. /* Write a new archive file from a given map. */
  646. /* When a map is used as the pattern for a new archive,
  647. each element represents one member to put in it, and
  648. the order of elements controls the order of writing.
  649. Ordinarily, the element describes a member of the old
  650. archive, to be copied into the new one.
  651. If the `offset' field of the element's info is 0,
  652. then the element describes a file to be copied into the
  653. new archive. The `name' field is the file's name.
  654. If the `name' field of an element is 0, the element is ignored.
  655. This makes it easy to specify deletion of archive members.
  656. Every operation that will eventually call `write_archive'
  657. should call `lock_for_update' before beginning
  658. to do any I/O on the archive file.
  659. */
  660. char *make_tempname ();
  661. void copy_out_member ();
  662. write_archive (map, appendflag)
  663. struct mapelt *map;
  664. int appendflag;
  665. {
  666. char *tempname = make_tempname (archive);
  667. int indesc = lock_indesc;
  668. int outdesc;
  669. struct mapelt *tail;
  670. /* Now open the output. */
  671. if (!appendflag)
  672. {
  673. /* Updating an existing archive normally.
  674. Write output as TEMPNAME and rename at the end.
  675. There can never be two invocations trying to do this at once,
  676. because of the lock made on the old archive file. */
  677. outdesc = open (tempname, O_WRONLY | O_CREAT, 0666);
  678. if (outdesc < 0)
  679. pfatal_with_name (tempname);
  680. write (outdesc, ARMAG, SARMAG);
  681. }
  682. else
  683. {
  684. /* Fast-append to existing archive. */
  685. outdesc = open (archive, O_WRONLY | O_APPEND, 0);
  686. }
  687. /* If archive has or should have a __.SYMDEF member,
  688. compute the contents for it. */
  689. if (symdef_flag || symdef_exists)
  690. {
  691. if (symdef_exists)
  692. {
  693. #if 0
  694. /* This is turned off because there seems to be a bug
  695. in deleting the symdefs for members that are deleted.
  696. The easiest way to fix it
  697. is to regenerate the symdefs from scratch each time,
  698. which happens if this is not done. */
  699. read_old_symdefs (map, indesc);
  700. #endif
  701. }
  702. else
  703. {
  704. struct mapelt *this = (struct mapelt *) xmalloc (sizeof (struct mapelt));
  705. this->info.name = "__.SYMDEF";
  706. this->info.offset = 0;
  707. this->info.data_offset = 0;
  708. this->info.date = 0;
  709. this->info.size = 0;
  710. this->info.uid = 0;
  711. this->info.gid = 0;
  712. this->info.mode = 0666;
  713. this->next = map;
  714. map = this;
  715. }
  716. original_num_symdefs = 0;
  717. old_strings_size = 0;
  718. update_symdefs (map, indesc);
  719. }
  720. /* Copy the members into the output, either from the old archive
  721. or from specified files. */
  722. for (tail = map; tail; tail = tail->next)
  723. {
  724. if (!strcmp (tail->info.name, "__.SYMDEF") && tail->info.date==0)
  725. write_symdef_member (tail, map, outdesc);
  726. else
  727. copy_out_member (tail, indesc, outdesc);
  728. }
  729. /* Mark the __.SYMDEF member as up to date. */
  730. if (symdef_mapelt)
  731. touch_symdef_member (outdesc);
  732. /* Install the new output under the intended name. */
  733. #ifndef USG
  734. fsync (outdesc);
  735. #endif
  736. close (outdesc);
  737. if (!appendflag)
  738. if (rename (tempname, archive))
  739. pfatal_with_name (tempname);
  740. #ifdef LOCKS
  741. {
  742. struct flock lock;
  743. /* Unlock the old archive. */
  744. lock.l_type = F_UNLCK;
  745. lock.l_whence = 0;
  746. lock.l_start = 0;
  747. lock.l_len = 0;
  748. fcntl (lock_indesc, F_SETLK, &lock);
  749. }
  750. #endif
  751. /* Close the archive. If we renamed a new one, the old one disappears. */
  752. close (lock_indesc);
  753. }
  754. void
  755. copy_out_member (mapelt, archive_indesc, outdesc)
  756. struct mapelt *mapelt;
  757. int archive_indesc;
  758. int outdesc;
  759. {
  760. struct ar_hdr header;
  761. int indesc;
  762. if (!mapelt->info.name)
  763. return; /* This element was cancelled. */
  764. /* Zero the header, then store in the data as text. */
  765. bzero (&header, sizeof (header));
  766. strncpy (header.ar_name, mapelt->info.name, sizeof (header.ar_name));
  767. sprintf (header.ar_date, "%d", mapelt->info.date);
  768. sprintf (header.ar_size, "%d", mapelt->info.size);
  769. sprintf (header.ar_uid, "%d", mapelt->info.uid);
  770. sprintf (header.ar_gid, "%d", mapelt->info.gid);
  771. sprintf (header.ar_mode, "%o", mapelt->info.mode);
  772. strncpy (header.ar_fmag, ARFMAG, sizeof (header.ar_fmag));
  773. /* Change all remaining nulls in the header into spaces. */
  774. {
  775. char *tem = (char *) &header;
  776. char *end = (char *) &header + sizeof (header);
  777. while (tem < end)
  778. {
  779. if (*tem == 0)
  780. *tem = ' ';
  781. tem++;
  782. }
  783. }
  784. if (mapelt->info.data_offset)
  785. {
  786. indesc = archive_indesc;
  787. lseek (indesc, mapelt->info.data_offset, 0);
  788. }
  789. else
  790. {
  791. indesc = open (mapelt->info.name, 0, 0);
  792. if (indesc < 0)
  793. {
  794. perror_with_name (mapelt->info.name);
  795. return;
  796. }
  797. }
  798. write (outdesc, &header, sizeof (header));
  799. {
  800. char buf[BUFSIZE];
  801. int tocopy = mapelt->info.size;
  802. while (tocopy > 0)
  803. {
  804. int thistime = tocopy;
  805. if (thistime > BUFSIZE) thistime = BUFSIZE;
  806. read (indesc, buf, thistime);
  807. write (outdesc, buf, thistime);
  808. tocopy -= thistime;
  809. }
  810. }
  811. if (indesc != archive_indesc)
  812. close (indesc);
  813. if (mapelt->info.size & 1)
  814. write (outdesc, "\n", 1);
  815. if (verbose)
  816. printf ("member %s copied to new archive\n", mapelt->info.name);
  817. }
  818. /* Update the time of the __.SYMDEF member; done when we updated
  819. that member, just before we close the new archive file.
  820. It is open on OUTDESC. */
  821. touch_symdef_member (outdesc)
  822. int outdesc;
  823. {
  824. struct stat statbuf;
  825. int i;
  826. /* See what mtime the archive file has as a result of our writing it. */
  827. fstat (outdesc, &statbuf);
  828. /* Advance member's time to that time */
  829. bzero (symdef_header.ar_date, sizeof symdef_header.ar_date);
  830. sprintf (symdef_header.ar_date, "%d", statbuf.st_mtime);
  831. for (i = 0; i < sizeof symdef_header.ar_date; i++)
  832. if (symdef_header.ar_date[i] == 0)
  833. symdef_header.ar_date[i] = ' ';
  834. /* Write back this member's header with the new time. */
  835. if (lseek (outdesc, symdef_mapelt->info.new_offset, 0) >= 0)
  836. write (outdesc, &symdef_header, sizeof symdef_header);
  837. }
  838. char *
  839. make_tempname (name)
  840. char *name;
  841. {
  842. return concat (name, "", "_supersede");
  843. }
  844. delete_members ()
  845. {
  846. struct mapelt *map = make_map (0);
  847. struct mapelt *tail;
  848. struct mapelt mapstart;
  849. char **p;
  850. mapstart.info.name = 0;
  851. mapstart.next = map;
  852. map = &mapstart;
  853. lock_for_update ();
  854. if (files)
  855. for (p = files; *p; p++)
  856. {
  857. /* If user says to delete the __.SYMDEF member,
  858. don't make a new one to replace it. */
  859. if (!strcmp (*p, "__.SYMDEF"))
  860. symdef_exists = 0;
  861. delete_from_map (*p, map);
  862. }
  863. write_archive (map->next, 0);
  864. }
  865. delete_from_map (name, map)
  866. char *name;
  867. struct mapelt *map;
  868. {
  869. struct mapelt *this = find_mapelt (map, name);
  870. struct mapelt *prev;
  871. if (!this) return;
  872. prev = prev_mapelt (map, this);
  873. prev->next = this->next;
  874. if (verbose)
  875. printf ("deleting member %s\n", name);
  876. }
  877. move_members ()
  878. {
  879. struct mapelt *map = make_map (0);
  880. char **p;
  881. struct mapelt *after_mapelt;
  882. struct mapelt mapstart;
  883. struct mapelt *change_map;
  884. mapstart.info.name = 0;
  885. mapstart.next = map;
  886. change_map = &mapstart;
  887. lock_for_update ();
  888. switch (postype)
  889. {
  890. case POS_DEFAULT:
  891. after_mapelt = last_mapelt (change_map);
  892. break;
  893. case POS_AFTER:
  894. after_mapelt = find_mapelt (map, posname);
  895. break;
  896. case POS_BEFORE:
  897. after_mapelt = prev_mapelt (change_map, find_mapelt (map, posname));
  898. }
  899. /* Failure to find specified "before" or "after" member
  900. is a fatal error; message has already been printed. */
  901. if (!after_mapelt) exit (1);
  902. if (files)
  903. for (p = files; *p; p++)
  904. {
  905. if (move_in_map (*p, change_map, after_mapelt))
  906. after_mapelt = after_mapelt->next;
  907. }
  908. write_archive (map, 0);
  909. }
  910. int
  911. move_in_map (name, map, after)
  912. char *name;
  913. struct mapelt *map, *after;
  914. {
  915. struct mapelt *this = find_mapelt (map, name);
  916. struct mapelt *prev;
  917. if (!this) return 0;
  918. prev = prev_mapelt (map, this);
  919. prev->next = this->next;
  920. this->next = after->next;
  921. after->next = this;
  922. if (verbose)
  923. printf ("moving member %s\n", name);
  924. return 1;
  925. }
  926. /* Insert files into the archive. */
  927. replace_members ()
  928. {
  929. struct mapelt *map = make_map (1);
  930. struct mapelt mapstart;
  931. struct mapelt *after_mapelt;
  932. struct mapelt *change_map;
  933. char **p;
  934. mapstart.info.name = 0;
  935. mapstart.next = map;
  936. change_map = &mapstart;
  937. lock_for_update ();
  938. switch (postype)
  939. {
  940. case POS_DEFAULT:
  941. after_mapelt = last_mapelt (change_map);
  942. break;
  943. case POS_AFTER:
  944. after_mapelt = find_mapelt (map, posname);
  945. break;
  946. case POS_BEFORE:
  947. after_mapelt = prev_mapelt (change_map, find_mapelt (map, posname));
  948. }
  949. /* Failure to find specified "before" or "after" member
  950. is a fatal error; message has already been printed. */
  951. if (!after_mapelt) exit (1);
  952. if (files)
  953. for (p = files; *p; p++)
  954. {
  955. if (insert_in_map (*p, change_map, after_mapelt))
  956. after_mapelt = after_mapelt->next;
  957. }
  958. write_archive (change_map->next, 0);
  959. }
  960. /* Handle the "quick insert" operation. */
  961. quick_append ()
  962. {
  963. struct mapelt *map;
  964. struct mapelt *after;
  965. struct mapelt mapstart;
  966. char **p;
  967. mapstart.info.name = 0;
  968. mapstart.next = 0;
  969. map = &mapstart;
  970. after = map;
  971. lock_for_update ();
  972. /* Insert the specified files into the "map",
  973. but is a map of the inserted files only,
  974. and starts out empty. */
  975. if (files)
  976. for (p = files; *p; p++)
  977. {
  978. if (insert_in_map (*p, map, after))
  979. after = after->next;
  980. }
  981. /* Append these files to the end of the existing archive file. */
  982. write_archive (map->next, 1);
  983. }
  984. /* Insert an entry for name NAME into the map MAP after the map entry AFTER.
  985. Delete an old entry for NAME.
  986. MAP is assumed to start with a dummy entry, which facilitates
  987. insertion at the beginning of the list.
  988. Return 1 if successful, 0 if did nothing because file NAME doesn't
  989. exist or (optionally) is older. */
  990. insert_in_map (name, map, after)
  991. char *name;
  992. struct mapelt *map, *after;
  993. {
  994. struct mapelt *old = find_mapelt_noerror (map, name);
  995. struct mapelt *this;
  996. struct stat status;
  997. if (stat (name, &status))
  998. {
  999. perror_with_name (name);
  1000. return 0;
  1001. }
  1002. if (old && newer_only && status.st_mtime <= old->info.date)
  1003. return 0;
  1004. if (old && verbose)
  1005. printf ("replacing old member %s\n", old->info.name);
  1006. if (old) old->info.name = 0; /* Delete the old one. */
  1007. this = (struct mapelt *) xmalloc (sizeof (struct mapelt));
  1008. this->info.name = name;
  1009. this->info.offset = 0;
  1010. this->info.data_offset = 0;
  1011. this->info.date = status.st_mtime;
  1012. this->info.size = status.st_size;
  1013. this->info.uid = status.st_uid;
  1014. this->info.gid = status.st_gid;
  1015. this->info.mode = status.st_mode;
  1016. this->next = after->next;
  1017. after->next = this;
  1018. if (verbose)
  1019. printf ("inserting file %s\n", name);
  1020. return 1;
  1021. }
  1022. /* Apply a function to each of the specified members.
  1023. */
  1024. extract_members (function)
  1025. void (*function) ();
  1026. {
  1027. struct mapelt *map;
  1028. int arcdesc;
  1029. char **p;
  1030. if (!files)
  1031. {
  1032. /* Handle case where we want to operate on every member.
  1033. No need to make a map and search it for this. */
  1034. scan (function, 0);
  1035. return;
  1036. }
  1037. arcdesc = open (archive, 0, 0);
  1038. if (!arcdesc)
  1039. fatal ("failure opening archive %s for the second time", archive);
  1040. map = make_map (0);
  1041. for (p = files; *p; p++)
  1042. {
  1043. struct mapelt *this = find_mapelt (map, *p);
  1044. if (!this) continue;
  1045. function (this->info, arcdesc);
  1046. }
  1047. close (arcdesc);
  1048. }
  1049. /* Write the __.SYMDEF member from data in core. */
  1050. void
  1051. write_symdef_member (mapelt, map, outdesc)
  1052. struct mapelt *mapelt;
  1053. struct mapelt *map;
  1054. int outdesc;
  1055. {
  1056. struct ar_hdr header;
  1057. int indesc;
  1058. struct mapelt *mapptr;
  1059. int symdefs_size;
  1060. if (!mapelt->info.name)
  1061. return; /* This element was cancelled. */
  1062. /* Clear the header, then store in the data as text. */
  1063. bzero (&header, sizeof header);
  1064. strncpy (header.ar_name, mapelt->info.name, sizeof (header.ar_name));
  1065. sprintf (header.ar_date, "%d", mapelt->info.date);
  1066. sprintf (header.ar_size, "%d", mapelt->info.size);
  1067. sprintf (header.ar_uid, "%d", mapelt->info.uid);
  1068. sprintf (header.ar_gid, "%d", mapelt->info.gid);
  1069. sprintf (header.ar_mode, "%o", mapelt->info.mode);
  1070. strncpy (header.ar_fmag, ARFMAG, sizeof (header.ar_fmag));
  1071. /* Change all remaining nulls in the header into spaces. */
  1072. {
  1073. char *tem = (char *) &header;
  1074. char *end = (char *) &header + sizeof (header);
  1075. while (tem < end)
  1076. {
  1077. if (*tem == 0)
  1078. *tem = ' ';
  1079. tem++;
  1080. }
  1081. }
  1082. bcopy (&header, &symdef_header, sizeof header);
  1083. write (outdesc, &header, sizeof (header));
  1084. /* Write long containing number of symdefs. */
  1085. symdefs_size = nsymdefs * sizeof (struct symdef);
  1086. write (outdesc, &symdefs_size, sizeof symdefs_size);
  1087. /* Write symdefs surviving from old archive. */
  1088. write (outdesc, old_symdefs, num_old_symdefs * sizeof (struct symdef));
  1089. /* Write symdefs for new members. */
  1090. for (mapptr = map; mapptr; mapptr = mapptr->next)
  1091. {
  1092. if (mapptr->info.nsymdefs)
  1093. {
  1094. write (outdesc, mapptr->info.symdefs,
  1095. mapptr->info.nsymdefs * sizeof (struct symdef));
  1096. }
  1097. }
  1098. /* Write long containing string table size. */
  1099. write (outdesc, &new_strings_size, sizeof new_strings_size);
  1100. /* Write string table */
  1101. write (outdesc, new_strings, new_strings_size);
  1102. if (mapelt->info.size & 1)
  1103. write (outdesc, "", 1);
  1104. if (verbose)
  1105. printf ("member %s copied to new archive\n", mapelt->info.name);
  1106. }
  1107. void
  1108. read_old_symdefs (map, archive_indesc)
  1109. int archive_indesc;
  1110. {
  1111. struct mapelt *mapelt;
  1112. char *data;
  1113. int val;
  1114. int symdefs_size;
  1115. mapelt = find_mapelt_noerror (map, "__.SYMDEF");
  1116. if (!mapelt)
  1117. abort (); /* Only call here if an old one exists */
  1118. data = (char *) xmalloc (mapelt->info.size);
  1119. lseek (archive_indesc, mapelt->info.data_offset, 0);
  1120. val = read (archive_indesc, data, mapelt->info.size);
  1121. symdefs_size = * (long *) data;
  1122. original_num_symdefs = symdefs_size / sizeof (struct symdef);
  1123. old_symdefs = (struct symdef *) (data + sizeof (long));
  1124. old_strings = (char *) (old_symdefs + original_num_symdefs) + sizeof (long);
  1125. old_strings_size = * (long *) (old_strings - sizeof (long));
  1126. }
  1127. /* Create the info.symdefs for a new member
  1128. by reading the file it is coming from.
  1129. This code was taken from the GNU nm.c. */
  1130. void
  1131. make_new_symdefs (mapelt, archive_indesc)
  1132. struct mapelt *mapelt;
  1133. int archive_indesc;
  1134. {
  1135. int indesc;
  1136. int len;
  1137. char *name = mapelt->info.name;
  1138. struct exec header; /* file header read in here */
  1139. int string_size;
  1140. struct nlist *symbols_and_strings;
  1141. int symcount;
  1142. int totalsize;
  1143. char *strings;
  1144. int i;
  1145. int offset;
  1146. if (mapelt->info.data_offset)
  1147. {
  1148. indesc = archive_indesc;
  1149. lseek (indesc, mapelt->info.data_offset, 0);
  1150. offset = mapelt->info.data_offset;
  1151. }
  1152. else
  1153. {
  1154. indesc = open (mapelt->info.name, 0, 0);
  1155. if (indesc < 0)
  1156. {
  1157. perror_with_name (mapelt->info.name);
  1158. return;
  1159. }
  1160. offset = 0;
  1161. }
  1162. #ifdef HEADER_SEEK_FD
  1163. HEADER_SEEK_FD (indesc);
  1164. #endif
  1165. len = read (indesc, &header, sizeof header);
  1166. if (len != sizeof header)
  1167. error_with_file ("failure reading header of ", mapelt);
  1168. else if (N_BADMAG(header))
  1169. error_with_file ("bad format (not an object file) in ", mapelt);
  1170. /* read the string-table-length out of the file */
  1171. lseek (indesc, N_STROFF(header) + offset, 0);
  1172. if (sizeof string_size != read (indesc, &string_size, sizeof string_size))
  1173. {
  1174. error_with_file ("bad string table in ", mapelt);
  1175. if (mapelt->info.data_offset)
  1176. close (indesc); /* We just opened it. Give up */
  1177. return;
  1178. }
  1179. /* number of symbol entries in the file */
  1180. symcount = header.a_syms / sizeof (struct nlist);
  1181. totalsize = string_size + header.a_syms;
  1182. /* allocate space for symbol entries and string table */
  1183. symbols_and_strings = (struct nlist *) xmalloc (totalsize);
  1184. strings = (char *) symbols_and_strings + header.a_syms;
  1185. /* read them both in all at once */
  1186. lseek (indesc, N_SYMOFF(header) + offset, 0);
  1187. if (totalsize != read (indesc, symbols_and_strings, totalsize))
  1188. {
  1189. error_with_file ("premature end of file in symbols/strings of ");
  1190. if (mapelt->info.data_offset)
  1191. close (indesc); /* Give up! */
  1192. return;
  1193. }
  1194. if (indesc != archive_indesc)
  1195. close (indesc);
  1196. /* discard the symbols we don't want to mention; compact the rest down */
  1197. symcount = filter_symbols (symbols_and_strings, symcount, strings);
  1198. /* We have a vector of struct nlist; we want a vector of struct symdef.
  1199. Convert it in place, reusing the space.
  1200. This works since a struct nlist is longer than a struct symdef.
  1201. Also make each symdef point directly at the symbol name string. */
  1202. mapelt->info.symdefs = (struct symdef *) symbols_and_strings;
  1203. mapelt->info.nsymdefs = symcount;
  1204. mapelt->info.string_size = 0;
  1205. for (i = 0; i < symcount; i++)
  1206. {
  1207. mapelt->info.symdefs[i].s.name = strings + symbols_and_strings[i].n_un.n_strx;
  1208. mapelt->info.string_size += strlen (mapelt->info.symdefs[i].s.name) + 1;
  1209. }
  1210. }
  1211. /* Choose which symbol entries to mention in __.SYMDEF;
  1212. compact them downward to get rid of the rest.
  1213. Return the number of symbols left. */
  1214. int
  1215. filter_symbols (syms, symcount, strings)
  1216. struct nlist *syms;
  1217. int symcount;
  1218. char *strings;
  1219. {
  1220. struct nlist *from = syms, *to = syms;
  1221. struct nlist *end = syms + symcount;
  1222. while (from < end)
  1223. {
  1224. if ((from->n_type & N_EXT)
  1225. && (from->n_type != N_EXT || from->n_value))
  1226. *to++ = *from;
  1227. from++;
  1228. }
  1229. return to - syms;
  1230. }
  1231. /* Update the __.SYMDEF data before writing a new archive. */
  1232. update_symdefs (map, archive_indesc)
  1233. struct mapelt *map;
  1234. int archive_indesc;
  1235. {
  1236. struct mapelt *tail;
  1237. int pos;
  1238. int i,j;
  1239. int len;
  1240. struct symdef *s;
  1241. nsymdefs = original_num_symdefs;
  1242. num_old_symdefs = original_num_symdefs;
  1243. new_strings_size = old_strings_size;
  1244. if (nsymdefs != 0)
  1245. {
  1246. /* We already had a __.SYMDEF member, so just update it. */
  1247. /* Mark as canceled any old symdefs for members being deleted. */
  1248. for (tail = map; tail; tail = tail->next)
  1249. {
  1250. if (tail->info.name == 0)
  1251. /* Old member being deleted. Delete its symdef entries too. */
  1252. {
  1253. for (i = 0; i < nsymdefs; i++)
  1254. if (old_symdefs[i].offset == tail->info.offset)
  1255. {
  1256. old_symdefs[i].offset = 0;
  1257. nsymdefs--;
  1258. num_old_symdefs--;
  1259. new_strings_size
  1260. -= strlen (old_strings + old_symdefs[i].s.stringoffset);
  1261. }
  1262. }
  1263. }
  1264. /* Now compactify old_symdefs */
  1265. for (i = 0, j = 0; i < num_old_symdefs; i++)
  1266. if (old_symdefs[i].offset)
  1267. old_symdefs[j++] = old_symdefs[i];
  1268. /* Create symdef data for any new members. */
  1269. for (tail = map; tail; tail = tail->next)
  1270. {
  1271. if (tail->info.offset || !strcmp (tail->info.name, "__.SYMDEF"))
  1272. continue;
  1273. make_new_symdefs (tail, archive_indesc);
  1274. nsymdefs += tail->info.nsymdefs;
  1275. new_strings_size += tail->info.string_size;
  1276. }
  1277. }
  1278. else
  1279. {
  1280. /* Create symdef data for all existing members. */
  1281. for (tail = map; tail; tail = tail->next)
  1282. {
  1283. if (!strcmp (tail->info.name, "__.SYMDEF"))
  1284. continue;
  1285. make_new_symdefs (tail, archive_indesc);
  1286. nsymdefs += tail->info.nsymdefs;
  1287. new_strings_size += tail->info.string_size;
  1288. }
  1289. }
  1290. /* Now we know the size of __.SYMDEF,
  1291. so assign the positions of all the members. */
  1292. tail = find_mapelt_noerror (map, "__.SYMDEF");
  1293. tail->info.size = nsymdefs * sizeof (struct symdef) + sizeof (long) + sizeof (long) + new_strings_size;
  1294. symdef_mapelt = tail;
  1295. pos = SARMAG;
  1296. for (tail = map; tail; tail = tail->next)
  1297. {
  1298. if (!tail->info.name) continue; /* Ignore deleted members */
  1299. tail->info.new_offset = pos;
  1300. pos += tail->info.size + sizeof (struct ar_hdr);
  1301. if (tail->info.size & 1) pos++;
  1302. }
  1303. /* Now update the offsets in the symdef data
  1304. to be the new offsets rather than the old ones. */
  1305. for (tail = map; tail; tail = tail->next)
  1306. {
  1307. if (!tail->info.name) continue;
  1308. if (!tail->info.symdefs)
  1309. /* Member without new symdef data.
  1310. Check the old symdef data; it may be included there. */
  1311. for (i = 0; i < num_old_symdefs; i++)
  1312. {
  1313. if (old_symdefs[i].offset == tail->info.offset)
  1314. old_symdefs[i].offset = tail->info.new_offset;
  1315. }
  1316. else
  1317. for (i = 0; i < tail->info.nsymdefs; i++)
  1318. tail->info.symdefs[i].offset = tail->info.new_offset;
  1319. }
  1320. /* Generate new, combined string table
  1321. and put each string's offset into the symdef that refers to it.
  1322. Note that old symdefs ref their strings by offsets into old_strings
  1323. but new symdefs contain addresses of strings. */
  1324. new_strings = (char *) xmalloc (new_strings_size);
  1325. pos = 0;
  1326. for (i = 0; i < num_old_symdefs; i++)
  1327. {
  1328. if (old_symdefs[i].offset == 0) continue;
  1329. strcpy (new_strings + pos, old_strings + old_symdefs[i].s.stringoffset);
  1330. old_symdefs[i].s.stringoffset = pos;
  1331. pos += strlen (new_strings + pos) + 1;
  1332. }
  1333. for (tail = map; tail; tail = tail->next)
  1334. {
  1335. len = tail->info.nsymdefs;
  1336. s = tail->info.symdefs;
  1337. for (i = 0; i < len; i++)
  1338. {
  1339. strcpy (new_strings + pos, s[i].s.name);
  1340. s[i].s.stringoffset = pos;
  1341. pos += strlen (new_strings + pos) + 1;
  1342. }
  1343. }
  1344. if (pos != new_strings_size)
  1345. fatal ("inconsistency in new_strings_size", 0);
  1346. }
  1347. /* Print error message and exit. */
  1348. fatal (s1, s2)
  1349. char *s1, *s2;
  1350. {
  1351. error (s1, s2);
  1352. exit (1);
  1353. }
  1354. /* Print error message. `s1' is printf control string, `s2' is arg for it. */
  1355. error (s1, s2)
  1356. char *s1, *s2;
  1357. {
  1358. fprintf (stderr, "ar: ");
  1359. fprintf (stderr, s1, s2);
  1360. fprintf (stderr, "\n");
  1361. }
  1362. error_with_file (string, mapelt)
  1363. char *string;
  1364. struct mapelt *mapelt;
  1365. {
  1366. fprintf (stderr, "ar: ");
  1367. fprintf (stderr, string);
  1368. if (mapelt->info.offset)
  1369. fprintf (stderr, "%s(%s)", archive, mapelt->info.name);
  1370. else
  1371. fprintf (stderr, "%s", mapelt->info.name);
  1372. fprintf (stderr, "\n");
  1373. }
  1374. perror_with_name (name)
  1375. char *name;
  1376. {
  1377. extern int errno, sys_nerr;
  1378. extern char *sys_errlist[];
  1379. char *s;
  1380. if (errno < sys_nerr)
  1381. s = concat ("", sys_errlist[errno], " for %s");
  1382. else
  1383. s = "cannot open %s";
  1384. error (s, name);
  1385. }
  1386. pfatal_with_name (name)
  1387. char *name;
  1388. {
  1389. extern int errno, sys_nerr;
  1390. extern char *sys_errlist[];
  1391. char *s;
  1392. if (errno < sys_nerr)
  1393. s = concat ("", sys_errlist[errno], " for %s");
  1394. else
  1395. s = "cannot open %s";
  1396. fatal (s, name);
  1397. }
  1398. /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
  1399. char *
  1400. concat (s1, s2, s3)
  1401. char *s1, *s2, *s3;
  1402. {
  1403. int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
  1404. char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
  1405. strcpy (result, s1);
  1406. strcpy (result + len1, s2);
  1407. strcpy (result + len1 + len2, s3);
  1408. *(result + len1 + len2 + len3) = 0;
  1409. return result;
  1410. }
  1411. /* Like malloc but get fatal error if memory is exhausted. */
  1412. int
  1413. xmalloc (size)
  1414. int size;
  1415. {
  1416. int result = malloc (size);
  1417. if (!result)
  1418. fatal ("virtual memory exhausted", 0);
  1419. return result;
  1420. }
  1421. int
  1422. xrealloc (ptr, size)
  1423. char *ptr;
  1424. int size;
  1425. {
  1426. int result = realloc (ptr, size);
  1427. if (!result)
  1428. fatal ("virtual memory exhausted");
  1429. return result;
  1430. }
  1431. #ifdef USG
  1432. bcmp (a, b, n)
  1433. char *a, *b;
  1434. {
  1435. return (memcmp (a, b, n));
  1436. }
  1437. bcopy (from, to, n)
  1438. char *from, *to;
  1439. {
  1440. memcpy (to, from, n);
  1441. }
  1442. bzero (p, n)
  1443. char *p;
  1444. {
  1445. memset (p, 0, n);
  1446. }
  1447. rename (from, to)
  1448. char *from, *to;
  1449. {
  1450. if (unlink (to) < 0
  1451. || link (from, to) < 0
  1452. || unlink (from) < 0)
  1453. return -1;
  1454. else
  1455. return 0;
  1456. }
  1457. #endif