DEADSOFTWARE

fixed small memory leak in archive reader
[d2df-sdl.git] / src / shared / WADEDITOR.pas
index b98b1596a5d89a594cfbf7d3d73cd38281e5142a..0a80f51d4d43091f3be64900719c3180a498e588 100644 (file)
@@ -1,52 +1,38 @@
 unit WADEDITOR;
 
-{
------------------------------------
-WADEDITOR.PAS ÂÅÐÑÈß ÎÒ 26.08.08
-
-Ïîääåðæêà âàäîâ âåðñèè 1
------------------------------------
-}
+{$DEFINE SFS_DWFAD_DEBUG}
 
 interface
 
-uses WADSTRUCT;
+uses
+  sfs, xstreams;
+
 
 type
   SArray = array of ShortString;
 
   TWADEditor_1 = class(TObject)
-   private
-    FResData:   Pointer;
-    FResTable:  packed array of TResourceTableRec_1;
-    FHeader:    TWADHeaderRec_1;
-    FDataSize:  LongWord;
-    FOffset:    LongWord;
-    FFileName:  string;
-    FWADOpened: Byte;
-    FLastError: Integer;
-    FVersion:   Byte;
-    function LastErrorString(): string;
-    function GetResName(ResName: string): Char16;
+  private
+    fFileName: string; // empty: not opened
+    fIter: TSFSFileList;
+
+    function getIsOpen (): Boolean;
+
    public
     constructor Create();
     destructor Destroy(); override;
+
     procedure FreeWAD();
-    function  ReadFile(FileName: string): Boolean;
-    function  ReadMemory(Data: Pointer; Len: LongWord): Boolean;
-    function HaveResource(Section, Resource: string): Boolean;
-    function HaveSection(Section: string): Boolean;
-    function GetResource(Section, Resource: string; var pData: Pointer;
-                         var Len: Integer): Boolean;
-    function GetSectionList(): SArray;
-    function GetResourcesList(Section: string): SArray;
-
-    property GetLastError: Integer read FLastError;
-    property GetLastErrorStr: string read LastErrorString;
-    property GetResourcesCount: Word read FHeader.RecordsCount;
-    property GetVersion: Byte read FVersion;
+
+    function ReadFile (FileName: string): Boolean;
+    function ReadMemory (Data: Pointer; Len: LongWord): Boolean;
+    function GetResource (Section, Resource: string; var pData: Pointer; var Len: Integer): Boolean;
+    function GetResourcesList (Section: string): SArray;
+
+    property isOpen: Boolean read getIsOpen;
   end;
 
+{
 const
   DFWAD_NOERROR                = 0;
   DFWAD_ERROR_WADNOTFOUND      = -1;
@@ -57,69 +43,25 @@ const
   DFWAD_ERROR_READRESOURCE     = -6;
   DFWAD_ERROR_READWAD          = -7;
   DFWAD_ERROR_WRONGVERSION     = -8;
+}
+
 
+procedure g_ProcessResourceStr (ResourceStr: String; var FileName, SectionName, ResourceName: String); overload;
+procedure g_ProcessResourceStr (ResourceStr: String; FileName, SectionName, ResourceName: PString); overload;
 
- procedure g_ProcessResourceStr(ResourceStr: String; var FileName,
-                                SectionName, ResourceName: String); overload;
- procedure g_ProcessResourceStr(ResourceStr: String; FileName,
-                                SectionName, ResourceName: PString); overload;
 
 implementation
 
 uses
-  SysUtils, BinEditor, ZLib;
+  SysUtils, Classes, BinEditor, e_log, g_options;
 
-const
-  DFWAD_OPENED_NONE   = 0;
-  DFWAD_OPENED_FILE   = 1;
-  DFWAD_OPENED_MEMORY = 2;
 
-procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
-  OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
-var
-  strm: TZStreamRec;
-  P: Pointer;
-  BufInc: Integer;
-begin
-  FillChar(strm, sizeof(strm), 0);
-  BufInc := (InBytes + 255) and not 255;
-  if OutEstimate = 0 then
-    OutBytes := BufInc
-  else
-    OutBytes := OutEstimate;
-  GetMem(OutBuf, OutBytes);
-  try
-    strm.next_in := InBuf;
-    strm.avail_in := InBytes;
-    strm.next_out := OutBuf;
-    strm.avail_out := OutBytes;
-    inflateInit_(strm, zlib_version, sizeof(strm));
-    try
-      while inflate(strm, Z_FINISH) <> Z_STREAM_END do
-      begin
-        P := OutBuf;
-        Inc(OutBytes, BufInc);
-        ReallocMem(OutBuf, OutBytes);
-        strm.next_out := PByteF(PChar(OutBuf) + (PChar(strm.next_out) - PChar(P)));
-        strm.avail_out := BufInc;
-      end;
-    finally
-      inflateEnd(strm);
-    end;
-    ReallocMem(OutBuf, strm.total_out);
-    OutBytes := strm.total_out;
-  except
-    FreeMem(OutBuf);
-    raise
-  end;
-end;
-
-procedure g_ProcessResourceStr(ResourceStr: String; var FileName,
-                               SectionName, ResourceName: String);
+procedure g_ProcessResourceStr (ResourceStr: String; var FileName, SectionName, ResourceName: String);
 var
   a, i: Integer;
 
 begin
+  //e_WriteLog(Format('g_ProcessResourceStr0: [%s]', [ResourceStr]), MSG_NOTIFY);
   for i := Length(ResourceStr) downto 1 do
     if ResourceStr[i] = ':' then
       Break;
@@ -133,12 +75,13 @@ begin
   SectionName := Copy(ResourceStr, i+1, Length(ResourceStr)-Length(ResourceName)-Length(FileName)-2);
 end;
 
-procedure g_ProcessResourceStr(ResourceStr: AnsiString; FileName,
-                               SectionName, ResourceName: PAnsiString);
+
+procedure g_ProcessResourceStr (ResourceStr: AnsiString; FileName, SectionName, ResourceName: PAnsiString);
 var
   a, i, l1, l2: Integer;
 
 begin
+  //e_WriteLog(Format('g_ProcessResourceStr1: [%s]', [ResourceStr]), MSG_NOTIFY);
   for i := Length(ResourceStr) downto 1 do
     if ResourceStr[i] = ':' then
       Break;
@@ -168,365 +111,247 @@ end;
 
 
 { TWADEditor_1 }
-
 constructor TWADEditor_1.Create();
 begin
- FResData := nil;
- FResTable := nil;
- FDataSize := 0;
- FOffset := 0;
- FHeader.RecordsCount := 0;
- FFileName := '';
- FWADOpened := DFWAD_OPENED_NONE;
- FLastError := DFWAD_NOERROR;
- FVersion := DFWAD_VERSION;
+  fFileName := '';
 end;
 
+
 destructor TWADEditor_1.Destroy();
 begin
- FreeWAD();
-
- inherited;
+  FreeWAD();
+  inherited;
 end;
 
-procedure TWADEditor_1.FreeWAD();
-begin
- if FResData <> nil then FreeMem(FResData);
- FResTable := nil;
- FDataSize := 0;
- FOffset := 0;
- FHeader.RecordsCount := 0;
- FFileName := '';
- FWADOpened := DFWAD_OPENED_NONE;
- FLastError := DFWAD_NOERROR;
- FVersion := DFWAD_VERSION;
-end;
 
-function TWADEditor_1.GetResName(ResName: string): Char16;
+function TWADEditor_1.getIsOpen (): Boolean;
 begin
- ZeroMemory(@Result[0], 16);
- if ResName = '' then Exit;
-
- ResName := Trim(UpperCase(ResName));
- if Length(ResName) > 16 then SetLength(ResName, 16);
-
- CopyMemory(@Result[0], @ResName[1], Length(ResName));
+  result := (fFileName <> '');
 end;
 
-function TWADEditor_1.HaveResource(Section, Resource: string): Boolean;
-var
-  a: Integer;
-  CurrentSection: string;
-begin
- Result := False;
-
- if FResTable = nil then Exit;
-
- CurrentSection := '';
- Section := AnsiUpperCase(Section);
- Resource := AnsiUpperCase(Resource);
 
- for a := 0 to High(FResTable) do
- begin
-  if FResTable[a].Length = 0 then
-  begin
-   CurrentSection := FResTable[a].ResourceName;
-   Continue;
-  end;
-
-  if (FResTable[a].ResourceName = Resource) and
-     (CurrentSection = Section) then
-  begin
-   Result := True;
-   Break;
-  end;
- end;
+procedure TWADEditor_1.FreeWAD();
+begin
+  if fIter <> nil then FreeAndNil(fIter);
+  //if fFileName <> '' then e_WriteLog(Format('TWADEditor_1.ReadFile: [%s] closed', [fFileName]), MSG_NOTIFY);
+  fFileName := '';
 end;
 
