Commit e02dd192a00919f0aa49ce5298d21acbff8b96f9

Implemented IPK1.1 layout

* Implemented IPK1.1 basic layout
  Some adjustments still need to be made.
  
532532 end;
533533 end;
534534
535 if not pkg.UnpackFile('arcinfo.pin') then
535 if not pkg.UnpackControlFile('arcinfo.pin') then
536536 begin
537537 MakeUsrRequest(rsExtractError + #10 + rsPkgDM + #10 + rsABLoad, rqError);
538538 Emergency_FreeAll();
568568 IIconPath := cont.Icon;
569569 if IIconPath <> '' then
570570 begin
571 pkg.UnpackFile(IIconPath);
571 pkg.UnpackControlFile(IIconPath);
572572 IIconPath := CleanFilePath(pkg.WDir + IIconPath);
573573 end;
574574
600600 for i := 0 to PkProfiles.Count - 1 do
601601 begin
602602 msg(StrSubst(rsFoundInstallProfileX, '%s', PkProfiles[PkProfiles.Count - 1]));
603 pkg.UnpackFile('pkgdata/fileinfo-' + IntToStr(i) + '.id');
603 pkg.UnpackControlFile('pkgdata/fileinfo-' + IntToStr(i) + '.id');
604604 end;
605605
606606 IAppName := cont.AppName;
637637 FWizImage := GetDataFile('graphics/wizardimage.png');
638638 if (FWizImage <> '') and (FWizImage[1] = '/') then
639639 begin
640 pkg.UnpackFile(FWizImage);
640 pkg.UnpackControlFile(FWizImage);
641641 if FileExists(pkg.WDir + FWizImage) then
642642 FWizImage := CleanFilePath(pkg.WDir + FWizImage);
643643 end;
644644
645 pkg.UnpackFile('preinst');
646 pkg.UnpackFile('postinst');
647 pkg.UnpackFile('prerm');
645 pkg.UnpackControlFile('preinst');
646 pkg.UnpackControlFile('postinst');
647 pkg.UnpackControlFile('prerm');
648648 ExecA := '<disabled>';
649649 ExecB := '<disabled>';
650650 ExecX := '<disabled>';
674674 Inc(i);
675675 end;
676676
677 i := 0;
678 while i <= Dependencies.Count - 1 do
679 begin
680 if StringReplace(Dependencies[i], ' ', '', [rfReplaceAll]) = '' then
681 Dependencies.Delete(i);
682 Inc(i);
683 end;
684
685{ if xnode.FindNode('pkcatalog')<>nil then
686 begin
687 z.ExtractFiles(ExtractFileName(xnode.FindNode('pkcatalog').NodeValue));
688 Dependencies.Add('cat:'+lp+PkgName+xnode.FindNode('pkcatalog').NodeValue)
689 end;}
690
691 for i := 0 to Dependencies.Count - 1 do
692 if Dependencies[i][1] = '.' then
693 pkg.UnpackFile(Dependencies[i]);
694
695677 msg('Profiles count is ' + IntToStr(PkProfiles.Count));
696678 if PkProfiles.Count < 0 then
697679 begin
860860 cont := TIPKControl.Create(pkg.WDir + '/arcinfo.pin'); //Read IPK configuration
861861 cont.LangCode := GetLangID; //Set language code, so we get localized entries
862862
863 pkg.UnpackFile(cont.Binary);
863 pkg.UnpackDataFile(cont.Binary);
864864
865865 tmp := TStringList.Create;
866866 cont.GetInternalFilesSection(tmp);
867867 for i := 0 to tmp.Count - 1 do
868 pkg.UnpackFile(tmp[i]);
868 pkg.UnpackDataFile(tmp[i]);
869869
870870 tmp.Free;
871871 WDir := pkg.WDir;
11191119
11201120
11211121 //Unpack files directory
1122 if not pkg.UnpackFile('files') then
1122 if not pkg.UnpackDataFile('files') then
11231123 begin
11241124 MakeUsrRequest(rsExtractError, rqError);
11251125 RollbackInstallation;
  
372372 end;
373373 fc.Add(CleanFilePath(h + '/' + ExtractFileName(DeleteModifiers(fname))));
374374
375 if not ipkpkg.AddFile(WDir + h + '/' + ExtractFileName(DeleteModifiers(fname))) then
375 if not ipkpkg.AddDataFile(WDir + h + '/' + ExtractFileName(DeleteModifiers(fname))) then
376376 begin
377377 writeLn('error: ');
378378 writeln(' Could not add file "' + DeleteModifiers(fname) + '" to TAR archive.');
606606 if prID <> '-1' then
607607 begin
608608 fc.SaveToFile(WDir + 'pkgdata/' + 'fileinfo-' + prID + '.id');
609 ipkpkg.AddFile(WDir + 'pkgdata/fileinfo-' + prID + '.id');
609 ipkpkg.AddControlFile(WDir + 'pkgdata/fileinfo-' + prID + '.id');
610610 end;
611611
612612 end; //End of file including
637637 FileCopy(h, WDir + 'pkgdata/' + 'packicon.png');
638638 //!!! Should be changed to support more picture-filetypes
639639 control.Icon := '/pkgdata/' + 'packicon.png';
640 ipkpkg.AddFile(WDir + 'pkgdata/' + 'packicon.png');
640 ipkpkg.AddControlFile(WDir + 'pkgdata/' + 'packicon.png');
641641 writeLn(' I: Icon included.');
642642 end;
643643 end; //END <>nil
719719 if FileExists(ExtractFilePath(fi) + '/preinst') then
720720 begin
721721 FileCopy(ExtractFilePath(fi) + '/preinst', WDir + 'preinst');
722 ipkpkg.AddFile(WDir + 'preinst');
722 ipkpkg.AddControlFile(WDir + 'preinst');
723723
724724 writeLn(' I: Preinst script found.');
725725 end;
726726 if FileExists(ExtractFilePath(fi) + '/postinst') then
727727 begin
728728 FileCopy(ExtractFilePath(fi) + '/postinst', WDir + 'postinst');
729 ipkpkg.AddFile(WDir + 'postinst');
729 ipkpkg.AddControlFile(WDir + 'postinst');
730730 writeLn(' I: Postinst script found.');
731731 end;
732732 if FileExists(ExtractFilePath(fi) + '/prerm') then
733733 begin
734734 FileCopy(ExtractFilePath(fi) + '/prerm', WDir + 'prerm');
735 ipkpkg.AddFile(WDir + 'prerm');
735 ipkpkg.AddControlFile(WDir + 'prerm');
736736 writeLn(' I: Prerm script found.');
737737 end;
738738
747747 if not FileCopy(sl[i], WDir + 'locale/' + ExtractFileName(sl[i])) then
748748 RaiseCopyError(sl[i]);
749749 writeLn(' I: Include locale: ' + ExtractFileName(sl[i]));
750 ipkpkg.AddFile(WDir + 'locale/' + ExtractFileName(sl[i]));
750 ipkpkg.AddControlFile(WDir + 'locale/' + ExtractFileName(sl[i]));
751751 end;
752752 sl.Free;
753753
786786 ExtractFileName(control.Binary)) then
787787 RaiseCopyError(control.Binary);
788788
789 ipkpkg.AddFile(WDir + 'files/' + ExtractFileName(control.Binary));
789 ipkpkg.AddControlFile(WDir + 'files/' + ExtractFileName(control.Binary));
790790 control.Binary := '/files/' + ExtractFileName(control.Binary);
791791 end;
792792 end;
797797
798798 control.SaveToFile(WDir + 'arcinfo.pin');
799799
800 ipkpkg.AddFile(WDir + 'arcinfo.pin');
800 ipkpkg.AddControlFile(WDir + 'arcinfo.pin');
801801
802802 ipkpkg.Finalize; //Freeze the IPK package state
803803 files.Free;
  
