LazUtils: move more Utf8 file routines to LazFileUtils (and inline them in FileUtil):

CompareFileExt, FileIsExecutable, CheckIfFileIsExecutable, FileIsSymlink, CheckIfFileIsSymlink,
FileIsHardLink, FileIsReadable, FileIsWritable.

git-svn-id: trunk@41358 -
This commit is contained in:
bart 2013-05-22 16:36:57 +00:00
parent 46d203865a
commit b9a543d619
7 changed files with 248 additions and 329 deletions

View File

@ -347,39 +347,13 @@ begin
end;
function CompareFileExt(const Filename, Ext: string; CaseSensitive: boolean): integer;
// Ext can contain a point or not
var
n, e : AnsiString;
FileLen, FilePos, ExtLen, ExtPos: integer;
begin
FileLen:=length(Filename);
ExtLen:=length(Ext);
FilePos:=FileLen;
while (FilePos>=1) and (Filename[FilePos]<>'.') do dec(FilePos);
if FilePos<1 then begin
// no extension in filename
Result:=1;
exit;
end;
// skip point
inc(FilePos);
ExtPos:=1;
if (ExtPos<=ExtLen) and (Ext[1]='.') then inc(ExtPos);
// compare extensions
n:=Copy(Filename, FilePos, length(FileName));
e:=Copy(Ext, ExtPos, length(Ext));
if CaseSensitive then
Result:=CompareStr(n, e)
else
Result:=UTF8CompareText(n, e);
if Result<0 then Result:=1
else if Result>0 then Result:=1;
Result := LazFileUtils.CompareFileExt(Filename, Ext, CaseSensitive);
end;
function CompareFileExt(const Filename, Ext: string): integer;
begin
Result:=CompareFileExt(Filename,Ext,false);
Result := LazFileUtils.CompareFileExt(Filename, Ext);
end;
function ChompPathDelim(const Path: string): string;
@ -397,6 +371,41 @@ begin
Result := LazFileUtils.FileIsText(AFileName, FileReadable);
end;
function FileIsExecutable(const AFilename: string): boolean;
begin
Result := LazFileUtils.FileIsExecutable(AFileName);
end;
procedure CheckIfFileIsExecutable(const AFilename: string);
begin
LazFileUtils.CheckIfFileIsExecutable(AFileName);
end;
function FileIsSymlink(const AFilename: string): boolean;
begin
Result := LazFileUtils.FileIsSymlink(AFilename);
end;
procedure CheckIfFileIsSymlink(const AFilename: string);
begin
LazFileUtils.CheckIfFileIsSymlink(AFilename);
end;
function FileIsHardLink(const AFilename: string): boolean;
begin
Result := LazFileUtils.FileIsHardLink(AFilename);
end;
function FileIsReadable(const AFilename: string): boolean;
begin
Result:= LazFileUtils.FileIsReadable(AFilename);
end;
function FileIsWritable(const AFilename: string): boolean;
begin
Result := LazFileUtils.FileIsWritable(AFilename);
end;
function TryReadAllLinks(const Filename: string): string;
begin
Result:=ReadAllLinks(Filename,false);

View File