-function TWADEditor_1.HaveSection(Section: string): Boolean;
+
+function removeExt (s: string): string;
 var
-  a: Integer;
+  i: Integer;
 begin
- Result := False;
-
- if FResTable = nil then Exit;
- if Section = '' then
- begin
-  Result := True;
-  Exit;
- end;
-
- Section := AnsiUpperCase(Section);
-
- for a := 0 to High(FResTable) do
-  if (FResTable[a].Length = 0) and (FResTable[a].ResourceName = Section) then
+  i := length(s)+1;
+  while (i > 1) and (s[i-1] <> '.') and (s[i-1] <> '/') do Dec(i);
+  if (i > 1) and (s[i-1] = '.') then
   begin
-   Result := True;
-   Exit;
+    //writeln('[', s, '] -> [', Copy(s, 1, i-2), ']');
+    s := Copy(s, 1, i-2);
   end;
+  result := s;
 end;
 
-function TWADEditor_1.GetResource(Section, Resource: string;
-  var pData: Pointer; var Len: Integer): Boolean;
+function TWADEditor_1.GetResource (Section, Resource: string; var pData: Pointer; var Len: Integer): Boolean;
 var
-  a: LongWord;
-  i: Integer;
-  WADFile: File;
-  CurrentSection: string;
-  TempData: Pointer;
-  OutBytes: Integer;
+  f: Integer;
+  fi: TSFSFileInfo;
+  fs: TStream;
+  fpp: Pointer;
+  //fn: string;
 begin
- Result := False;
-
- CurrentSection := '';
-
- if FWADOpened = DFWAD_OPENED_NONE then
- begin
-  FLastError := DFWAD_ERROR_WADNOTLOADED;
-  Exit;
- end;
-
- Section := UpperCase(Section);
- Resource := UpperCase(Resource);
-
- i := -1;
- for a := 0 to High(FResTable) do
- begin
-  if FResTable[a].Length = 0 then
-  begin
-   CurrentSection := FResTable[a].ResourceName;
-   Continue;
-  end;
-
-  if (FResTable[a].ResourceName = Resource) and
-     (CurrentSection = Section) then
+  Result := False;
+  if not isOpen or (fIter = nil) then Exit;
+  if length(Resource) = 0 then Exit; // just in case
+  if (length(Section) <> 0) and (Section[length(Section)] <> '/') then Section := Section+'/';
+  // backwards, due to possible similar names and such
+  for f := fIter.Count-1 downto 0 do
   begin
-   i := a;
-   Break;
-  end;
- end;
-
- if i = -1 then
- begin
-  FLastError := DFWAD_ERROR_RESOURCENOTFOUND;
-  Exit;
- end;
-
- if FWADOpened = DFWAD_OPENED_FILE then
- begin
-  try
-   AssignFile(WADFile, FFileName);
-   Reset(WADFile, 1);
-
-   Seek(WADFile, FResTable[i].Address+6+
-        LongWord(SizeOf(TWADHeaderRec_1)+SizeOf(TResourceTableRec_1)*Length(FResTable)));
-   TempData := GetMemory(FResTable[i].Length);
-   BlockRead(WADFile, TempData^, FResTable[i].Length);
-   DecompressBuf(TempData, FResTable[i].Length, 0, pData, OutBytes);
-   FreeMem(TempData);
-
-   Len := OutBytes;
-
-   CloseFile(WADFile);
-  except
-   FLastError := DFWAD_ERROR_CANTOPENWAD;
-   CloseFile(WADFile);
-   Exit;
+    fi := fIter.Files[f];
+    if fi = nil then continue;
+    //e_WriteLog(Format('DFWAD: searching for [%s : %s] in [%s]; current is [%s : %s] (%d, %d)', [Section, Resource, fFileName, fi.path, fi.name, SFSStrEqu(fi.path, Section), SFSStrEqu(fi.name, Resource)]), MSG_NOTIFY);
+    if {SFSStrEqu}SFSDFPathEqu(fi.path, Section) and SFSStrEqu(removeExt(fi.name), Resource) then
+    begin
+      // i found her!
+      //fn := fFileName+'::'+fi.path+fi.name;
+      //fs := SFSFileOpen(fn);
+      try
+        fs := fIter.volume.OpenFileByIndex(f);
+      except
+        fs := nil;
+      end;
+      if fs = nil then
+      begin
+        e_WriteLog(Format('DFWAD: can''t open file [%s%s] in [%s]', [Section, Resource, fFileName]), MSG_WARNING);
+        break;
+      end;
+      Len := Integer(fs.size);
+      GetMem(pData, Len);
+      fpp := pData;
+      try
+        fs.ReadBuffer(pData^, Len);
+        fpp := nil;
+      finally
+        if fpp <> nil then
+        begin
+          FreeMem(fpp);
+          pData := nil;
+          Len := 0;
+        end;
+        fs.Free;
+      end;
+      result := true;
+      {$IFDEF SFS_DWFAD_DEBUG}
+      if gSFSDebug then
+        e_WriteLog(Format('DFWAD: file [%s%s] FOUND in [%s]; size is %d bytes', [Section, Resource, fFileName, Len]), MSG_NOTIFY);
+      {$ENDIF}
+      exit;
+    end;
   end;
