mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-14 13:19:20 +02:00
lcl: fileutil initial unix/windows separation. improved support for Windows unicode file operations (bug #15642)
git-svn-id: trunk@27248 -
This commit is contained in:
parent
dc60c4d504
commit
319db72532
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -4596,10 +4596,12 @@ lcl/include/toolbutton.inc svneol=native#text/pascal
|
|||||||
lcl/include/toolwindow.inc svneol=native#text/pascal
|
lcl/include/toolwindow.inc svneol=native#text/pascal
|
||||||
lcl/include/trackbar.inc svneol=native#text/pascal
|
lcl/include/trackbar.inc svneol=native#text/pascal
|
||||||
lcl/include/treeview.inc svneol=native#text/pascal
|
lcl/include/treeview.inc svneol=native#text/pascal
|
||||||
|
lcl/include/unixfileutil.inc svneol=native#text/plain
|
||||||
lcl/include/untabbednotebook.inc svneol=native#text/plain
|
lcl/include/untabbednotebook.inc svneol=native#text/plain
|
||||||
lcl/include/winapi.inc svneol=native#text/pascal
|
lcl/include/winapi.inc svneol=native#text/pascal
|
||||||
lcl/include/winapih.inc svneol=native#text/pascal
|
lcl/include/winapih.inc svneol=native#text/pascal
|
||||||
lcl/include/wincontrol.inc svneol=native#text/pascal
|
lcl/include/wincontrol.inc svneol=native#text/pascal
|
||||||
|
lcl/include/winfileutil.inc svneol=native#text/plain
|
||||||
lcl/inipropstorage.pas svneol=native#text/pascal
|
lcl/inipropstorage.pas svneol=native#text/pascal
|
||||||
lcl/interfacebase.pp svneol=native#text/pascal
|
lcl/interfacebase.pp svneol=native#text/pascal
|
||||||
lcl/interfaces/LAYOUT.txt svneol=native#text/plain
|
lcl/interfaces/LAYOUT.txt svneol=native#text/plain
|
||||||
|
@ -27,7 +27,7 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
// For Smart Linking: Do not use the LCL!
|
// For Smart Linking: Do not use the LCL!
|
||||||
Classes, SysUtils, LCLStrConsts, Masks;
|
SysConst, Classes, SysUtils, LCLStrConsts, Masks;
|
||||||
|
|
||||||
{$if defined(Windows) or defined(darwin)}
|
{$if defined(Windows) or defined(darwin)}
|
||||||
{$define CaseInsensitiveFilenames}
|
{$define CaseInsensitiveFilenames}
|
||||||
@ -205,7 +205,7 @@ function FileGetAttrUTF8(const FileName: String): Longint;
|
|||||||
function FileSetAttrUTF8(const Filename: String; Attr: longint): Longint;
|
function FileSetAttrUTF8(const Filename: String; Attr: longint): Longint;
|
||||||
function DeleteFileUTF8(const FileName: String): Boolean;
|
function DeleteFileUTF8(const FileName: String): Boolean;
|
||||||
function RenameFileUTF8(const OldName, NewName: String): Boolean;
|
function RenameFileUTF8(const OldName, NewName: String): Boolean;
|
||||||
function FileSearchUTF8(const Name, DirList : String): String;
|
function FileSearchUTF8(const Name, DirList : String; ImplicitCurrentDir : Boolean = True): String;
|
||||||
function FileIsReadOnlyUTF8(const FileName: String): Boolean;
|
function FileIsReadOnlyUTF8(const FileName: String): Boolean;
|
||||||
function GetCurrentDirUTF8: String;
|
function GetCurrentDirUTF8: String;
|
||||||
function SetCurrentDirUTF8(const NewDir: String): Boolean;
|
function SetCurrentDirUTF8(const NewDir: String): Boolean;
|
||||||
@ -236,6 +236,13 @@ uses
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
{$I fileutil.inc}
|
{$I fileutil.inc}
|
||||||
|
{$IFDEF windows}
|
||||||
|
{$i winfileutil.inc}
|
||||||
|
{$ELSE}
|
||||||
|
{$i unixfileutil.inc}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
initialization
|
||||||
|
InitFileUtils;
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -21,44 +21,6 @@ var
|
|||||||
FNeedRTLAnsi: boolean = false;
|
FNeedRTLAnsi: boolean = false;
|
||||||
FNeedRTLAnsiValid: boolean = false;
|
FNeedRTLAnsiValid: boolean = false;
|
||||||
|
|
||||||
function NeedRTLAnsi: boolean;
|
|
||||||
{$IFDEF WinCE}
|
|
||||||
// CP_UTF8 is missing in the windows unit of the Windows CE RTL
|
|
||||||
const
|
|
||||||
CP_UTF8 = 65001;
|
|
||||||
{$ENDIF}
|
|
||||||
{$IFNDEF windows}
|
|
||||||
var
|
|
||||||
Lang: String;
|
|
||||||
i: LongInt;
|
|
||||||
Encoding: String;
|
|
||||||
{$ENDIF}
|
|
||||||
begin
|
|
||||||
if FNeedRTLAnsiValid then
|
|
||||||
exit(FNeedRTLAnsi);
|
|
||||||
{$IFDEF Windows}
|
|
||||||
FNeedRTLAnsi:=GetACP<>CP_UTF8;
|
|
||||||
{$ELSE}
|
|
||||||
FNeedRTLAnsi:=false;
|
|
||||||
Lang := SysUtils.GetEnvironmentVariable('LC_ALL');
|
|
||||||
if Length(lang) = 0 then
|
|
||||||
begin
|
|
||||||
Lang := SysUtils.GetEnvironmentVariable('LC_MESSAGES');
|
|
||||||
if Length(Lang) = 0 then
|
|
||||||
begin
|
|
||||||
Lang := SysUtils.GetEnvironmentVariable('LANG');
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
i:=System.Pos('.',Lang);
|
|
||||||
if (i>0) then begin
|
|
||||||
Encoding:=copy(Lang,i+1,length(Lang)-i);
|
|
||||||
FNeedRTLAnsi:=(SysUtils.CompareText(Encoding,'UTF-8')=0)
|
|
||||||
or (SysUtils.CompareText(Encoding,'UTF8')=0);
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
FNeedRTLAnsiValid:=true;
|
|
||||||
Result:=FNeedRTLAnsi;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure SetNeedRTLAnsi(NewValue: boolean);
|
procedure SetNeedRTLAnsi(NewValue: boolean);
|
||||||
begin
|
begin
|
||||||
@ -82,40 +44,6 @@ begin
|
|||||||
Result := s;
|
Result := s;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ConsoleToUTF8(const s: string): string;// converts UTF8 string to console encoding (used by Write, WriteLn)
|
|
||||||
{$ifdef MSWindows}
|
|
||||||
var
|
|
||||||
Dst: PChar;
|
|
||||||
{$endif}
|
|
||||||
begin
|
|
||||||
{$ifdef MSWindows}
|
|
||||||
Dst := AllocMem((Length(s) + 1) * SizeOf(Char));
|
|
||||||
if OemToChar(PChar(s), Dst) then
|
|
||||||
Result := StrPas(Dst)
|
|
||||||
else
|
|
||||||
Result := s;
|
|
||||||
FreeMem(Dst);
|
|
||||||
Result := SysToUTF8(Result);
|
|
||||||
{$else}
|
|
||||||
Result := SysToUTF8(S);
|
|
||||||
{$endif}
|
|
||||||
end;
|
|
||||||
|
|
||||||
function UTF8ToConsole(const s: string): string;
|
|
||||||
{$ifdef MSWindows}
|
|
||||||
var
|
|
||||||
Dst: PChar;
|
|
||||||
{$endif}
|
|
||||||
begin
|
|
||||||
Result := UTF8ToSys(s);
|
|
||||||
{$ifdef MSWindows}
|
|
||||||
Dst := AllocMem((Length(Result) + 1) * SizeOf(Char));
|
|
||||||
if CharToOEM(PChar(Result), Dst) then
|
|
||||||
Result := StrPas(Dst);
|
|
||||||
FreeMem(Dst);
|
|
||||||
{$endif}
|
|
||||||
end;
|
|
||||||
|
|
||||||
function SysToUTF8(const s: string): string;
|
function SysToUTF8(const s: string): string;
|
||||||
begin
|
begin
|
||||||
if NeedRTLAnsi and (not IsASCII(s)) then
|
if NeedRTLAnsi and (not IsASCII(s)) then
|
||||||
@ -142,22 +70,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
|
|
||||||
function FileExistsUTF8(const Filename: string): boolean;
|
|
||||||
begin
|
|
||||||
Result:=SysUtils.FileExists(UTF8ToSys(Filename));
|
|
||||||
end;
|
|
||||||
|
|
||||||
function FileAgeUTF8(const FileName: String): Longint;
|
function FileAgeUTF8(const FileName: String): Longint;
|
||||||
begin
|
begin
|
||||||
Result:=SysUtils.FileAge(UTF8ToSys(Filename));
|
Result:=SysUtils.FileAge(UTF8ToSys(Filename));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function DirectoryExistsUTF8(const Directory: string): Boolean;
|
|
||||||
begin
|
|
||||||
Result:=SysUtils.DirectoryExists(UTF8ToSys(Directory));
|
|
||||||
end;
|
|
||||||
|
|
||||||
function ExpandFileNameUTF8(const FileName: string): string;
|
function ExpandFileNameUTF8(const FileName: string): string;
|
||||||
begin
|
begin
|
||||||
Result:=SysToUTF8(SysUtils.ExpandFileName(UTF8ToSys(Filename)));
|
Result:=SysToUTF8(SysUtils.ExpandFileName(UTF8ToSys(Filename)));
|
||||||
@ -177,85 +94,11 @@ begin
|
|||||||
{$endif}
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function FindFirstUTF8(const Path: string; Attr: Longint; out Rslt: TSearchRec
|
|
||||||
): Longint;
|
|
||||||
begin
|
|
||||||
Result:=SysUtils.FindFirst(UTF8ToSys(Path),Attr,Rslt);
|
|
||||||
Rslt.Name:=SysToUTF8(Rslt.Name);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function FindNextUTF8(var Rslt: TSearchRec): Longint;
|
|
||||||
begin
|
|
||||||
Rslt.Name:=UTF8ToSys(Rslt.Name);
|
|
||||||
Result:=SysUtils.FindNext(Rslt);
|
|
||||||
Rslt.Name:=SysToUTF8(Rslt.Name);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure FindCloseUTF8(var F: TSearchrec);
|
|
||||||
begin
|
|
||||||
SysUtils.FindClose(F);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function FileSetDateUTF8(const FileName: String; Age: Longint): Longint;
|
function FileSetDateUTF8(const FileName: String; Age: Longint): Longint;
|
||||||
begin
|
begin
|
||||||
Result:=SysUtils.FileSetDate(UTF8ToSys(Filename),Age);
|
Result:=SysUtils.FileSetDate(UTF8ToSys(Filename),Age);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function FileGetAttrUTF8(const FileName: String): Longint;
|
|
||||||
begin
|
|
||||||
Result:=SysUtils.FileGetAttr(UTF8ToSys(Filename));
|
|
||||||
end;
|
|
||||||
|
|
||||||
function FileSetAttrUTF8(const Filename: String; Attr: longint): Longint;
|
|
||||||
begin
|
|
||||||
Result:=SysUtils.FileSetAttr(UTF8ToSys(Filename),Attr);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function DeleteFileUTF8(const FileName: String): Boolean;
|
|
||||||
begin
|
|
||||||
Result:=SysUtils.DeleteFile(UTF8ToSys(Filename));
|
|
||||||
end;
|
|
||||||
|
|
||||||
function RenameFileUTF8(const OldName, NewName: String): Boolean;
|
|
||||||
begin
|
|
||||||
Result:=SysUtils.RenameFile(UTF8ToSys(OldName),UTF8ToSys(NewName));
|
|
||||||
end;
|
|
||||||
|
|
||||||
function FileSearchUTF8(const Name, DirList: String): String;
|
|
||||||
begin
|
|
||||||
Result:=SysToUTF8(SysUtils.FileSearch(UTF8ToSys(Name),UTF8ToSys(DirList)));
|
|
||||||
end;
|
|
||||||
|
|
||||||
function FileIsReadOnlyUTF8(const FileName: String): Boolean;
|
|
||||||
begin
|
|
||||||
Result:=SysUtils.FileIsReadOnly(UTF8ToSys(Filename));
|
|
||||||
end;
|
|
||||||
|
|
||||||
function GetCurrentDirUTF8: String;
|
|
||||||
begin
|
|
||||||
Result:=SysToUTF8(SysUtils.GetCurrentDir);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function SetCurrentDirUTF8(const NewDir: String): Boolean;
|
|
||||||
begin
|
|
||||||
Result:=SysUtils.SetCurrentDir(UTF8ToSys(NewDir));
|
|
||||||
end;
|
|
||||||
|
|
||||||
function CreateDirUTF8(const NewDir: String): Boolean;
|
|
||||||
begin
|
|
||||||
Result:=SysUtils.CreateDir(UTF8ToSys(NewDir));
|
|
||||||
end;
|
|
||||||
|
|
||||||
function RemoveDirUTF8(const Dir: String): Boolean;
|
|
||||||
begin
|
|
||||||
Result:=SysUtils.RemoveDir(UTF8ToSys(Dir));
|
|
||||||
end;
|
|
||||||
|
|
||||||
function ForceDirectoriesUTF8(const Dir: string): Boolean;
|
|
||||||
begin
|
|
||||||
Result:=SysUtils.ForceDirectories(UTF8ToSys(Dir));
|
|
||||||
end;
|
|
||||||
|
|
||||||
function ParamStrUTF8(Param: Integer): string;
|
function ParamStrUTF8(Param: Integer): string;
|
||||||
begin
|
begin
|
||||||
Result:=SysToUTF8(ObjPas.ParamStr(Param));
|
Result:=SysToUTF8(ObjPas.ParamStr(Param));
|
||||||
@ -419,20 +262,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
|
||||||
function FilenameIsAbsolute(const TheFilename: string):boolean;
|
|
||||||
------------------------------------------------------------------------------}
|
|
||||||
function FilenameIsAbsolute(const TheFilename: string):boolean;
|
|
||||||
begin
|
|
||||||
{$IFDEF WINDOWS}
|
|
||||||
// windows
|
|
||||||
Result:=FilenameIsWinAbsolute(TheFilename);
|
|
||||||
{$ELSE}
|
|
||||||
// unix
|
|
||||||
Result:=FilenameIsUnixAbsolute(TheFilename);
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
|
||||||
|
|
||||||
function FilenameIsWinAbsolute(const TheFilename: string): boolean;
|
function FilenameIsWinAbsolute(const TheFilename: string): boolean;
|
||||||
begin
|
begin
|
||||||
Result:=((length(TheFilename)>=2) and (TheFilename[1] in ['A'..'Z','a'..'z'])
|
Result:=((length(TheFilename)>=2) and (TheFilename[1] in ['A'..'Z','a'..'z'])
|
||||||
@ -769,271 +598,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
|
||||||
procedure CheckIfFileIsSymlink(const AFilename: string);
|
|
||||||
------------------------------------------------------------------------------}
|
|
||||||
procedure CheckIfFileIsSymlink(const AFilename: string);
|
|
||||||
{$IFNDEF WINDOWS}
|
|
||||||
var
|
|
||||||
AText: string;
|
|
||||||
{$ENDIF}
|
|
||||||
begin
|
|
||||||
// to get good error messages consider the OS
|
|
||||||
if not FileExistsUTF8(AFilename) then begin
|
|
||||||
raise Exception.Create('file "'+AFilename+'" does not exist');
|
|
||||||
end;
|
|
||||||
{$IFDEF WINDOWS}
|
|
||||||
raise Exception.Create('"'+AFilename+'" is not symlink');
|
|
||||||
{$ELSE}
|
|
||||||
if FpReadLink(AFilename)='' 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:=AText+' is not a symbolic link';
|
|
||||||
end;
|
|
||||||
raise Exception.Create(AText);
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
|
||||||
function FileIsSymlink(const AFilename: string): boolean;
|
|
||||||
------------------------------------------------------------------------------}
|
|
||||||
function FileIsSymlink(const AFilename: string): boolean;
|
|
||||||
{$IFDEF WINDOWS}
|
|
||||||
var
|
|
||||||
FileHandle: THandle;
|
|
||||||
FileInfo: TBYHANDLEFILEINFORMATION;
|
|
||||||
{$ENDIF}
|
|
||||||
begin
|
|
||||||
{$IFDEF WINDOWS}
|
|
||||||
FileHandle := FileOpen(UTF8ToSys(AFileName), fmOpenRead or fmShareDenyNone);
|
|
||||||
if FileHandle <> feInvalidHandle then
|
|
||||||
begin
|
|
||||||
GetFileInformationByHandle(HFile(FileHandle), FileInfo);
|
|
||||||
Result := FileInfo.nNumberOfLinks > 1;
|
|
||||||
FileClose(FileHandle);
|
|
||||||
end
|
|
||||||
else
|
|
||||||
Result := False;
|
|
||||||
{$ELSE}
|
|
||||||
Result := FpReadLink(AFilename) <> '';
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
|
||||||
function FileIsReadable(const AFilename: string): boolean;
|
|
||||||
------------------------------------------------------------------------------}
|
|
||||||
function FileIsReadable(const AFilename: string): boolean;
|
|
||||||
begin
|
|
||||||
{$IFDEF WINDOWS}
|
|
||||||
Result:=true;
|
|
||||||
{$ELSE}
|
|
||||||
Result:= BaseUnix.FpAccess(AFilename,BaseUnix.R_OK)=0;
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
|
||||||
FileIsWritable
|
|
||||||
------------------------------------------------------------------------------}
|
|
||||||
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 FileSize(const Filename: string): int64;
|
|
||||||
{$IFDEF Unix}
|
|
||||||
var
|
|
||||||
st: baseunix.stat;
|
|
||||||
begin
|
|
||||||
if not fpstat(pointer(Filename),st)>=0 then
|
|
||||||
exit(-1);
|
|
||||||
Result:=st.st_size;
|
|
||||||
end;
|
|
||||||
{$ELSE}
|
|
||||||
var
|
|
||||||
FindData: TWIN32FindDataW;
|
|
||||||
FindHandle: THandle;
|
|
||||||
Str: widestring;
|
|
||||||
begin
|
|
||||||
// Fix for the bug 14360:
|
|
||||||
// Don't assign the widestring to TSearchRec.name because it is of type
|
|
||||||
// string, which will generate a conversion to the system encoding
|
|
||||||
Str := UTF8Decode(Filename);
|
|
||||||
FindHandle:=Windows.FindFirstFileW(PWideChar(Str), FindData);
|
|
||||||
if FindHandle=Windows.Invalid_Handle_value then
|
|
||||||
begin
|
|
||||||
Result:=-1;
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
Result:=(int64(FindData.nFileSizeHigh) shl 32)+FindData.nFileSizeLow;
|
|
||||||
Windows.FindClose(FindHandle);
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
|
||||||
GetFileDescription
|
|
||||||
------------------------------------------------------------------------------}
|
|
||||||
function GetFileDescription(const AFilename: string): string;
|
|
||||||
{$IFDEF WINDOWS}
|
|
||||||
{$ELSE}
|
|
||||||
var
|
|
||||||
info: Stat;
|
|
||||||
// permissions
|
|
||||||
// user
|
|
||||||
// group
|
|
||||||
// size
|
|
||||||
// date
|
|
||||||
// time
|
|
||||||
mode: mode_t;
|
|
||||||
{$ENDIF}
|
|
||||||
begin
|
|
||||||
Result:='';
|
|
||||||
{$IFDEF WINDOWS}
|
|
||||||
|
|
||||||
{$ELSE}
|
|
||||||
if not (FpStat(AFilename,info)=0) then exit;
|
|
||||||
|
|
||||||
// permissions
|
|
||||||
// file type
|
|
||||||
mode:= info.st_mode;
|
|
||||||
if STAT_IFLNK and mode=STAT_IFLNK then
|
|
||||||
Result:=Result+'l'
|
|
||||||
else
|
|
||||||
if STAT_IFDIR and mode=STAT_IFDIR then
|
|
||||||
Result:=Result+'d'
|
|
||||||
else
|
|
||||||
if STAT_IFBLK and mode=STAT_IFBLK then
|
|
||||||
Result:=Result+'b'
|
|
||||||
else
|
|
||||||
if STAT_IFCHR and mode=STAT_IFCHR then
|
|
||||||
Result:=Result+'c'
|
|
||||||
else
|
|
||||||
Result:=Result+'-';
|
|
||||||
// user permissions
|
|
||||||
if STAT_IRUSR and mode=STAT_IRUsr then
|
|
||||||
Result:=Result+'r'
|
|
||||||
else
|
|
||||||
Result:=Result+'-';
|
|
||||||
if STAT_IWUsr and mode=STAT_IWUsr then
|
|
||||||
Result:=Result+'w'
|
|
||||||
else
|
|
||||||
Result:=Result+'-';
|
|
||||||
if STAT_IXUsr and mode=STAT_IXUsr then
|
|
||||||
Result:=Result+'x'
|
|
||||||
else
|
|
||||||
Result:=Result+'-';
|
|
||||||
// group permissions
|
|
||||||
if STAT_IRGRP and mode=STAT_IRGRP then
|
|
||||||
Result:=Result+'r'
|
|
||||||
else
|
|
||||||
Result:=Result+'-';
|
|
||||||
if STAT_IWGRP and mode=STAT_IWGRP then
|
|
||||||
Result:=Result+'w'
|
|
||||||
else
|
|
||||||
Result:=Result+'-';
|
|
||||||
if STAT_IXGRP and mode=STAT_IXGRP then
|
|
||||||
Result:=Result+'x'
|
|
||||||
else
|
|
||||||
Result:=Result+'-';
|
|
||||||
// other permissions
|
|
||||||
if STAT_IROTH and mode=STAT_IROTH then
|
|
||||||
Result:=Result+'r'
|
|
||||||
else
|
|
||||||
Result:=Result+'-';
|
|
||||||
if STAT_IWOTH and mode=STAT_IWOTH then
|
|
||||||
Result:=Result+'w'
|
|
||||||
else
|
|
||||||
Result:=Result+'-';
|
|
||||||
if STAT_IXOTH and mode=STAT_IXOTH then
|
|
||||||
Result:=Result+'x'
|
|
||||||
else
|
|
||||||
Result:=Result+'-';
|
|
||||||
|
|
||||||
|
|
||||||
// user name
|
|
||||||
//Result:=Result+' Owner: '+IntToStr(info.uid)+'.'+IntToStr(info.gid);
|
|
||||||
|
|
||||||
// size
|
|
||||||
Result:=Result+rsSize+IntToStr(info.st_size);
|
|
||||||
|
|
||||||
{$ENDIF}
|
|
||||||
// date + time
|
|
||||||
Result:=Result+rsModified;
|
|
||||||
try
|
|
||||||
Result:=Result+FormatDateTime('DD/MM/YYYY hh:mm',
|
|
||||||
FileDateToDateTime(FileAgeUTF8(AFilename)));
|
|
||||||
except
|
|
||||||
Result:=Result+'?';
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
|
||||||
function ReadAllLinks(const Filename: string;
|
|
||||||
ExceptionOnError: boolean): string;
|
|
||||||
------------------------------------------------------------------------------}
|
|
||||||
function ReadAllLinks(const Filename: string;
|
|
||||||
ExceptionOnError: boolean): string;
|
|
||||||
{$IFNDEF WINDOWS}
|
|
||||||
var
|
|
||||||
LinkFilename: string;
|
|
||||||
AText: string;
|
|
||||||
{$ENDIF}
|
|
||||||
begin
|
|
||||||
Result:=Filename;
|
|
||||||
{$IFDEF WINDOWS}
|
|
||||||
|
|
||||||
{$ELSE}
|
|
||||||
repeat
|
|
||||||
LinkFilename:=FpReadLink(Result);
|
|
||||||
if LinkFilename='' then begin
|
|
||||||
AText:='"'+Filename+'"';
|
|
||||||
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
|
|
||||||
// not a symbolic link, just a regular file
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
if (not ExceptionOnError) then begin
|
|
||||||
Result:='';
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
raise EFOpenError.Create(AText);
|
|
||||||
end else begin
|
|
||||||
if not FilenameIsAbsolute(LinkFilename) then
|
|
||||||
Result:=ExpandFileNameUTF8(ExtractFilePath(Result)+LinkFilename)
|
|
||||||
else
|
|
||||||
Result:=LinkFilename;
|
|
||||||
end;
|
|
||||||
until false;
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TryReadAllLinks(const Filename: string): string;
|
function TryReadAllLinks(const Filename: string): string;
|
||||||
begin
|
begin
|
||||||
Result:=ReadAllLinks(Filename,false);
|
Result:=ReadAllLinks(Filename,false);
|
||||||
@ -1062,63 +626,6 @@ begin
|
|||||||
Result:=copy(AFilename,StartPos,ExtPos-StartPos);
|
Result:=copy(AFilename,StartPos,ExtPos-StartPos);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
|
||||||
function FileIsExecutable(const AFilename: string): boolean;
|
|
||||||
------------------------------------------------------------------------------}
|
|
||||||
function FileIsExecutable(const AFilename: string): boolean;
|
|
||||||
{$IFNDEF WINDOWS}
|
|
||||||
var
|
|
||||||
Info : Stat;
|
|
||||||
{$ENDIF}
|
|
||||||
begin
|
|
||||||
{$IFDEF WINDOWS}
|
|
||||||
Result:=FileExistsUTF8(AFilename);
|
|
||||||
{$ELSE}
|
|
||||||
// first check AFilename is not a directory and then check if executable
|
|
||||||
Result:= (FpStat(AFilename,info)<>-1) and FPS_ISREG(info.st_mode) and
|
|
||||||
(BaseUnix.FpAccess(AFilename,BaseUnix.X_OK)=0);
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
|
||||||
procedure CheckIfFileIsExecutable(const AFilename: string);
|
|
||||||
------------------------------------------------------------------------------}
|
|
||||||
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.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;
|
|
||||||
{$IFNDEF WINDOWS}
|
|
||||||
if not FileIsExecutable(AFilename) 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:=AText+' is not executable';
|
|
||||||
end;
|
|
||||||
raise Exception.Create(AText);
|
|
||||||
end;
|
|
||||||
{$ENDIF}
|
|
||||||
end;
|
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
{------------------------------------------------------------------------------
|
||||||
function ForceDirectory(DirectoryName: string): boolean;
|
function ForceDirectory(DirectoryName: string): boolean;
|
||||||
@ -1940,4 +1447,95 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
function FileSearchUTF8(const Name, DirList: String): String;
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function FileSearchUTF8(const Name, DirList: String; ImplicitCurrentDir : Boolean = True): String;
|
||||||
|
Var
|
||||||
|
I : longint;
|
||||||
|
Temp : String;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Result:=Name;
|
||||||
|
temp:=SetDirSeparators(DirList);
|
||||||
|
// Start with checking the file in the current directory
|
||||||
|
If ImplicitCurrentDir and (Result <> '') and FileExistsUTF8(Result) Then
|
||||||
|
exit;
|
||||||
|
while True do begin
|
||||||
|
If Temp = '' then
|
||||||
|
Break; // No more directories to search - fail
|
||||||
|
I:=pos(PathSeparator,Temp);
|
||||||
|
If I<>0 then
|
||||||
|
begin
|
||||||
|
Result:=Copy (Temp,1,i-1);
|
||||||
|
system.Delete(Temp,1,I);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
Result:=Temp;
|
||||||
|
Temp:='';
|
||||||
|
end;
|
||||||
|
If Result<>'' then
|
||||||
|
Result:=IncludeTrailingPathDelimiter(Result)+name;
|
||||||
|
If (Result <> '') and FileExistsUTF8(Result) Then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
Result:='';
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
function ForceDirectoriesUTF8(const Dir: string): Boolean;
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function ForceDirectoriesUTF8(const Dir: string): Boolean;
|
||||||
|
|
||||||
|
var
|
||||||
|
E: EInOutError;
|
||||||
|
ADrv : String;
|
||||||
|
|
||||||
|
function DoForceDirectories(Const Dir: string): Boolean;
|
||||||
|
var
|
||||||
|
ADir : String;
|
||||||
|
APath: String;
|
||||||
|
begin
|
||||||
|
Result:=True;
|
||||||
|
ADir:=ExcludeTrailingPathDelimiter(Dir);
|
||||||
|
if (ADir='') then Exit;
|
||||||
|
if Not DirectoryExistsUTF8(ADir) then
|
||||||
|
begin
|
||||||
|
APath := ExtractFilePath(ADir);
|
||||||
|
//this can happen on Windows if user specifies Dir like \user\name/test/
|
||||||
|
//and would, if not checked for, cause an infinite recusrsion and a stack overflow
|
||||||
|
if (APath = ADir) then Result := False
|
||||||
|
else Result:=DoForceDirectories(APath);
|
||||||
|
If Result then
|
||||||
|
Result := CreateDirUTF8(ADir);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function IsUncDrive(const Drv: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result := (Length(Drv) > 2) and (Drv[1] = PathDelim) and (Drv[2] = PathDelim);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
ADrv := ExtractFileDrive(Dir);
|
||||||
|
if (ADrv<>'') and (not DirectoryExistsUTF8(ADrv))
|
||||||
|
{$IFNDEF FORCEDIR_NO_UNC_SUPPORT} and (not IsUncDrive(ADrv)){$ENDIF} then Exit;
|
||||||
|
if Dir='' then
|
||||||
|
begin
|
||||||
|
E:=EInOutError.Create(SCannotCreateEmptyDir);
|
||||||
|
E.ErrorCode:=3;
|
||||||
|
Raise E;
|
||||||
|
end;
|
||||||
|
Result := DoForceDirectories(SetDirSeparators(Dir));
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
function ForceDirectoriesUTF8(const Dir: string): Boolean;
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function FileIsReadOnlyUTF8(const FileName: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=FileGetAttrUTF8(FileName) and faReadOnly > 0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
374
lcl/include/unixfileutil.inc
Normal file
374
lcl/include/unixfileutil.inc
Normal file
@ -0,0 +1,374 @@
|
|||||||
|
{------------------------------------------------------------------------------
|
||||||
|
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('file "'+AFilename+'" does not exist');
|
||||||
|
end;
|
||||||
|
if DirPathExists(AFilename) then begin
|
||||||
|
raise Exception.Create('file "'+AFilename+'" is a directory and not an executable');
|
||||||
|
end;
|
||||||
|
if not FileIsExecutable(AFilename) 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:=AText+' is not executable';
|
||||||
|
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('file "'+AFilename+'" does not exist');
|
||||||
|
end;
|
||||||
|
if FpReadLink(AFilename)='' 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:=AText+' is not a symbolic link';
|
||||||
|
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)<>-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;
|
||||||
|
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
FileSize
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function FileSize(const Filename: string): int64;
|
||||||
|
var
|
||||||
|
st: baseunix.stat;
|
||||||
|
begin
|
||||||
|
if not fpstat(pointer(Filename),st)>=0 then
|
||||||
|
exit(-1);
|
||||||
|
Result:=st.st_size;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
GetFileDescription
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function GetFileDescription(const AFilename: string): string;
|
||||||
|
var
|
||||||
|
info: Stat;
|
||||||
|
// permissions
|
||||||
|
// user
|
||||||
|
// group
|
||||||
|
// size
|
||||||
|
// date
|
||||||
|
// time
|
||||||
|
mode: mode_t;
|
||||||
|
begin
|
||||||
|
Result:='';
|
||||||
|
if not (FpStat(AFilename,info)=0) then exit;
|
||||||
|
|
||||||
|
// permissions
|
||||||
|
// file type
|
||||||
|
mode:= info.st_mode;
|
||||||
|
if STAT_IFLNK and mode=STAT_IFLNK then
|
||||||
|
Result:=Result+'l'
|
||||||
|
else
|
||||||
|
if STAT_IFDIR and mode=STAT_IFDIR then
|
||||||
|
Result:=Result+'d'
|
||||||
|
else
|
||||||
|
if STAT_IFBLK and mode=STAT_IFBLK then
|
||||||
|
Result:=Result+'b'
|
||||||
|
else
|
||||||
|
if STAT_IFCHR and mode=STAT_IFCHR then
|
||||||
|
Result:=Result+'c'
|
||||||
|
else
|
||||||
|
Result:=Result+'-';
|
||||||
|
// user permissions
|
||||||
|
if STAT_IRUSR and mode=STAT_IRUsr then
|
||||||
|
Result:=Result+'r'
|
||||||
|
else
|
||||||
|
Result:=Result+'-';
|
||||||
|
if STAT_IWUsr and mode=STAT_IWUsr then
|
||||||
|
Result:=Result+'w'
|
||||||
|
else
|
||||||
|
Result:=Result+'-';
|
||||||
|
if STAT_IXUsr and mode=STAT_IXUsr then
|
||||||
|
Result:=Result+'x'
|
||||||
|
else
|
||||||
|
Result:=Result+'-';
|
||||||
|
// group permissions
|
||||||
|
if STAT_IRGRP and mode=STAT_IRGRP then
|
||||||
|
Result:=Result+'r'
|
||||||
|
else
|
||||||
|
Result:=Result+'-';
|
||||||
|
if STAT_IWGRP and mode=STAT_IWGRP then
|
||||||
|
Result:=Result+'w'
|
||||||
|
else
|
||||||
|
Result:=Result+'-';
|
||||||
|
if STAT_IXGRP and mode=STAT_IXGRP then
|
||||||
|
Result:=Result+'x'
|
||||||
|
else
|
||||||
|
Result:=Result+'-';
|
||||||
|
// other permissions
|
||||||
|
if STAT_IROTH and mode=STAT_IROTH then
|
||||||
|
Result:=Result+'r'
|
||||||
|
else
|
||||||
|
Result:=Result+'-';
|
||||||
|
if STAT_IWOTH and mode=STAT_IWOTH then
|
||||||
|
Result:=Result+'w'
|
||||||
|
else
|
||||||
|
Result:=Result+'-';
|
||||||
|
if STAT_IXOTH and mode=STAT_IXOTH then
|
||||||
|
Result:=Result+'x'
|
||||||
|
else
|
||||||
|
Result:=Result+'-';
|
||||||
|
|
||||||
|
|
||||||
|
// user name
|
||||||
|
//Result:=Result+' Owner: '+IntToStr(info.uid)+'.'+IntToStr(info.gid);
|
||||||
|
|
||||||
|
// size
|
||||||
|
Result:=Result+rsSize+IntToStr(info.st_size);
|
||||||
|
|
||||||
|
// date + time
|
||||||
|
Result:=Result+rsModified;
|
||||||
|
try
|
||||||
|
Result:=Result+FormatDateTime('DD/MM/YYYY hh:mm',
|
||||||
|
FileDateToDateTime(FileAgeUTF8(AFilename)));
|
||||||
|
except
|
||||||
|
Result:=Result+'?';
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
function ReadAllLinks(const Filename: string;
|
||||||
|
ExceptionOnError: boolean): string;
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function ReadAllLinks(const Filename: string;
|
||||||
|
ExceptionOnError: boolean): string;
|
||||||
|
var
|
||||||
|
LinkFilename: string;
|
||||||
|
AText: string;
|
||||||
|
begin
|
||||||
|
Result:=Filename;
|
||||||
|
repeat
|
||||||
|
LinkFilename:=FpReadLink(Result);
|
||||||
|
if LinkFilename='' then begin
|
||||||
|
AText:='"'+Filename+'"';
|
||||||
|
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
|
||||||
|
// not a symbolic link, just a regular file
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
if (not ExceptionOnError) then begin
|
||||||
|
Result:='';
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
raise EFOpenError.Create(AText);
|
||||||
|
end else begin
|
||||||
|
if not FilenameIsAbsolute(LinkFilename) then
|
||||||
|
Result:=ExpandFileNameUTF8(ExtractFilePath(Result)+LinkFilename)
|
||||||
|
else
|
||||||
|
Result:=LinkFilename;
|
||||||
|
end;
|
||||||
|
until false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
function FilenameIsAbsolute(const TheFilename: string):boolean;
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function FilenameIsAbsolute(const TheFilename: string):boolean;
|
||||||
|
begin
|
||||||
|
Result:=FilenameIsUnixAbsolute(TheFilename);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function NeedRTLAnsi: boolean;
|
||||||
|
var
|
||||||
|
Lang: String;
|
||||||
|
i: LongInt;
|
||||||
|
Encoding: String;
|
||||||
|
begin
|
||||||
|
if FNeedRTLAnsiValid then
|
||||||
|
exit(FNeedRTLAnsi);
|
||||||
|
FNeedRTLAnsi:=false;
|
||||||
|
Lang := SysUtils.GetEnvironmentVariable('LC_ALL');
|
||||||
|
if Length(lang) = 0 then
|
||||||
|
begin
|
||||||
|
Lang := SysUtils.GetEnvironmentVariable('LC_MESSAGES');
|
||||||
|
if Length(Lang) = 0 then
|
||||||
|
begin
|
||||||
|
Lang := SysUtils.GetEnvironmentVariable('LANG');
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
i:=System.Pos('.',Lang);
|
||||||
|
if (i>0) then begin
|
||||||
|
Encoding:=copy(Lang,i+1,length(Lang)-i);
|
||||||
|
FNeedRTLAnsi:=(SysUtils.CompareText(Encoding,'UTF-8')=0)
|
||||||
|
or (SysUtils.CompareText(Encoding,'UTF8')=0);
|
||||||
|
end;
|
||||||
|
FNeedRTLAnsiValid:=true;
|
||||||
|
Result:=FNeedRTLAnsi;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ConsoleToUTF8(const s: string): string;// converts UTF8 string to console encoding (used by Write, WriteLn)
|
||||||
|
begin
|
||||||
|
Result := SysToUTF8(S);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function UTF8ToConsole(const s: string): string;
|
||||||
|
begin
|
||||||
|
Result := UTF8ToSys(s);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function FileExistsUTF8(const Filename: string): boolean;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.FileExists(UTF8ToSys(Filename));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FindFirstUTF8(const Path: string; Attr: Longint; out Rslt: TSearchRec
|
||||||
|
): Longint;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.FindFirst(UTF8ToSys(Path),Attr,Rslt);
|
||||||
|
Rslt.Name:=SysToUTF8(Rslt.Name);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FindNextUTF8(var Rslt: TSearchRec): Longint;
|
||||||
|
begin
|
||||||
|
Rslt.Name:=UTF8ToSys(Rslt.Name);
|
||||||
|
Result:=SysUtils.FindNext(Rslt);
|
||||||
|
Rslt.Name:=SysToUTF8(Rslt.Name);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure FindCloseUTF8(var F: TSearchrec);
|
||||||
|
begin
|
||||||
|
SysUtils.FindClose(F);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FileGetAttrUTF8(const FileName: String): Longint;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.FileGetAttr(UTF8ToSys(Filename));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FileSetAttrUTF8(const Filename: String; Attr: longint): Longint;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.FileSetAttr(UTF8ToSys(Filename),Attr);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DeleteFileUTF8(const FileName: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.DeleteFile(UTF8ToSys(Filename));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RenameFileUTF8(const OldName, NewName: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.RenameFile(UTF8ToSys(OldName),UTF8ToSys(NewName));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function GetCurrentDirUTF8: String;
|
||||||
|
begin
|
||||||
|
Result:=SysToUTF8(SysUtils.GetCurrentDir);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SetCurrentDirUTF8(const NewDir: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.SetCurrentDir(UTF8ToSys(NewDir));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function CreateDirUTF8(const NewDir: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.CreateDir(UTF8ToSys(NewDir));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RemoveDirUTF8(const Dir: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.RemoveDir(UTF8ToSys(Dir));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DirectoryExistsUTF8(const Directory: string): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.DirectoryExists(UTF8ToSys(Directory));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InitFileUtils;
|
||||||
|
begin
|
||||||
|
end;
|
||||||
|
|
532
lcl/include/winfileutil.inc
Normal file
532
lcl/include/winfileutil.inc
Normal file
@ -0,0 +1,532 @@
|
|||||||
|
{------------------------------------------------------------------------------
|
||||||
|
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;
|
||||||
|
var
|
||||||
|
FileHandle: THandle;
|
||||||
|
FileInfo: TBYHANDLEFILEINFORMATION;
|
||||||
|
begin
|
||||||
|
FileHandle := FileOpen(UTF8ToSys(AFileName), fmOpenRead or fmShareDenyNone);
|
||||||
|
if FileHandle <> feInvalidHandle then
|
||||||
|
begin
|
||||||
|
GetFileInformationByHandle(HFile(FileHandle), FileInfo);
|
||||||
|
Result := FileInfo.nNumberOfLinks > 1;
|
||||||
|
FileClose(FileHandle);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Result := False;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
GetFileDescription
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function GetFileDescription(const AFilename: string): string;
|
||||||
|
begin
|
||||||
|
// date + time
|
||||||
|
Result:=rsModified;
|
||||||
|
try
|
||||||
|
Result:=Result+FormatDateTime('DD/MM/YYYY hh:mm',
|
||||||
|
FileDateToDateTime(FileAgeUTF8(AFilename)));
|
||||||
|
except
|
||||||
|
Result:=Result+'?';
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
function ReadAllLinks(const Filename: string;
|
||||||
|
ExceptionOnError: boolean): string;
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function ReadAllLinks(const Filename: string;
|
||||||
|
ExceptionOnError: boolean): string;
|
||||||
|
begin
|
||||||
|
Result:=Filename;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
function FilenameIsAbsolute(const TheFilename: string):boolean;
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function FilenameIsAbsolute(const TheFilename: string):boolean;
|
||||||
|
begin
|
||||||
|
Result:=FilenameIsWinAbsolute(TheFilename);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function NeedRTLAnsi: boolean;
|
||||||
|
{$IFDEF WinCE}
|
||||||
|
// CP_UTF8 is missing in the windows unit of the Windows CE RTL
|
||||||
|
const
|
||||||
|
CP_UTF8 = 65001;
|
||||||
|
{$ENDIF}
|
||||||
|
begin
|
||||||
|
if FNeedRTLAnsiValid then
|
||||||
|
exit(FNeedRTLAnsi);
|
||||||
|
FNeedRTLAnsi:=GetACP<>CP_UTF8;
|
||||||
|
FNeedRTLAnsiValid:=true;
|
||||||
|
Result:=FNeedRTLAnsi;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ConsoleToUTF8(const s: string): string;// converts UTF8 string to console encoding (used by Write, WriteLn)
|
||||||
|
var
|
||||||
|
Dst: PChar;
|
||||||
|
begin
|
||||||
|
Dst := AllocMem((Length(s) + 1) * SizeOf(Char));
|
||||||
|
if OemToChar(PChar(s), Dst) then
|
||||||
|
Result := StrPas(Dst)
|
||||||
|
else
|
||||||
|
Result := s;
|
||||||
|
FreeMem(Dst);
|
||||||
|
Result := SysToUTF8(Result);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function UTF8ToConsole(const s: string): string;
|
||||||
|
var
|
||||||
|
Dst: PChar;
|
||||||
|
begin
|
||||||
|
Result := UTF8ToSys(s);
|
||||||
|
Dst := AllocMem((Length(Result) + 1) * SizeOf(Char));
|
||||||
|
if CharToOEM(PChar(Result), Dst) then
|
||||||
|
Result := StrPas(Dst);
|
||||||
|
FreeMem(Dst);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
FileSize
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function FileSizeAnsi(const Filename: string): int64;
|
||||||
|
var
|
||||||
|
FindData: TWIN32FindDataA;
|
||||||
|
FindHandle: THandle;
|
||||||
|
Str: AnsiString;
|
||||||
|
begin
|
||||||
|
// Fix for the bug 14360:
|
||||||
|
// Don't assign the widestring to TSearchRec.name because it is of type
|
||||||
|
// string, which will generate a conversion to the system encoding
|
||||||
|
Str := UTF8Decode(Filename);
|
||||||
|
FindHandle:=Windows.FindFirstFileA(PAnsiChar(Str), FindData);
|
||||||
|
if FindHandle=Windows.Invalid_Handle_value then
|
||||||
|
begin
|
||||||
|
Result:=-1;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
Result:=(int64(FindData.nFileSizeHigh) shl 32)+FindData.nFileSizeLow;
|
||||||
|
Windows.FindClose(FindHandle);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FileSizeWide(const Filename: string): int64;
|
||||||
|
var
|
||||||
|
FindData: TWIN32FindDataW;
|
||||||
|
FindHandle: THandle;
|
||||||
|
Str: WideString;
|
||||||
|
begin
|
||||||
|
// Fix for the bug 14360:
|
||||||
|
// Don't assign the widestring to TSearchRec.name because it is of type
|
||||||
|
// string, which will generate a conversion to the system encoding
|
||||||
|
Str := UTF8Decode(Filename);
|
||||||
|
FindHandle:=Windows.FindFirstFileW(PWideChar(Str), FindData);
|
||||||
|
if FindHandle=Windows.Invalid_Handle_value then
|
||||||
|
begin
|
||||||
|
Result:=-1;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
Result:=(int64(FindData.nFileSizeHigh) shl 32)+FindData.nFileSizeLow;
|
||||||
|
Windows.FindClose(FindHandle);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
FindFirstUTF8
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function FindFirstAnsi(const Path: string; Attr: Longint; out Rslt: TSearchRec): Longint;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.FindFirst(UTF8ToSys(Path),Attr,Rslt);
|
||||||
|
Rslt.Name:=SysToUTF8(Rslt.Name);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function WinToDosTime (Var Wtime : TFileTime;var DTime:longint):longbool;
|
||||||
|
var
|
||||||
|
lft : TFileTime;
|
||||||
|
begin
|
||||||
|
WinToDosTime:=FileTimeToLocalFileTime(WTime,lft) and
|
||||||
|
FileTimeToDosDateTime(lft,Longrec(Dtime).Hi,LongRec(DTIME).lo);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FindMatch(var f: TSearchRec) : Longint;
|
||||||
|
begin
|
||||||
|
{ Find file with correct attribute }
|
||||||
|
While (F.FindData.dwFileAttributes and cardinal(F.ExcludeAttr))<>0 do
|
||||||
|
begin
|
||||||
|
if FindNextUTF8(F)<>0 then
|
||||||
|
begin
|
||||||
|
Result:=GetLastError;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{ Convert some attributes back }
|
||||||
|
WinToDosTime(F.FindData.ftLastWriteTime,F.Time);
|
||||||
|
f.size:=F.FindData.NFileSizeLow+(qword(maxdword)+1)*F.FindData.NFileSizeHigh;
|
||||||
|
f.attr:=F.FindData.dwFileAttributes;
|
||||||
|
f.Name:=StrPas(@F.FindData.cFileName[0]);
|
||||||
|
Result:=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure FindWideToAnsi(const wide: TWIN32FINDDATAW; var ansi: TWIN32FINDDATA);
|
||||||
|
var
|
||||||
|
ws : WideString;
|
||||||
|
an : AnsiString;
|
||||||
|
begin
|
||||||
|
SetLength(ws, length(wide.cAlternateFileName));
|
||||||
|
Move(wide.cAlternateFileName[0], ws[1], length(ws)*2);
|
||||||
|
an:=ws; // no need to utf8 for cAlternateFileName (it's always ansi encoded)
|
||||||
|
Move(an[1], ansi.cAlternateFileName, sizeof(ansi.cAlternateFileName));
|
||||||
|
|
||||||
|
ws:=PWideChar(@wide.cFileName[0]);
|
||||||
|
an:=UTF8Encode(ws);
|
||||||
|
ansi.cFileName:=an;
|
||||||
|
if length(an)<length(ansi.cFileName) then ansi.cFileName[ length(an)]:=#0;
|
||||||
|
|
||||||
|
with ansi do begin
|
||||||
|
dwFileAttributes := wide.dwFileAttributes;
|
||||||
|
ftCreationTime := wide.ftCreationTime;
|
||||||
|
ftLastAccessTime := wide.ftLastAccessTime;
|
||||||
|
ftLastWriteTime := wide.ftLastWriteTime;
|
||||||
|
nFileSizeHigh := wide.nFileSizeHigh;
|
||||||
|
nFileSizeLow := wide.nFileSizeLow;
|
||||||
|
dwReserved0 := wide.dwReserved0;
|
||||||
|
dwReserved1 := wide.dwReserved1;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FindFirstWide(const Path: string; Attr: Longint; out Rslt: TSearchRec): Longint;
|
||||||
|
var
|
||||||
|
find : TWIN32FINDDATAW;
|
||||||
|
begin
|
||||||
|
Rslt.Name:=Path;
|
||||||
|
Rslt.Attr:=attr;
|
||||||
|
Rslt.ExcludeAttr:=(not Attr) and ($1e);
|
||||||
|
{ $1e = faHidden or faSysFile or faVolumeID or faDirectory }
|
||||||
|
{ FindFirstFile is a Win32 Call }
|
||||||
|
Rslt.FindHandle:=Windows.FindFirstFileW( PWideChar(UTF8Decode(Path)),find);
|
||||||
|
If Rslt.FindHandle=Invalid_Handle_value then
|
||||||
|
begin
|
||||||
|
Result:=GetLastError;
|
||||||
|
Exit;
|
||||||
|
end;
|
||||||
|
{ Find file with correct attribute }
|
||||||
|
FindWideToAnsi(find, Rslt.FindData);
|
||||||
|
Result:=FindMatch(Rslt);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
FindNextUTF8
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function FindNextAnsi(var Rslt: TSearchRec): Longint;
|
||||||
|
begin
|
||||||
|
Rslt.Name:=UTF8ToSys(Rslt.Name);
|
||||||
|
Result:=SysUtils.FindNext(Rslt);
|
||||||
|
Rslt.Name:=SysToUTF8(Rslt.Name);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FindNextWide(var Rslt: TSearchRec): Longint;
|
||||||
|
var
|
||||||
|
wide : TWIN32FINDDATAW;
|
||||||
|
begin
|
||||||
|
if FindNextFileW(Rslt.FindHandle, wide) then begin
|
||||||
|
FindWideToAnsi(wide, Rslt.FindData);
|
||||||
|
Result := FindMatch(Rslt);
|
||||||
|
end else
|
||||||
|
Result := GetLastError;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
FindNextUTF8
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
procedure FindCloseAnsi(var F: TSearchrec);
|
||||||
|
begin
|
||||||
|
SysUtils.FindClose(F);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure FindCloseWide(var F: TSearchrec);
|
||||||
|
begin
|
||||||
|
Windows.FindClose(f.FindHandle);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
FileGetAttrUTF8
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function FileGetAttrAnsi(const FileName: String): Longint;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.FileGetAttr(UTF8ToSys(Filename));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FileGetAttrWide(const FileName: String): Longint;
|
||||||
|
begin
|
||||||
|
Result:=Windows.GetFileAttributesW(PWideChar(UTF8Decode(FileName)));
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
FileSetAttrUTF8
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function FileSetAttrAnsi(const Filename: String; Attr: longint): Longint;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.FileSetAttr(UTF8ToSys(Filename),Attr);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FileSetAttrWide(const Filename: String; Attr: longint): Longint;
|
||||||
|
begin
|
||||||
|
if Windows.SetFileAttributesW(PWideChar(UTF8Decode(FileName)), Attr) then
|
||||||
|
Result:=0
|
||||||
|
else
|
||||||
|
Result := Windows.GetLastError;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
DeleteFileUTF8
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function DeleteFileAnsi(const FileName: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.DeleteFile(UTF8ToSys(Filename));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DeleteFileWide(const FileName: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=Windows.DeleteFileW(PWideChar(UTF8Decode(FileName)));
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
RenameFileUTF8
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function RenameFileAnsi(const OldName, NewName: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.RenameFile(UTF8ToSys(OldName),UTF8ToSys(NewName));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RenameFileWide(const OldName, NewName: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=MoveFileW(PWideChar(UTF8Decode(OldName)), PWideChar(UTF8Decode(NewName)));
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
GetCurrentDirUTF8
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function GetCurrentDirAnsi: String;
|
||||||
|
begin
|
||||||
|
Result:=SysToUTF8(SysUtils.GetCurrentDir);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetCurrentDirWide: String;
|
||||||
|
var
|
||||||
|
w : WideString;
|
||||||
|
res : Integer;
|
||||||
|
begin
|
||||||
|
res:=GetCurrentDirectoryW(0, nil);
|
||||||
|
SetLength(w, res);
|
||||||
|
res:=Windows.GetCurrentDirectoryW(res, @w[1]);
|
||||||
|
SetLength(w, res);
|
||||||
|
Result:=UTF8Encode(w);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
SetCurrentDirUTF8
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function SetCurrentDirAnsi(const NewDir: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.SetCurrentDir(UTF8ToSys(NewDir));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SetCurrentDirWide(const NewDir: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=Windows.SetCurrentDirectoryW(PWidechar(UTF8Decode(NewDir)));
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
CreateDirUTF8
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function CreateDirAnsi(const NewDir: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.CreateDir(UTF8ToSys(NewDir));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function CreateDirWide(const NewDir: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=Windows.CreateDirectoryW(PWideChar(UTF8Decode(NewDir)), nil);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{------------------------------------------------------------------------------
|
||||||
|
RemoveDirUTF8
|
||||||
|
------------------------------------------------------------------------------}
|
||||||
|
function RemoveDirAnsi(const Dir: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=SysUtils.RemoveDir(UTF8ToSys(Dir));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RemoveDirWide(const Dir: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=Windows.RemoveDirectoryW(PWideChar(UTF8Decode(Dir)));
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
FileSize_ : function (const Filename: string): int64 = @FileSizeAnsi;
|
||||||
|
FindFirst_ : function (const Path: string; Attr: Longint;
|
||||||
|
out Rslt: TSearchRec): Longint = @FindFirstAnsi;
|
||||||
|
FindNext_ : function (var Rslt: TSearchRec): Longint = @FindNextAnsi;
|
||||||
|
FindClose_ : procedure (var F: TSearchrec) = @FindCloseAnsi;
|
||||||
|
FileGetAttr_ : function (const FileName: String): Longint = @FileGetAttrAnsi;
|
||||||
|
FileSetAttr_ : function (const Filename: String; Attr: longint): Longint = @FileSetAttrAnsi;
|
||||||
|
DeleteFile_ : function (const FileName: String): Boolean = @DeleteFileAnsi;
|
||||||
|
RenameFile_ : function (const OldName, NewName: String): Boolean = @RenameFileAnsi;
|
||||||
|
GetCurrentDir_ : function : String = @GetCurrentDirAnsi;
|
||||||
|
SetCurrentDir_ : function (const NewDir: String): Boolean = @SetCurrentDirAnsi;
|
||||||
|
CreateDir_ : function (const NewDir: String): Boolean = @CreateDirAnsi;
|
||||||
|
RemoveDir_ : function (const Dir: String): Boolean = @RemoveDirAnsi;
|
||||||
|
|
||||||
|
function FileSize(const Filename: string): int64;
|
||||||
|
begin
|
||||||
|
Result:=FileSize_(FileName);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FindFirstUTF8(const Path: string; Attr: Longint; out Rslt: TSearchRec): Longint;
|
||||||
|
begin
|
||||||
|
Result:=FindFirst_(Path, Attr, Rslt);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FindNextUTF8(var Rslt: TSearchRec): Longint;
|
||||||
|
begin
|
||||||
|
Result:=FindNext_(Rslt);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure FindCloseUTF8(var F: TSearchrec);
|
||||||
|
begin
|
||||||
|
FindClose_(F);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DeleteFileUTF8(const FileName: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=DeleteFile_(FileName);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RenameFileUTF8(const OldName, NewName: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=RenameFile_(OldName, NewName);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetCurrentDirUTF8: String;
|
||||||
|
begin
|
||||||
|
Result:=GetCurrentDir_();
|
||||||
|
end;
|
||||||
|
|
||||||
|
function SetCurrentDirUTF8(const NewDir: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=SetCurrentDir_(NewDir);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function CreateDirUTF8(const NewDir: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=CreateDir_(NewDir);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RemoveDirUTF8(const Dir: String): Boolean;
|
||||||
|
begin
|
||||||
|
Result:=RemoveDir_(Dir);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FileGetAttrUTF8(const FileName: String): Longint;
|
||||||
|
begin
|
||||||
|
Result:=FileGetAttr_(FileName);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FileSetAttrUTF8(const Filename: String; Attr: longint): Longint;
|
||||||
|
begin
|
||||||
|
Result:=FileSetAttr_(Filename, Attr);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function FileExistsUTF8(const Filename: string): boolean;
|
||||||
|
var
|
||||||
|
Attr:Dword;
|
||||||
|
begin
|
||||||
|
Attr:=FileGetAttrUTF8(FileName);
|
||||||
|
if Attr <> $ffffffff then
|
||||||
|
Result:= (Attr and FILE_ATTRIBUTE_DIRECTORY) = 0
|
||||||
|
else
|
||||||
|
Result:=False;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DirectoryExistsUTF8(const Directory: string): boolean;
|
||||||
|
var
|
||||||
|
Attr:Dword;
|
||||||
|
begin
|
||||||
|
Attr:=FileGetAttrUTF8(Directory);
|
||||||
|
if Attr <> $ffffffff then
|
||||||
|
Result:= (Attr and FILE_ATTRIBUTE_DIRECTORY) > 0
|
||||||
|
else
|
||||||
|
Result:=False;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InitFileUtils;
|
||||||
|
begin
|
||||||
|
if Win32MajorVersion > 4 then begin
|
||||||
|
FileSize_:=@FileSizeWide;
|
||||||
|
FileGetAttr_:=@FileGetAttrWide;
|
||||||
|
FileSetAttr_:=@FileSetAttrWide;
|
||||||
|
DeleteFile_:=@DeleteFileWide;
|
||||||
|
RenameFile_:=@RenameFileWide;
|
||||||
|
SetCurrentDir_:=@SetCurrentDirWide;
|
||||||
|
GetCurrentDir_:=@GetCurrentDirWide;
|
||||||
|
CreateDir_:=@CreateDirWide;
|
||||||
|
RemoveDir_:=@RemoveDirWide;
|
||||||
|
FindFirst_:=@FindFirstWide;
|
||||||
|
FindNext_:=@FindNextWide;
|
||||||
|
FindClose_:=@FindCloseWide;
|
||||||
|
end;
|
||||||
|
end;
|
Loading…
Reference in New Issue
Block a user