@ -77,15 +77,15 @@ function CompareFilenames(Filename1: PChar; Len1: integer;
function FilenameIsAbsolute(const TheFilename: string):boolean; inline;
function FilenameIsWinAbsolute(const TheFilename: string):boolean; inline;
function FilenameIsUnixAbsolute(const TheFilename: string):boolean; inline;
procedure CheckIfFileIsExecutable(const AFilename: string);
procedure CheckIfFileIsSymlink(const AFilename: string);
function FileIsReadable(const AFilename: string): boolean;
function FileIsWritable(const AFilename: string): boolean;
procedure CheckIfFileIsExecutable(const AFilename: string); inline;
procedure CheckIfFileIsSymlink(const AFilename: string); inline;
function FileIsReadable(const AFilename: string): boolean; inline;
function FileIsWritable(const AFilename: string): boolean; inline;
function FileIsText(const AFilename: string): boolean; inline;
function FileIsText(const AFilename: string; out FileReadable: boolean): boolean; inline;
function FileIsExecutable(const AFilename: string): boolean;
function FileIsSymlink(const AFilename: string): boolean;
function FileIsHardLink(const AFilename: string): boolean;
function FileIsExecutable(const AFilename: string): boolean; inline;
function FileIsSymlink(const AFilename: string): boolean; inline;
function FileIsHardLink(const AFilename: string): boolean; inline;
function FileSize(const Filename: string): int64; overload; inline;
function GetFileDescription(const AFilename: string): string;
function ReadAllLinks(const Filename: string;
@ -105,11 +105,11 @@ const
function ExtractFileNameOnly(const AFilename: string): string;
function ExtractFileNameWithoutExt(const AFilename: string): string;
function CompareFileExt(const Filename, Ext: string; CaseSensitive: boolean): integer; overload;
function CompareFileExt(const Filename, Ext: string): integer; overload;
function CompareFileExt(const Filename, Ext: string; CaseSensitive: boolean): integer; overload; inline;
function CompareFileExt(const Filename, Ext: string): integer; overload; inline;
function FilenameIsPascalUnit(const Filename: string): boolean;
function AppendPathDelim(const Path: string): string;
function ChompPathDelim(const Path: string): string;
function AppendPathDelim(const Path: string): string; inline;
function ChompPathDelim(const Path: string): string; inline;
function TrimFilename(const AFilename: string): string; inline;
function CleanAndExpandFilename(const Filename: string): string; inline;
function CleanAndExpandDirectory(const Filename: string): string; inline;

View File

@ -5,7 +5,7 @@ unit LazFileUtils;
interface
uses
Classes, SysUtils, LazUTF8, LazUtf8Classes, LUResStrings;
Classes, SysUtils, LazUTF8, LazUtf8Classes, LUResStrings, LazUtilsStrConsts;
{$IFDEF Windows}
{$define CaseInsensitiveFilenames}
@ -21,7 +21,9 @@ uses
function CompareFilenames(const Filename1, Filename2: string): integer;
function CompareFilenamesIgnoreCase(const Filename1, Filename2: string): integer;
function CompareFileExt(const Filename, Ext: string;
CaseSensitive: boolean): integer;
CaseSensitive: boolean): integer; overload;
function CompareFileExt(const Filename, Ext: string): integer; overload;
function CompareFilenameStarts(const Filename1, Filename2: string): integer;
function CompareFilenames(Filename1: PChar; Len1: integer;
Filename2: PChar; Len2: integer): integer;
@ -37,7 +39,10 @@ function FilenameIsWinAbsolute(const TheFilename: string):boolean;
function FilenameIsUnixAbsolute(const TheFilename: string):boolean;
function ForceDirectory(DirectoryName: string): boolean;
procedure CheckIfFileIsExecutable(const AFilename: string);
procedure CheckIfFileIsSymlink(const AFilename: string);
function FileIsExecutable(const AFilename: string): boolean;
function FileIsSymlink(const AFilename: string): boolean;
function FileIsHardLink(const AFilename: string): boolean;
function FileIsReadable(const AFilename: string): boolean;
function FileIsWritable(const AFilename: string): boolean;
function FileIsText(const AFilename: string): boolean;
@ -204,56 +209,13 @@ begin
if Result > 0 then Result := 1;
end;
function FileIsExecutable(const AFilename: string): boolean;
{$IFNDEF WINDOWS}
var
Info : Stat;
{$ENDIF}
function CompareFileExt(const Filename, Ext: string): integer;
begin
{$IFDEF WINDOWS}
Result:=FileExistsUTF8(AFilename);
{$ELSE}
// first check AFilename is not a directory and then check if executable
Result:= (FpStat(AFilename,info{%H-})<>-1) and FPS_ISREG(info.st_mode) and
(BaseUnix.FpAccess(AFilename,BaseUnix.X_OK)=0);
{$ENDIF}
Result := CompareFileExt(Filename, Ext, False);
end;
procedure CheckIfFileIsExecutable(const AFilename: string);
{$IFNDEF Windows}
var AText: string;
{$ENDIF}
begin
// TProcess does not report, if a program can not be executed
// to get good error messages consider the OS
if not FileExistsUTF8(AFilename) then begin
raise Exception.CreateFmt(ctsFileDoesNotExist,[AFilename]);
end;
{$IFNDEF Windows}
if not(BaseUnix.FpAccess(AFilename,BaseUnix.X_OK)=0) then
begin
AText:='"'+AFilename+'"';
case fpGetErrno of
ESysEAcces:
AText:='read access denied for '+AText;
ESysENoEnt:
AText:='a directory component in '+AText
+' does not exist or is a dangling symlink';
ESysENotDir:
AText:='a directory component in '+Atext+' is not a directory';
ESysENoMem:
AText:='insufficient memory';
ESysELoop:
AText:=AText+' has a circular symbolic link';
else
AText:=Format(ctsFileIsNotExecutable,[AText]);
end;
raise Exception.Create(AText);
end;
{$ENDIF}
// ToDo: windows and xxxbsd
end;
function ExtractFileNameOnly(const AFilename: string): string;
var ExtLen: integer;
@ -442,23 +404,6 @@ begin
Result:=true;
end;
function FileIsReadable(const AFilename: string): boolean;
begin
{$IFDEF Windows}
Result:=true;
{$ELSE}
Result:= BaseUnix.FpAccess(AFilename,BaseUnix.R_OK)=0;
{$ENDIF}
end;
function FileIsWritable(const AFilename: string): boolean;
begin
{$IFDEF Windows}
Result:=((FileGetAttrUTF8(AFilename) and faReadOnly)=0);
{$ELSE}
Result:= BaseUnix.FpAccess(AFilename,BaseUnix.W_OK)=0;
{$ENDIF}
end;
function FileIsText(const AFilename: string): boolean;
var

View File

@ -1,126 +1,4 @@
{%MainUnit fileutil.pas}
{------------------------------------------------------------------------------
procedure CheckIfFileIsExecutable(const AFilename: string);
------------------------------------------------------------------------------}
procedure CheckIfFileIsExecutable(const AFilename: string);
var AText: string;
begin
// TProcess does not report, if a program can not be executed
// to get good error messages consider the OS
if not FileExistsUTF8(AFilename) then begin
raise Exception.Create(Format(lrsFileDoesNotExist, [AFilename]));
end;
if DirPathExists(AFilename) then begin
raise Exception.Create(Format(lrsFileIsADirectoryAndNotAnExecutable, [
AFilename]));
end;
if not FileIsExecutable(AFilename) then
begin
AText:='"'+AFilename+'"';
case fpGetErrno() of
ESysEAcces:
AText:=Format(lrsReadAccessDeniedFor, [AText]);
ESysENoEnt:
AText:=Format(lrsADirectoryComponentInDoesNotExistOrIsADanglingSyml, [
AText]);
ESysENotDir:
AText:=Format(lrsADirectoryComponentInIsNotADirectory, [Atext]);
ESysENoMem:
AText:=lrsInsufficientMemory;
ESysELoop:
AText:=Format(lrsHasACircularSymbolicLink, [AText]);
else
AText:=Format(lrsIsNotExecutable, [AText]);
end;
raise Exception.Create(AText);
end;
end;
{------------------------------------------------------------------------------
procedure CheckIfFileIsSymlink(const AFilename: string);
------------------------------------------------------------------------------}
procedure CheckIfFileIsSymlink(const AFilename: string);
var
AText: string;
begin
// to get good error messages consider the OS
if not FileExistsUTF8(AFilename) then begin
raise Exception.Create(Format(lrsFileDoesNotExist, [AFilename]));
end;
if FpReadLink(AFilename)='' then begin
AText:='"'+AFilename+'"';
case fpGetErrno() of
ESysEAcces:
AText:=Format(lrsReadAccessDeniedFor, [AText]);
ESysENoEnt:
AText:=Format(lrsADirectoryComponentInDoesNotExistOrIsADanglingSyml2, [
AText]);
ESysENotDir:
AText:=Format(lrsADirectoryComponentInIsNotADirectory2, [Atext]);
ESysENoMem:
AText:=lrsInsufficientMemory;
ESysELoop:
AText:=Format(lrsHasACircularSymbolicLink, [AText]);
else
AText:=Format(lrsIsNotASymbolicLink, [AText]);
end;
raise Exception.Create(AText);
end;
end;
{------------------------------------------------------------------------------
function FileIsReadable(const AFilename: string): boolean;
------------------------------------------------------------------------------}
function FileIsReadable(const AFilename: string): boolean;
begin
Result:= BaseUnix.FpAccess(AFilename,BaseUnix.R_OK)=0;
end;
{------------------------------------------------------------------------------
FileIsWritable
------------------------------------------------------------------------------}
function FileIsWritable(const AFilename: string): boolean;
begin
Result:= BaseUnix.FpAccess(AFilename,BaseUnix.W_OK)=0;
end;
{------------------------------------------------------------------------------
function FileIsExecutable(const AFilename: string): boolean;
------------------------------------------------------------------------------}
function FileIsExecutable(const AFilename: string): boolean;
var
Info : Stat;
begin
// first check AFilename is not a directory and then check if executable
Result:= (FpStat(AFilename,info{%H-})<>-1) and FPS_ISREG(info.st_mode) and
(BaseUnix.FpAccess(AFilename,BaseUnix.X_OK)=0);
end;
{------------------------------------------------------------------------------
function FileIsSymlink(const AFilename: string): boolean;
------------------------------------------------------------------------------}
function FileIsSymlink(const AFilename: string): boolean;
begin
Result := FpReadLink(AFilename) <> '';
end;
{------------------------------------------------------------------------------
function FileIsHardLink(const AFilename: string): boolean;
------------------------------------------------------------------------------}
function FileIsHardLink(const AFilename: string): boolean;
var
H: THandle;
FileInfo: stat;
begin
Result := false;
H := FileOpenUtf8(aFilename, fmOpenRead);
if H <> feInvalidHandle then
begin
if FPFStat(H, FileInfo{%H-}) = 0 then
Result := (FileInfo.st_nlink > 1);
FileClose(H);
end;
end;
{------------------------------------------------------------------------------

View File

@ -160,6 +160,108 @@ begin
Result:=SysToUTF8(SysUtils.GetCurrentDir);
end;
function FileIsExecutable(const AFilename: string): boolean;
var
Info : Stat;
begin
// first check AFilename is not a directory and then check if executable
Result:= (FpStat(AFilename,info{%H-})<>-1) and FPS_ISREG(info.st_mode) and
(BaseUnix.FpAccess(AFilename,BaseUnix.X_OK)=0);
end;
procedure CheckIfFileIsExecutable(const AFilename: string);
begin
// TProcess does not report, if a program can not be executed
// to get good error messages consider the OS
if not FileExistsUTF8(AFilename) then begin
raise Exception.Create(Format(lrsFileDoesNotExist, [AFilename]));
end;
if DirPathExists(AFilename) then begin
raise Exception.Create(Format(lrsFileIsADirectoryAndNotAnExecutable, [
AFilename]));
end;
if not(BaseUnix.FpAccess(AFilename,BaseUnix.X_OK)=0) then
begin
AText:='"'+AFilename+'"';
case fpGetErrno() of
ESysEAcces:
AText:=Format(lrsReadAccessDeniedFor, [AText]);
ESysENoEnt:
AText:=Format(lrsADirectoryComponentInDoesNotExistOrIsADanglingSyml, [
AText]);
ESysENotDir:
AText:=Format(lrsADirectoryComponentInIsNotADirectory, [Atext]);
ESysENoMem:
AText:=lrsInsufficientMemory;
ESysELoop:
AText:=Format(lrsHasACircularSymbolicLink, [AText]);
else
AText:=Format(lrsIsNotExecutable, [AText]);
end;
raise Exception.Create(AText);
end;
// ToDo: xxxbsd
end;
function FileIsSymlink(const AFilename: string): boolean;
begin
Result := FpReadLink(AFilename) <> '';
end;
procedure CheckIfFileIsSymlink(const AFilename: string);
var
AText: string;
begin
// to get good error messages consider the OS
if not FileExistsUTF8(AFilename) then begin
raise Exception.Create(Format(lrsFileDoesNotExist, [AFilename]));
end;
if FpReadLink(AFilename)='' then begin
AText:='"'+AFilename+'"';
case fpGetErrno() of
ESysEAcces:
AText:=Format(lrsReadAccessDeniedFor, [AText]);
ESysENoEnt:
AText:=Format(lrsADirectoryComponentInDoesNotExistOrIsADanglingSyml2, [
AText]);
ESysENotDir:
AText:=Format(lrsADirectoryComponentInIsNotADirectory2, [Atext]);
ESysENoMem:
AText:=lrsInsufficientMemory;
ESysELoop:
AText:=Format(lrsHasACircularSymbolicLink, [AText]);
else
AText:=Format(lrsIsNotASymbolicLink, [AText]);
end;
raise Exception.Create(AText);
end;
end;
function FileIsHardLink(const AFilename: string): boolean;
var
H: THandle;
FileInfo: stat;
begin
Result := false;
H := FileOpenUtf8(aFilename, fmOpenRead);
if H <> feInvalidHandle then
begin
if FPFStat(H, FileInfo{%H-}) = 0 then
Result := (FileInfo.st_nlink > 1);
FileClose(H);
end;
end;
function FileIsReadable(const AFilename: string): boolean;
begin
Result:= BaseUnix.FpAccess(AFilename,BaseUnix.R_OK)=0;
end;
function FileIsWritable(const AFilename: string): boolean;
begin
Result := (BaseUnix.FpAccess(AFilename, BaseUnix.W_OK) = 0);
end;
procedure InitLazFileUtils;
begin

View File

@ -1,109 +1,6 @@
{%MainUnit fileutil.pas}
{------------------------------------------------------------------------------
procedure CheckIfFileIsExecutable(const AFilename: string);
------------------------------------------------------------------------------}
procedure CheckIfFileIsExecutable(const AFilename: string);
begin
// TProcess does not report, if a program can not be executed
// to get good error messages consider the OS
if not FileExistsUTF8(AFilename) then begin
raise Exception.Create('file "'+AFilename+'" does not exist');
end;
if DirPathExists(AFilename) then begin
raise Exception.Create('file "'+AFilename+'" is a directory and not an executable');
end;
end;
{------------------------------------------------------------------------------
procedure CheckIfFileIsSymlink(const AFilename: string);
------------------------------------------------------------------------------}
procedure CheckIfFileIsSymlink(const AFilename: string);
begin
// to get good error messages consider the OS
if not FileExistsUTF8(AFilename) then begin
raise Exception.Create('file "'+AFilename+'" does not exist');
end;
raise Exception.Create('"'+AFilename+'" is not symlink');
end;
{------------------------------------------------------------------------------
function FileIsReadable(const AFilename: string): boolean;
------------------------------------------------------------------------------}
function FileIsReadable(const AFilename: string): boolean;
begin
Result:=true;
end;
{------------------------------------------------------------------------------
FileIsWritable
------------------------------------------------------------------------------}
function FileIsWritable(const AFilename: string): boolean;
begin
Result:=((FileGetAttrUTF8(AFilename) and faReadOnly)=0);
end;
{------------------------------------------------------------------------------
function FileIsExecutable(const AFilename: string): boolean;
------------------------------------------------------------------------------}
function FileIsExecutable(const AFilename: string): boolean;
begin
Result:=FileExistsUTF8(AFilename);
end;
{------------------------------------------------------------------------------
function FileIsSymlink(const AFilename: string): boolean;
------------------------------------------------------------------------------}
function FileIsSymlink(const AFilename: string): boolean;
{$ifndef wince}
const
IO_REPARSE_TAG_MOUNT_POINT = $A0000003;
IO_REPARSE_TAG_SYMLINK = $A000000C;
var
Attr: Longint;
Rec: TSearchRec;
{$endif}
begin
{$ifndef wince}
Attr := FileGetAttrUTF8(AFilename);
if (Attr <> -1) and (Attr and FILE_ATTRIBUTE_REPARSE_POINT <> 0) then
begin
FindFirstUTF8(AFilename, Attr, Rec);
if Rec.FindHandle <> feInvalidHandle then
begin
Windows.FindClose(Rec.FindHandle);
Result := (Rec.FindData.dwReserved0 = IO_REPARSE_TAG_SYMLINK) or (Rec.FindData.dwReserved0 = IO_REPARSE_TAG_MOUNT_POINT);
end
else
Result := False;
end
else
{$endif}
Result := False;
end;
{------------------------------------------------------------------------------
function FileIsHardLink(const AFilename: string): boolean;
------------------------------------------------------------------------------}
function FileIsHardLink(const AFilename: string): boolean;
var
H: THandle;
FileInfo: BY_HANDLE_FILE_INFORMATION;
begin
Result := false;
{$ifndef wince}
//HardLinks are not supported in Win9x platform
if (Win32Platform = VER_PLATFORM_WIN32_WINDOWS) then Exit;
H := FileOpenUtf8(aFilename, fmOpenRead);
if (H <> feInvalidHandle) then
begin
FillChar(FileInfo, SizeOf(BY_HANDLE_FILE_INFORMATION),0);
if GetFileInformationByHandle(H, FileInfo) then
Result := (FileInfo.nNumberOfLinks > 1);
FileClose(H);
end;
{$endif}
end;
{------------------------------------------------------------------------------
GetFileDescription

View File

@ -708,6 +708,94 @@ begin
Result := False;
end;
function FileIsExecutable(const AFilename: string): boolean;
begin
Result:=FileExistsUTF8(AFilename);
end;
procedure CheckIfFileIsExecutable(const AFilename: string);
var AText: string;
begin
// TProcess does not report, if a program can not be executed
// to get good error messages consider the OS
if not FileExistsUTF8(AFilename) then begin
raise Exception.Create(Format(lrsFileDoesNotExist, [AFilename]));
end;
if DirPathExists(AFilename) then begin
raise Exception.Create(Format(lrsFileIsADirectoryAndNotAnExecutable, [
AFilename]));
end;
end;
function FileIsSymlink(const AFilename: string): boolean;
{$ifndef wince}
const
IO_REPARSE_TAG_MOUNT_POINT = $A0000003;
IO_REPARSE_TAG_SYMLINK = $A000000C;
var
Attr: Longint;
Rec: TSearchRec;
{$endif}
begin
{$ifndef wince}
Attr := FileGetAttrUTF8(AFilename);
if (Attr <> -1) and (Attr and FILE_ATTRIBUTE_REPARSE_POINT <> 0) then
begin
FindFirstUTF8(AFilename, Attr, Rec);
if Rec.FindHandle <> feInvalidHandle then
begin
Windows.FindClose(Rec.FindHandle);
Result := (Rec.FindData.dwReserved0 = IO_REPARSE_TAG_SYMLINK) or (Rec.FindData.dwReserved0 = IO_REPARSE_TAG_MOUNT_POINT);
end
else
Result := False;
end
else
{$endif}
Result := False;
end;
procedure CheckIfFileIsSymlink(const AFilename: string);
begin
// to get good error messages consider the OS
if not FileExistsUTF8(AFilename) then begin
raise Exception.Create(Format(lrsFileDoesNotExist, [AFilename]));
end;
if not FileIsSymLink(AFilename) then
raise Exception.Create(Format(lrsIsNotASymbolicLink, [AFilename]));
end;
function FileIsHardLink(const AFilename: string): boolean;
var
H: THandle;
FileInfo: BY_HANDLE_FILE_INFORMATION;
begin
Result := false;
{$ifndef wince}
//HardLinks are not supported in Win9x platform
if (Win32Platform = VER_PLATFORM_WIN32_WINDOWS) then Exit;
H := FileOpenUtf8(aFilename, fmOpenRead);
if (H <> feInvalidHandle) then
begin
FillChar(FileInfo, SizeOf(BY_HANDLE_FILE_INFORMATION),0);
if GetFileInformationByHandle(H, FileInfo) then
Result := (FileInfo.nNumberOfLinks > 1);
FileClose(H);
end;
{$endif}
end;
function FileIsReadable(const AFilename: string): boolean;
begin
Result:=true;
end;
function FileIsWritable(const AFilename: string): boolean;
begin
Result := ((FileGetAttrUTF8(AFilename) and faReadOnly) = 0);
end;