11<?xml version="1.0"?>
22<CONFIG>
33 <ProjectOptions>
4 <Version Value="7"/>
4 <Version Value="8"/>
55 <General>
66 <SessionStorage Value="InProjectDir"/>
77 <MainUnit Value="0"/>
4747 </Units>
4848 </ProjectOptions>
4949 <CompilerOptions>
50 <Version Value="8"/>
50 <Version Value="9"/>
5151 <Target>
5252 <Filename Value="../../build/libuild"/>
5353 </Target>
5858 <UnitOutputDirectory Value="../../build/$(TargetCPU)-$(TargetOS)"/>
5959 <LCLWidgetType Value="nogui"/>
6060 </SearchPaths>
61 <Parsing>
62 <SyntaxOptions>
63 <UseAnsiStrings Value="False"/>
64 </SyntaxOptions>
65 </Parsing>
6166 <Other>
6267 <CustomOptions Value="-dOpbCompat"/>
6368 <CompilerPath Value="$(CompPath)"/>
  
2121interface
2222
2323uses
24 Classes, FileUtil, GPGSign, LiUtils, LiTypes, SysUtils, TarArchive;
24 Unix, Classes, GPGSign, LiTypes, LiUtils, FileUtil, SysUtils, TarArchive;
2525
2626type
27 //** Creates IPK packages from preprocessed source files
2827
2928 { TLiPackager }
3029
30 //** Creates IPK packages from preprocessed source files
3131 TLiPackager = class
3232 private
3333 OutFileName: String;
3434 pkrandom: String;
35 basename: String;
36 mntar: TTarArchive;
35 wdir: String;
36 ctar, dtar: TTarArchive;
3737 finalized: Boolean;
3838 bdir: String;
39 maxbytes: Int64;
39 arcdata, arccontrol: String;
4040
4141 function RandomID: String;
4242 public
4343 constructor Create(aIPKFile: String);
4444 destructor Destroy; override;
4545
46 //** Add a new file to the IPK structure @return False if already finalized or other error
47 function AddFile(fname: String): Boolean;
48 //** Finalize the base file for signing
49 procedure Finalize;
46 //** Add new data to the IPK structure @return False if already finalized or other error
47 function AddDataFile(fname: String): Boolean;
48 //** Add a control file to the IPK structure @return False if already finalized or other error
49 function AddControlFile(fname: String): Boolean;
50 //** Finalize the package
51 function Finalize: Integer;
5052 //** Sign the package
5153 function SignPackage: Boolean;
5254 //** Compress package and copy it to output @returns Success of operation
5959 property IPKFile: String read OutFileName write OutFileName;
6060 end;
6161
62 //** Unpacks IPK package structure
63
6462 { TLiUnpacker }
6563
64 //** Unpacks IPK package structure
6665 TLiUnpacker = class
6766 private
6867 ipkfile: String;
7171 constructor Create(aIPKFile: String);
7272 destructor Destroy; override;
7373
74 //** Prepare IPK tar file for extracting
75 procedure Prepare;
74 //** Prepare IPK tar file for installation & signature verifying
75 function Prepare: Boolean;
7676 //** Verify signature (if there is any)
7777 function CheckSignature: TPkgSigState;
78 //** Unpack file @returns Success of operation
79 function UnpackFile(fname: String): Boolean;
78 //** Unpack data file @returns Success of operation
79 function UnpackDataFile(fname: String): Boolean;
80 //** Unpack data file @returns Success of operation
81 function UnpackControlFile(fname: String): Boolean;
8082 //** Unpacker's working dir
8183 property WDir: String read workdir;
8284 end;
105105begin
106106 inherited Create;
107107 randomize;
108 pkrandom := '-' + RandomID + RandomID + RandomID;
109108 finalized := false;
110109 OutFileName := aIPKFile;
111 basename := tmpdir + ExtractFileName(OutFileName) + pkrandom + '.tar';
112 mntar := TTarArchive.Create;
113 mntar.Compression:=cmXZ; //IPK packages are XZ compressed
114 mntar.TarArchive := basename;
110 wdir := tmpdir + ChangeFileExt(ExtractFileName(OutFileName), '') + '-build/';
111 ForceDirectories(wdir);
112 arcdata := wdir + 'data.tar.xz';
113 arccontrol := wdir + 'control.tar.xz';
114
115 ctar := TTarArchive.Create;
116 ctar.Compression := cmXZ; //Control Tar is always XZ compressed
117 ctar.TarArchive := arccontrol;
118 dtar := TTarArchive.Create;
119 dtar.Compression := cmXZ;
120 //Data Tar can have various compression methods (XZ by default)
121 dtar.TarArchive := arcdata;
115122end;
116123
117124destructor TLiPackager.Destroy;
118125begin
119 if not finalized then
120 mntar.Free;
126 ctar.Free;
127 dtar.Free;
121128 inherited;
122129end;
123130
133133 Result := IntToStr(random(99));
134134end;
135135
136function TLiPackager.AddFile(fname: String): Boolean;
136function TLiPackager.AddDataFile(fname: String): Boolean;
137137begin
138138 if finalized then
139139 Result := false
140140 else
141141 begin
142 mntar.BaseDir := bdir;
143 if mntar.AddFile(fname) = 0 then
142 dtar.BaseDir := bdir;
143 if dtar.AddFile(fname) = 0 then
144144 Result := true
145145 else
146146 Result := false;
147147 end;
148148end;
149149
150procedure TLiPackager.Finalize;
150function TLiPackager.AddControlFile(fname: String): Boolean;
151151begin
152 if finalized then
153 Result := false
154 else
155 begin
156 ctar.BaseDir := bdir;
157 if ctar.AddFile(fname) = 0 then
158 Result := true
159 else
160 Result := false;
161 end;
162end;
163
164function TLiPackager.Finalize: Integer;
165begin
166 Result := 0;
167 if finalized then
168 exit;
169
152170 p_info('Finalizing package.');
153 if mntar.Finalize > 0 then
154 raise Exception.Create('Error while building package.');
155 mntar.Free;
171 if ctar.Finalize > 0 then
172 raise Exception.Create('Error while creating control container!');
173 if dtar.Finalize > 0 then
174 raise Exception.Create('Error while creating data container!');
175
156176 finalized := true;
157177end;
158178
159179function TLiPackager.SignPackage: Boolean;
160180var
161181 sign: TGPGSignWrapper;
162 oldbase: String;
163182 rs: Integer;
164183begin
165184 Result := false;
166185 if (not Finalized) then
167186 raise Exception.Create('IPK file was not finalized before signing.');
168187
169 oldbase := basename;
188 //Concat data to sign it
189 fpsystem(FindBinary('cat') + ' ' + ctar.TarArchive + ' ' + dtar.TarArchive +
190 ' > ' + wdir + 'combined.tmp');
191
170192 sign := TGPGSignWrapper.Create;
171 sign.FileName := oldbase;
193 sign.FileName := wdir + 'combined.tmp';
172194 Result := true;
173 if FileExistsUTF8(ExtractFilePath(oldbase) + '/signature.asc') then
174 DeleteFile(ExtractFilePath(oldbase) + '/signature.asc');
195 if FileExistsUTF8(wdir + '_signature') then
196 DeleteFile(wdir + '_signature');
175197
176 if not sign.Signfile(ExtractFilePath(oldbase) + '/signature.asc') then
198 if not sign.Signfile(wdir + '_signature') then
177199 begin
178200 Result := false;
179201 sign.Free;
203203 end;
204204 sign.Free;
205205
206 pkrandom := '-' + RandomID + RandomID + RandomID;
207 basename := tmpdir + ExtractFileName(OutFileName) + pkrandom + '.tar';
206 DeleteFile(wdir + 'combined.tmp');
207end;
208
209function TLiPackager.ProduceIPKPackage: Boolean;
210var
211 mntar: TTarArchive;
212 basename: String;
213begin
214 Result := true;
215 basename := basedir + ExtractFileName(OutFileName) +
216 RandomID + RandomID + RandomID + '.tar';
208217 mntar := TTarArchive.Create;
209 mntar.Compression:=cmNone; //No compression here
218 mntar.Compression := cmNone; //Container Tar is not compressed
210219 mntar.TarArchive := basename;
220 mntar.BaseDir := wdir;
211221
212 mntar.BaseDir := ExtractFilePath(oldbase);
222 if (not Finalized) then
223 raise Exception.Create('IPK file was not finalized.');
213224
214 RenameFile(oldbase, ExtractFilePath(oldbase) + '/content.tar');
215 oldbase := ExtractFilePath(oldbase) + '/content.tar';
216
217 rs := mntar.AddFile(oldbase);
218 if rs = 0 then
225 if mntar.AddFile(arccontrol) > 0 then
219226 begin
220 rs := mntar.AddFile(ExtractFilePath(oldbase) + 'signature.asc');
221 if rs <> 0 then
222 raise Exception.Create('Error while combining signed package.');
223 end
224 else
225 raise Exception.Create('Error while combining signed package.');
226 mntar.Finalize;
227 mntar.Free;
227 Result := false;
228 exit;
229 end;
230 if mntar.AddFile(arcdata) > 0 then
231 begin
232 Result := false;
233 exit;
234 end;
235 if FileExists(wdir + '_signature') then
236 if mntar.AddFile(wdir + '_signature') > 0 then
237 begin
238 Result := false;
239 exit;
240 end;
228241
229 DeleteFile(ExtractFilePath(oldbase) + 'signature.asc');
230 DeleteFile(oldbase);
231end;
242 if mntar.Finalize > 0 then
243 raise Exception.Create('Error while building package.');
232244
233function TLiPackager.ProduceIPKPackage: Boolean;
234begin
235 Result := true;
236245 if FileExists(OutFileName) then
237246 Exception.Create('Output file already exists!');
238 if (not Finalized) then
239 raise Exception.Create('IPK file was not finalized.');
240247
241 if not finalized then mntar.Finalize;
248 mntar.Free;
242249
243 FileCopy(basename,outfilename);
250 FileCopy(basename, outfilename);
244251 DeleteFile(basename);
245252end;
246253
257257begin
258258 inherited Create;
259259 ipkfile := aIPKFile;
260 workdir := tmpdir + ExtractFileName(ipkfile) + '/';
261 SysUtils.ForceDirectories(workdir);
260 workdir := tmpdir + ChangeFileExt(ExtractFileName(ipkfile),'') + '-install/';
261 ForceDirectories(workdir);
262262 signChecked := false;
263263end;
264264
267267 inherited;
268268end;
269269
270procedure TLiUnpacker.Prepare;
270function TLiUnpacker.Prepare: Boolean;
271var
272 mnarc: TTarArchive;
271273begin
274 Result := true;
272275 if not FileExists(ipkfile) then
273276 Exception.Create('IPK file does not exists!');
274277
275 FileCopy(ipkfile, workdir+'ipktar.tar');
276 //Some more praparation later...
278 FileCopy(ipkfile, workdir + 'ipktar.tar');
279 mnarc := TTarArchive.Create;
280 mnarc.TarArchive := workdir + 'ipktar.tar';
281 mnarc.Compression := cmNone; //Covering tar is not compressed
282 mnarc.BaseDir := workdir;
283 if mnarc.ExtractFile('*') > 0 then //Extract everything
284 Result := false;
285 mnarc.Free;
286 DeleteFile(workdir + 'ipktar.tar');
277287end;
278288
279289function TLiUnpacker.CheckSignature: TPkgSigState;
280290var
281 mnarc: TTarArchive;
282291 hasSignature: Boolean;
283292 sign: TGPGSignWrapper;
284293 res: Integer;
285294begin
286295 hasSignature := false;
287 mnarc := TTarArchive.Create;
288 mnarc.TarArchive := workdir + 'ipktar.tar';
289 mnarc.Compression:=cmNone; //If we have a signature, covering tar is not compressed
290 mnarc.BaseDir := workdir;
291296
292297 Result := psNone;
293298 //Check if package has signature
294 hasSignature := mnarc.FileInArchive('signature.asc');
299 hasSignature := FileExists(workdir + '_signature');
295300
296301 if hasSignature then
297302 begin
298 res := mnarc.ExtractFile('signature.asc');
299 res += mnarc.ExtractFile('content.tar');
300
301 if res <> 0 then
302 begin
303 //!!! This should be done better!
304 raise Exception.Create('Could not verify signature!');
305 end;
306
307 DeleteFile(workdir + 'ipktar.tar');
308 RenameFile(workdir + 'content.tar', workdir + 'ipktar.tar');
303 fpsystem(FindBinary('cat') + ' ' + workdir + 'control.tar.xz ' + workdir + 'data.tar.xz > ' + workdir + 'combined.tmp');
309304 Result := psUntrusted;
310305 //Now check signature
311306 sign := TGPGSignWrapper.Create;
312 sign.FileName := workdir + 'ipktar.tar';
313 if sign.Verify(workdir + 'signature.asc') then
307 sign.FileName := workdir + 'combined.tmp';
308 if sign.Verify(workdir + '_signature') then
314309 Result := psTrusted;
315310 sign.Free;
311 DeleteFile(workdir + 'combined.tmp');
316312 end;
317 mnarc.Free;
318313 signChecked := true;
319314end;
320315
321function TLiUnpacker.UnpackFile(fname: String): Boolean;
316function TLiUnpacker.UnpackDataFile(fname: String): Boolean;
322317var
323318 arc: TTarArchive;
324319begin
326326 fname := CleanFilePath(fname);
327327
328328 arc := TTarArchive.Create;
329 arc.TarArchive := workdir + 'ipktar.tar';
329 arc.TarArchive := workdir + 'data.tar.xz';
330330 arc.BaseDir := workdir;
331 arc.Compression:=cmXZ;
331 arc.Compression := cmXZ;
332332 //Create dir struct
333333 //ForceDirectories(ExtractFilePath(fdest));
334 //Check if package has signature
335334 if arc.ExtractFile(fname) = 0 then
336335 Result := true;
337336
338337 arc.Free;
339338end;
340339
340function TLiUnpacker.UnpackControlFile(fname: String): Boolean;
341var
342 arc: TTarArchive;
343begin
344 if not signChecked then
345 CheckSignature;
346 Result := false;
347 if length(fname) < 2 then
348 exit;
349
350 fname := CleanFilePath(fname);
351 arc := TTarArchive.Create;
352 arc.TarArchive := workdir + 'control.tar.xz';
353 arc.BaseDir := workdir;
354 arc.Compression := cmXZ;
355 //Create dir struct
356 //ForceDirectories(ExtractFilePath(fdest));
357 if arc.ExtractFile(fname) = 0 then
358 Result := true;
359
360 arc.Free;
361end;
362
341363{ TLiUpdateBit }
342364
343365constructor TLiUpdateBit.Create;
344366begin
345367 inherited;
346368 xz := TTarArchive.Create;
347 xz.Compression:=cmLZMA;
369 xz.Compression := cmLZMA;
348370end;
349371
350372destructor TLiUpdateBit.Destroy;
377377
378378procedure TLiUpdateBit.Compress(infile: String; outfile: String);
379379begin
380 xz.BaseDir:=ExtractFilePath(infile);
381 xz.TarArchive:=outfile;
380 xz.BaseDir := ExtractFilePath(infile);
381 xz.TarArchive := outfile;
382382 xz.AddFile(infile);
383383 xz.Finalize;
384384end;
386386procedure TLiUpdateBit.Decompress(infile: String; outfile: String);
387387begin
388388 //NEEDS WORK!
389 xz.TarArchive:=infile;
390 xz.BaseDir:=ExtractFilePath(outfile);
389 xz.TarArchive := infile;
390 xz.BaseDir := ExtractFilePath(outfile);
391391 xz.ExtractFile('*');
392392end;
393393