summaryrefslogtreecommitdiff
path: root/UCoreWorkers.pas
diff options
context:
space:
mode:
Diffstat (limited to 'UCoreWorkers.pas')
-rw-r--r--UCoreWorkers.pas71
1 files changed, 39 insertions, 32 deletions
diff --git a/UCoreWorkers.pas b/UCoreWorkers.pas
index 507e2b7..75a9453 100644
--- a/UCoreWorkers.pas
+++ b/UCoreWorkers.pas
@@ -1019,11 +1019,12 @@ var DefResponse: integer; // Global variables for this function
var fsrc, fdst: TEngineFileDes;
BSize: integer;
Buffer: Pointer;
- BytesDone, BytesRead, BytesWritten: Int64;
+ BytesDone, BytesRead, BytesWritten, BytesRemaining: Int64;
LocalError: PGError;
begin
Result := False;
LocalError := nil;
+ BytesDone := 0;
DebugMsg(['ManualCopyFile: ', SourceFile, ' ---> ', DestFile]);
fsrc := SrcEngine.OpenFile(SourceFile, omRead, @LocalError);
if fsrc = nil then begin
@@ -1042,7 +1043,6 @@ var DefResponse: integer; // Global variables for this function
Exit;
end;
- BytesDone := 0;
BSize := DestEngine.GetBlockSize;
Buffer := malloc(BSize);
if Buffer = nil then begin
@@ -1050,60 +1050,66 @@ var DefResponse: integer; // Global variables for this function
CopyFilesWorker_ProgressFunc(Self, 0, Error^); // Memory allocation failed
Exit;
end;
- memset(Buffer, 0, BSize);
- BytesWritten := 0;
repeat
+ // Read block
BytesRead := SrcEngine.ReadFile(fsrc, Buffer, BSize, @LocalError);
- if (BytesRead = 0) and (Error^ <> nil) then begin
+ if BytesRead < 0 then begin
g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SOURCE_READ), LocalError^.message);
g_error_free(LocalError);
LocalError := nil;
- Result := CopyFilesWorker_ProgressFunc(Self, BytesWritten, Error^); // Cannot read from source file
+ Result := CopyFilesWorker_ProgressFunc(Self, BytesDone, Error^); // Cannot read from source file
if Result then begin
g_error_free(Error^);
Error^ := nil;
Continue;
end else Break;
end;
+
+ // Write block
if BytesRead > 0 then begin
- BytesWritten := DestEngine.WriteFile(fdst, Buffer, BytesRead, @LocalError);
- if (BytesWritten < BytesRead) then begin
+ BytesRemaining := BytesRead;
+ repeat
+ BytesWritten := DestEngine.WriteFile(fdst, Buffer + (BytesRead - BytesRemaining), BytesRemaining, @LocalError);
+ if BytesWritten > 0 then
+ BytesRemaining := BytesRemaining - BytesWritten;
+ until (BytesRemaining = 0) or (BytesWritten <= 0);
+ if BytesWritten < 0 then begin
g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_TARGET_WRITE), LocalError^.message);
g_error_free(LocalError);
LocalError := nil;
- Result := CopyFilesWorker_ProgressFunc(Self, BytesWritten, Error^); // Cannot write to target file
- if Result then begin
- g_error_free(Error^);
- Error^ := nil;
- Continue;
- end else Break;
+ Result := False;
+ CopyFilesWorker_ProgressFunc(Self, BytesDone, Error^); // Cannot write to target file
+ Break;
end;
end;
+ // BytesRead == 0 means EOF
BytesDone := BytesDone + BytesRead;
Result := CopyFilesWorker_ProgressFunc(Self, BytesDone, nil);
if not Result then Break;
- until (BytesRead = 0) or (BytesWritten < BytesRead);
+ until BytesRead <= 0;
libc_free(Buffer);
- if not DestEngine.CloseFile(fdst, @LocalError) then begin
- g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_TARGET_CLOSE), LocalError^.message);
- g_error_free(LocalError);
- Result := False;
- SrcEngine.CloseFile(fsrc, nil);
- CopyFilesWorker_ProgressFunc(Self, BytesDone, Error^); // Cannot close target file
- Exit;
- end;
- if not SrcEngine.CloseFile(fsrc, @LocalError) then begin
- g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SOURCE_CLOSE), LocalError^.message);
- g_error_free(LocalError);
- Result := CopyFilesWorker_ProgressFunc(Self, BytesDone, Error^); // Cannot close source file
+ if not DestEngine.CloseFile(fdst, @LocalError) then
if Result then begin
- // user has chosen to ignore the error
- g_error_free(Error^);
- Error^ := nil;
- end else Exit;
- end;
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_TARGET_CLOSE), LocalError^.message);
+ g_error_free(LocalError);
+ Result := False;
+ SrcEngine.CloseFile(fsrc, nil);
+ CopyFilesWorker_ProgressFunc(Self, BytesDone, Error^); // Cannot close target file
+ Exit;
+ end;
+ if not SrcEngine.CloseFile(fsrc, @LocalError) then
+ if Result then begin
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SOURCE_CLOSE), LocalError^.message);
+ g_error_free(LocalError);
+ Result := CopyFilesWorker_ProgressFunc(Self, BytesDone, Error^); // Cannot close source file
+ if Result then begin
+ // user has chosen to ignore the error
+ g_error_free(Error^);
+ Error^ := nil;
+ end else Exit;
+ end;
end;
// Returns True if the file was successfully copied and will be deleted on move
@@ -1120,6 +1126,7 @@ var DefResponse: integer; // Global variables for this function
then Result := DestEngine.CopyFileIn(SourceFile, DestFile, Append, @CopyFilesWorker_ProgressFunc, Self, Error)
else
+ // TODO: check for reported Append capability and fall back to manual copy if needed
// from local engine to VFS engine
if (SrcEngine is TLocalTreeEngine) and (DestEngine is TVFSEngine) then
begin