FIX: Copy attributes (Windows)

This commit is contained in:
Alexander Koblov 2021-05-02 15:05:27 +03:00
commit c0886e2ee5
3 changed files with 44 additions and 13 deletions

View file

@ -84,6 +84,9 @@ type
caoCopyOwnership,
caoCopyPermissions,
caoCopyXattributes,
// Modifiers
caoCopyTimeEx,
caoCopyAttrEx,
caoRemoveReadOnlyAttr);
TCopyAttributesOptions = set of TCopyAttributesOption;
TCopyAttributesResult = array[TCopyAttributesOption] of Integer;
@ -470,11 +473,13 @@ var
begin
Result := [];
if caoCopyAttributes in Options then
if [caoCopyAttributes, caoCopyAttrEx] * Options <> [] then
begin
Attr := mbFileGetAttr(sSrc);
if Attr <> faInvalidAttributes then
begin
if (not (caoCopyAttributes in Options)) and (Attr and faDirectory = 0) then
Attr := (Attr or faArchive);
if (caoRemoveReadOnlyAttr in Options) and ((Attr and faReadOnly) <> 0) then
Attr := (Attr and not faReadOnly);
if not mbFileSetAttr(sDst, Attr) then
@ -498,13 +503,25 @@ begin
end;
end;
if caoCopyTime in Options then
if [caoCopyTime, caoCopyTimeEx] * Options <> [] then
begin
if not (mbFileGetTime(sSrc, ModificationTime, CreationTime, LastAccessTime) and
mbFileSetTime(sDst, ModificationTime, CreationTime, LastAccessTime)) then
if not mbFileGetTime(sSrc, ModificationTime, CreationTime, LastAccessTime) then
begin
Include(Result, caoCopyTime);
if Assigned(Errors) then Errors^[caoCopyTime]:= GetLastOSError;
end
else begin
if not (caoCopyTime in Options) then
begin
CreationTime:= 0;
LastAccessTime:= 0;
end;
if not mbFileSetTime(sDst, ModificationTime, CreationTime, LastAccessTime) then
begin
Include(Result, caoCopyTime);
if Assigned(Errors) then Errors^[caoCopyTime]:= GetLastOSError;
end;
end;
end;

View file

@ -675,9 +675,7 @@ begin
begin
Result:= CompareFiles(SourceFile.FullPath, TargetFileName, SourceFile.Size);
end;
if Result and (FCopyAttributesOptions <> []) then
begin
FCopyAttributesOptions := FCopyAttributesOptions * [caoCopyXattributes, caoCopyPermissions];
if Result then begin
CopyProperties(SourceFile, TargetFileName);
end;
Exit;
@ -861,23 +859,37 @@ procedure TFileSystemOperationHelper.CopyProperties(SourceFile: TFile;
var
Msg: String = '';
ACopyTime: Boolean;
CreationTime, LastAccessTime: TFileTime;
CopyAttrResult: TCopyAttributesOptions = [];
ACopyAttributesOptions: TCopyAttributesOptions;
begin
if FCopyAttributesOptions <> [] then
begin
ACopyAttributesOptions := FCopyAttributesOptions;
ACopyTime := (FMode = fsohmMove) and (caoCopyTime in ACopyAttributesOptions);
if ACopyTime then ACopyAttributesOptions -= [caoCopyTime];
if SourceFile.IsDirectory or SourceFile.IsLink then ACopyAttributesOptions += CopyAttributesOptionEx;
ACopyTime := (FMode = fsohmMove) and ([caoCopyTime, caoCopyTimeEx] * ACopyAttributesOptions <> []);
if ACopyTime then ACopyAttributesOptions -= [caoCopyTime, caoCopyTimeEx];
if ACopyAttributesOptions <> [] then begin
CopyAttrResult := FileCopyAttrUAC(SourceFile.FullPath, TargetFileName, ACopyAttributesOptions);
end;
if ACopyTime then
try
if not (caoCopyTimeEx in CopyAttributesOptionEx) then
begin
if fpCreationTime in SourceFile.AssignedProperties then
CreationTime:= DateTimeToFileTime(SourceFile.CreationTime)
else begin
CreationTime:= 0;
end;
LastAccessTime:= DateTimeToFileTime(SourceFile.LastAccessTime);
end
else begin
CreationTime:= 0;
LastAccessTime:= 0;
end;
// Copy time from properties because move operation change time of original folder
if not FileSetTimeUAC(TargetFileName, DateTimeToFileTime(SourceFile.ModificationTime),
{$IF DEFINED(MSWINDOWS)}DateTimeToFileTime(SourceFile.CreationTime){$ELSE}0{$ENDIF},
DateTimeToFileTime(SourceFile.LastAccessTime)) then
CreationTime, LastAccessTime) then
CopyAttrResult += [caoCopyTime];
except
on E: EDateOutOfRange do CopyAttrResult += [caoCopyTime];

View file

@ -5,7 +5,7 @@ unit uFileCopyEx;
interface
uses
Classes, SysUtils;
Classes, SysUtils, DCOSUtils;
const
FILE_COPY_NO_BUFFERING = $01;
@ -17,12 +17,13 @@ type
var
FileCopyEx: TFileCopyEx = nil;
CopyAttributesOptionEx: TCopyAttributesOptions = [];
implementation
{$IF DEFINED(MSWINDOWS)}
uses
Windows, DCWindows, DCOSUtils;
Windows, DCWindows;
type
TCopyInfo = class
@ -61,6 +62,7 @@ end;
initialization
FileCopyEx:= @CopyFile;
CopyAttributesOptionEx:= [caoCopyTimeEx, caoCopyAttrEx];
{$ENDIF}
end.