diff --git a/src/sfs/sfs.pas b/src/sfs/sfs.pas
index 3776a0036d7742c6df3160222d12328f5d35e3b1..0f2ff81379c0802bb6936867fa1ee693d17dc1e5 100644 (file)
--- a/src/sfs/sfs.pas
+++ b/src/sfs/sfs.pas
// ïðåîáðàçîâàòü ÷èñëî â ñòðîêó, êðàñèâî ðàçáàâëÿÿ çàïÿòûìè
function Int64ToStrComma (i: Int64): string;
+// `name` will be modified
+// return `true` if file was found
+function sfsFindFileCI (path: string; var name: string): Boolean;
+
// Wildcard matching
// this code is meant to allow wildcard pattern matches. tt is VERY useful
// for matching filename wildcard patterns. tt allows unix grep-like pattern
end;
+// `name` will be modified
+function sfsFindFileCI (path: string; var name: string): Boolean;
+var
+ sr: TSearchRec;
+ bestname: string = '';
+begin
+ if length(path) = 0 then path := '.';
+ while (length(path) > 0) and (path[length(path)] = '/') do Delete(path, length(path), 1);
+ if (length(path) = 0) or (path[length(path)] <> '/') then path := path+'/';
+ if FileExists(path+name) then begin result := true; exit; end;
+ if FindFirst(path+'*', faAnyFile, sr) = 0 then
+ repeat
+ if (sr.name = '.') or (sr.name = '..') then continue;
+ if (sr.attr and faDirectory) <> 0 then continue;
+ if sr.name = name then
+ begin
+ FindClose(sr);
+ result := true;
+ exit;
+ end;
+ if (length(bestname) = 0) and SFSStrEqu(sr.name, name) then bestname := sr.name;
+ until FindNext(sr) <> 0;
+ FindClose(sr);
+ if length(bestname) > 0 then begin result := true; name := bestname; end else result := false;
+end;
+
+
const
// character defines
WILD_CHAR_ESCAPE = '\';
*)
end;
+// adds '/' too
+function normalizePath (fn: string): string;
+var
+ i: Integer;
+begin
+ result := '';
+ i := 1;
+ while i <= length(fn) do
+ begin
+ if (fn[i] = '.') and ((length(fn)-i = 0) or (fn[i+1] = '/') or (fn[i+1] = '\')) then
+ begin
+ i := i+2;
+ continue;
+ end;
+ if (fn[i] = '/') or (fn[i] = '\') then
+ begin
+ if (length(result) > 0) and (result[length(result)] <> '/') then result := result+'/';
+ end
+ else
+ begin
+ result := result+fn[i];
+ end;
+ Inc(i);
+ end;
+ if (length(result) > 0) and (result[length(result)] <> '/') then result := result+'/';
+end;
+
function SFSReplacePathDelims (const s: TSFSString; newDelim: TSFSChar): TSFSString;
var
f: Integer;
procedure TSFSVolume.DoDirectoryRead ();
var
- fl: TStringList; //!!!FIXME! change to list of wide TSFSStrings or so!
- f, c, n: Integer;
+ f, c: Integer;
sfi: TSFSFileInfo;
- tmp, fn, ext: TSFSString;
+ tmp: TSFSString;
begin
- fl := nil;
fFileName := ExpandFileName(SFSReplacePathDelims(fFileName, '/'));
- try
- ReadDirectory();
- fFiles.Pack();
+ ReadDirectory();
+ fFiles.Pack();
- // check for duplicate file names
- fl := TStringList.Create(); fl.Sorted := true;
- for f := 0 to fFiles.Count-1 do
+ for f := 0 to fFiles.Count-1 do
+ begin
+ sfi := TSFSFileInfo(fFiles[f]);
+ // normalize name & path
+ sfi.fPath := SFSReplacePathDelims(sfi.fPath, '/');
+ if (sfi.fPath <> '') and (sfi.fPath[1] = '/') then Delete(sfi.fPath, 1, 1);
+ if (sfi.fPath <> '') and (sfi.fPath[Length(sfi.fPath)] <> '/') then sfi.fPath := sfi.fPath+'/';
+ tmp := SFSReplacePathDelims(sfi.fName, '/');
+ c := Length(tmp); while (c > 0) and (tmp[c] <> '/') do Dec(c);
+ if c > 0 then
begin
- sfi := TSFSFileInfo(fFiles[f]);
-
- // normalize name & path
- sfi.fPath := SFSReplacePathDelims(sfi.fPath, '/');
- if (sfi.fPath <> '') and (sfi.fPath[1] = '/') then Delete(sfi.fPath, 1, 1);
- if (sfi.fPath <> '') and (sfi.fPath[Length(sfi.fPath)] <> '/') then sfi.fPath := sfi.fPath+'/';
- tmp := SFSReplacePathDelims(sfi.fName, '/');
- c := Length(tmp); while (c > 0) and (tmp[c] <> '/') do Dec(c);
- if c > 0 then
- begin
- // split path and name
- Delete(sfi.fName, 1, c); // cut name
- tmp := Copy(tmp, 1, c); // get path
- if tmp = '/' then tmp := ''; // just delimiter; ignore it
- sfi.fPath := sfi.fPath+tmp;
- end;
-
- // check for duplicates
- if fl.Find(sfi.fPath+sfi.fName, c) then
- begin
- n := 0; tmp := sfi.fName;
- c := Length(tmp); while (c > 0) and (tmp[c] <> '.') do Dec(c);
- if c < 1 then c := Length(tmp)+1;
- fn := Copy(tmp, 1, c-1); ext := Copy(tmp, c, Length(tmp));
- repeat
- tmp := fn+'_'+IntToStr(n)+ext;
- if not fl.Find(sfi.fPath+tmp, c) then break;
- Inc(n);
- until false;
- sfi.fName := tmp;
- end;
- fl.Add(sfi.fName);
+ // split path and name
+ Delete(sfi.fName, 1, c); // cut name
+ tmp := Copy(tmp, 1, c); // get path
+ if tmp = '/' then tmp := ''; // just delimiter; ignore it
+ sfi.fPath := sfi.fPath+tmp;
end;
- fl.Free();
- except
- fl.Free();
- raise;
+ sfi.fPath := normalizePath(sfi.fPath);
end;
removeCommonPath();
end;
initialization
factories := TObjectList.Create(true);
volumes := TObjectList.Create(true);
-finalization
+//finalization
//volumes.Free(); // it fails for some reason... Runtime 217 (^C hit). wtf?!
//factories.Free(); // not need to be done actually...
end.