- end
-  else
- begin
-  TempData := GetMemory(FResTable[i].Length);
-  CopyMemory(TempData, Pointer(LongWord(FResData)+FResTable[i].Address+6+
-             LongWord(SizeOf(TWADHeaderRec_1)+SizeOf(TResourceTableRec_1)*Length(FResTable))),
-             FResTable[i].Length);
-  DecompressBuf(TempData, FResTable[i].Length, 0, pData, OutBytes);
-  FreeMem(TempData);
-
-  Len := OutBytes;
- end;
-
- FLastError := DFWAD_NOERROR;
- Result := True;
+  e_WriteLog(Format('DFWAD: file [%s%s] not found in [%s]', [Section, Resource, fFileName]), MSG_WARNING);
 end;
 
-function TWADEditor_1.GetResourcesList(Section: string): SArray;
+
+function TWADEditor_1.GetResourcesList (Section: string): SArray;
 var
-  a: Integer;
-  CurrentSection: Char16;
+  f: Integer;
+  fi: TSFSFileInfo;
 begin
- Result := nil;
-
- if FResTable = nil then Exit;
- if Length(Section) > 16 then Exit;
-
- CurrentSection := '';
-
- for a := 0 to High(FResTable) do
- begin
-  if FResTable[a].Length = 0 then
-  begin
-   CurrentSection := FResTable[a].ResourceName;
-   Continue;
-  end;
-
-  if CurrentSection = Section then
+  Result := nil;
+  if not isOpen or (fIter = nil) then Exit;
+  if (length(Section) <> 0) and (Section[length(Section)] <> '/') then Section := Section+'/';
+  for f := 0 to fIter.Count-1 do
   begin
-   SetLength(Result, Length(Result)+1);
-   Result[High(Result)] := FResTable[a].ResourceName;
+    fi := fIter.Files[f];
+    if fi = nil then continue;
+    if length(fi.name) = 0 then continue;
+    if {SFSStrEqu}SFSDFPathEqu(fi.path, Section) then
+    begin
+      SetLength(result, Length(result)+1);
+      result[high(result)] := removeExt(fi.name);
+    end;
   end;
- end;
 end;
 
-function TWADEditor_1.GetSectionList(): SArray;
+
+function TWADEditor_1.ReadFile (FileName: string): Boolean;
 var
-  i: DWORD;
+  rfn: string;
+  //f: Integer;
+  //fi: TSFSFileInfo;
 begin
- Result := nil;
-
- if FResTable = nil then Exit;
-
- if FResTable[0].Length <> 0 then
- begin
-  SetLength(Result, 1);
-  Result[0] := '';
- end;
-
- for i := 0 to High(FResTable) do
-  if FResTable[i].Length = 0 then
+  Result := False;
+  //e_WriteLog(Format('TWADEditor_1.ReadFile: [%s]', [FileName]), MSG_NOTIFY);
+  FreeWAD();
+  rfn := FileName;
+  if not FileExists(rfn) then
   begin
