mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 20:49:23 +02:00
* FindFirst/FindNext replaced with optimized versions based on the
code in the dos unit. git-svn-id: trunk@4772 -
This commit is contained in:
parent
9a36c6d7a6
commit
25fe773e25
@ -303,50 +303,8 @@ begin
|
|||||||
Result:=Result or faSymLink;
|
Result:=Result or faSymLink;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
type
|
|
||||||
|
|
||||||
pglob = ^tglob;
|
Function FNMatch(const Pattern,Name:string):Boolean;
|
||||||
tglob = record
|
|
||||||
name : pchar;
|
|
||||||
next : pglob;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Function Dirname(Const path:pathstr):pathstr;
|
|
||||||
{
|
|
||||||
This function returns the directory part of a complete path.
|
|
||||||
Unless the directory is root '/', The last character is not
|
|
||||||
a slash.
|
|
||||||
}
|
|
||||||
var
|
|
||||||
Dir : DirStr;
|
|
||||||
Name : NameStr;
|
|
||||||
Ext : ExtStr;
|
|
||||||
begin
|
|
||||||
FSplit(Path,Dir,Name,Ext);
|
|
||||||
if length(Dir)>1 then
|
|
||||||
Delete(Dir,length(Dir),1);
|
|
||||||
DirName:=Dir;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
Function Basename(Const path:pathstr;Const suf:pathstr):pathstr;
|
|
||||||
{
|
|
||||||
This function returns the filename part of a complete path. If suf is
|
|
||||||
supplied, it is cut off the filename.
|
|
||||||
}
|
|
||||||
var
|
|
||||||
Dir : DirStr;
|
|
||||||
Name : NameStr;
|
|
||||||
Ext : ExtStr;
|
|
||||||
begin
|
|
||||||
FSplit(Path,Dir,Name,Ext);
|
|
||||||
if Suf<>Ext then
|
|
||||||
Name:=Name+Ext;
|
|
||||||
BaseName:=Name;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
Function FNMatch(const Pattern,Name:shortstring):Boolean;
|
|
||||||
Var
|
Var
|
||||||
LenPat,LenName : longint;
|
LenPat,LenName : longint;
|
||||||
|
|
||||||
@ -428,187 +386,144 @@ Begin {start FNMatch}
|
|||||||
End;
|
End;
|
||||||
|
|
||||||
|
|
||||||
Procedure Globfree(var p : pglob);
|
|
||||||
{
|
|
||||||
Release memory occupied by pglob structure, and names in it.
|
|
||||||
sets p to nil.
|
|
||||||
}
|
|
||||||
var
|
|
||||||
temp : pglob;
|
|
||||||
begin
|
|
||||||
while assigned(p) do
|
|
||||||
begin
|
|
||||||
temp:=p^.next;
|
|
||||||
if assigned(p^.name) then
|
|
||||||
freemem(p^.name);
|
|
||||||
dispose(p);
|
|
||||||
p:=temp;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
Function Glob(Const path:pathstr):pglob;
|
|
||||||
{
|
|
||||||
Fills a tglob structure with entries matching path,
|
|
||||||
and returns a pointer to it. Returns nil on error,
|
|
||||||
linuxerror is set accordingly.
|
|
||||||
}
|
|
||||||
var
|
|
||||||
temp,
|
|
||||||
temp2 : string[255];
|
|
||||||
thedir : pdir;
|
|
||||||
buffer : pdirent;
|
|
||||||
root,
|
|
||||||
current : pglob;
|
|
||||||
begin
|
|
||||||
{ Get directory }
|
|
||||||
temp:=dirname(path);
|
|
||||||
if temp='' then
|
|
||||||
temp:='.';
|
|
||||||
temp:=temp+#0;
|
|
||||||
thedir:=fpopendir(@temp[1]);
|
|
||||||
if thedir=nil then
|
|
||||||
exit(nil);
|
|
||||||
temp:=basename(path,''); { get the pattern }
|
|
||||||
if thedir^.dd_fd<0 then
|
|
||||||
exit(nil);
|
|
||||||
{get the entries}
|
|
||||||
root:=nil;
|
|
||||||
current:=nil;
|
|
||||||
repeat
|
|
||||||
buffer:=fpreaddir(thedir^);
|
|
||||||
if buffer=nil then
|
|
||||||
break;
|
|
||||||
temp2:=strpas(@(buffer^.d_name[0]));
|
|
||||||
if fnmatch(temp,temp2) then
|
|
||||||
begin
|
|
||||||
if root=nil then
|
|
||||||
begin
|
|
||||||
new(root);
|
|
||||||
current:=root;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
new(current^.next);
|
|
||||||
current:=current^.next;
|
|
||||||
end;
|
|
||||||
if current=nil then
|
|
||||||
begin
|
|
||||||
fpseterrno(ESysENOMEM);
|
|
||||||
globfree(root);
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
current^.next:=nil;
|
|
||||||
getmem(current^.name,length(temp2)+1);
|
|
||||||
if current^.name=nil then
|
|
||||||
begin
|
|
||||||
fpseterrno(ESysENOMEM);
|
|
||||||
globfree(root);
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
move(buffer^.d_name[0],current^.name^,length(temp2)+1);
|
|
||||||
end;
|
|
||||||
until false;
|
|
||||||
fpclosedir(thedir^);
|
|
||||||
glob:=root;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
GlobToSearch takes a glob entry, stats the file.
|
|
||||||
The glob entry is removed.
|
|
||||||
If FileAttributes match, the entry is reused
|
|
||||||
}
|
|
||||||
|
|
||||||
Type
|
Type
|
||||||
TGlobSearchRec = Record
|
TUnixFindData = Record
|
||||||
Path : shortString;
|
NamePos : LongInt; {to track which search this is}
|
||||||
GlobHandle : PGlob;
|
DirPtr : Pointer; {directory pointer for reading directory}
|
||||||
end;
|
SearchSpec : String;
|
||||||
PGlobSearchRec = ^TGlobSearchRec;
|
SearchType : Byte; {0=normal, 1=open will close, 2=only 1 file}
|
||||||
|
SearchAttr : Byte; {attribute we are searching for}
|
||||||
|
End;
|
||||||
|
PUnixFindData = ^TUnixFindData;
|
||||||
|
Var
|
||||||
|
CurrSearchNum : LongInt;
|
||||||
|
|
||||||
Function GlobToTSearchRec (Var Info : TSearchRec) : Boolean;
|
Procedure FindClose(Var f: TSearchRec);
|
||||||
|
var
|
||||||
Var SInfo : Stat;
|
UnixFindData : PUnixFindData;
|
||||||
p : Pglob;
|
Begin
|
||||||
GlobSearchRec : PGlobSearchrec;
|
UnixFindData:=PUnixFindData(f.FindHandle);
|
||||||
|
if UnixFindData=nil then
|
||||||
begin
|
exit;
|
||||||
GlobSearchRec:=Info.FindHandle;
|
if UnixFindData^.SearchType=0 then
|
||||||
P:=GlobSearchRec^.GlobHandle;
|
|
||||||
Result:=P<>Nil;
|
|
||||||
If Result then
|
|
||||||
begin
|
begin
|
||||||
GlobSearchRec^.GlobHandle:=P^.Next;
|
if UnixFindData^.dirptr<>nil then
|
||||||
Result:=Fpstat(GlobSearchRec^.Path+StrPas(p^.name),SInfo)>=0;
|
fpclosedir(pdir(UnixFindData^.dirptr)^);
|
||||||
Info.PathOnly:=GlobSearchRec^.Path;
|
|
||||||
If Result then
|
|
||||||
begin
|
|
||||||
Info.Attr:=LinuxToWinAttr(p^.name,SInfo);
|
|
||||||
Result:=(Info.ExcludeAttr and Info.Attr)=0;
|
|
||||||
If Result Then
|
|
||||||
With Info do
|
|
||||||
begin
|
|
||||||
Attr:=Info.Attr;
|
|
||||||
If P^.Name<>Nil then
|
|
||||||
Name:=strpas(p^.name);
|
|
||||||
Time:=UnixToWinAge(Sinfo.st_mtime);
|
|
||||||
Size:=Sinfo.st_Size;
|
|
||||||
Mode:=Sinfo.st_mode;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
P^.Next:=Nil;
|
|
||||||
GlobFree(P);
|
|
||||||
end;
|
end;
|
||||||
end;
|
Dispose(UnixFindData);
|
||||||
|
f.FindHandle:=nil;
|
||||||
|
End;
|
||||||
|
|
||||||
Function DoFind(Var Rslt : TSearchRec) : Longint;
|
|
||||||
|
|
||||||
Var
|
|
||||||
GlobSearchRec : PGlobSearchRec;
|
|
||||||
|
|
||||||
|
Function FindGetFileInfo(const s:string;var f:TSearchRec):boolean;
|
||||||
|
var
|
||||||
|
st : baseunix.stat;
|
||||||
|
WinAttr : longint;
|
||||||
begin
|
begin
|
||||||
Result:=-1;
|
FindGetFileInfo:=false;
|
||||||
GlobSearchRec:=Rslt.FindHandle;
|
if not fpstat(s,st)>=0 then
|
||||||
If (GlobSearchRec^.GlobHandle<>Nil) then
|
exit;
|
||||||
While (GlobSearchRec^.GlobHandle<>Nil) and not (Result=0) do
|
WinAttr:=LinuxToWinAttr(PChar(s),st);
|
||||||
If GlobToTSearchRec(Rslt) Then Result:=0;
|
If ((WinAttr and Not(PUnixFindData(f.FindHandle)^.searchattr))=0) Then
|
||||||
end;
|
Begin
|
||||||
|
f.Name:=Copy(s,PUnixFindData(f.FindHandle)^.NamePos+1,Length(s));
|
||||||
|
f.Attr:=WinAttr;
|
||||||
|
f.Size:=st.st_Size;
|
||||||
Function FindFirst (Const Path : String; Attr : Longint; out Rslt : TSearchRec) : Longint;
|
f.Mode:=st.st_mode;
|
||||||
|
f.Time:=UnixToWinAge(st.st_mtime);
|
||||||
Var
|
result:=true;
|
||||||
GlobSearchRec : PGlobSearchRec;
|
End;
|
||||||
|
|
||||||
begin
|
|
||||||
New(GlobSearchRec);
|
|
||||||
GlobSearchRec^.Path:=ExpandFileName(ExtractFilePath(Path));
|
|
||||||
GlobSearchRec^.GlobHandle:=Glob(Path);
|
|
||||||
Rslt.ExcludeAttr:=Not Attr and (faHidden or faSysFile or faVolumeID or faDirectory); //!! Not correct !!
|
|
||||||
Rslt.FindHandle:=GlobSearchRec;
|
|
||||||
Result:=DoFind (Rslt);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
Function FindNext (Var Rslt : TSearchRec) : Longint;
|
Function FindNext (Var Rslt : TSearchRec) : Longint;
|
||||||
|
{
|
||||||
begin
|
re-opens dir if not already in array and calls FindWorkProc
|
||||||
Result:=DoFind (Rslt);
|
}
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
Procedure FindClose (Var F : TSearchrec);
|
|
||||||
|
|
||||||
Var
|
Var
|
||||||
GlobSearchRec : PGlobSearchRec;
|
DirName : String;
|
||||||
|
i,
|
||||||
|
ArrayPos : Longint;
|
||||||
|
FName,
|
||||||
|
SName : string;
|
||||||
|
Found,
|
||||||
|
Finished : boolean;
|
||||||
|
p : pdirent;
|
||||||
|
UnixFindData : PUnixFindData;
|
||||||
|
Begin
|
||||||
|
Result:=-1;
|
||||||
|
UnixFindData:=PUnixFindData(Rslt.FindHandle);
|
||||||
|
if UnixFindData=nil then
|
||||||
|
exit;
|
||||||
|
if (UnixFindData^.SearchType=0) and
|
||||||
|
(UnixFindData^.Dirptr=nil) then
|
||||||
|
begin
|
||||||
|
If UnixFindData^.NamePos = 0 Then
|
||||||
|
DirName:='./'
|
||||||
|
Else
|
||||||
|
DirName:=Copy(UnixFindData^.SearchSpec,1,UnixFindData^.NamePos);
|
||||||
|
UnixFindData^.DirPtr := fpopendir(Pchar(DirName));
|
||||||
|
end;
|
||||||
|
SName:=Copy(UnixFindData^.SearchSpec,UnixFindData^.NamePos+1,Length(UnixFindData^.SearchSpec));
|
||||||
|
Found:=False;
|
||||||
|
Finished:=(UnixFindData^.dirptr=nil);
|
||||||
|
While Not Finished Do
|
||||||
|
Begin
|
||||||
|
p:=fpreaddir(pdir(UnixFindData^.dirptr)^);
|
||||||
|
if p=nil then
|
||||||
|
FName:=''
|
||||||
|
else
|
||||||
|
FName:=p^.d_name;
|
||||||
|
If FName='' Then
|
||||||
|
Finished:=True
|
||||||
|
Else
|
||||||
|
Begin
|
||||||
|
If FNMatch(SName,FName) Then
|
||||||
|
Begin
|
||||||
|
Found:=FindGetFileInfo(Copy(UnixFindData^.SearchSpec,1,UnixFindData^.NamePos)+FName,Rslt);
|
||||||
|
if Found then
|
||||||
|
begin
|
||||||
|
Result:=0;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
|
||||||
begin
|
|
||||||
GlobSearchRec:=F.FindHandle;
|
Function FindFirst (Const Path : String; Attr : Longint; out Rslt : TSearchRec) : Longint;
|
||||||
GlobFree (GlobSearchRec^.GlobHandle);
|
{
|
||||||
Dispose(GlobSearchRec);
|
opens dir and calls FindWorkProc
|
||||||
end;
|
}
|
||||||
|
var
|
||||||
|
UnixFindData : PUnixFindData;
|
||||||
|
Begin
|
||||||
|
Result:=-1;
|
||||||
|
fillchar(Rslt,sizeof(Rslt),0);
|
||||||
|
if Path='' then
|
||||||
|
exit;
|
||||||
|
{ Allocate UnixFindData }
|
||||||
|
New(UnixFindData);
|
||||||
|
FillChar(UnixFindData^,sizeof(UnixFindData),0);
|
||||||
|
Rslt.FindHandle:=UnixFindData;
|
||||||
|
{Create Info}
|
||||||
|
UnixFindData^.SearchSpec := Path;
|
||||||
|
{We always also search for readonly and archive, regardless of Attr:}
|
||||||
|
UnixFindData^.SearchAttr := Attr or faarchive or fareadonly;
|
||||||
|
UnixFindData^.NamePos := Length(UnixFindData^.SearchSpec);
|
||||||
|
while (UnixFindData^.NamePos>0) and (UnixFindData^.SearchSpec[UnixFindData^.NamePos]<>'/') do
|
||||||
|
dec(UnixFindData^.NamePos);
|
||||||
|
{Wildcards?}
|
||||||
|
if (Pos('?',Path)=0) and (Pos('*',Path)=0) then
|
||||||
|
begin
|
||||||
|
if FindGetFileInfo(Path,Rslt) then
|
||||||
|
Result:=0;
|
||||||
|
UnixFindData^.SearchType:=1;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Result:=FindNext(Rslt);
|
||||||
|
End;
|
||||||
|
|
||||||
|
|
||||||
Function FileGetDate (Handle : Longint) : Longint;
|
Function FileGetDate (Handle : Longint) : Longint;
|
||||||
@ -718,7 +633,7 @@ begin
|
|||||||
inc(Drives);
|
inc(Drives);
|
||||||
if Drives>26 then
|
if Drives>26 then
|
||||||
Drives:=4;
|
Drives:=4;
|
||||||
Result:=Drives;
|
Result:=Drives;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user