Browse Source

FIX: Copy attributes (Windows)

Alexander Koblov 4 years ago
parent
commit
c0886e2ee5

+ 21 - 4
components/doublecmd/dcosutils.pas

@@ -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;
 

+ 19 - 7
src/filesources/filesystem/ufilesystemutil.pas

@@ -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];

+ 4 - 2
src/platform/ufilecopyex.pas

@@ -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.