-   SetLength(Result, Length(Result)+1);
-   Result[High(Result)] := FResTable[i].ResourceName;
+    //if length(rfn) >= 4 then e_WriteLog(Format('XXXX TWADEditor_1.ReadFile: [%s] [%s]', [Copy(rfn, length(rfn)-3, 4), Copy(rfn, 1, length(rfn)-4)]), MSG_NOTIFY);
+    if (length(rfn) >= 4) and SFSStrEqu(Copy(rfn, length(rfn)-3, 4), '.wad') then
+    begin
+      rfn := Copy(rfn, 1, length(rfn)-4);
+           if FileExists(rfn+'.pk3') then rfn := rfn+'.pk3'
+      else if FileExists(rfn+'.zip') then rfn := rfn+'.zip'
+      else rfn := FileName;
+      {.$IFDEF SFS_DWFAD_DEBUG}
+      if gSFSDebug then
+        if FileExists(rfn) then e_WriteLog(Format('TWADEditor_1.ReadFile: FOUND [%s]', [rfn]), MSG_NOTIFY);
+      {.$ENDIF}
+    end;
   end;
+  if not FileExists(rfn) then exit;
+  {$IFDEF SFS_DWFAD_DEBUG}
+  if gSFSDebug then
+    e_WriteLog(Format('TWADEditor_1.ReadFile: FOUND [%s]', [rfn]), MSG_NOTIFY);
+  {$ENDIF}
+  // cache this wad
+  SFSAddDataFile(rfn);
+  fIter := SFSFileList(rfn);
+  if fIter = nil then Exit;
+  fFileName := rfn;
+  {$IFDEF SFS_DWFAD_DEBUG}
+  if gSFSDebug then
+    e_WriteLog(Format('TWADEditor_1.ReadFile: [%s] opened', [fFileName]), MSG_NOTIFY);
+  {$ENDIF}
+  {
+    for f := 0 to fIter.Count-1 do
+    begin
+      fi := fIter.Files[f];
+      if fi = nil then continue;
+      e_WriteLog(Format('[%s]: [%s : %s] %u', [fFileName, fi.path, fi.name, fi.size]), MSG_NOTIFY);
+    end;
+  }
+  Result := True;
 end;
 
-function TWADEditor_1.LastErrorString(): string;
-begin
- case FLastError of
-  DFWAD_NOERROR: Result := '';
-  DFWAD_ERROR_WADNOTFOUND: Result := 'DFWAD file not found';
-  DFWAD_ERROR_CANTOPENWAD: Result := 'Can''t open DFWAD file';
-  DFWAD_ERROR_RESOURCENOTFOUND: Result := 'Resource not found';
-  DFWAD_ERROR_FILENOTWAD: Result := 'File is not DFWAD';
-  DFWAD_ERROR_WADNOTLOADED: Result := 'DFWAD file is not loaded';
-  DFWAD_ERROR_READRESOURCE: Result := 'Read resource error';
-  DFWAD_ERROR_READWAD: Result := 'Read DFWAD error';
-  else Result := 'Unknown DFWAD error';
- end;
-end;
 
-function TWADEditor_1.ReadFile(FileName: string): Boolean;
 var
-  WADFile: File;
-  Signature: array[0..4] of Char;
-  a: Integer;
-begin
- FreeWAD();
-
- Result := False;
-
- if not FileExists(FileName) then
- begin
-  FLastError := DFWAD_ERROR_WADNOTFOUND;
-  Exit;
- end;
-
- FFileName := FileName;
-
- AssignFile(WADFile, FFileName);
+  uniqueCounter: Integer = 0;
 
- try
-  Reset(WADFile, 1);
- except
-  FLastError := DFWAD_ERROR_CANTOPENWAD;
-  Exit;
- end;
-
- try
-  BlockRead(WADFile, Signature, 5);
-  if Signature <> DFWAD_SIGNATURE then
-  begin
-   FLastError := DFWAD_ERROR_FILENOTWAD;
-   CloseFile(WADFile);
-   Exit;
-  end;
-
-  BlockRead(WADFile, FVersion, 1);
-  if FVersion <> DFWAD_VERSION then
+function TWADEditor_1.ReadMemory (Data: Pointer; Len: LongWord): Boolean;
+var
+  fn: string;
+  st: TStream = nil;
+  //f: Integer;
+  //fi: TSFSFileInfo;
+begin
+  Result := False;
+  FreeWAD();
+  if (Data = nil) or (Len = 0) then
   begin
-    FLastError := DFWAD_ERROR_WRONGVERSION;
-    CloseFile(WADFile);
+    e_WriteLog('TWADEditor_1.ReadMemory: EMPTY SUBWAD!', MSG_WARNING);
     Exit;
   end;
 
