mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
FIX: Copy relative symbolic links under Windows (issue #2171)
(cherry picked from commit 52ee174822)
This commit is contained in:
parent
3619468fcc
commit
aa50acce68
6 changed files with 56 additions and 16 deletions
|
|
@ -95,7 +95,7 @@ type
|
|||
@param(ALinkName The name of the symbolic link)
|
||||
@returns(The function returns @true if successful, @false otherwise)
|
||||
}
|
||||
function CreateSymLink(const ATargetName, ALinkName: UnicodeString): Boolean;
|
||||
function CreateSymLink(const ATargetName, ALinkName: UnicodeString; Attr: UInt32): Boolean;
|
||||
{en
|
||||
Established a hard link beetwen an existing file and new file. This function
|
||||
is only supported on the NTFS file system, and only for files, not directories.
|
||||
|
|
@ -305,7 +305,7 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
function CreateSymLink(const ATargetName, ALinkName: UnicodeString): Boolean;
|
||||
function CreateSymLink(const ATargetName, ALinkName: UnicodeString; Attr: UInt32): Boolean;
|
||||
var
|
||||
dwAttributes: DWORD;
|
||||
lpFilePart: LPWSTR = nil;
|
||||
|
|
@ -324,7 +324,11 @@ begin
|
|||
AFullPathName:= ATargetName;
|
||||
end;
|
||||
end;
|
||||
dwAttributes:= Windows.GetFileAttributesW(PWideChar(AFullPathName));
|
||||
if (Attr <> FILE_DOES_NOT_EXIST) then
|
||||
dwAttributes:= Attr
|
||||
else begin
|
||||
dwAttributes:= Windows.GetFileAttributesW(PWideChar(AFullPathName));
|
||||
end;
|
||||
if dwAttributes = FILE_DOES_NOT_EXIST then Exit;
|
||||
if HasNewApi = False then
|
||||
begin
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ type
|
|||
PCopyAttributesResult = ^TCopyAttributesResult;
|
||||
|
||||
const
|
||||
faInvalidAttributes: TFileAttrs = TFileAttrs(-1);
|
||||
faInvalidAttributes = TFileAttrs(-1);
|
||||
CopyAttributesOptionCopyAll = [caoCopyAttributes, caoCopyTime, caoCopyOwnership];
|
||||
|
||||
{en
|
||||
|
|
@ -308,7 +308,7 @@ function CreateHardLink(const Path, LinkName: String) : Boolean;
|
|||
@param(LinkName Name of symbolic link)
|
||||
@returns(The function returns @true if successful, @false otherwise)
|
||||
}
|
||||
function CreateSymLink(const Path, LinkName: string) : Boolean;
|
||||
function CreateSymLink(const Path, LinkName: string; Attr: UInt32 = faInvalidAttributes) : Boolean;
|
||||
{en
|
||||
Read destination of symbolic link
|
||||
@param(LinkName Name of symbolic link)
|
||||
|
|
@ -2020,14 +2020,14 @@ begin
|
|||
end;
|
||||
{$ENDIF}
|
||||
|
||||
function CreateSymLink(const Path, LinkName: string) : Boolean;
|
||||
function CreateSymLink(const Path, LinkName: string; Attr: UInt32): Boolean;
|
||||
{$IFDEF MSWINDOWS}
|
||||
var
|
||||
wsPath, wsLinkName: UnicodeString;
|
||||
begin
|
||||
wsPath:= CeUtf8ToUtf16(Path);
|
||||
wsLinkName:= UTF16LongName(LinkName);
|
||||
Result:= DCNtfsLinks.CreateSymlink(wsPath, wsLinkName);
|
||||
Result:= DCNtfsLinks.CreateSymlink(wsPath, wsLinkName, Attr);
|
||||
end;
|
||||
{$ELSE}
|
||||
begin
|
||||
|
|
|
|||
|
|
@ -1347,7 +1347,7 @@ begin
|
|||
LinkTarget := CorrectedLink;
|
||||
end;
|
||||
|
||||
if CreateSymbolicLinkUAC(LinkTarget, AbsoluteTargetFileName) then
|
||||
if CreateSymbolicLinkUAC(LinkTarget, AbsoluteTargetFileName, aFile.Attributes) then
|
||||
begin
|
||||
CopyProperties(aFile, AbsoluteTargetFileName);
|
||||
if (FMode = fsohmMove) then Result:= DeleteFile(aFile);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ function CreateDirectoryUAC(const Directory: String): Boolean;
|
|||
function RemoveDirectoryUAC(const Directory: String): Boolean;
|
||||
function DirectoryExistsUAC(const Directory : String): Boolean;
|
||||
|
||||
function CreateSymbolicLinkUAC(const Path, LinkName: String) : Boolean;
|
||||
function CreateSymbolicLinkUAC(const Path, LinkName: String; Attr: UInt32 = faInvalidAttributes) : Boolean;
|
||||
function CreateHardLinkUAC(const Path, LinkName: String) : Boolean;
|
||||
|
||||
type
|
||||
|
|
@ -367,16 +367,16 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
function CreateSymbolicLinkUAC(const Path, LinkName: String): Boolean;
|
||||
function CreateSymbolicLinkUAC(const Path, LinkName: String; Attr: UInt32): Boolean;
|
||||
var
|
||||
LastError: Integer;
|
||||
begin
|
||||
Result:= CreateSymLink(Path, LinkName);
|
||||
Result:= CreateSymLink(Path, LinkName, Attr);
|
||||
if (not Result) and ElevationRequired then
|
||||
begin
|
||||
LastError:= GetLastOSError;
|
||||
if RequestElevation(rsElevationRequiredSymLink, LinkName) then
|
||||
Result:= TWorkerProxy.Instance.CreateSymbolicLink(Path, LinkName)
|
||||
Result:= TWorkerProxy.Instance.CreateSymbolicLink(Path, LinkName, Attr)
|
||||
else
|
||||
SetLastOSError(LastError);
|
||||
end;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ type
|
|||
function ProcessObject(ACommand: UInt32; const OldName, NewName: String): LongBool;
|
||||
function ProcessObject(ACommand: UInt32; const ObjectName: String; Attr: UInt32): LongBool;
|
||||
function ProcessObject(ACommand: UInt32; const ObjectName: String; Mode: Integer): THandle;
|
||||
function ProcessObject(ACommand: UInt32; const OldName, NewName: String; Attr: UInt32): LongBool;
|
||||
public
|
||||
function Terminate: Boolean;
|
||||
function FileExists(const FileName: String): LongBool; inline;
|
||||
|
|
@ -54,7 +55,7 @@ type
|
|||
function FindNext(var SearchRec: TSearchRecEx): Integer;
|
||||
procedure FindClose(var SearchRec: TSearchRecEx);
|
||||
function CreateHardLink(const Path, LinkName: String): LongBool; inline;
|
||||
function CreateSymbolicLink(const Path, LinkName: String): LongBool; inline;
|
||||
function CreateSymbolicLink(const Path, LinkName: String; Attr: UInt32): LongBool; inline;
|
||||
function CreateDirectory(const Directory: String): LongBool; inline;
|
||||
function RemoveDirectory(const Directory: String): LongBool; inline;
|
||||
function DirectoryExists(const Directory: String): LongBool; inline;
|
||||
|
|
@ -327,6 +328,40 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
function TWorkerProxy.ProcessObject(ACommand: UInt32; const OldName,
|
||||
NewName: String; Attr: UInt32): LongBool;
|
||||
var
|
||||
LastError: Integer;
|
||||
Stream: TMemoryStream;
|
||||
begin
|
||||
Result:= False;
|
||||
try
|
||||
Stream:= TMemoryStream.Create;
|
||||
try
|
||||
// Write header
|
||||
Stream.WriteDWord(ACommand);
|
||||
Stream.Seek(SizeOf(UInt32), soFromCurrent);
|
||||
// Write arguments
|
||||
Stream.WriteAnsiString(OldName);
|
||||
Stream.WriteAnsiString(NewName);
|
||||
Stream.WriteDWord(Attr);
|
||||
// Write data size
|
||||
Stream.Seek(SizeOf(UInt32), soFromBeginning);
|
||||
Stream.WriteDWord(Stream.Size - SizeOf(UInt32) * 2);
|
||||
// Send command
|
||||
FClient.WriteBuffer(Stream.Memory^, Stream.Size);
|
||||
// Receive command result
|
||||
FClient.ReadBuffer(Result, SizeOf(Result));
|
||||
FClient.ReadBuffer(LastError, SizeOf(LastError));
|
||||
SetLastOSError(LastError);
|
||||
finally
|
||||
Stream.Free;
|
||||
end;
|
||||
except
|
||||
on E: Exception do DCDebug(E.Message);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TWorkerProxy.Terminate: Boolean;
|
||||
var
|
||||
Stream: TMemoryStream;
|
||||
|
|
@ -653,9 +688,9 @@ begin
|
|||
Result:= ProcessObject(RPC_CreateHardLink, Path, LinkName);
|
||||
end;
|
||||
|
||||
function TWorkerProxy.CreateSymbolicLink(const Path, LinkName: String): LongBool;
|
||||
function TWorkerProxy.CreateSymbolicLink(const Path, LinkName: String; Attr: UInt32): LongBool;
|
||||
begin
|
||||
Result:= ProcessObject(RPC_CreateSymbolicLink, Path, LinkName);
|
||||
Result:= ProcessObject(RPC_CreateSymbolicLink, Path, LinkName, Attr);
|
||||
end;
|
||||
|
||||
function TWorkerProxy.CreateDirectory(const Directory: String): LongBool;
|
||||
|
|
|
|||
|
|
@ -322,8 +322,9 @@ begin
|
|||
begin
|
||||
FileName:= ARequest.ReadAnsiString;
|
||||
NewName:= ARequest.ReadAnsiString;
|
||||
Attr:= ARequest.ReadDWord;
|
||||
DCDebug('CreateSymbolicLink ', NewName);
|
||||
Result:= CreateSymLink(FileName, NewName);
|
||||
Result:= CreateSymLink(FileName, NewName, Attr);
|
||||
LastError:= GetLastOSError;
|
||||
ATransport.WriteBuffer(Result, SizeOf(Result));
|
||||
ATransport.WriteBuffer(LastError, SizeOf(LastError));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue