DEADSOFTWARE

sfs: hacked around segfault on exit
[d2df-sdl.git] / src / sfs / sfsZipFS.pas
index 9fb1137e0ca70d054282ddc68c6a01a190b67717..ee1cc1c272b7e6c42e884a78f643632fe376f570 100644 (file)
@@ -9,6 +9,7 @@
 //   dfwad   : D2D:F wad archives
 //
 {.$DEFINE SFS_DEBUG_ZIPFS}
+{.$DEFINE SFS_ZIPFS_FULL}
 {$MODE DELPHI}
 {.$R-}
 unit sfsZipFS;
@@ -19,18 +20,27 @@ uses
   SysUtils, Classes, Contnrs, sfs;
 
 
-
 type
-  TSFSZipVolumeType = (sfszvNone, sfszvZIP, sfszvF2DAT, sfszvVTDB, sfszvDFWAD);
+  TSFSZipVolumeType = (
+    sfszvNone,
+    sfszvZIP,
+    {$IFDEF SFS_ZIPFS_FULL}
+    sfszvF2DAT,
+    sfszvVTDB,
+    {$ENDIF}
+    sfszvDFWAD
+  );
 
   TSFSZipVolume = class(TSFSVolume)
   protected
     fType: TSFSZipVolumeType;
 
     procedure ZIPReadDirectory ();
+    procedure DFWADReadDirectory ();
+    {$IFDEF SFS_ZIPFS_FULL}
     procedure F2DATReadDirectory ();
     procedure VTDBReadDirectory ();
-    procedure DFWADReadDirectory ();
+    {$ENDIF}
 
     procedure ReadDirectory (); override;
     procedure removeCommonPath (); override;
@@ -89,6 +99,7 @@ begin
   result := true;
 end;
 
+{$IFDEF SFS_ZIPFS_FULL}
 function F2DATCheckMagic (st: TStream): Boolean;
 var
   dsize, fiSz: Integer;
@@ -115,6 +126,7 @@ begin
   if (fcnt < 0) or (dofs < 32) or (dofs+fcnt*8 > st.Size) then exit;
   result := true;
 end;
+{$ENDIF}
 
 function DFWADCheckMagic (st: TStream): Boolean;
 var
@@ -191,6 +203,7 @@ begin
   end;
 end;
 
+
 { TSFSZipVolume }
 procedure TSFSZipVolume.ZIPReadDirectory ();
 var
@@ -319,6 +332,7 @@ begin
   end;
 end;
 
+{$IFDEF SFS_ZIPFS_FULL}
 procedure TSFSZipVolume.F2DATReadDirectory ();
 var
   dsize: Integer;
@@ -392,6 +406,7 @@ begin
     fi.fMethod := 255;
   end;
 end;
+{$ENDIF}
 
 procedure TSFSZipVolume.DFWADReadDirectory ();
 // idiotic format
@@ -445,8 +460,10 @@ procedure TSFSZipVolume.ReadDirectory ();
 begin
   case fType of
     sfszvZIP: ZIPReadDirectory();
+    {$IFDEF SFS_ZIPFS_FULL}
     sfszvF2DAT: F2DATReadDirectory();
     sfszvVTDB: VTDBReadDirectory();
+    {$ENDIF}
     sfszvDFWAD: DFWADReadDirectory();
     else raise ESFSError.Create('invalid zipped SFS');
   end;
@@ -455,7 +472,7 @@ end;
 function TSFSZipVolume.OpenFileByIndex (const index: Integer): TStream;
 var
   zs: TZDecompressionStream;
-  fs: TStream;
+  fs, rs: TStream;
   gs: TSFSGuardStream;
   kill: Boolean;
   buf: packed array [0..1023] of Char;
@@ -465,6 +482,7 @@ begin
   zs := nil;
   fs := nil;
   gs := nil;
+  rs := nil;
   if fFiles = nil then exit;
   if (index < 0) or (index >= fFiles.Count) or (fFiles[index] = nil) then exit;
   kill := false;
@@ -489,37 +507,41 @@ begin
       fs.Seek(TSFSZipFileInfo(fFiles[index]).fOfs, soBeginning);
       if TSFSZipFileInfo(fFiles[index]).fMethod = 255 then
       begin