-  BlockRead(WADFile, FHeader, SizeOf(TWADHeaderRec_1));
-  SetLength(FResTable, FHeader.RecordsCount);
-  if FResTable <> nil then
-  begin
-   BlockRead(WADFile, FResTable[0], SizeOf(TResourceTableRec_1)*FHeader.RecordsCount);
+  fn := Format(' -- memwad %d -- ', [uniqueCounter]);
+  Inc(uniqueCounter);
+  {$IFDEF SFS_DWFAD_DEBUG}
+    e_WriteLog(Format('TWADEditor_1.ReadMemory: [%s]', [fn]), MSG_NOTIFY);
+  {$ENDIF}
 
-   for a := 0 to High(FResTable) do
-    if FResTable[a].Length <> 0 then
-     FResTable[a].Address := FResTable[a].Address-6-(LongWord(SizeOf(TWADHeaderRec_1)+
-                             SizeOf(TResourceTableRec_1)*Length(FResTable)));
+  try
+    st := TSFSMemoryStreamRO.Create(Data, Len);
+    if not SFSAddSubDataFile(fn, st) then
+    begin
+      st.Free;
+      Exit;
+    end;
+  except
+    st.Free;
+    Exit;
   end;
 
-  CloseFile(WADFile);
- except
-  FLastError := DFWAD_ERROR_READWAD;
-  CloseFile(WADFile);
-  Exit;
- end;
-
- FWADOpened := DFWAD_OPENED_FILE;
- FLastError := DFWAD_NOERROR;
- Result := True;
-end;
-
-function TWADEditor_1.ReadMemory(Data: Pointer; Len: LongWord): Boolean;
-var
-  Signature: array[0..4] of Char;
-  a: Integer;
-begin
- FreeWAD();
-
- Result := False;
-
- CopyMemory(@Signature[0], Data, 5);
- if Signature <> DFWAD_SIGNATURE then
- begin
-  FLastError := DFWAD_ERROR_FILENOTWAD;
-  Exit;
- end;
-
- CopyMemory(@FVersion, Pointer(LongWord(Data)+5), 1);
- if FVersion <> DFWAD_VERSION then
- begin
-   FLastError := DFWAD_ERROR_WRONGVERSION;
-   Exit;
- end;
+  fIter := SFSFileList(fn);
+  if fIter = nil then Exit;
 
- CopyMemory(@FHeader, Pointer(LongWord(Data)+6), SizeOf(TWADHeaderRec_1));
+  fFileName := fn;
+  {$IFDEF SFS_DWFAD_DEBUG}
+    e_WriteLog(Format('TWADEditor_1.ReadMemory: [%s] opened', [fFileName]), MSG_NOTIFY);
+  {$ENDIF}
 
- SetLength(FResTable, FHeader.RecordsCount);
- if FResTable <> nil then
- begin
-  CopyMemory(@FResTable[0], Pointer(LongWord(Data)+6+SizeOf(TWADHeaderRec_1)),
-             SizeOf(TResourceTableRec_1)*FHeader.RecordsCount);
-
-  for a := 0 to High(FResTable) do
-   if FResTable[a].Length <> 0 then
-    FResTable[a].Address := FResTable[a].Address-6-(LongWord(SizeOf(TWADHeaderRec_1)+
-                            SizeOf(TResourceTableRec_1)*Length(FResTable)));
- end;
-
- GetMem(FResData, Len);
- CopyMemory(FResData, Data, Len);
-
- FWADOpened := DFWAD_OPENED_MEMORY;
- FLastError := DFWAD_NOERROR;
+  {
+  for f := 0 to fIter.Count-1 do
+  begin
+    fi := fIter.Files[f];
+    if fi = nil then continue;
+    st := fIter.volume.OpenFileByIndex(f);
+    if st = nil then
+    begin
+      e_WriteLog(Format('[%s]: [%s : %s] CAN''T OPEN', [fFileName, fi.path, fi.name]), MSG_NOTIFY);
+    end
+    else
+    begin
+      e_WriteLog(Format('[%s]: [%s : %s] %u', [fFileName, fi.path, fi.name, st.size]), MSG_NOTIFY);
+      st.Free;
+    end;
+  end;
+  //fIter.volume.OpenFileByIndex(0);
+  }
 
- Result := True;
 Result := True;
 end;
 
+
+begin
+  sfsDiskDirs := '<exedir>/data'; //FIXME
 end.