owar.pas 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  4. Contains the stuff for writing .a files directly
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit owar;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. cobjects,owbase;
  23. type
  24. tarhdr=packed record
  25. name : array[0..15] of char;
  26. date : array[0..11] of char;
  27. uid : array[0..5] of char;
  28. gid : array[0..5] of char;
  29. mode : array[0..7] of char;
  30. size : array[0..9] of char;
  31. fmag : array[0..1] of char;
  32. end;
  33. parobjectwriter=^tarobjectwriter;
  34. tarobjectwriter=object(tobjectwriter)
  35. constructor Init(const Aarfn:string);
  36. destructor Done;virtual;
  37. procedure create(const fn:string);virtual;
  38. procedure close;virtual;
  39. procedure writesym(const sym:string);virtual;
  40. procedure write(const b;len:longint);virtual;
  41. private
  42. arfn : string;
  43. arhdr : tarhdr;
  44. symreloc,
  45. symstr,
  46. lfnstr,
  47. ardata : PDynamicArray;
  48. objpos : longint;
  49. objfn : string;
  50. timestamp : string[12];
  51. procedure createarhdr(fn:string;size:longint;const gid,uid,mode:string);
  52. procedure writear;
  53. end;
  54. implementation
  55. uses
  56. verbose,
  57. {$ifdef Delphi}
  58. dmisc;
  59. {$else Delphi}
  60. dos;
  61. {$endif Delphi}
  62. const
  63. symrelocbufsize = 4096;
  64. symstrbufsize = 8192;
  65. lfnstrbufsize = 4096;
  66. arbufsize = 65536;
  67. objbufsize = 16384;
  68. {*****************************************************************************
  69. Helpers
  70. *****************************************************************************}
  71. const
  72. C1970=2440588;
  73. D0=1461;
  74. D1=146097;
  75. D2=1721119;
  76. Function Gregorian2Julian(DT:DateTime):LongInt;
  77. Var
  78. Century,XYear,Month : LongInt;
  79. Begin
  80. Month:=DT.Month;
  81. If Month<=2 Then
  82. Begin
  83. Dec(DT.Year);
  84. Inc(Month,12);
  85. End;
  86. Dec(Month,3);
  87. Century:=(longint(DT.Year Div 100)*D1) shr 2;
  88. XYear:=(longint(DT.Year Mod 100)*D0) shr 2;
  89. Gregorian2Julian:=((((Month*153)+2) div 5)+DT.Day)+D2+XYear+Century;
  90. End;
  91. function DT2Unix(DT:DateTime):LongInt;
  92. Begin
  93. DT2Unix:=(Gregorian2Julian(DT)-C1970)*86400+(LongInt(DT.Hour)*3600)+(DT.Min*60)+DT.Sec;
  94. end;
  95. {*****************************************************************************
  96. TArObjectWriter
  97. *****************************************************************************}
  98. constructor tarobjectwriter.init(const Aarfn:string);
  99. var
  100. time : datetime;
  101. dummy : word;
  102. begin
  103. arfn:=Aarfn;
  104. new(arData,init(arbufsize));
  105. new(symreloc,init(symrelocbufsize));
  106. new(symstr,init(symstrbufsize));
  107. new(lfnstr,init(lfnstrbufsize));
  108. { create timestamp }
  109. getdate(time.year,time.month,time.day,dummy);
  110. gettime(time.hour,time.min,time.sec,dummy);
  111. Str(DT2Unix(time),timestamp);
  112. end;
  113. destructor tarobjectwriter.done;
  114. begin
  115. if Errorcount=0 then
  116. writear;
  117. dispose(arData,done);
  118. dispose(symreloc,done);
  119. dispose(symstr,done);
  120. dispose(lfnstr,done);
  121. end;
  122. procedure tarobjectwriter.createarhdr(fn:string;size:longint;const gid,uid,mode:string);
  123. var
  124. tmp : string[9];
  125. begin
  126. fillchar(arhdr,sizeof(tarhdr),' ');
  127. { create ar header }
  128. fn:=fn+'/';
  129. if length(fn)>16 then
  130. begin
  131. arhdr.name[0]:='/';
  132. str(lfnstr^.size,tmp);
  133. move(tmp[1],arhdr.name[1],length(tmp));
  134. fn:=fn+#10;
  135. lfnstr^.write(fn[1],length(fn));
  136. end
  137. else
  138. move(fn[1],arhdr.name,length(fn));
  139. { don't write a date if also no gid/uid/mode is specified }
  140. if gid<>'' then
  141. move(timestamp[1],arhdr.date,sizeof(timestamp));
  142. str(size,tmp);
  143. move(tmp[1],arhdr.size,length(tmp));
  144. move(gid[1],arhdr.gid,length(gid));
  145. move(uid[1],arhdr.uid,length(uid));
  146. move(mode[1],arhdr.mode,length(mode));
  147. arhdr.fmag:='`'#10;
  148. end;
  149. procedure tarobjectwriter.create(const fn:string);
  150. begin
  151. objfn:=fn;
  152. objpos:=ardata^.size;
  153. ardata^.seek(objpos + sizeof(tarhdr));
  154. end;
  155. procedure tarobjectwriter.close;
  156. begin
  157. ardata^.align(2);
  158. { fix the size in the header }
  159. createarhdr(objfn,ardata^.size-objpos-sizeof(tarhdr),'42','42','644');
  160. { write the header }
  161. ardata^.seek(objpos);
  162. ardata^.write(arhdr,sizeof(tarhdr));
  163. end;
  164. procedure tarobjectwriter.writesym(const sym:string);
  165. var
  166. c : char;
  167. begin
  168. c:=#0;
  169. symreloc^.write(objpos,4);
  170. symstr^.write(sym[1],length(sym));
  171. symstr^.write(c,1);
  172. end;
  173. procedure tarobjectwriter.write(const b;len:longint);
  174. begin
  175. ardata^.write(b,len);
  176. end;
  177. procedure tarobjectwriter.writear;
  178. function lsb2msb(l:longint):longint;
  179. type
  180. bytearr=array[0..3] of byte;
  181. var
  182. l1 : longint;
  183. begin
  184. bytearr(l1)[0]:=bytearr(l)[3];
  185. bytearr(l1)[1]:=bytearr(l)[2];
  186. bytearr(l1)[2]:=bytearr(l)[1];
  187. bytearr(l1)[3]:=bytearr(l)[0];
  188. lsb2msb:=l1;
  189. end;
  190. const
  191. armagic:array[1..8] of char='!<arch>'#10;
  192. type
  193. plongint=^longint;
  194. var
  195. arf : file;
  196. fixup,l,
  197. relocs,i : longint;
  198. begin
  199. assign(arf,arfn);
  200. {$I-}
  201. rewrite(arf,1);
  202. {$I+}
  203. if ioresult<>0 then
  204. begin
  205. Message1(exec_e_cant_create_archivefile,arfn);
  206. exit;
  207. end;
  208. blockwrite(arf,armagic,sizeof(armagic));
  209. { align first, because we need the size for the fixups of the symbol reloc }
  210. if lfnstr^.size>0 then
  211. lfnstr^.align(2);
  212. if symreloc^.size>0 then
  213. begin
  214. symstr^.align(2);
  215. fixup:=12+sizeof(tarhdr)+symreloc^.size+symstr^.size;
  216. if lfnstr^.size>0 then
  217. inc(fixup,lfnstr^.size+sizeof(tarhdr));
  218. relocs:=symreloc^.size div 4;
  219. { fixup relocs }
  220. for i:=0to relocs-1 do
  221. begin
  222. symreloc^.seek(i*4);
  223. symreloc^.read(l,4);
  224. symreloc^.seek(i*4);
  225. l:=lsb2msb(l+fixup);
  226. symreloc^.write(l,4);
  227. end;
  228. createarhdr('',4+symreloc^.size+symstr^.size,'0','0','0');
  229. blockwrite(arf,arhdr,sizeof(tarhdr));
  230. relocs:=lsb2msb(relocs);
  231. blockwrite(arf,relocs,4);
  232. symreloc^.blockwrite(arf);
  233. symstr^.blockwrite(arf);
  234. end;
  235. if lfnstr^.size>0 then
  236. begin
  237. createarhdr('/',lfnstr^.size,'','','');
  238. blockwrite(arf,arhdr,sizeof(tarhdr));
  239. lfnstr^.blockwrite(arf);
  240. end;
  241. ardata^.blockwrite(arf);
  242. system.close(arf);
  243. end;
  244. end.
  245. {
  246. $Log$
  247. Revision 1.5 2000-09-24 15:06:20 peter
  248. * use defines.inc
  249. Revision 1.4 2000/08/19 18:44:27 peter
  250. * new tdynamicarray implementation using blocks instead of
  251. reallocmem (merged)
  252. Revision 1.3 2000/08/08 19:28:57 peter
  253. * memdebug/memory patches (merged)
  254. * only once illegal directive (merged)
  255. Revision 1.2 2000/07/13 11:32:44 michael
  256. + removed logs
  257. }