-        zs := TZDecompressionStream.Create(fs)
+        // sorry, pals, DFWAD is completely broken, so users of it should SUFFER
+        if TSFSZipFileInfo(fFiles[index]).fSize = -1 then
+        begin
+          TSFSZipFileInfo(fFiles[index]).fSize := 0;
+          //writeln('trying to determine file size for [', TSFSZipFileInfo(fFiles[index]).fPath, TSFSZipFileInfo(fFiles[index]).fName, ']');
+          zs := TZDecompressionStream.Create(fs);
+          try
+            while true do
+            begin
+              rd := zs.read(buf, 1024);
+              //writeln('  got ', rd, ' bytes');
+              if rd > 0 then Inc(TSFSZipFileInfo(fFiles[index]).fSize, rd);
+              if rd < 1024 then break;
+            end;
+            //writeln('  resulting size: ', TSFSZipFileInfo(fFiles[index]).fSize, ' bytes');
+            // recreate stream
+            FreeAndNil(zs);
+            fs.Seek(TSFSZipFileInfo(fFiles[index]).fOfs, soBeginning);
+          except
+            //writeln('*** CAN''T determine file size for [', TSFSZipFileInfo(fFiles[index]).fPath, TSFSZipFileInfo(fFiles[index]).fName, ']');
+            FreeAndNil(zs);
+            if kill then FreeAndNil(fs);
+            result := nil;
+            exit;
+          end;
+        end;
+        rs := TSFSPartialStream.Create(fs, TSFSZipFileInfo(fFiles[index]).fOfs, TSFSZipFileInfo(fFiles[index]).fPackSz, true);
+        zs := TZDecompressionStream.Create(rs);
+        rs := nil;
       end
       else
       begin
-        zs := TZDecompressionStream.Create(fs, true {-15}{MAX_WBITS});
-      end;
-      // sorry, pals, DFWAD is completely broken, so users of it should SUFFER
-      if TSFSZipFileInfo(fFiles[index]).fSize = -1 then
-      begin
-        TSFSZipFileInfo(fFiles[index]).fSize := 0;
-        //writeln('trying to determine file size for [', TSFSZipFileInfo(fFiles[index]).fPath, TSFSZipFileInfo(fFiles[index]).fName, ']');
-        try
-          while true do
-          begin
-            rd := zs.read(buf, 1024);
-            //writeln('  got ', rd, ' bytes');
-            if rd > 0 then Inc(TSFSZipFileInfo(fFiles[index]).fSize, rd);
-            if rd < 1024 then break;
-          end;
-          //writeln('  resulting size: ', TSFSZipFileInfo(fFiles[index]).fSize, ' bytes');
-          // recreate stream
-          FreeAndNil(zs);
-          fs.Seek(TSFSZipFileInfo(fFiles[index]).fOfs, soBeginning);
-          zs := TZDecompressionStream.Create(fs)
-        except
-          //writeln('*** CAN''T determine file size for [', TSFSZipFileInfo(fFiles[index]).fPath, TSFSZipFileInfo(fFiles[index]).fName, ']');
-          FreeAndNil(zs);
-          if kill then FreeAndNil(fs);
-          result := nil;
-          exit;
-        end;
+        rs := TSFSPartialStream.Create(fs, TSFSZipFileInfo(fFiles[index]).fOfs, TSFSZipFileInfo(fFiles[index]).fPackSz, true);
+        zs := TZDecompressionStream.Create(rs, true {-15}{MAX_WBITS});
+        rs := nil;
       end;
       gs := TSFSGuardStream.Create(zs, fs, true, kill, false);
       zs := nil;
@@ -527,6 +549,7 @@ begin
       result := TSFSPartialStream.Create(gs, 0, TSFSZipFileInfo(fFiles[index]).fSize, true);
     end;
   except
+    FreeAndNil(rs);
     FreeAndNil(gs);
     FreeAndNil(zs);
     if kill then FreeAndNil(fs);
@@ -541,11 +564,14 @@ function TSFSZipVolumeFactory.IsMyVolumePrefix (const prefix: TSFSString): Boole
 begin
   result :=
     SFSStrEqu(prefix, 'zip') or
-    SFSStrEqu(prefix, 'jar') or
+    SFSStrEqu(prefix, 'dfwad')
+    {$IFDEF SFS_ZIPFS_FULL}
+    or SFSStrEqu(prefix, 'jar') or
     SFSStrEqu(prefix, 'fout2') or
     SFSStrEqu(prefix, 'vtdb') or
-    SFSStrEqu(prefix, 'wad') or
-    SFSStrEqu(prefix, 'dfwad');
+    SFSStrEqu(prefix, 'wad')
+    {$ENDIF}
+    ;
 end;
 
 procedure TSFSZipVolumeFactory.Recycle (vol: TSFSVolume);
@@ -558,10 +584,13 @@ var
   vt: TSFSZipVolumeType;
 begin
   vt := sfszvNone;
-  if ZIPCheckMagic(st) then vt := sfszvZIP
+       if ZIPCheckMagic(st) then vt := sfszvZIP
   else if DFWADCheckMagic(st) then vt := sfszvDFWAD
+  {$IFDEF SFS_ZIPFS_FULL}
   else if F2DATCheckMagic(st) then vt := sfszvF2DAT
-  else if VTDBCheckMagic(st) then vt := sfszvVTDB;
+  else if VTDBCheckMagic(st) then vt := sfszvVTDB
+  {$ENDIF}
+  ;
 
   if vt <> sfszvNone then
   begin
@@ -589,6 +618,6 @@ var
 initialization
   zipf := TSFSZipVolumeFactory.Create();
   SFSRegisterVolumeFactory(zipf);
-finalization
-  SFSUnregisterVolumeFactory(zipf);
+//finalization
+//  SFSUnregisterVolumeFactory(zipf);
 end.