DEADSOFTWARE

net: game: other: hash database and resource downloader converted to new dirsys
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Sun, 20 Oct 2019 23:15:06 +0000 (02:15 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Sun, 20 Oct 2019 23:16:00 +0000 (02:16 +0300)
src/game/g_game.pas
src/game/g_main.pas
src/game/g_map.pas
src/game/g_net.pas
src/game/g_res_downloader.pas
src/shared/fhashdb.pas

index e371e0b3efe1bb221b8f7750ac35db1f637ca82d..6564a23464337389d03aa98db59c0c0ee65623c8 100644 (file)
@@ -6750,6 +6750,7 @@ begin
             if found then
             begin
               // no such map, found wad
+              pw := P[1];
               SetLength(P, 3);
               P[1] := ExpandFileName(pw);
               P[2] := g_Game_GetFirstMap(P[1]);
index b0648049143f24291d0b00ea063294c3b5a4df70..808f7f643f0666dade55438487d967695f2019e4 100644 (file)
@@ -29,7 +29,7 @@ procedure CharPress (C: AnsiChar);
 
 var
   {--- TO REMOVE ---}
-  GameDir: string;
+  //GameDir: string;
   {-----------------}
 
   {--- Read-only dirs ---}
@@ -86,7 +86,7 @@ procedure InitPath;
   end;
 
 begin
-  GetDir(0, GameDir);
+  //GetDir(0, GameDir);
 
   i := 1;
   while i < ParamCount do
@@ -138,7 +138,7 @@ begin
   AddDef(CacheDirs, 'data/cache');
   AddDef(ConfigDirs, '.');
   AddDef(MapDownloadDirs, 'maps/downloads');
-  AddDef(WadDownloadDirs, 'wad/downloads');
+  AddDef(WadDownloadDirs, 'wads/downloads');
   AddDef(ScreenshotDirs, 'screenshots');
 
   for i := 0 to High(MapDirs) do
@@ -266,7 +266,7 @@ begin
   if assigned(oglInitCB) then oglInitCB;
 {$ENDIF}
 
-  //g_Res_CreateDatabases(); // it will be done before connecting to the server for the first time
+  //g_Res_CreateDatabases(true); // it will be done before connecting to the server for the first time
 
   e_WriteLog('Entering SDLMain', TMsgType.Notify);
 
index 95bb1a02fd813f82536e759ee6a2b0cfa1f86f8c..e99d47b19186dd65974751d9a2dd3e90539e3439 100644 (file)
@@ -900,21 +900,100 @@ begin
 end;
 
 
+function extractWadName (resourceName: string): string;
+var
+  posN: Integer;
+begin
+  posN := Pos(':', resourceName);
+  if posN > 0 then
+    Result:= Copy(resourceName, 0, posN-1)
+  else
+    Result := '';
+end;
+
+
+procedure addResToExternalResList (res: AnsiString);
+var
+  uname: AnsiString;
+  f: Integer;
+  fi: TDiskFileInfo;
+begin
+  if g_Game_IsClient or not g_Game_IsNet then exit;
+  if (length(res) = 0) then exit; // map wad
+  //res := extractWadName(res);
+  //if (length(res) = 0) then exit; // map wad
+  uname := toLowerCase1251(res);
+  // do not add duplicates
+  for f := 0 to High(gExternalResources) do
+  begin
+    if (gExternalResources[f].userName = uname) then exit;
+  end;
+  //writeln('***(000) addResToExternalResList: res=[', res, ']');
+  // add new resource
+  fi.userName := uname;
+  if not findFileCI(res) then exit;
+  //writeln('***(001) addResToExternalResList: res=[', res, ']');
+  fi.diskName := res;
+  if (not GetDiskFileInfo(res, fi)) then
+  begin
+    fi.tag := -1;
+  end
+  else
+  begin
+    //writeln('***(002) addResToExternalResList: res=[', res, ']');
+    fi.tag := 0; // non-zero means "cannot caclucate hash"
+    try
+      fi.hash := MD5File(fi.diskName);
+    except
+      fi.tag := -1;
+    end;
+  end;
+  //e_LogWritefln('addext: res=[%s]; uname=[%s]; diskName=[%s]', [res, fi.userName, fi.diskName]);
+  SetLength(gExternalResources, length(gExternalResources)+1);
+  gExternalResources[High(gExternalResources)] := fi;
+end;
+
+
+procedure compactExtResList ();
+var
+  src, dest: Integer;
+begin
+  src := 0;
+  dest := 0;
+  for src := 0 to High(gExternalResources) do
+  begin
+    if (gExternalResources[src].tag = 0) then
+    begin
+      // copy it
+      if (dest <> src) then gExternalResources[dest] := gExternalResources[src];
+      Inc(dest);
+    end;
+  end;
+  if (dest <> length(gExternalResources)) then SetLength(gExternalResources, dest);
+end;
+
+
 function GetReplacementWad (WadName: AnsiString): AnsiString;
 begin
   result := '';
   if WadName <> '' then
   begin
     result := WadName;
-    if g_Game_IsClient then
-      result := g_Res_FindReplacementWad(WadName);
-    if (result = WadName) then
-      result := e_FindWad(WadDirs, result)
+    if g_Game_IsClient then result := g_Res_FindReplacementWad(WadName);
+    if (result = WadName) then result := e_FindWad(WadDirs, result)
   end;
 end;
 
 
-function CreateTexture(RecName: AnsiString; Map: string; log: Boolean): Integer;
+procedure generateExternalResourcesList (map: TDynRecord);
+begin
+  SetLength(gExternalResources, 0);
+  addResToExternalResList(GetReplacementWad(g_ExtractWadName(map.MusicName)));
+  addResToExternalResList(GetReplacementWad(g_ExtractWadName(map.SkyName)));
+end;
+
+
+function CreateTexture (RecName: AnsiString; Map: string; log: Boolean): Integer;
 var
   WAD: TWADFile;
   TextureData: Pointer;
@@ -973,6 +1052,7 @@ begin
 
   // Çàãðóæàåì ðåñóðñ òåêñòóðû â ïàìÿòü èç WAD'à:
   WADName := GetReplacementWad(g_ExtractWadName(RecName));
+  if (WADName <> '') then addResToExternalResList(WADName);
   if WADName = '' then WADName := Map; //WADName := GameDir+'/wads/'+WADName else
 
   WAD := TWADFile.Create();
@@ -1059,6 +1139,7 @@ begin
 
   // ×èòàåì WAD-ðåñóðñ àíèì.òåêñòóðû èç WAD'à â ïàìÿòü:
   WADName := GetReplacementWad(g_ExtractWadName(RecName));
+  if (WADName <> '') then addResToExternalResList(WADName);
   if WADName = '' then WADName := Map; //WADName := GameDir+'/wads/'+WADName else
 
   WAD := TWADFile.Create();
@@ -1449,82 +1530,6 @@ begin
   g_Mons_ForEach(monsDieTrig);
 end;
 
-function extractWadName(resourceName: string): string;
-var
-  posN: Integer;
-begin
-  posN := Pos(':', resourceName);
-  if posN > 0 then
-    Result:= Copy(resourceName, 0, posN-1)
-  else
-    Result := '';
-end;
-
-
-procedure addResToExternalResList (res: AnsiString);
-var
-  uname: AnsiString;
-  f: Integer;
-  fi: TDiskFileInfo;
-begin
-  if g_Game_IsClient or not g_Game_IsNet then exit;
-  if (length(res) = 0) then exit; // map wad
-  res := extractWadName(res);
-  if (length(res) = 0) then exit; // map wad
-  uname := toLowerCase1251(res);
-  // do not add duplicates
-  for f := 0 to High(gExternalResources) do
-  begin
-    if (gExternalResources[f].userName = uname) then exit;
-  end;
-  // add new resource
-  fi.userName := uname;
-  if (not GetDiskFileInfo(GameDir+'/wads/'+res, fi)) then
-  begin
-    fi.tag := -1;
-  end
-  else
-  begin
-    fi.tag := 0; // non-zero means "cannot caclucate hash"
-    try
-      fi.hash := MD5File(fi.diskName);
-    except
-      fi.tag := -1;
-    end;
-  end;
-  //e_LogWritefln('addext: res=[%s]; uname=[%s]; diskName=[%s]', [res, fi.userName, fi.diskName]);
-  SetLength(gExternalResources, length(gExternalResources)+1);
-  gExternalResources[High(gExternalResources)] := fi;
-end;
-
-
-procedure compactExtResList ();
-var
-  src, dest: Integer;
-begin
-  src := 0;
-  dest := 0;
-  for src := 0 to High(gExternalResources) do
-  begin
-    if (gExternalResources[src].tag = 0) then
-    begin
-      // copy it
-      if (dest <> src) then gExternalResources[dest] := gExternalResources[src];
-      Inc(dest);
-    end;
-  end;
-  if (dest <> length(gExternalResources)) then SetLength(gExternalResources, dest);
-end;
-
-
-procedure generateExternalResourcesList (map: TDynRecord);
-begin
-  SetLength(gExternalResources, 0);
-  addResToExternalResList(map.MusicName);
-  addResToExternalResList(map.SkyName);
-end;
-
-
 procedure mapCreateGrid ();
 var
   mapX0: Integer = $3fffffff;
@@ -1864,14 +1869,7 @@ begin
               ntn := CreateTexture(rec.Resource, FileName, True);
               if (ntn < 0) then g_SimpleError(Format(_lc[I_GAME_ERROR_TEXTURE_SIMPLE], [rec.Resource]));
             end;
-            if (ntn < 0) then
-            begin
-              ntn := CreateNullTexture(rec.Resource);
-            end
-            else
-            begin
-              addResToExternalResList(rec.Resource);
-            end;
+            if (ntn < 0) then ntn := CreateNullTexture(rec.Resource);
 
             rec.tagInt := ntn; // remember texture number
           end;
index 099ab76f4f248319c002751bd5d6f864a5c98c8b..2e00600ae3ffea0f7dc03ddbe2655724718bba28 100644 (file)
@@ -540,7 +540,6 @@ begin
           exit;
         end;
         tf.diskName := findDiskWad(fname);
-        //if (length(tf.diskName) = 0) then tf.diskName := findDiskWad(GameDir+'/wads/'+fname);
         if (length(tf.diskName) = 0) then
         begin
           e_LogWritefln('NETWORK: file "%s" not found!', [fname], TMsgType.Fatal);
index 43a60874b997d9d50f812922f0d40d1a09ec44c9..f334e2f806d30ce5753aa533449888a99d15cfe8 100644 (file)
@@ -35,7 +35,7 @@ procedure g_Res_CreateDatabases (allowRescan: Boolean=false);
 
 implementation
 
-uses g_language, sfs, utils, wadreader, g_game, hashtable, fhashdb;
+uses g_language, sfs, utils, wadreader, g_game, hashtable, fhashdb, e_res;
 
 var
   // cvars
@@ -58,8 +58,11 @@ procedure saveDatabases (saveMap, saveRes: Boolean);
 var
   err: Boolean;
   st: TStream;
+  ccdir: AnsiString = '';
 begin
   if (not saveDBsToDiskEnabled) or (not g_res_save_databases) then exit;
+  ccdir := e_GetWriteableDir(CacheDirs, false);
+  if (length(ccdir) = 0) then exit;
   // rescan dirs
   // save map database
   if (saveMap) then
@@ -67,7 +70,7 @@ begin
     err := true;
     st := nil;
     try
-      st := createDiskFile(GameDir+'/data/maphash.db');
+      st := createDiskFile(ccdir+'/maphash.db');
       knownMaps.saveTo(st);
       err := false;
     except
@@ -81,7 +84,7 @@ begin
     err := true;
     st := nil;
     try
-      st := createDiskFile(GameDir+'/data/reshash.db');
+      st := createDiskFile(ccdir+'/reshash.db');
       knownRes.saveTo(st);
       err := false;
     except
@@ -103,28 +106,38 @@ var
   upmap: Boolean;
   upres: Boolean;
   forcesave: Boolean;
+  ccdir: AnsiString = '';
 begin
   if not assigned(knownMaps) then
   begin
     // create and load a know map database, if necessary
-    knownMaps := TFileHashDB.Create(GameDir+'/maps/');
-    knownRes := TFileHashDB.Create(GameDir+'/wads/');
+    knownMaps := TFileHashDB.Create({GameDir}'', MapDirs);
+    knownMaps.appendMoreDirs(MapDownloadDirs);
+    knownRes := TFileHashDB.Create({GameDir}'', WadDirs);
+    knownRes.appendMoreDirs(WadDownloadDirs);
     saveDBsToDiskEnabled := true;
     // load map database
     st := nil;
     try
-      st := openDiskFileRO(GameDir+'/data/maphash.db');
-      knownMaps.loadFrom(st);
-      e_LogWriteln('loaded map database');
+      ccdir := e_GetWriteableDir(CacheDirs, false);
+      if (length(ccdir) > 0) then
+      begin
+        st := openDiskFileRO(ccdir+'/maphash.db');
+        knownMaps.loadFrom(st);
+        e_LogWriteln('loaded map database');
+      end;
     except
     end;
     st.Free;
     // load resource database
     st := nil;
     try
-      st := openDiskFileRO(GameDir+'/data/reshash.db');
-      knownRes.loadFrom(st);
-      e_LogWriteln('loaded resource database');
+      if (length(ccdir) > 0) then
+      begin
+        st := openDiskFileRO(ccdir+'/reshash.db');
+        knownRes.loadFrom(st);
+        e_LogWriteln('loaded resource database');
+      end;
     except
     end;
     st.Free;
@@ -265,11 +278,10 @@ end;
 //==========================================================================
 function findExistingMapWadWithHash (fname: AnsiString; const resMd5: TMD5Digest): AnsiString;
 begin
-  //result := scanDir(GameDir+'/maps', ExtractFileName(fname), resMd5);
   result := knownMaps.findByHash(resMd5);
   if (length(result) > 0) then
   begin
-    result := GameDir+'/maps/'+result;
+    //result := GameDir+'/maps/'+result;
     if not FileExists(result) then
     begin
       if (knownMaps.scanFiles()) then saveDatabases(true, false);
@@ -290,11 +302,10 @@ end;
 //==========================================================================
 function findExistingResWadWithHash (fname: AnsiString; const resMd5: TMD5Digest): AnsiString;
 begin
-  //result := scanDir(GameDir+'/wads', ExtractFileName(fname), resMd5);
   result := knownRes.findByHash(resMd5);
   if (length(result) > 0) then
   begin
-    result := GameDir+'/wads/'+result;
+    //result := GameDir+'/wads/'+result;
     if not FileExists(result) then
     begin
       if (knownRes.scanFiles()) then saveDatabases(false, true);
@@ -355,6 +366,8 @@ var
   mapdbUpdated: Boolean = false;
   resdbUpdated: Boolean = false;
   transStarted: Boolean;
+  destMapDir: AnsiString = '';
+  destResDir: AnsiString = '';
 begin
   result := '';
   clearReplacementWads();
@@ -387,10 +400,16 @@ begin
         exit;
       end;
       try
-        CreateDir(GameDir+'/maps/downloads');
+        destMapDir := e_GetWriteableDir(MapDownloadDirs, false); // not required
       except
       end;
-      fname := GameDir+'/maps/downloads/'+generateFileName(FileName, mapHash);
+      if (length(destMapDir) = 0) then
+      begin
+        e_LogWriteln('cannot create map download directory', TMsgType.Fatal);
+        result := '';
+        exit;
+      end;
+      fname := destMapDir+'/'+generateFileName(FileName, mapHash);
       tf.diskName := fname;
       e_LogWritefln('map disk file for `%s` is `%s`', [FileName, fname], TMsgType.Fatal);
       try
@@ -493,10 +512,16 @@ begin
           if (res <> 0) then begin result := ''; exit; end;
         end;
         try
-          CreateDir(GameDir+'/wads/downloads');
+          destResDir := e_GetWriteableDir(WadDownloadDirs, false); // not required
         except
         end;
-        fname := GameDir+'/wads/downloads/'+generateFileName(tf.diskName, tf.hash);
+        if (length(destResDir) = 0) then
+        begin
+          e_LogWriteln('cannot create wad download directory', TMsgType.Fatal);
+          result := '';
+          exit;
+        end;
+        fname := destResDir+'/'+generateFileName(tf.diskName, tf.hash);
         e_LogWritefln('downloading resource `%s` to `%s`...', [tf.diskName, fname]);
         try
           strm := openDiskFileRW(fname);
index 7e45c10b461eb68706b0ca5b5d57596960accdcc..09797e8b27fb07cd22d489f2a00006753fa4fbe9 100644 (file)
@@ -36,9 +36,11 @@ type
 
   TFileHashDB = class
   private
+    type TStrDynArray = array of AnsiString;
+
     type
       TFileInfo = record
-        name: AnsiString; // names are relative to `mBasePath`
+        name: AnsiString; // name includes `mBasePath`, if necessary
         hash: TMD5Digest;
         size: LongWord;
         age: LongInt;
@@ -48,7 +50,8 @@ type
       end;
 
   private
-    mBasePath: AnsiString; // ends with '/'
+    mBasePath: AnsiString; // ends with '/', or empty string
+    mPathList: TStrDynArray;
     mHash2List: THashMD5Int; // hash -> list index
     mFile2List: THashStrCIInt; // file name -> list index
     mFileList: array of TFileInfo;
@@ -60,10 +63,18 @@ type
 
     procedure scanDir (path: AnsiString; var changed: Boolean);
 
+    procedure appendOneDir (dir: AnsiString);
+
+    procedure setup (aBasePath: AnsiString; const aPathList: TStrDynArray);
+
   public
-    constructor Create (aBasePath: AnsiString);
+    constructor Create (aBasePath: AnsiString; const aPathList: TStrDynArray);
+    constructor Create (aBasePath: AnsiString; const aPathList: SSArray);
     destructor Destroy (); override;
 
+    // doesn't automatically rescans
+    procedure appendMoreDirs (const aPathList: SSArray);
+
     // doesn't clear base path
     procedure clear ();
 
@@ -81,7 +92,7 @@ type
     function findByHash (const md5: TMD5Digest): AnsiString;
     // returns `true` if something was changed
     // name is relative to base
-    function addWithHash (relname: AnsiString; const md5: TMD5Digest): Boolean;
+    function addWithHash (fdiskname: AnsiString; const md5: TMD5Digest): Boolean;
   end;
 
 
@@ -116,10 +127,42 @@ end;
 
 //==========================================================================
 //
-//  TFileHashDB.Create
+//  TFileHashDB.appendOneDir
 //
 //==========================================================================
-constructor TFileHashDB.Create (aBasePath: AnsiString);
+procedure TFileHashDB.appendOneDir (dir: AnsiString);
+var
+  mps: AnsiString;
+  found: Boolean;
+begin
+  if (length(dir) = 0) then exit;
+  if not findFileCI(dir, true) then exit;
+  dir := fixSlashes(dir, true);
+  if (mBasePath <> '') and (dir[1] <> '/') then
+  begin
+    dir := mBasePath+dir;
+    if not findFileCI(dir, true) then exit;
+    dir := fixSlashes(dir, true);
+  end;
+  if (dir = '/') then exit;
+  found := false;
+  for mps in mPathList do if (dir = mps) then begin found := true; break; end;
+  if not found then
+  begin
+    SetLength(mPathList, length(mPathList)+1);
+    mPathList[High(mPathList)] := dir;
+  end;
+end;
+
+
+//==========================================================================
+//
+//  TFileHashDB.setup
+//
+//==========================================================================
+procedure TFileHashDB.setup (aBasePath: AnsiString; const aPathList: TStrDynArray);
+var
+  s: AnsiString;
 begin
   mBasePath := aBasePath;
   if (length(aBasePath) <> 0) then
@@ -127,6 +170,8 @@ begin
     if not findFileCI(mBasePath, true) then mBasePath := aBasePath;
   end;
   mBasePath := fixSlashes(mBasePath, true);
+  SetLength(mPathList, 0);
+  for s in aPathList do appendOneDir(s);
   mHash2List := THashMD5Int.Create();
   mFile2List := THashStrCIInt.Create();
   SetLength(mFileList, 0);
@@ -134,6 +179,46 @@ begin
 end;
 
 
+//==========================================================================
+//
+//  TFileHashDB.Create
+//
+//==========================================================================
+constructor TFileHashDB.Create (aBasePath: AnsiString; const aPathList: TStrDynArray);
+begin
+  setup(aBasePath, aPathList);
+end;
+
+
+//==========================================================================
+//
+//  TFileHashDB.Create
+//
+//==========================================================================
+constructor TFileHashDB.Create (aBasePath: AnsiString; const aPathList: SSArray);
+var
+  f: Integer;
+  pl: TStrDynArray = nil;
+begin
+  SetLength(pl, length(aPathList));
+  for f := Low(pl) to High(pl) do pl[f] := aPathList[f-Low(pl)+Low(aPathList)];
+  setup(aBasePath, pl);
+end;
+
+
+//==========================================================================
+//
+//  TFileHashDB.appendMoreDirs
+//
+//==========================================================================
+procedure TFileHashDB.appendMoreDirs (const aPathList: SSArray);
+var
+  f: Integer;
+begin
+  for f := Low(aPathList) to High(aPathList) do appendOneDir(aPathList[f]);
+end;
+
+
 //==========================================================================
 //
 //  TFileHashDB.Destroy
@@ -145,6 +230,7 @@ begin
   mHash2List.Free;
   mFile2List.Free;
   SetLength(mFileList, 0);
+  SetLength(mPathList, 0);
   mFreeHead := -1;
 end;
 
@@ -161,6 +247,7 @@ begin
   mHash2List.clear();
   mFile2List.clear();
   SetLength(mFileList, 0);
+  //SetLength(mPathList, 0);
   mFreeHead := -1;
 end;
 
@@ -177,7 +264,7 @@ var
 begin
   sign := 'FHDB';
   st.WriteBuffer(sign, 4);
-  st.WriteWord(0); // version
+  st.WriteWord(1); // version
   st.WriteDWord(LongWord(mFile2List.count));
   for f := Low(mFileList) to High(mFileList) do
   begin
@@ -207,7 +294,7 @@ begin
     st.ReadBuffer(sign, 4);
     if (sign <> 'FHDB') then raise Exception.Create('invalid database signature');
     count := st.ReadWord();
-    if (count <> 0) then raise Exception.Create('invalid database version');
+    if (count <> 1) then raise Exception.Create('invalid database version');
     count := Integer(st.ReadDWord());
     if (count < 0) or (count > 1024*1024) then raise Exception.Create('invalid database file count');
     while (count > 0) do
@@ -285,7 +372,13 @@ var
   age: LongInt;
   needUpdate: Boolean;
 begin
-  if (FindFirst(path+'*', faAnyFile, sr) <> 0) then exit;
+  //writeln('TFileHashDB.scanDir(000): [', path, ']');
+  if (FindFirst(path+'*', faAnyFile, sr) <> 0) then
+  begin
+    FindClose(sr);
+    exit;
+  end;
+  //writeln('TFileHashDB.scanDir(001): [', path, ']');
   try
     repeat
       if ((sr.Attr and faDirectory) <> 0) then
@@ -299,7 +392,7 @@ begin
         dfn := fixSlashes(path+sr.Name, false);
         // build internal file name
         hfn := dfn;
-        Delete(hfn, 1, length(mBasePath)); // remove prefix
+        //Delete(hfn, 1, length(mBasePath)); // remove prefix
         // find file in hash
         if not mFile2List.get(hfn, idx) then idx := -1;
         // check if we already have this file
@@ -395,7 +488,9 @@ var
 begin
   result := false;
   for f := Low(mFileList) to High(mFileList) do mFileList[f].wasSeen := false;
-  scanDir(mBasePath, result);
+  //scanDir(mBasePath, result);
+  //writeln('TFileHashDB.scanFiles: dll=', length(mPathList));
+  for f := Low(mPathList) to High(mPathList) do scanDir(mPathList[f], result);
   // remove all unseen files
   f := High(mFileList);
   while (f >= 0) do
@@ -427,10 +522,10 @@ end;
 //  TFileHashDB.addWithHash
 //
 //  returns `true` if something was changed
-//  name is relative to base
+//  name is *NOT* relative to base
 //
 //==========================================================================
-function TFileHashDB.addWithHash (relname: AnsiString; const md5: TMD5Digest): Boolean;
+function TFileHashDB.addWithHash (fdiskname: AnsiString; const md5: TMD5Digest): Boolean;
 var
   age: LongInt;
   size: LongInt;
@@ -439,9 +534,10 @@ var
   idx: Integer;
 begin
   result := false;
-  if (length(relname) > length(mBasePath)) and strEquCI1251(mBasePath, Copy(relname, 1, length(mBasePath))) then Delete(relname, 1, Length(mBasePath));
-  if (length(relname) = 0) then exit;
-  fn := mBasePath+relname;
+  //if (length(fdiskname) > length(mBasePath)) and strEquCI1251(mBasePath, Copy(fdiskname, 1, length(mBasePath))) then Delete(fdiskname, 1, Length(mBasePath));
+  if (length(fdiskname) = 0) then exit;
+  //fn := mBasePath+fdiskname;
+  fn := fdiskname;
   if not findFileCI(fn) then exit;
   // get age
   age := FileAge(fn);
@@ -453,7 +549,7 @@ begin
   FileClose(handle);
   if (size = -1) then exit;
   // find old file, if any
-  Delete(fn, 1, length(mBasePath));
+  //Delete(fn, 1, length(mBasePath));
   if not mFile2List.get(fn, idx) then idx := -1;
   // check for changes
   if (idx >= 0) then