summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@redhat.com>2024-10-11 23:38:44 +0200
committerTomas Bzatek <tbzatek@redhat.com>2024-10-23 18:13:05 +0200
commit7d757b8452daed2575e3a9cc300459d7e8674345 (patch)
tree1b4c0107964cc871dc6e2d732c615af710592c4c
parent81c8cd22e61701c1145dc267b0925add6cc0e78a (diff)
downloadtuxcmd-0.6.81.tar.xz
Full port to GErrorv0.6.81
Started 15 years ago, picking up on that work. Introduced the new TUXCMD_ERROR domain to distinguish between operations or their steps. Plugins may continue reporting the G_IO_ERROR domain.
-rw-r--r--UConfig.pas6
-rw-r--r--UCore.pas18
-rw-r--r--UCoreWorkers.pas781
-rw-r--r--UDirDelete.pas6
-rw-r--r--UEngines.pas235
-rw-r--r--UError.pas236
-rw-r--r--UGnome.pas26
-rw-r--r--vfs/UVFSCore.pas216
8 files changed, 851 insertions, 673 deletions
diff --git a/UConfig.pas b/UConfig.pas
index a51591f..3c54cc5 100644
--- a/UConfig.pas
+++ b/UConfig.pas
@@ -19,14 +19,14 @@
*)
unit UConfig;
-interface
+interface
uses Classes, ULocale;
resourcestring
ConstAppTitle = 'Tux Commander';
- ConstAboutVersion = '0.6.80-dev';
- ConstAboutBuildDate = '2024-10-08';
+ ConstAboutVersion = '0.6.81-dev';
+ ConstAboutBuildDate = '2024-10-23';
{$IFDEF FPC}
{$INCLUDE fpcver.inc}
diff --git a/UCore.pas b/UCore.pas
index bf5c012..ed89fd0 100644
--- a/UCore.pas
+++ b/UCore.pas
@@ -28,7 +28,7 @@ function FillPanel(List: TList; ListView: TGTKListView; Engine: TPanelEngine; Le
procedure FindNextSelected(ListView: TGTKListView; DataList: TList; var Item1, Item2: string);
procedure UnselectAll(ListView: TGTKListView; DataList: TList);
-procedure FillDirFiles(Engine: TPanelEngine; DestList: TList; InputFiles: TStringList; DoNotRecurse, SortForStream: boolean; InaccessiblePaths: TStringList);
+procedure FillDirFiles(Engine: TPanelEngine; DestList: TList; InputFiles: TStringList; DoNotRecurse, SortForStream: boolean; InaccessiblePaths: TStringList; CancelFlag: Pboolean);
function GetFileInfoSL(Engine: TPanelEngine; const APath: string): PDataItemSL;
procedure DebugWriteListSL(List: TList);
@@ -348,7 +348,7 @@ end;
(********************************************************************************************************************************)
(********************************************************************************************************************************)
-procedure FillDirFiles(Engine: TPanelEngine; DestList: TList; InputFiles: TStringList; DoNotRecurse, SortForStream: boolean; InaccessiblePaths: TStringList);
+procedure FillDirFiles(Engine: TPanelEngine; DestList: TList; InputFiles: TStringList; DoNotRecurse, SortForStream: boolean; InaccessiblePaths: TStringList; CancelFlag: Pboolean);
var DirStage1List, FilesList, DirStage2List: TList;
function FillDirFiles_compare_func(Item1, Item2: Pointer): integer;
@@ -418,6 +418,7 @@ var DirStage1List, FilesList, DirStage2List: TList;
ParentDir: string;
Error: PGError;
begin
+ if (CancelFlag <> nil) and CancelFlag^ then Exit;
LocalList := TList.Create;
Error := nil;
if Engine.GetListing(LocalList, LocalPath, True, False, True, @Error) then begin
@@ -603,11 +604,14 @@ end;
(********************************************************************************************************************************)
function MakeDirectory(ListView: TGTKListView; Engine: TPanelEngine; LeftPanel: boolean; NewDir: string): boolean;
var Error: PGError;
+ Dir: string;
begin
Error := nil;
- Result := Engine.MakeDir(IncludeTrailingPathDelimiter(Engine.Path) + NewDir, @Error);
+ Dir := IncludeTrailingPathDelimiter(Engine.Path) + NewDir;
+ Result := Engine.MakeDir(Dir, @Error);
if not Result then begin
- ShowError(FMain, Format('Error creating new directory ''%s'' in %s panel', [StrToUTF8(NewDir), LANGPanelStrings[LeftPanel]]), Error);
+ PrefixTuxcmdError(@Error, StrToUTF8(Dir));
+ ShowError(FMain, 'Error creating new directory', Error);
g_error_free(Error);
end;
end;
@@ -632,8 +636,8 @@ var AFSymLink: TFSymlink;
FDirDelete.Label3.Caption := Format(LANGCouldNotBeCreatedS, [Error^.message]);
FDirDelete.Label3.Visible := True;
Response := Integer(FDirDelete.Run);
- g_error_free(Error);
finally
+ g_error_free(Error);
FDirDelete.Free;
end;
case Response of
@@ -684,8 +688,8 @@ var Data: PDataItem;
FDirDelete.Label3.Caption := Format(LANGCouldNotBeDeletedS, [Error^.message]);
FDirDelete.Label3.Visible := True;
Response := Integer(FDirDelete.Run);
- g_error_free(Error);
finally
+ g_error_free(Error);
FDirDelete.Free;
end;
case Response of
@@ -706,8 +710,8 @@ var Data: PDataItem;
FDirDelete.Label3.Caption := Format(LANGCouldNotBeCreatedS, [Error^.message]);
FDirDelete.Label3.Visible := True;
Response := Integer(FDirDelete.Run);
- g_error_free(Error);
finally
+ g_error_free(Error);
FDirDelete.Free;
end;
case Response of
diff --git a/UCoreWorkers.pas b/UCoreWorkers.pas
index 7c0fb02..3ff94f8 100644
--- a/UCoreWorkers.pas
+++ b/UCoreWorkers.pas
@@ -20,7 +20,7 @@
unit UCoreWorkers;
interface
-uses glib2, gtk2, SyncObjs, Classes, GTKForms, GTKView, ULibc, UEngines, UCoreUtils, UVFSCore, uVFSprototypes, UCore, UDirDelete;
+uses glib2, gtk2, SyncObjs, Classes, GTKForms, ULibc, UEngines, UCoreUtils, UVFSCore, uVFSprototypes, UCore, UDirDelete;
type TWorkerThreadJobType = (WORKER_JOB_DUMMY, WORKER_JOB_DELETE, WORKER_JOB_COPY, WORKER_JOB_MOVE, WORKER_JOB_EXTRACT_TO_TEMP,
@@ -80,7 +80,10 @@ type TVFSCallbackThread = class(TThread)
// Copy worker progress values
FTotalSize, FTotalDone, FFileSize: cuLongLong;
FCopySkipAllErrors: boolean;
+ FCopyErrorHandledInProgress: boolean;
+ FCopySilentCancel: boolean;
FCopyProgressFunc: TEngineProgressFunc;
+ FCopySourceFile, FCopyDestFile: string;
// Dialogs
FCancelMessage: string;
@@ -95,8 +98,7 @@ type TVFSCallbackThread = class(TThread)
FGUIChanged: boolean;
FDirDeleteButtonsType: TFDirDeleteButtonSet;
- FDirDeleteTitle, FDirDeleteFileName: string;
- FDirDeleteError: PGError;
+ FDirDeleteText1, FDirDeleteFileName, FDirDeleteText2: string;
FOverwriteShowAppend: boolean;
FOverwriteSourceItem, FOverwriteDestItem: PDataItem;
@@ -117,7 +119,7 @@ type TVFSCallbackThread = class(TThread)
procedure SetProgress2Params(const ProgressMax: Int64);
procedure UpdateCaption1(const CaptionText: string);
procedure UpdateCaption2(const CaptionText: string);
- function ShowDirDeleteDialog(ButtonsType: TFDirDeleteButtonSet; const Title, FileName: string; Error: PGError): integer;
+ function ShowDirDeleteDialog(ButtonsType: TFDirDeleteButtonSet; const Text1, FileName, Text2: string): integer;
function ShowOverwriteDialog(ShowAppend: boolean; SourceItem, DestItem: PDataItem; const SourceFile, DestFile: string; var RenameStr: string): integer;
function ShowInaccessibleDialog(InaccessiblePaths: TStringList): integer;
function ShowNewDirDialog(Caption, LabelCaption, Edit: string): integer;
@@ -137,7 +139,7 @@ type TVFSCallbackThread = class(TThread)
public
JobType: TWorkerThreadJobType;
SrcEngine, DestEngine: TPanelEngine;
- ErrorHappened: boolean;
+ ErrorHappened: boolean; // checked in UMain
// For getting list of selected items in the panel
DataList: TList;
@@ -214,8 +216,8 @@ procedure ProcessThreadEvents(SenderThread: TVFSCallbackThread);
implementation
uses SysUtils, DateUtils, StrUtils, UConfig, UOverwrite, ULocale,
- UFileAssoc, UCoreClasses, URemoteWait, UMain, UGnome, UNewDir, UProgress,
- crc;
+ UCoreClasses, URemoteWait, UMain, UGnome, UNewDir, UProgress,
+ UError, crc;
@@ -502,12 +504,12 @@ begin
FGUIMutex.Release;
end;
-function TWorkerThread.ShowDirDeleteDialog(ButtonsType: TFDirDeleteButtonSet; const Title, FileName: string; Error: PGError): integer;
+function TWorkerThread.ShowDirDeleteDialog(ButtonsType: TFDirDeleteButtonSet; const Text1, FileName, Text2: string): integer;
begin
FDialogResultDirDelete := DIR_DELETE_CANCEL;
- FDirDeleteTitle := Title;
+ FDirDeleteText1 := Text1;
FDirDeleteFileName := FileName;
- FDirDeleteError := Error;
+ FDirDeleteText2 := Text2;
FDirDeleteButtonsType := ButtonsType;
FDialogShowDirDelete := True;
FCallbackLockEvent.ResetEvent;
@@ -579,11 +581,11 @@ begin
with PDataItem(DataList[i])^ do
if (not UpDir) and Selected then
InputFiles.Add(CurrPath + String(FName));
- // If not files are selected, take into account the current active item
+ // If no files are selected, take into account the current active item
if (InputFiles.Count = 0) and Assigned(SelectedItem) and (not SelectedItem^.UpDir) then
InputFiles.Add(CurrPath + String(SelectedItem^.FName));
- FillDirFiles(AEngine, AList, InputFiles, DoNotRecurse, True, InaccessiblePaths);
+ FillDirFiles(AEngine, AList, InputFiles, DoNotRecurse, True, InaccessiblePaths, @FCancelled);
InputFiles.Free;
end;
@@ -709,10 +711,10 @@ begin
try
AFDirDelete := TFDirDelete.Create(ParentDialogForm);
AFDirDelete.AddButtons(FDirDeleteButtonsType);
- AFDirDelete.Label1.Caption := FDirDeleteTitle;
+ AFDirDelete.Label1.Caption := FDirDeleteText1;
AFDirDelete.Label2.Caption := FDirDeleteFileName;
- if FDirDeleteError <> nil then
- AFDirDelete.Label3.Caption := FDirDeleteError^.message;
+ AFDirDelete.Label3.Caption := FDirDeleteText2;
+ AFDirDelete.Label3.Visible := Length(FDirDeleteText2) > 0;
FDialogResultDirDelete := Integer(AFDirDelete.Run);
if (FDirDeleteButtonsType = DIR_DELETE_SET_COPY_ERROR) and (FDialogResultDirDelete = DIR_DELETE_IGNORE) and (JobType = WORKER_JOB_MOVE)
then case Application.MessageBox(LANGIgnoreError, [mbYes, mbNo{, mbCancel}], mbWarning, mbYes, mbNo) of
@@ -830,21 +832,17 @@ var SkipAll: boolean;
// DebugMsg(['Debug: IsDir: ', AFileRec^.IsDir, ', Stage1: ', AFileRec^.Stage1, ', IsLnk: ', AFileRec^.IsLnk, '; Result = ', AFileRec^.IsDir and AFileRec^.Stage1 and (not AFileRec^.IsLnk)]);
if AFileRec^.DataItem^.IsDir and AFileRec^.Stage1 and (not AFileRec^.DataItem^.IsLnk) then Exit;
Res := AEngine.Remove(String(AFileRec^.DataItem^.FName), @Error);
-// DebugMsg(['Result : ', Res]);
- if not Res then
- if SkipAll then Result := True else
- begin
- Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, 'Error deleting file/directory:', String(AFileRec^.DataItem^.FDisplayName), Error);
- if Error <> nil then
+ if not Res then begin
+ if SkipAll then Result := True
+ else begin
+ Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, 'Error deleting file/directory', AFileRec^.DataItem^.FDisplayName, Error^.message);
g_error_free(Error);
- case Response of
- DIR_DELETE_SKIP : Result := True;
- DIR_DELETE_SKIP_ALL : begin
- SkipAll := True;
- Result := True;
- end;
- DIR_DELETE_RETRY : Result := HandleDelete(AFileRec);
- else Result := False;
+ case Response of
+ DIR_DELETE_SKIP : Result := True;
+ DIR_DELETE_SKIP_ALL : begin SkipAll := True; Result := True; end;
+ DIR_DELETE_RETRY : Result := HandleDelete(AFileRec);
+ else Result := False;
+ end;
end;
end;
end;
@@ -893,7 +891,7 @@ begin
if (not DeleteAll) and (PDataItemSL(AList[i])^.Level = 1) and PDataItemSL(AList[i])^.Stage1 and PDataItemSL(AList[i])^.DataItem^.IsDir and
(not PDataItemSL(AList[i])^.DataItem^.IsLnk) and (i < AList.Count - 2) and (PDataItemSL(AList[i + 1])^.Level = 2) then
begin
- Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_NON_EMPTY, 'The directory is not empty, do you want to delete it with all its files and subdirectories?', string(PDataItemSL(AList[i])^.DataItem^.FDisplayName), nil);
+ Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_NON_EMPTY, 'The directory is not empty, do you want to delete it with all its files and subdirectories?', PDataItemSL(AList[i])^.DataItem^.FDisplayName, '');
case Response of
DIR_DELETE_DELETE : ; // Do nothing in this case - I will not bother with changing the structure; it works :-)
DIR_DELETE_ALL : DeleteAll := True;
@@ -925,6 +923,35 @@ end;
(********************************************************************************************************************************)
(********************************************************************************************************************************)
+ procedure GetCopyProgressErrorLabels(Thread: TWorkerThread; Error: PGError; var s1, s2: string);
+ begin
+ if (Thread.JobType in [WORKER_JOB_COPY, WORKER_JOB_EXTRACT_TO_TEMP]) then s1 := LANGCopyError
+ else s1 := LANGMoveError;
+ s2 := Thread.FCopySourceFile;
+ if (Error^.domain = TUXCMD_ERROR) then
+ case TuxcmdErrorEnum(Error^.code) of
+ TUXCMD_ERROR_ALLOC_FAILED: s1 := LANGMemoryAllocationFailed;
+ TUXCMD_ERROR_SOURCE_OPEN: s1 := LANGCannotOpenSourceFile;
+ TUXCMD_ERROR_TARGET_OPEN: begin
+ s1 := LANGCannotOpenDestinationFile;
+ s2 := Thread.FCopyDestFile;
+ end;
+ TUXCMD_ERROR_SOURCE_READ: s1 := LANGCannotReadFromSourceFile;
+ TUXCMD_ERROR_TARGET_WRITE: begin
+ s1 := LANGCannotWriteToDestinationFile;
+ s2 := Thread.FCopyDestFile;
+ end;
+ TUXCMD_ERROR_SOURCE_CLOSE: s1 := LANGCannotCloseSourceFile;
+ TUXCMD_ERROR_TARGET_CLOSE: begin
+ s1 := LANGCannotCloseDestinationFile;
+ s2 := Thread.FCopyDestFile;
+ end;
+ TUXCMD_ERROR_RENAME: begin
+ s1 := 'Cannot move the file to';
+ s2 := Thread.FCopyDestFile;
+ end;
+ end;
+ end;
// Keep in sync with uVFSprototypes.pas/TVFSProgressCallback
function vfs_copy_progress_callback(position: guint64; error: PGError; user_data: Pointer): gboolean; cdecl;
@@ -941,147 +968,146 @@ end;
// Keep in sync with UEngines.pas/TEngineProgressFunc
function CopyFilesWorker_ProgressFunc(Sender: Pointer; BytesDone: Int64; Error: PGError): boolean; cdecl;
+ var s, s2: string;
begin
Result := True;
try
if Assigned(Sender) and (TObject(Sender) is TWorkerThread) then
with TWorkerThread(Sender) do begin
- if BytesDone = 0 then UpdateProgress1(0, '0%')
- else UpdateProgress1(BytesDone, Format('%d%%', [Round(BytesDone / FFileSize * 100)]));
- UpdateProgress2(FTotalDone + BytesDone, Format('%d%%', [Round((FTotalDone + BytesDone) / FTotalSize * 100)]));
Result := not FCancelled;
- CommitGUIUpdate;
+ if Error <> nil then begin
+ // Error handling
+ if FCopySkipAllErrors then Exit;
+ GetCopyProgressErrorLabels(TWorkerThread(Sender), Error, s, s2);
+ case ShowDirDeleteDialog(DIR_DELETE_SET_COPY_ERROR, s, s2, StrToUTF8(Error^.message)) of
+ DIR_DELETE_IGNORE : Result := True;
+ DIR_DELETE_SKIP : Result := False;
+ DIR_DELETE_SKIP_ALL : begin
+ FCopySkipAllErrors := True;
+ Result := False;
+ end;
+ DIR_DELETE_CANCEL, 124, 255 : begin
+ Result := False;
+ FCancelled := True;
+ end;
+ else begin
+ Result := False; // Cancel
+ FCopySilentCancel := True;
+ end;
+ end;
+ FCopyErrorHandledInProgress := not Result;
+ end else begin
+ // Progress update
+ if BytesDone = 0 then UpdateProgress1(0, '0%')
+ else UpdateProgress1(BytesDone, Format('%d%%', [Round(BytesDone / FFileSize * 100)]));
+ UpdateProgress2(FTotalDone + BytesDone, Format('%d%%', [Round((FTotalDone + BytesDone) / FTotalSize * 100)]));
+ CommitGUIUpdate;
+ end;
end else DebugMsg(['*** CopyFilesWorker: Sender is not TWorkerThread']);
except
on E: Exception do DebugMsg(['*** Exception raised in ProgressFunc(Sender=', Sender, ', BytesDone=', BytesDone, '): (', E.ClassName, '): ', E.Message]);
end;
end;
- // Return True to ignore the error (Skip, Skip All, Ignore, Cancel)
- function CopyFilesWorker_ErrorFunc(Sender: Pointer; ErrorType, ErrorNum: integer; FileName: string): boolean; cdecl;
- var s, s2, s3: string;
- begin
- Result := False;
- with TWorkerThread(Sender) do begin
- if FCopySkipAllErrors then begin
- Result := True;
- Exit;
- end;
- case ErrorType of
- 0 : begin
- FCancelled := True;
- Exit;
- end;
- 1 : s := LANGMemoryAllocationFailed;
- 2 : s := LANGCannotOpenSourceFile;
- 3 : s := LANGCannotOpenDestinationFile;
- 4 : s := LANGCannotCloseDestinationFile;
- 5 : s := LANGCannotCloseSourceFile;
- 6 : s := LANGCannotReadFromSourceFile;
- 7 : s := LANGCannotWriteToDestinationFile;
- end;
- if (JobType in [WORKER_JOB_COPY, WORKER_JOB_EXTRACT_TO_TEMP]) then s2 := LANGCopyError
- else s2 := LANGMoveError;
- if ErrorType <> 1 then s3 := StrToUTF8(FileName)
- else s3 := '';
-
- // * TODO: fix error string, port to GError
- case ShowDirDeleteDialog(DIR_DELETE_SET_COPY_ERROR, s, s3, nil) of
- DIR_DELETE_CANCEL : begin
- Result := False;
- FCancelled := True;
- end;
- DIR_DELETE_IGNORE : Result := True;
- DIR_DELETE_SKIP_ALL : begin
- FCopySkipAllErrors := True; { Skip All Err }
- Result := False; //** True?
- end;
- else Result := False; // Skip
- end;
- end;
- end;
-
procedure TWorkerThread.CopyFilesWorker;
var DefResponse: integer; // Global variables for this function
- SkipAll: boolean;
// Returns True if file was successfully copied, if not, the file will be deleted in LocalCopyFile
- function ManualCopyFile(SourceFile, DestFile: string; Append: boolean): boolean;
+ function ManualCopyFile(SourceFile, DestFile: string; Append: boolean; Error: PPGError): boolean;
var fsrc, fdst: TEngineFileDes;
BSize: integer;
Buffer: Pointer;
BytesDone, BytesRead, BytesWritten: Int64;
- Res: boolean;
- Error: PGError;
+ LocalError: PGError;
begin
- DebugMsg(['ManualCopyFile: ', SourceFile, ' ---> ', DestFile]);
Result := False;
- Error := nil;
- fsrc := SrcEngine.OpenFile(SourceFile, omRead, @Error);
+ LocalError := nil;
+ DebugMsg(['ManualCopyFile: ', SourceFile, ' ---> ', DestFile]);
+ fsrc := SrcEngine.OpenFile(SourceFile, omRead, @LocalError);
if fsrc = nil then begin
- // * TODO: set real error, also free it
- CopyFilesWorker_ErrorFunc(Self, 2, 1 { Error }, SourceFile); // Cannot open source file
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SOURCE_OPEN), LocalError^.message);
+ g_error_free(LocalError);
+ CopyFilesWorker_ProgressFunc(Self, 0, Error^); // Cannot open source file
Exit;
end;
- if Append then fdst := DestEngine.OpenFile(DestFile, omAppend, @Error)
- else fdst := DestEngine.OpenFile(DestFile, omWrite, @Error);
+ if Append then fdst := DestEngine.OpenFile(DestFile, omAppend, @LocalError)
+ else fdst := DestEngine.OpenFile(DestFile, omWrite, @LocalError);
if fdst = nil then begin
- // * TODO: set real error, also free it
SrcEngine.CloseFile(fsrc, nil);
- CopyFilesWorker_ErrorFunc(Self, 3, 1 { Error }, SourceFile); // Cannot open target file
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_TARGET_OPEN), LocalError^.message);
+ g_error_free(LocalError);
+ CopyFilesWorker_ProgressFunc(Self, 0, Error^); // Cannot open target file
Exit;
end;
BytesDone := 0;
- Res := True;
-
BSize := DestEngine.GetBlockSize;
Buffer := malloc(BSize);
if Buffer = nil then begin
- CopyFilesWorker_ErrorFunc(Self, 1, errno, SourceFile); // Memory allocation failed
- libc_free(Buffer);
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_ALLOC_FAILED), '%m');
+ CopyFilesWorker_ProgressFunc(Self, 0, Error^); // Memory allocation failed
Exit;
end;
memset(Buffer, 0, BSize);
BytesWritten := 0;
repeat
- BytesRead := SrcEngine.ReadFile(fsrc, Buffer, BSize, @Error);
- if (BytesRead = 0) and (Error <> nil) then
- // * TODO: set real error, also free it
- Res := CopyFilesWorker_ErrorFunc(Self, 6, 1 { Error }, SourceFile); // Cannot read from source file
+ BytesRead := SrcEngine.ReadFile(fsrc, Buffer, BSize, @LocalError);
+ if (BytesRead = 0) and (Error^ <> nil) 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
+ if Result then begin
+ g_error_free(Error^);
+ Error^ := nil;
+ Continue;
+ end else Break;
+ end;
if BytesRead > 0 then begin
- Error := nil;
- BytesWritten := DestEngine.WriteFile(fdst, Buffer, BytesRead, @Error);
- if (BytesWritten < BytesRead) then
- // * TODO: set real error, also free it
- Res := CopyFilesWorker_ErrorFunc(Self, 7, 1 { Error }, DestFile); // Cannot write to source file
+ BytesWritten := DestEngine.WriteFile(fdst, Buffer, BytesRead, @LocalError);
+ if (BytesWritten < BytesRead) 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;
+ end;
end;
BytesDone := BytesDone + BytesRead;
- if not CopyFilesWorker_ProgressFunc(Self, BytesDone, nil) then begin
- Res := False;
- Break;
- end;
+ Result := CopyFilesWorker_ProgressFunc(Self, BytesDone, nil);
+ if not Result then Break;
until (BytesRead = 0) or (BytesWritten < BytesRead);
libc_free(Buffer);
- // * TODO: set real error, also free it
- if not DestEngine.CloseFile(fdst, nil) then begin
- CopyFilesWorker_ErrorFunc(Self, 4, errno, DestFile); // Cannot close target file
+ 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;
- // * TODO: set real error, also free it
- if not SrcEngine.CloseFile(fsrc, nil) then begin
- CopyFilesWorker_ErrorFunc(Self, 5, errno, SourceFile); // Cannot close source file
- Exit;
+ 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 Result then begin
+ // user has chosen to ignore the error
+ g_error_free(Error^);
+ Error^ := nil;
+ end else Exit;
end;
- Result := Res;
end;
// Returns True if the file was successfully copied and will be deleted on move
- function LocalCopyFile(SourceFile, DestFile: string; Append: boolean): boolean;
+ function LocalCopyFile(SourceFile, DestFile: string; Append: boolean; Error: PPGError): boolean;
var DataSrc, DataDest: PDataItem;
begin
Result := False;
@@ -1091,28 +1117,28 @@ var DefResponse: integer; // Global variables for this function
// local -> local
if (SrcEngine is TLocalTreeEngine) and (DestEngine is TLocalTreeEngine)
- then Result := DestEngine.CopyFileIn(SourceFile, DestFile, Append, @CopyFilesWorker_ProgressFunc, Self)
+ then Result := DestEngine.CopyFileIn(SourceFile, DestFile, Append, @CopyFilesWorker_ProgressFunc, Self, Error)
else
// from local engine to VFS engine
if (SrcEngine is TLocalTreeEngine) and (DestEngine is TVFSEngine) then
begin
AEngine := DestEngine;
- Result := (DestEngine as TVFSEngine).CopyFileInEx(SourceFile, DestFile, Append);
+ Result := (DestEngine as TVFSEngine).CopyFileInEx(SourceFile, DestFile, Append, Error);
end else
// from VFS engine to local (most common use)
if (SrcEngine is TVFSEngine) and (DestEngine is TLocalTreeEngine) then
begin
AEngine := SrcEngine;
- Result := (SrcEngine as TVFSEngine).CopyFileOutEx(SourceFile, DestFile, Append);
+ Result := (SrcEngine as TVFSEngine).CopyFileOutEx(SourceFile, DestFile, Append, Error);
end
- // VFS to VFS (not supported yet)
+ // VFS to VFS (mostly unsupported)
else
begin
AEngine := SrcEngine;
- Result := ManualCopyFile(SourceFile, DestFile, Append);
+ Result := ManualCopyFile(SourceFile, DestFile, Append, Error);
end;
AEngine := nil;
@@ -1130,7 +1156,11 @@ var DefResponse: integer; // Global variables for this function
FreeDataItem(DataDest);
end;
except
- on E: Exception do DebugMsg(['*** Exception raised in LocalCopyFile(SourceFile=', SourceFile, ', DestFile=', DestFile, ', Append=', Append, '): (', E.ClassName, '): ', E.Message]);
+ on E: Exception do begin
+ Result := False;
+ tuxcmd_set_error_from_exception(Error, E);
+ DebugMsg(['*** Exception raised in LocalCopyFile(SourceFile=', SourceFile, ', DestFile=', DestFile, ', Append=', Append, '): (', E.ClassName, '): ', E.Message]);
+ end;
end;
end;
@@ -1161,31 +1191,24 @@ var DefResponse: integer; // Global variables for this function
Result := TestCaseInsensitiveFS and DestEngine.TwoSameFiles(Path1, Path2, False);
end;
- function DoOperation(AFileRec: PDataItemSL; const Dst: string; var ErrorKind: integer; const Append: boolean): integer;
+ function DoOperation(AFileRec: PDataItemSL; const Dst: string; const Append: boolean; Error: PPGError): boolean;
begin
- ErrorKind := 0;
- Result := 0;
+ Result := False;
try
with AFileRec^ do begin
if DataItem^.IsLnk then begin
// Explicit copy the file
if (JobType in [WORKER_JOB_COPY, WORKER_JOB_EXTRACT_TO_TEMP]) or (not IsOnSameFS(String(DataItem^.FName), ExtractFileDir(Dst))) then begin
- // * TODO: check error
- ErrorKind := Ord(DestEngine.MakeSymLink(Dst, String(DataItem^.LnkPointTo), nil));
-// if ErrorKind <> 0 then Result := ERRCreateLink;
- if JobType = WORKER_JOB_MOVE then begin
- // * TODO: check error
- ErrorKind := Ord(SrcEngine.Remove(String(DataItem^.FName), nil));
-// if ErrorKind <> 0 then Result := ERRRemove;
- end;
+ Result := DestEngine.MakeSymLink(Dst, String(DataItem^.LnkPointTo), Error);
+ if Result and (JobType = WORKER_JOB_MOVE) then
+ Result := SrcEngine.Remove(String(DataItem^.FName), Error);
end else begin // Move the file
- // * TODO: check error
- ErrorKind := Ord(DestEngine.RenameFile(String(DataItem^.FName), Dst, nil));
-// if ErrorKind <> 0 then Result := ERRCopyMove;
+ Result := DestEngine.RenameFile(String(DataItem^.FName), Dst, Error);
end;
- end else // is not link
+ end else // is not a symlink
if (JobType in [WORKER_JOB_COPY, WORKER_JOB_EXTRACT_TO_TEMP]) then begin // Copy mode
- if LocalCopyFile(String(DataItem^.FName), Dst, Append) then begin
+ Result := LocalCopyFile(String(DataItem^.FName), Dst, Append, Error);
+ if Result then begin
if IsOnRO and ConfClearReadOnlyAttr and (DataItem^.Mode and S_IWUSR = 0) then DataItem^.Mode := DataItem^.Mode or S_IWUSR;
// * TODO: check error
DestEngine.Chmod(Dst, DataItem^.Mode, nil);
@@ -1196,187 +1219,179 @@ var DefResponse: integer; // Global variables for this function
if IsOnSameFS(String(DataItem^.FName), ExtractFileDir(Dst)) then begin
if TwoSameFiles(String(DataItem^.FName), Dst, True) and (not TwoSameFiles(String(DataItem^.FName), Dst, False)) then begin
DebugMsg(['*** Activating double-rename due to renaming on case-insensitive FS']);
- // * TODO: check error
- ErrorKind := Ord(DestEngine.RenameFile(String(DataItem^.FName), Dst + '_tcmd', nil));
- if ErrorKind = 0 then ErrorKind := Ord(DestEngine.RenameFile(Dst + '_tcmd', Dst, nil));
- end else ErrorKind := Ord(DestEngine.RenameFile(String(DataItem^.FName), Dst, nil));
-// if ErrorKind <> 0 then Result := ERRCopyMove;
+ Result := DestEngine.RenameFile(String(DataItem^.FName), Dst + '_tcmd', Error);
+ if Result then
+ Result := DestEngine.RenameFile(Dst + '_tcmd', Dst, Error);
+ end else Result := DestEngine.RenameFile(String(DataItem^.FName), Dst, Error);
end else begin
- if LocalCopyFile(String(DataItem^.FName), Dst, Append) then begin
+ Result := LocalCopyFile(String(DataItem^.FName), Dst, Append, Error);
+ if Result then begin
if IsOnRO and ConfClearReadOnlyAttr and (DataItem^.Mode and S_IWUSR = 0) then DataItem^.Mode := DataItem^.Mode or S_IWUSR;
// * TODO: check error
DestEngine.Chmod(Dst, DataItem^.Mode, nil);
DestEngine.Chown(Dst, DataItem^.UID, DataItem^.GID, nil);
DestEngine.ChangeTimes(Dst, DataItem^.mtime, DataItem^.atime, nil);
- if not FCancelled then begin
- ErrorKind := Ord(SrcEngine.Remove(String(DataItem^.FName), nil));
-// if ErrorKind <> 0 then Result := ERRRemove;
- end;
+ Result := SrcEngine.Remove(String(DataItem^.FName), Error);
end;
end;
end;
// DebugMsg(['(II) CopyFilesWorker.DoOperation: finished']);
except
- on E: Exception do DebugMsg(['*** Exception raised in DoOperation(AFileRec=', AFileRec, ', Dst=', Dst, ', ErrorKind=', ErrorKind, ', Append=', Append, '): (', E.ClassName, '): ', E.Message]);
+ on E: Exception do begin
+ Result := False;
+ tuxcmd_set_error_from_exception(Error, E);
+ DebugMsg(['*** Exception raised in DoOperation(AFileRec=', AFileRec, ', Dst=', Dst, ', Append=', Append, '): (', E.ClassName, '): ', E.Message]);
+ end;
end;
end;
// Return False to break the processing (Cancel)
function HandleCopy(AFileRec: PDataItemSL; NewFilePath: string): boolean;
- var Res, Response, ErrorKind, r: integer;
+ var Response: integer;
+ Res: boolean;
Item: PDataItem;
- s, s1, s3, cap: string;
- FromInfoLabel, ToInfoLabel, InfoLabelFormat: string;
+ s, s2, s3: string;
RenameStr: string;
+ Error: PGError;
begin
Result := True;
+ Res := True;
+ Error := nil;
try
+ // Second stage - change permissions
+ if (not AFileRec^.Stage1) and ((JobType in [WORKER_JOB_COPY, WORKER_JOB_EXTRACT_TO_TEMP]) or (not AFileRec^.ForceMove)) then begin
+ with AFileRec^ do begin
+ if IsOnRO and ConfClearReadOnlyAttr and (DataItem^.Mode and S_IWUSR = 0) then DataItem^.Mode := DataItem^.Mode or S_IWUSR;
+ // * TODO: check error
+ DestEngine.Chmod(NewFilePath, DataItem^.Mode, nil);
+ DestEngine.Chown(NewFilePath, DataItem^.UID, DataItem^.GID, nil);
+ DestEngine.ChangeTimes(NewFilePath, DataItem^.mtime, DataItem^.atime, nil);
+ if JobType = WORKER_JOB_MOVE then
+ Res := SrcEngine.Remove(String(DataItem^.FName), @Error); // Remove directory
+ end;
+ end else
- // Second stage - change permissions
- if (not AFileRec^.Stage1) and ((JobType in [WORKER_JOB_COPY, WORKER_JOB_EXTRACT_TO_TEMP]) or (not AFileRec^.ForceMove)) then
- with AFileRec^ do begin
- if IsOnRO and ConfClearReadOnlyAttr and (DataItem^.Mode and S_IWUSR = 0) then DataItem^.Mode := DataItem^.Mode or S_IWUSR;
- // * TODO: check error
- DestEngine.Chmod(NewFilePath, DataItem^.Mode, nil);
- DestEngine.Chown(NewFilePath, DataItem^.UID, DataItem^.GID, nil);
- DestEngine.ChangeTimes(NewFilePath, DataItem^.mtime, DataItem^.atime, nil);
- if JobType = WORKER_JOB_MOVE then
- SrcEngine.Remove(String(DataItem^.FName), nil); // Remove directory
- Exit;
- end;
-
- // First stage - copy data
- if AFileRec^.DataItem^.IsDir then begin
- Res := 0;
- if AFileRec^.ForceMove and (JobType = WORKER_JOB_MOVE)
+ // First stage - copy data
+ if AFileRec^.DataItem^.IsDir then begin
+ if AFileRec^.ForceMove and (JobType = WORKER_JOB_MOVE)
then begin
if TwoSameFiles(ExcludeTrailingPathDelimiter(string(AFileRec^.DataItem^.FName)), ExcludeTrailingPathDelimiter(string(AFileRec^.ADestination)), True) and (not
TwoSameFiles(ExcludeTrailingPathDelimiter(string(AFileRec^.DataItem^.FName)), ExcludeTrailingPathDelimiter(string(AFileRec^.ADestination)), False)) then
begin
DebugMsg(['*** Activating double-rename due to renaming on case-insensitive FS']);
- // * TODO: check error
- ErrorKind := Ord(DestEngine.RenameFile(string(AFileRec^.DataItem^.FName), ExcludeTrailingPathDelimiter(string(AFileRec^.ADestination)) + '_tcmd', nil));
- if ErrorKind = 0 then ErrorKind := ord(DestEngine.RenameFile(ExcludeTrailingPathDelimiter(string(AFileRec^.ADestination)) + '_tcmd', ExcludeTrailingPathDelimiter(string(AFileRec^.ADestination)), nil));
- end else ErrorKind := Ord(DestEngine.RenameFile(string(AFileRec^.DataItem^.FName), string(AFileRec^.ADestination), nil));
-{ if ErrorKind <> 0 then Res := ERRCopyMove
- else Res := 0; }
+ Res := DestEngine.RenameFile(string(AFileRec^.DataItem^.FName), ExcludeTrailingPathDelimiter(string(AFileRec^.ADestination)) + '_tcmd', @Error);
+ if Res then Res := DestEngine.RenameFile(ExcludeTrailingPathDelimiter(string(AFileRec^.ADestination)) + '_tcmd', ExcludeTrailingPathDelimiter(string(AFileRec^.ADestination)), @Error);
+ end else Res := DestEngine.RenameFile(string(AFileRec^.DataItem^.FName), string(AFileRec^.ADestination), @Error);
end else
if not DestEngine.DirectoryExists(NewFilePath, False) then begin
- // * TODO: check error
- ErrorKind := Ord(DestEngine.MakeDir(NewFilePath, nil));
-{ if ErrorKind <> 0 then Res := ERRMkDir
- else Res := 0; }
- end;
- end else begin // not a directory
- if not DestEngine.DirectoryExists(ExtractFileDir(NewFilePath), False) then
- // * TODO: check error
- DestEngine.MakeDir(ExtractFileDir(NewFilePath), nil);
- SetProgress1Params(AFileRec^.DataItem^.Size + Ord(AFileRec^.DataItem^.Size = 0));
- FFileSize := AFileRec^.DataItem^.Size;
- CopyFilesWorker_ProgressFunc(Self, 0, nil);
- Res := 0;
- if DestEngine.FileExists(NewFilePath, False) and
- (not ((JobType = WORKER_JOB_MOVE) and (not TwoSameFiles(NewFilePath, AFileRec^.DataItem^.FName, False)) and TwoSameFiles(NewFilePath, AFileRec^.DataItem^.FName, True)))
- then begin
- Response := DefResponse;
- // * TODO: check error --> display dialog
- // * TODO: should be SrcEngine?
- Item := DestEngine.GetFileInfo(NewFilePath, False, True, nil);
- if Item = nil then begin
- DebugMsg(['Something went terribly wrong during copy - Item := DestEngine.GetFileInfoSL(NewFilePath) == NULL!']);
- Result := False;
- Exit;
- end;
- if Response = 0 then begin
- case ConfSizeFormat of
- 5: InfoLabelFormat := '%s, %s';
- else InfoLabelFormat := LANGOvewriteSBytesS;
- end;
- RenameStr := ExtractFileName(NewFilePath);
- Response := ShowOverwriteDialog(JobType in [WORKER_JOB_COPY], Item, AFileRec^.DataItem, NewFilePath, AFileRec^.DataItem^.FName, RenameStr);
- case Response of
- // OVERWRITE_OVERWRITE
- // OVERWRITE_SKIP
- OVERWRITE_OVERWRITE_ALL, OVERWRITE_OVERWRITE_ALL_OLDER, OVERWRITE_SKIP_ALL: DefResponse := Response;
- OVERWRITE_CANCEL, 124 {Close Window}, 255: begin
- Result := False;
- Exit;
- end;
- OVERWRITE_RENAME: begin
- NewFilePath := Copy(NewFilePath, 1, LastDelimiter(PathDelim, NewFilePath)) + RenameStr;
- Result := HandleCopy(AFileRec, NewFilePath);
- Exit;
- end;
- OVERWRITE_APPEND: begin
- Res := DoOperation(AFileRec, NewFilePath, ErrorKind, True);
- end;
+ Res := DestEngine.MakeDir(NewFilePath, @Error);
end;
- end;
-
- // Remove destination file if exists and should be overwritten
- if (Response in [OVERWRITE_OVERWRITE, OVERWRITE_OVERWRITE_ALL]) or ((Response = OVERWRITE_OVERWRITE_ALL_OLDER) and (Item^.mtime < AFileRec^.DataItem^.mtime)) then begin
+ end else begin // not a directory
+ if not DestEngine.DirectoryExists(ExtractFileDir(NewFilePath), False) then
// * TODO: check error
- r := ord(DestEngine.Remove(NewFilePath, nil));
- while r <> 0 do begin
- // * TODO: check error, port to GError
- Res := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, 'The file could not be deleted', StrToUTF8(String(NewFilePath)), nil);
- case Res of
- DIR_DELETE_SKIP: begin
- Result := True;
- Exit;
- end;
- // * TODO: check error
- DIR_DELETE_RETRY: r := Ord(DestEngine.Remove(NewFilePath, nil));
- DIR_DELETE_CANCEL, 124, 255: begin
- Result := False;
- Exit;
- end;
+ DestEngine.MakeDir(ExtractFileDir(NewFilePath), nil);
+ SetProgress1Params(AFileRec^.DataItem^.Size + Ord(AFileRec^.DataItem^.Size = 0));
+ FFileSize := AFileRec^.DataItem^.Size;
+ CopyFilesWorker_ProgressFunc(Self, 0, nil);
+ // Overwrite handling
+ if DestEngine.FileExists(NewFilePath, False) and
+ (not ((JobType = WORKER_JOB_MOVE) and (not TwoSameFiles(NewFilePath, AFileRec^.DataItem^.FName, False)) and TwoSameFiles(NewFilePath, AFileRec^.DataItem^.FName, True)))
+ then begin
+ Response := DefResponse;
+ Item := DestEngine.GetFileInfo(NewFilePath, False, True, @Error);
+ if Item = nil then begin
+ // Display an error and bail out
+ Res := False;
+ end else begin
+ if Response = 0 then begin
+ RenameStr := ExtractFileName(NewFilePath);
+ Response := ShowOverwriteDialog(JobType in [WORKER_JOB_COPY], Item, AFileRec^.DataItem, NewFilePath, AFileRec^.DataItem^.FName, RenameStr);
+ case Response of
+ // OVERWRITE_OVERWRITE
+ // OVERWRITE_SKIP
+ OVERWRITE_OVERWRITE_ALL, OVERWRITE_OVERWRITE_ALL_OLDER, OVERWRITE_SKIP_ALL: DefResponse := Response;
+ OVERWRITE_RENAME: begin
+ NewFilePath := Copy(NewFilePath, 1, LastDelimiter(PathDelim, NewFilePath)) + RenameStr;
+ FCopyDestFile := NewFilePath; // ... for the label
+ Result := HandleCopy(AFileRec, NewFilePath);
+ Exit;
+ end;
+ OVERWRITE_APPEND: Res := DoOperation(AFileRec, NewFilePath, True, @Error);
+ OVERWRITE_CANCEL, 124 {Close Window}, 255, 252: begin
+ Result := False;
+ Exit;
+ end;
+ end;
+ end;
+
+ // Remove destination file if exists and should be overwritten
+ if (Response in [OVERWRITE_OVERWRITE, OVERWRITE_OVERWRITE_ALL]) or ((Response = OVERWRITE_OVERWRITE_ALL_OLDER) and (Item^.mtime < AFileRec^.DataItem^.mtime)) then begin
+ while not DestEngine.Remove(NewFilePath, @Error) do begin
+ Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, 'Error deleting file', StrToUTF8(String(NewFilePath)), Error^.message);
+ g_error_free(Error);
+ Error := nil;
+ case Response of
+ DIR_DELETE_SKIP: begin
+ Result := True;
+ Exit;
+ end;
+ DIR_DELETE_RETRY: ; // Continue
+ DIR_DELETE_CANCEL, 124, 255: begin
+ Result := False;
+ Exit;
+ end;
+ else begin // Cancel
+ Result := False;
+ Exit;
+ end;
+ end;
+ end;
+ Res := DoOperation(AFileRec, NewFilePath, False, @Error);
end;
end;
- Res := DoOperation(AFileRec, NewFilePath, ErrorKind, False);
- end;
- end else Res := DoOperation(AFileRec, NewFilePath, ErrorKind, False);
- end;
+ end else Res := DoOperation(AFileRec, NewFilePath, False, @Error);
+ end;
// Error handling
- if (Res <> 0) and (not SkipAll) then begin
- if (JobType in [WORKER_JOB_COPY, WORKER_JOB_EXTRACT_TO_TEMP]) then cap := LANGCopy
- else cap := LANGMove;
- // * TODO: port to GError
-{ case Res of
- ERRCreateLink: begin
- s1 := LANGTheSymbolicLink;
- if ErrorKind = 0 then s3 := LANGCouldNotBeCreated else
- s3 := Format(LANGCouldNotBeCreatedS, [GetErrorString(ErrorKind)]);
- end;
- ERRMkDir: begin
- s1 := LANGTheDirectory;
- if ErrorKind = 0 then s3 := LANGCouldNotBeCreated else
- s3 := Format(LANGCouldNotBeCreatedS, [GetErrorString(ErrorKind)]);
- end;
- ERRRemove: begin
- if AFileRec^.DataItem^.IsDir then s1 := LANGTheDirectory else
- if AFileRec^.DataItem^.IsLnk then s1 := LANGTheSymbolicLink else
- s1 := LANGTheFile;
- if ErrorKind = 0 then s3 := LANGCouldNotBeDeleted else
- s3 := Format(LANGCouldNotBeDeletedS, [GetErrorString(ErrorKind)]);
- end;
- ERRCopyMove: begin
- if ParamBool3 then s1 := LANGCannotCopyFile else
- s1 := LANGCannotMoveFile;
- if ErrorKind = 0 then s3 := '' else
- s3 := GetErrorString(ErrorKind);
- end;
- end; }
- Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, s1, StrToUTF8(String(NewFilePath)), nil);
+ if (not Res) and (not FCopySkipAllErrors) then begin
+ if FCopyErrorHandledInProgress then begin
+ if FCopySilentCancel then Result := False; // Break the processing
+ Exit;
+ end;
+ GetCopyProgressErrorLabels(Self, Error, s, s2);
+ s3 := StrToUTF8(Error^.message);
+ if (Error^.domain = TUXCMD_ERROR) then
+ case TuxcmdErrorEnum(Error^.code) of
+ TUXCMD_ERROR_SYMLINK: begin
+ s := LANGTheSymbolicLink;
+ s2 := FCopyDestFile;
+ s3 := Format(LANGCouldNotBeCreatedS, [StrToUTF8(Error^.message)]);
+ end;
+ TUXCMD_ERROR_MKDIR: begin
+ s := LANGTheDirectory;
+ s2 := FCopyDestFile;
+ s3 := Format(LANGCouldNotBeCreatedS, [StrToUTF8(Error^.message)]);
+ end;
+ TUXCMD_ERROR_REMOVE: begin
+ if AFileRec^.DataItem^.IsDir then s := LANGTheDirectory else
+ if AFileRec^.DataItem^.IsLnk then s := LANGTheSymbolicLink else
+ s := LANGTheFile;
+ s2 := FCopyDestFile;
+ s3 := Format(LANGCouldNotBeDeletedS, [StrToUTF8(Error^.message)]);
+ end;
+ end;
+ Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, s, s2, s3);
case Response of
DIR_DELETE_SKIP : Result := True; // Skip
DIR_DELETE_RETRY : Result := HandleCopy(AFileRec, NewFilePath); // Retry
DIR_DELETE_SKIP_ALL : begin // Skip All
- SkipAll := True;
+ FCopySkipAllErrors := True;
Result := True;
end;
0, 124, 255 : Result := False; // Cancel
+ else begin
+ Result := False;
+ end;
end;
end;
// DebugMsg(['(II) CopyFilesWorker.HandleCopy: finished']);
@@ -1417,7 +1432,6 @@ var DefResponse: integer; // Global variables for this function
if Info = nil then begin
InaccessiblePaths.Add(FullPath);
DebugMsg(['$$$ Copy: Something went wrong while building the filelist...']);
- // TODO: ?
ErrorHappened := True;
end else begin
Info^.ADestination := strdup(PChar(s));
@@ -1426,17 +1440,18 @@ var DefResponse: integer; // Global variables for this function
end;
end else InputFiles.Add(FullPath);
end;
- FillDirFiles(SrcEngine, AList, InputFiles, False, True, InaccessiblePaths);
+ FillDirFiles(SrcEngine, AList, InputFiles, False, True, InaccessiblePaths, @FCancelled);
InputFiles.Free;
end;
var i: longint;
List: TList;
InaccessiblePaths: TStringList;
+ SkipInaccessible: boolean;
CurrPath, SaveDestPath, SaveSrcPath, s: string;
StartPassed: boolean;
- SkipInaccessible: boolean;
begin
+ FCopySilentCancel := False;
List := TList.Create;
InaccessiblePaths := TStringList.Create;
ErrorHappened := False;
@@ -1448,13 +1463,13 @@ begin
// Prepare list of files to copy
if JobType = WORKER_JOB_EXTRACT_TO_TEMP then begin
- if not ExtractFromVFSAll then HandleProcessPattern(List, InaccessiblePaths, CurrPath, ExtractFile, ExtractFileName(ExtractFile), False, False)
- else begin
- SaveSrcPath := IncludeTrailingPathDelimiter(SrcEngine.Path);
- SrcEngine.SetPath('/');
- CurrPath := '/';
- HandleProcessPattern(List, InaccessiblePaths, '/', '/', '', True, False);
- end;
+ if not ExtractFromVFSAll then HandleProcessPattern(List, InaccessiblePaths, CurrPath, ExtractFile, ExtractFileName(ExtractFile), False, False)
+ else begin
+ SaveSrcPath := IncludeTrailingPathDelimiter(SrcEngine.Path);
+ SrcEngine.SetPath('/');
+ CurrPath := '/';
+ HandleProcessPattern(List, InaccessiblePaths, '/', '/', '', True, False);
+ end;
end else
if QuickRenameDataItem <> nil then begin // Quick-Rename
with QuickRenameDataItem^ do
@@ -1482,6 +1497,8 @@ begin
end;
end;
+ // * TODO: cancellation check
+
{ if DestEngine.ChangeDir(CurrPath) <> 0 then DebugMsg(['*** WARNING: Cannot change to the origin location, strange behaviour may occur.']);
if SrcEngine.ChangeDir(CurrPath) <> 0 then DebugMsg(['*** WARNING: Cannot change to the origin location, strange behaviour may occur.']); }
DebugWriteListSL(List);
@@ -1509,7 +1526,6 @@ begin
CommitGUIUpdate;
DefResponse := 0;
- SkipAll := False;
FCopySkipAllErrors := False;
if List.Count > 0 then begin
@@ -1530,12 +1546,14 @@ begin
// DebugMsg(['s2 = ', Copy(PDataItemSL(List[i])^.AName, Length(CurrPath) + 1, Length(PDataItemSL(List[i])^.AName) - Length(CurrPath)), ', s = ', s]);
end;
- if not (SrcEngine is TVFSEngine) then UpdateCaption1(Format(LANGFromS, [string(PDataItemSL(List[i])^.DataItem^.FDisplayName)])) else
- if (SrcEngine as TVFSEngine).ArchiveMode then UpdateCaption1(Format(LANGFromS, [Format(ConstFullPathFormatStr, [(SrcEngine as TVFSEngine).ArchivePath, string(PDataItemSL(List[i])^.DataItem^.FDisplayName)])]))
- else UpdateCaption1(Format(LANGFromS, [GetURIPrefix((SrcEngine as TVFSEngine).GetPathURI) + StrToUTF8(string(PDataItemSL(List[i])^.DataItem^.FDisplayName))]));
- if not (DestEngine is TVFSEngine) then UpdateCaption2(Format(LANGToS, [StrToUTF8(s)])) else
- if (DestEngine as TVFSEngine).ArchiveMode then UpdateCaption2(Format(LANGToS, [Format(ConstFullPathFormatStr, [(DestEngine as TVFSEngine).ArchivePath, StrToUTF8(s)])]))
- else UpdateCaption2(Format(LANGToS, [GetURIPrefix((DestEngine as TVFSEngine).GetPathURI) + StrToUTF8(s)]));
+ if not (SrcEngine is TVFSEngine) then FCopySourceFile := string(PDataItemSL(List[i])^.DataItem^.FDisplayName) else
+ if (SrcEngine as TVFSEngine).ArchiveMode then FCopySourceFile := Format(ConstFullPathFormatStr, [(SrcEngine as TVFSEngine).ArchivePath, string(PDataItemSL(List[i])^.DataItem^.FDisplayName)])
+ else FCopySourceFile := GetURIPrefix((SrcEngine as TVFSEngine).GetPathURI) + StrToUTF8(string(PDataItemSL(List[i])^.DataItem^.FDisplayName));
+ if not (DestEngine is TVFSEngine) then FCopyDestFile := StrToUTF8(s) else
+ if (DestEngine as TVFSEngine).ArchiveMode then FCopyDestFile := Format(ConstFullPathFormatStr, [(DestEngine as TVFSEngine).ArchivePath, StrToUTF8(s)])
+ else FCopyDestFile := GetURIPrefix((DestEngine as TVFSEngine).GetPathURI) + StrToUTF8(s);
+ UpdateCaption1(Format(LANGFromS, [FCopySourceFile]));
+ UpdateCaption2(Format(LANGToS, [FCopyDestFile]));
CommitGUIUpdate;
if TwoSameFiles(s, string(PDataItemSL(List[i])^.DataItem^.FName), (JobType in [WORKER_JOB_COPY, WORKER_JOB_EXTRACT_TO_TEMP])) and (not PDataItemSL(List[i])^.DataItem^.IsDir) then begin
FCancelMessage := LANGCannotCopyFileToItself;
@@ -1547,7 +1565,7 @@ begin
// if s <> string(PDataItemSL(List[i])^.DataItem^.FName) then
if not HandleCopy(List[i], s) then begin
ErrorHappened := True;
- Break;
+ Break; // Cancelled
end;
if (not PDataItemSL(List[i])^.DataItem^.IsDir) and (not PDataItemSL(List[i])^.DataItem^.IsLnk)
then FTotalDone := FTotalDone + PDataItemSL(List[i])^.DataItem^.Size;
@@ -1596,42 +1614,39 @@ var FD: TEngineFileDes;
PrivateCancel: boolean;
SizeDone: Int64;
TargetName: string;
- Error: PGError;
function PasteFile(FName: string): boolean;
var FDR: TEngineFileDes;
wCount: integer;
Stat: PDataItem;
+ Error: PGError;
begin
Result := False;
+ Error := nil;
if MergeHasInitialCRC then UpdateCaption2(Format(LANGToS, [StrToUTF8(FName)]))
- else UpdateCaption1(Format(LANGFromS, [StrToUTF8(FName)]));
+ else UpdateCaption1(Format(LANGFromS, [StrToUTF8(FName)]));
UpdateProgress1(0, '0 %');
CommitGUIUpdate;
- // * TODO: check error
Stat := AEngine.GetFileInfo(FName, True, True, nil);
if not Assigned(Stat) then Exit;
SetProgress1Params(Stat^.Size);
FreeDataItem(Stat);
- // * TODO: check error
- Error := nil;
FDR := AEngine.OpenFile(FName, omRead, @Error);
if FDR = nil then Exit;
repeat
- // * TODO: check error
Count := AEngine.ReadFile(FDR, Buffer, MergeBlockSize, @Error);
if Error <> nil then begin
AEngine.CloseFile(FD, nil);
Exit;
end;
- // * TODO: check error
wCount := AEngine.WriteFile(FD, Buffer, Count, @Error);
if (Error <> nil) or (Count <> wCount) then begin
FCancelMessage := Format(LANGAnErrorOccuredWhileWritingFileSS, [ExtractFileName(TargetName), Error^.message]);
FShowCancelMessage := True;
PrivateCancel := True;
Result := True; // Fake this to don't show next disc dialog
+ g_error_free(Error);
Exit;
end;
CurrentCRC := CRC32(CurrentCRC, Buffer, Count);
@@ -1640,7 +1655,6 @@ var FD: TEngineFileDes;
if MergeHasInitialCRC then UpdateProgress2(SizeDone, Format('%d %%', [Trunc(SizeDone / FProgress2Max * 100)]));
CommitGUIUpdate;
until (Count < MergeBlockSize) or FCancelled;
- // * TODO: set real error, also free it
AEngine.CloseFile(FDR, nil);
Result := True;
end;
@@ -1649,7 +1663,9 @@ var FD: TEngineFileDes;
var CurrFile, SourcePath, TargetFinalName: string;
HasFinalCRC, b: boolean;
Stat: PDataItem;
+ Error: PGError;
begin
+ Error := nil;
HasFinalCRC := MergeHasInitialCRC;
TargetFinalName := MergeTargetFinalName;
if (Length(MergeSourceFile) > 4) and (WideUpperCase(RightStr(MergeSourceFile, 4)) = '.CRC')
@@ -1661,16 +1677,14 @@ begin
if AEngine.FileExists(TargetName, False) then
if ShowMessageBox(Format(LANGTheTargetFileSAlreadyExistsDoYouWantToOverwriteIt, [StrToUTF8(TargetName)]), [mbYes, mbNo], mbQuestion, mbNone, mbNo) = mbYes then
begin
- // * TODO: check error
-{ Error := Ord(Engine.Remove(TargetName, nil));
- if Error <> 0 then begin
- FCancelMessage := Format(LANGTheTargetFileSCannotBeRemovedS, [StrToUTF8(ExtractFileName(TargetName)), GetErrorString(Error)]);
+ if not AEngine.Remove(TargetName, @Error) then begin
+ FCancelMessage := Format(LANGTheTargetFileSCannotBeRemovedS, [StrToUTF8(ExtractFileName(TargetName)), Error^.message]);
FShowCancelMessage := True;
+ g_error_free(Error);
Exit;
- end; }
+ end;
end else Exit;
- // * TODO: check error
Stat := AEngine.GetFileInfo(MergeSourceFile, True, True, nil);
if Assigned(Stat) then MergeBlockSize := ComputeBlockSize(Stat^.Size)
else MergeBlockSize := 65536*4;
@@ -1683,12 +1697,12 @@ begin
FShowCancelMessage := True;
Exit;
end;
- // * TODO: check error
FD := AEngine.OpenFile(TargetName, omWrite, @Error);
if Error <> nil then begin
FCancelMessage := Format(LANGAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(TargetName), Error^.message]);
FShowCancelMessage := True;
libc_free(Buffer);
+ g_error_free(Error);
Exit;
end;
@@ -1723,8 +1737,16 @@ begin
CurrFile := '';
end;
until (SizeDone = MergeTargetSize) or FCancelled or PrivateCancel {or ((not b) and (not HasInitialCRC))} or (CurrFile = '');
- // * TODO: check error
- if (not MergeHasInitialCRC) and HasFinalCRC then AEngine.RenameFile(TargetName, IncludeTrailingPathDelimiter(ExtractFilePath(TargetName)) + TargetFinalName, nil);
+ libc_free(Buffer);
+ if (not MergeHasInitialCRC) and HasFinalCRC then begin
+ if not AEngine.RenameFile(TargetName, IncludeTrailingPathDelimiter(ExtractFilePath(TargetName)) + TargetFinalName, @Error) then begin
+ FCancelMessage := Format(LANGAnErrorOccuredWhileWritingFileSS, [StrToUTF8(ExtractFileName(TargetName)), Error^.message]);
+ FShowCancelMessage := True;
+ g_error_free(Error);
+ AEngine.CloseFile(FD, nil);
+ Exit;
+ end;
+ end;
if FCancelled and (not PrivateCancel) then begin
FCancelMessage := LANGUserCancelled;
FShowCancelMessage := True;
@@ -1735,9 +1757,11 @@ begin
then ShowMessageBox(Format(LANGMergeOfSSucceeded, [StrToUTF8(ExtractFileName(TargetFinalName))]), [mbOK], mbInfo, mbNone, mbOK)
else ShowMessageBox(LANGWarningCreatedFileFailsCRCCheck, [mbOK], mbWarning, mbNone, mbOK);
end else ShowMessageBox(Format(LANGMergeOfSSucceeded_NoCRCFileAvailable, [StrToUTF8(ExtractFileName(TargetFinalName))]), [mbOK], mbInfo, mbNone, mbOK);
- // * TODO: set real error, also free it
- AEngine.CloseFile(FD, nil);
- libc_free(Buffer);
+ if not AEngine.CloseFile(FD, @Error) then begin
+ FCancelMessage := Format(LANGAnErrorOccuredWhileWritingFileSS, [StrToUTF8(ExtractFileName(TargetName)), Error^.message]);
+ FShowCancelMessage := True;
+ g_error_free(Error);
+ end;
end;
@@ -1748,12 +1772,12 @@ end;
procedure TWorkerThread.SplitFilesWorker;
const SplitBlockSize = 65536*4;
var FD: TEngineFileDes;
- Error: PGError;
FileCRC: LongWord;
Buffer: Pointer;
PrivateCancel: boolean;
FilePath: string;
SizeDone, TDF, FileSize, CurrSize: Int64;
+ Error: PGError;
function WriteSplitPart(TargetFile: string; PartSize: Int64; var Written: Int64): boolean;
@@ -1762,9 +1786,8 @@ var FD: TEngineFileDes;
begin
Result := False;
Written := 0;
- // * TODO: check error
- FDW := AEngine.OpenFile(TargetFile, omWrite, @Error);
DebugMsg(['-- Opening file ', ExtractFileName(TargetFile), ', PartSize = ', PartSize]);
+ FDW := AEngine.OpenFile(TargetFile, omWrite, @Error);
if Error <> nil then Exit;
if SplitMaxSize > 0 then begin
UpdateCaption2(Format(LANGToS, [StrToUTF8(TargetFile)]));
@@ -1773,37 +1796,34 @@ var FD: TEngineFileDes;
end else UpdateCaption1(Format(LANGToS, [StrToUTF8(TargetFile)]));
CommitGUIUpdate;
repeat
- // * TODO: check error
DebugMsg(['Seek to ', AEngine.FileSeek(FD, SizeDone + Written, @Error), ', Written = ', Written]);
+ if Error <> nil then begin
+ AEngine.CloseFile(FDW, nil);
+ Exit;
+ end;
if Written + SplitBlockSize > PartSize then bl := PartSize - Written
else bl := SplitBlockSize;
- // * TODO: check error
Count := AEngine.ReadFile(FD, Buffer, bl, @Error);
if (Error <> nil) or (Count <> bl) then begin
- // * TODO: set real error, also free it
AEngine.CloseFile(FDW, nil);
- DebugMsg(['Read Error: ', Error^.message, ', Count = ', Count, ', bl = ', bl]);
-// if (Count <> bl) and (Error = 0) then Error := EIO;
+ if Error <> nil then
+ DebugMsg(['Read Error: ', Error^.message, ', Count = ', Count, ', bl = ', bl]);
Exit;
end;
- // * TODO: check error
wCount := AEngine.WriteFile(FDW, Buffer, Count, @Error);
Written := Written + wCount;
FileCRC := CRC32(FileCRC, Buffer, wCount);
if (Error <> nil) or (Count <> wCount) then begin
- // * TODO: set real error, also free it
AEngine.CloseFile(FDW, nil);
- // * TODO: check error
- DebugMsg(['Write Error: ', Error^.message, ', Count = ', Count, ', wCount = ', wCount]);
-// if (wCount <> Count) and (Error = 0) then Error := ENOSPC;
+ if Error <> nil then
+ DebugMsg(['Write Error: ', Error^.message, ', Count = ', Count, ', wCount = ', wCount]);
Exit;
end;
UpdateProgress1(FProgress1Pos + wCount, Format('%d %%', [Trunc((FProgress1Pos + wCount) / FProgress1Max * 100)]));
if SplitMaxSize > 0 then UpdateProgress2(FProgress2Pos + wCount, Format('%d %%', [Trunc((FProgress2Pos + wCount) / FProgress2Max * 100)]));
CommitGUIUpdate;
until (Written = PartSize) or FCancelled or PrivateCancel;
- // * TODO: set real error, also free it
- AEngine.CloseFile(FDW, nil);
+ if not AEngine.CloseFile(FDW, @Error) then Exit;
DebugMsg(['-- Closing file ', ExtractFileName(TargetFile), ', PartSize = ', PartSize, ', Written = ', Written]);
Result := True;
end;
@@ -1842,11 +1862,12 @@ var i: integer;
x: Int64;
xx: string;
begin
- // * TODO: check error
- Stat := AEngine.GetFileInfo(SplitSourceFile, True, True, nil);
+ Error := nil;
+ Stat := AEngine.GetFileInfo(SplitSourceFile, True, True, @Error);
if not Assigned(Stat) then begin
- FCancelMessage := Format(LANGCannotOpenFileS, [StrToUTF8(SplitSourceFile)]);
+ FCancelMessage := Format('Cannot open file ''%s'': %s', [StrToUTF8(SplitSourceFile), Error^.message]);
FShowCancelMessage := True;
+ g_error_free(Error);
Exit;
end;
if (SplitMaxSize > 0) and (Stat^.Size > SplitMaxSize * 999) then begin
@@ -1868,11 +1889,11 @@ begin
FShowCancelMessage := True;
Exit;
end;
- // * TODO: check error
FD := AEngine.OpenFile(SplitSourceFile, omRead, @Error);
if Error <> nil then begin
FCancelMessage := Format(LANGAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(SplitSourceFile), Error^.message]);
libc_free(Buffer);
+ g_error_free(Error);
Exit;
end;
FilePath := IncludeTrailingPathDelimiter(ProcessPattern(AEngine, SplitTargetPath, AEngine.Path, '', True));
@@ -1900,9 +1921,8 @@ begin
for i := List.Count - 1 downto 0 do
FreeDataItem(PDataItem(List[i]));
List.Clear;
- // * TODO: check error
-{ Error := Engine.GetListing(List, FilePath, ConfShowDotFiles, False, False, nil);
- if (Error = 0) and (List.Count > 0) then begin
+ b := AEngine.GetListing(List, FilePath, ConfShowDotFiles, False, False, nil);
+ if b and (List.Count > 0) then begin
st := '';
if List.Count < 6 then begin
for i := 0 to List.Count - 1 do
@@ -1911,23 +1931,26 @@ begin
end else b := ShowMessageBox(Format(LANGThereAreDFilesInTheTargetDirectoryDoYouWantToDeleteThem, [List.Count]), [mbYes, mbNo], mbQuestion, mbNone, mbNo) = mbYes;
if b then
for i := 0 to List.Count - 1 do begin
- Error := Engine.Remove(IncludeTrailingPathDelimiter(FilePath) + string(PDataItem(List[i])^.FName));
- if Error <> 0 then ShowMessageBox(Format(LANGTheTargetFileSCannotBeRemovedS, [StrToUTF8(IncludeTrailingPathDelimiter(FilePath)) + string(PDataItem(List[i])^.FDisplayName), GetErrorString(Error)]), [mbOK], mbError, mbNone, mbOK);
+ if not AEngine.Remove(IncludeTrailingPathDelimiter(FilePath) + string(PDataItem(List[i])^.FName), @Error) then begin
+ ShowMessageBox(Format(LANGTheTargetFileSCannotBeRemovedS, [StrToUTF8(IncludeTrailingPathDelimiter(FilePath)) + string(PDataItem(List[i])^.FDisplayName), Error^.message]), [mbOK], mbError, mbNone, mbOK);
+ g_error_free(Error);
+ Error := nil;
+ end;
end;
- end; }
+ end;
except end;
// Test for target file existence
if AEngine.FileExists(IncludeTrailingPathDelimiter(FilePath) + FileName, False) then begin
b := ShowMessageBox(Format(LANGTheTargetFileSAlreadyExistsDoYouWantToOverwriteIt, [StrToUTF8(IncludeTrailingPathDelimiter(FilePath) + FileName)]), [mbYes, mbNo], mbQuestion, mbNone, mbNo) = mbYes;
if b then begin
- // * TODO: check error
-{ Error := Engine.Remove(IncludeTrailingPathDelimiter(FilePath) + FileName);
- if Error <> 0 then begin
- FCancelMessage := Format(LANGTheTargetFileSCannotBeRemovedS, [StrToUTF8(IncludeTrailingPathDelimiter(FilePath) + FileName), GetErrorString(Error)]);
+ if not AEngine.Remove(IncludeTrailingPathDelimiter(FilePath) + FileName, @Error) then begin
+ FCancelMessage := Format(LANGTheTargetFileSCannotBeRemovedS, [StrToUTF8(IncludeTrailingPathDelimiter(FilePath) + FileName), Error^.message]);
FShowCancelMessage := True;
PrivateCancel := True;
+ g_error_free(Error);
+ Error := nil;
Break;
- end; }
+ end;
end else begin
PrivateCancel := True;
Break;
@@ -1940,7 +1963,12 @@ begin
if (CurrSize >= 512) and (TDF >= CurrSize) then begin
b := WriteSplitPart(IncludeTrailingPathDelimiter(FilePath) + FileName, CurrSize, ws);
if (not b) and (SplitMaxSize > 0) then begin
- FCancelMessage := Format(LANGAnErrorOccuredWhileOperationS, [Error^.message]);
+ if Error <> nil then begin
+ FCancelMessage := Format(LANGAnErrorOccuredWhileOperationS, [Error^.message]);
+ g_error_free(Error);
+ Error := nil;
+ end else
+ FCancelMessage := Format(LANGAnErrorOccuredWhileOperationS, ['(unknown)']);
FShowCancelMessage := True;
PrivateCancel := True;
Break;
@@ -1977,7 +2005,6 @@ begin
FShowCancelMessage := True;
end;
end;
- // * TODO: set real error, also free it
AEngine.CloseFile(FD, nil);
if List.Count > 0 then
for i := List.Count - 1 downto 0 do
@@ -1999,31 +2026,25 @@ var SkipAll: boolean;
Error: PGError;
begin
Result := True;
+ Error := nil;
// DebugMsg(['Chmod Debug: IsDir: ', AFileRec^.IsDir, ', Stage1: ', AFileRec^.Stage1, ', IsLnk: ', AFileRec^.IsLnk, '; Result = ', AFileRec^.IsDir and AFileRec^.Stage1 and (not AFileRec^.IsLnk)]);
if AFileRec^.DataItem^.IsDir and (ChmodRecurseType >= 0) and AFileRec^.Stage1 and (not AFileRec^.DataItem^.IsLnk) then Exit;
if (not AFileRec^.DataItem^.IsDir) and (ChmodRecurseType >= 0) and (ChmodRecurseType = 1) then Exit; // Directories only
if AFileRec^.DataItem^.IsDir and (ChmodRecurseType >= 0) and (ChmodRecurseType = 2) then Exit; // Files only
- // * TODO: check error
- Error := nil;
Res := AEngine.Chmod(String(AFileRec^.DataItem^.FName), ChmodMode, @Error);
-// DebugMsg(['Result : ', Res]);
- if not Res then
- if SkipAll then Result := True else
- begin
- // * TODO: check error
- Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, 'Error changing permissions', String(AFileRec^.DataItem^.FDisplayName), Error);
- if Error <> nil then
- g_error_free(Error);
+ if not Res then begin
+ if SkipAll then Result := True
+ else begin
+ Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, 'Error changing permissions', AFileRec^.DataItem^.FDisplayName, Error^.message);
+ g_error_free(Error);
case Response of
DIR_DELETE_SKIP : Result := True;
- DIR_DELETE_SKIP_ALL : begin
- SkipAll := True;
- Result := True;
- end;
+ DIR_DELETE_SKIP_ALL : begin SkipAll := True; Result := True; end;
DIR_DELETE_RETRY : Result := HandleChmod(AFileRec);
else Result := False;
end;
end;
+ end;
end;
var i: longint;
@@ -2086,30 +2107,24 @@ var SkipAll: boolean;
Error: PGError;
begin
Result := True;
+ Error := nil;
// DebugMsg(['Chown Debug: IsDir: ', AFileRec^.IsDir, ', Stage1: ', AFileRec^.Stage1, ', IsLnk: ', AFileRec^.IsLnk, '; Result = ', AFileRec^.IsDir and AFileRec^.Stage1 and (not AFileRec^.IsLnk)]);
if (AFileRec^.DataItem^.IsDir and ChownRecursive and AFileRec^.Stage1 and (not AFileRec^.DataItem^.IsLnk)) or
((not AFileRec^.DataItem^.IsDir) and ChownRecursive) then Exit;
- // * TODO: check error
- Error := nil;
Res := AEngine.Chown(String(AFileRec^.DataItem^.FName), ChownUID, ChownGID, @Error);
-// DebugMsg(['Result : ', Res]);
- if not Res then
- if SkipAll then Result := True else
- begin
- // * TODO: check error
- Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, 'Error changing owner', String(AFileRec^.DataItem^.FDisplayName), Error);
- if Error <> nil then
- g_error_free(Error);
+ if not Res then begin
+ if SkipAll then Result := True
+ else begin
+ Response := ShowDirDeleteDialog(DIR_DELETE_SET_DELETE_ERROR, 'Error changing owner', AFileRec^.DataItem^.FDisplayName, Error^.message);
+ g_error_free(Error);
case Response of
DIR_DELETE_SKIP : Result := True;
- DIR_DELETE_SKIP_ALL : begin
- SkipAll := True;
- Result := True;
- end;
+ DIR_DELETE_SKIP_ALL : begin SkipAll := True; Result := True; end;
DIR_DELETE_RETRY : Result := HandleChown(AFileRec);
else Result := False;
end;
end;
+ end;
end;
var i: longint;
@@ -2246,11 +2261,17 @@ begin
// AutoFallback loop
repeat
+ if ChDirError <> nil then begin
+ g_error_free(ChDirError);
+ ChDirError := nil;
+ end;
if Engine is TVFSEngine
then Result := (Engine as TVFSEngine).ChangeDirEx(APath, @vfs_ask_question_callback, @vfs_ask_password_callback, nil, Self, @ChDirError)
else Result := Engine.ChangeDir(APath, @ChDirError);
- if not Result then
- GoUp(APath);
+ if not Result then begin
+ PrefixTuxcmdError(@ChDirError, ExcludeTrailingPathDelimiter(APath));
+ GoUp(APath);
+ end;
until Result or (not AutoFallback) or (Length(APath) <= 1);
if Result then
Engine.Path := APath;
@@ -2282,8 +2303,10 @@ begin
if VFSOpenResult and (not FCancelled) then begin
ChDirResult := ChangeDir(AEngine, APath, ASelItem, AAutoFallBack);
- if ChDirResult and (not FCancelled) then
+ if ChDirResult and (not FCancelled) then begin
ListingResult := AEngine.GetListing(ADirList, AEngine.GetPath, ConfShowDotFiles, True, False, @ListingError);
+ if not ListingResult then PrefixTuxcmdError(@ListingError, AEngine.GetPath);
+ end;
end;
except
on E: Exception do DebugMsg(['*** Exception raised in TOpenDirThread.Execute (', E.ClassName, '): ', E.Message]);
diff --git a/UDirDelete.pas b/UDirDelete.pas
index 8d22d42..3a3b4c5 100644
--- a/UDirDelete.pas
+++ b/UDirDelete.pas
@@ -22,7 +22,7 @@ unit UDirDelete;
interface
uses
- SysUtils, Types, Classes, Variants, GTKControls, GTKForms, GTKStdCtrls, GTKExtCtrls, GTKConsts;
+ SysUtils, Classes, Variants, GTKControls, GTKForms, GTKStdCtrls, GTKConsts;
const DIR_DELETE_CANCEL = 0;
DIR_DELETE_DELETE = 1;
@@ -60,10 +60,10 @@ begin
WindowPosition := wpCenter;
Caption := '';
Label1 := TGTKLabel.Create(Self);
- Label1.Caption := 'The directory /tmp is not empty!';
+ Label1.UseMarkup := True;
Label2 := TGTKLabel.Create(Self);
- Label2.Caption := LANGDoYouWantToDeleteItWithAllItsFilesAndSubdirectories;
Label3 := TGTKLabel.Create(Self);
+ Label3.UseMarkup := True;
Label3.Visible := False;
ClientArea.AddControlEx(Label1, True, True, 0);
ClientArea.AddControlEx(Label2, True, True, 0);
diff --git a/UEngines.pas b/UEngines.pas
index 4891314..8a0e9e6 100644
--- a/UEngines.pas
+++ b/UEngines.pas
@@ -29,8 +29,8 @@ const omRead = 0;
omAppend = 2;
ConfDefaultDirCreationMask = 755;
-
-
+
+
type
PDataItem = ^TDataItem;
TDataItem = record
@@ -103,8 +103,8 @@ type
// Copy-related routines
function GetBlockSize: guint32; virtual; abstract;
procedure SetBlockSize(Value: guint32); virtual; abstract;
- function CopyFileIn(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean; virtual; abstract; // returns True if file is successfully copied
- function CopyFileOut(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean; virtual; abstract; // returns True if file is successfully copied
+ function CopyFileIn(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer; Error: PPGError): boolean; virtual; abstract; // returns True if file is successfully copied
+ function CopyFileOut(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer; Error: PPGError): boolean; virtual; abstract; // returns True if file is successfully copied
function IsOnSameFS(const Path1, Path2: string; FollowSymlinks: boolean): boolean; virtual; abstract;
function TwoSameFiles(const Path1, Path2: string; FollowSymlinks: boolean): boolean; virtual; abstract;
@@ -153,8 +153,8 @@ type
function GetBlockSize: guint32; override;
procedure SetBlockSize(Value: guint32); override;
- function CopyFileIn(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean; override;
- function CopyFileOut(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean; override;
+ function CopyFileIn(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer; Error: PPGError): boolean; override;
+ function CopyFileOut(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer; Error: PPGError): boolean; override;
function IsOnSameFS(const Path1, Path2: string; FollowSymlinks: boolean): boolean; override;
function TwoSameFiles(const Path1, Path2: string; FollowSymlinks: boolean): boolean; override;
@@ -235,26 +235,21 @@ var Item: PDataItem;
Handle: PDIR;
DirEnt: PDirent64;
Buf: PChar;
- saved_errno: integer;
- FError: PGError;
begin
Result := False;
try
if libc_chdir(PChar(APath)) <> 0 then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error changing directory to ''''%s'''': %s', StrToUTF8(PChar(APath)), g_strerror(saved_errno));
- DebugMsg(['*** TLocalTreeEngine.GetListing(APath=', APath, '): chdir error: ', strerror(saved_errno)]);
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_CHDIR), '%m');
+ DebugMsg(['*** TLocalTreeEngine.GetListing(APath=', APath, '): chdir error: ', strerror(errno)]);
Exit;
end;
Handle := opendir(PChar(APath));
if Handle = nil then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error opening directory ''''%s'''': %s', StrToUTF8(PChar(APath)), g_strerror(saved_errno));
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_OPENDIR), '%m');
DebugMsg(['*** TLocalTreeEngine.GetListing(APath=', APath, '): opendir() handle == NULL: ', strerror(errno)]);
Exit;
end;
- FError := nil;
repeat
DirEnt := readdir64(Handle);
if (DirEnt <> nil) and (DirEnt^.d_name[0] <> #0) then begin
@@ -269,14 +264,13 @@ begin
List.Add(Item);
end;
end;
- until (DirEnt = nil) or (FError <> nil);
+ until (DirEnt = nil);
closedir(Handle);
-
- if FError <> nil then g_propagate_error(Error, FError)
- else Result := True;
+ Result := True;
except
on E: Exception do begin
Result := False;
+ tuxcmd_set_error_from_exception(Error, E);
DebugMsg(['*** TLocalTreeEngine.GetListing(APath=', APath, ') -Exception: ', E.Message]);
Exit;
end;
@@ -288,14 +282,12 @@ var Item: PDataItem;
StatBuf: Pstat64;
LnkBuf: array[0..65535] of char;
i: integer;
- saved_errno: integer;
begin
StatBuf := malloc(sizeof(Tstat64));
memset(StatBuf, 0, sizeof(Tstat64));
if lstat64(PChar(APath), StatBuf) <> 0 then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error getting file info for ''''%s'''': %s', StrToUTF8(PChar(APath)), g_strerror(saved_errno));
- DebugMsg(['*** TLocalTreeEngine.GetFileInfo(APath=', APath, '): Error reading file via lstat64: ', strerror(saved_errno)]);
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_STAT), '%m');
+ DebugMsg(['*** TLocalTreeEngine.GetFileInfo(APath=', APath, '): Error reading file via lstat64: ', strerror(errno)]);
libc_free(StatBuf);
Result := nil;
Exit;
@@ -388,20 +380,17 @@ end;
function TLocalTreeEngine.ChangeDir(const NewPath: string; Error: PPGError): boolean;
var APath: string;
Handle : PDIR;
- saved_errno: integer;
begin
Result := False;
try
APath := IncludeTrailingPathDelimiter(NewPath);
if libc_chdir(PChar(APath)) <> 0 then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error changing directory to ''''%s'''': %s', StrToUTF8(PChar(NewPath)), g_strerror(saved_errno));
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_CHDIR), '%m');
Exit;
end;
Handle := opendir(PChar(APath));
if Handle = nil then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error changing directory to ''''%s'''': %s', StrToUTF8(PChar(NewPath)), g_strerror(saved_errno));
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_OPENDIR), '%m');
Exit;
end;
{ if not Assigned(readdir(Handle)) then begin
@@ -409,14 +398,13 @@ begin
Exit;
end; }
if closedir(Handle) <> 0 then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error changing directory to ''''%s'''': %s', StrToUTF8(PChar(NewPath)), g_strerror(saved_errno));
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_OPENDIR), '%m');
Exit;
end;
Result := True;
except
on E: Exception do begin
- Result := False;
+ tuxcmd_set_error_from_exception(Error, E);
DebugMsg(['*** TLocalTreeEngine.ChangeDir(APath=', APath, ') -Exception: ', E.Message]);
Exit;
end;
@@ -476,76 +464,63 @@ end;
(********************************************************************************************************************************)
function TLocalTreeEngine.MakeDir(const NewDir: string; Error: PPGError): boolean;
-var saved_errno: integer;
begin
Result := False;
if __mkdir(PChar(NewDir), OctalToAttr(ConfDefaultDirCreationMask)) <> 0 then begin
- if Self.DirectoryExists(NewDir, False) or (@g_mkdir_with_parents = nil) or (g_mkdir_with_parents(PChar(NewDir), OctalToAttr(ConfDefaultDirCreationMask)) <> 0) then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error creating directory ''''%s'''': %s', StrToUTF8(PChar(NewDir)), g_strerror(saved_errno));
- end else Result := True;
+ if Self.DirectoryExists(NewDir, False) or (@g_mkdir_with_parents = nil) or (g_mkdir_with_parents(PChar(NewDir), OctalToAttr(ConfDefaultDirCreationMask)) <> 0)
+ then g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_MKDIR), '%m')
+ else Result := True;
end else Result := True;
end;
(********************************************************************************************************************************)
function TLocalTreeEngine.Remove(const APath: string; Error: PPGError): boolean;
-var saved_errno: integer;
begin
Result := False;
if libc_remove(PChar(ExcludeTrailingPathDelimiter(APath))) <> 0 then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error deleting ''''%s'''': %s', StrToUTF8(PChar(APath)), g_strerror(saved_errno));
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_REMOVE), '%m');
end else Result := True;
end;
(********************************************************************************************************************************)
function TLocalTreeEngine.MakeSymLink(const NewFileName, PointTo: string; Error: PPGError): boolean;
-var saved_errno: integer;
begin
Result := False;
if symlink(PChar(PointTo), PChar(NewFileName)) <> 0 then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error creating symlink ''''%s'''': %s', StrToUTF8(PChar(NewFileName)), g_strerror(saved_errno));
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SYMLINK), '%m');
end else Result := True;
end;
(********************************************************************************************************************************)
function TLocalTreeEngine.Chmod(const FileName: string; Mode: cuLong; Error: PPGError): boolean;
-var saved_errno: integer;
begin
Result := False;
if libc_chmod(PChar(FileName), Mode) <> 0 then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error during chmod of ''''%s'''': %s', StrToUTF8(PChar(FileName)), g_strerror(saved_errno));
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_CHMOD), '%m');
end else Result := True;
end;
(********************************************************************************************************************************)
function TLocalTreeEngine.Chown(const FileName: string; UID, GID: cuLong; Error: PPGError): boolean;
-var saved_errno: integer;
begin
Result := False;
if libc_chown(PChar(FileName), UID, GID) <> 0 then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error during chown of ''''%s'''': %s', StrToUTF8(PChar(FileName)), g_strerror(saved_errno));
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_CHOWN), '%m');
end else Result := True;
end;
(********************************************************************************************************************************)
function TLocalTreeEngine.RenameFile(const SourceFile, DestFile: string; Error: PPGError): boolean;
-var saved_errno: integer;
begin
Result := False;
if libc_rename(PChar(SourceFile), PChar(DestFile)) <> 0 then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error renaming file ''''%s'''': %s', StrToUTF8(PChar(SourceFile)), g_strerror(saved_errno));
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_RENAME), '%m');
end else Result := True;
end;
(********************************************************************************************************************************)
function TLocalTreeEngine.ChangeTimes(const APath: string; mtime, atime: time_t; Error: PPGError): boolean;
var timebuf: Putimbuf;
- saved_errno: integer;
begin
Result := False;
try
@@ -554,87 +529,85 @@ begin
timebuf^.actime := atime;
timebuf^.modtime := mtime;
if utime(PChar(APath), timebuf) <> 0 then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error while changing timestamps of ''''%s'''': %s', StrToUTF8(PChar(APath)), g_strerror(saved_errno));
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_TIMESTAMPS), '%m');
end else Result := True;
libc_free(timebuf);
except
- on E: Exception do DebugMsg(['*** Exception raised in TLocalTreeEngine.ChangeTimes(APath=', APath, '): (', E.ClassName, '): ', E.Message]);
+ on E: Exception do begin
+ tuxcmd_set_error_from_exception(Error, E);
+ DebugMsg(['*** Exception raised in TLocalTreeEngine.ChangeTimes(APath=', APath, '): (', E.ClassName, '): ', E.Message]);
+ Result := False;
+ end;
end;
end;
(********************************************************************************************************************************)
-function TLocalTreeEngine.CopyFileIn(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean;
+function TLocalTreeEngine.CopyFileIn(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer; Error: PPGError): boolean;
begin
- Result := CopyFileOut(SourceFile, DestFile, Append, ProgressFunc, Sender);
+ Result := CopyFileOut(SourceFile, DestFile, Append, ProgressFunc, Sender, Error);
end;
-function TLocalTreeEngine.CopyFileOut(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean;
+function TLocalTreeEngine.CopyFileOut(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer; Error: PPGError): boolean;
var fsrc, fdest: PFILE;
Buffer: Pointer;
BytesDone, BytesRead, BytesWritten: Int64;
- Ignore: boolean;
- saved_errno: integer;
- Error: PGError;
begin
Result := False;
- Error := nil;
+ BytesDone := 0;
try
// Open source file for reading
fsrc := fopen64(PChar(SourceFile), 'r');
if fsrc = nil then begin
- if @ProgressFunc <> nil then begin
- saved_errno := errno;
- g_set_error(@Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error opening source file ''''%s'''': %s', StrToUTF8(PChar(SourceFile)), g_strerror(saved_errno));
- ProgressFunc(Sender, 0, Error);
- g_error_free(Error);
- end;
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SOURCE_OPEN), '%m');
+ if @ProgressFunc <> nil then
+ ProgressFunc(Sender, 0, Error^);
Exit;
end;
// Open target file for writing/appending
if Append then fdest := fopen64(PChar(DestFile), 'a')
else fdest := fopen64(PChar(DestFile), 'w');
- if fsrc = nil then begin
- if @ProgressFunc <> nil then begin
- saved_errno := errno;
- g_set_error(@Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error opening target file ''''%s'''': %s', StrToUTF8(PChar(DestFile)), g_strerror(saved_errno));
- ProgressFunc(Sender, 0, Error);
- g_error_free(Error);
- end;
+ if fdest = nil then begin
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_TARGET_OPEN), '%m');
fclose(fsrc);
+ if @ProgressFunc <> nil then
+ ProgressFunc(Sender, 0, Error^);
Exit;
end;
- BytesDone := 0;
Buffer := malloc(FBlockSize);
+ if Buffer = nil then begin
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_ALLOC_FAILED), '%m');
+ fclose(fdest);
+ fclose(fsrc);
+ if @ProgressFunc <> nil then
+ ProgressFunc(Sender, 0, Error^);
+ Exit;
+ end;
while feof(fsrc) = 0 do begin
- Error := nil;
-
// Read block
BytesRead := fread(Buffer, 1, FBlockSize, fsrc);
if (BytesRead < FBlockSize) and (feof(fsrc) = 0) then begin
- Ignore := False;
- if @ProgressFunc <> nil then begin
- saved_errno := errno;
- g_set_error(@Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error reading from source file ''''%s'''': %s', StrToUTF8(PChar(SourceFile)), g_strerror(saved_errno));
- Ignore := ProgressFunc(Sender, BytesDone + BytesRead, Error);
- g_error_free(Error);
- end;
- if Ignore then Continue
- else Break;
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SOURCE_READ), '%m');
+ Result := False;
+ if @ProgressFunc <> nil then
+ Result := ProgressFunc(Sender, BytesDone + BytesRead, Error^);
+ if Result then begin
+ // user has chosen to ignore the error
+ g_error_free(Error^);
+ Error^ := nil;
+ Continue;
+ end else Break;
end;
// Write block
BytesWritten := fwrite(Buffer, 1, BytesRead, fdest);
if BytesWritten < BytesRead then begin
- if @ProgressFunc <> nil then begin
- saved_errno := ferror(fdest);
- g_set_error(@Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error writing to target file ''''%s'''': %s', StrToUTF8(PChar(DestFile)), g_strerror(saved_errno));
- ProgressFunc(Sender, BytesDone + BytesWritten, Error);
- g_error_free(Error);
- end;
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_TARGET_WRITE), '%m');
+ Result := False;
+ if @ProgressFunc <> nil then
+ ProgressFunc(Sender, BytesDone + BytesRead, Error^);
Break; // We cannot ignore write errors
end;
@@ -642,34 +615,41 @@ begin
if (@ProgressFunc <> nil) and (not ProgressFunc(Sender, BytesDone, nil)) then
Break;
end;
- Result := feof(fsrc) <> 0;
+ Result := (feof(fsrc) <> 0) and (Error^ = nil);
libc_free(Buffer);
if fclose(fdest) <> 0 then begin
- fclose(fsrc);
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_TARGET_CLOSE), '%m');
Result := False;
- if @ProgressFunc <> nil then begin
- Error := nil;
- saved_errno := errno;
- g_set_error(@Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error closing target file ''''%s'''': %s', StrToUTF8(PChar(DestFile)), g_strerror(saved_errno));
- Result := ProgressFunc(Sender, BytesDone, Error);
- g_error_free(Error);
- end;
+ if @ProgressFunc <> nil then
+ ProgressFunc(Sender, BytesDone, Error^);
+ fclose(fsrc);
Exit;
end;
if fclose(fsrc) <> 0 then begin
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SOURCE_CLOSE), '%m');
Result := False;
- if @ProgressFunc <> nil then begin
- Error := nil;
- saved_errno := errno;
- g_set_error(@Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error closing source file ''''%s'''': %s', StrToUTF8(PChar(SourceFile)), g_strerror(saved_errno));
- Result := ProgressFunc(Sender, BytesDone, Error);
- g_error_free(Error);
- end;
- Exit;
+ if @ProgressFunc <> nil then
+ Result := ProgressFunc(Sender, BytesDone, Error^);
+ if Result then begin
+ // user has chosen to ignore the error
+ g_error_free(Error^);
+ Error^ := nil;
+ end else Exit;
end;
except
- on E: Exception do DebugMsg(['*** Exception raised in TLocalTreeEngine.CopyFile(Sender=', Sender, ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]);
+ on E: Exception do begin
+ Result := False;
+ tuxcmd_set_error_from_exception(@Error, E);
+ DebugMsg(['*** Exception raised in TLocalTreeEngine.CopyFile(Sender=', Sender, ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]);
+ if @ProgressFunc <> nil then
+ Result := ProgressFunc(Sender, BytesDone, Error^);
+ if Result then begin
+ // user has chosen to ignore the error
+ g_error_free(Error^);
+ Error^ := nil;
+ end;
+ end;
end;
end;
@@ -802,7 +782,6 @@ end;
(********************************************************************************************************************************)
function TLocalTreeEngine.OpenFile(const APath: string; Mode: integer; Error: PPGError): TEngineFileDes;
var m: PChar;
- saved_errno: integer;
begin
case Mode of
omRead: m := 'r';
@@ -811,54 +790,40 @@ begin
else m := 'r';
end;
Result := fopen64(PChar(APath), m);
- if Result = nil then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error opening file ''''%s'''': %s', StrToUTF8(PChar(APath)), g_strerror(saved_errno));
- end;
+ if Result = nil then
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_OPEN_FILE), '%m');
end;
(********************************************************************************************************************************)
function TLocalTreeEngine.ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; Error: PPGError): integer;
-var saved_errno: integer;
begin
Result := fread(Buffer, 1, ABlockSize, FileDescriptor);
- if (Result = 0) and (feof(FileDescriptor) = 0) then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error reading from file: %s', g_strerror(saved_errno));
- end;
+ if (Result = 0) and (feof(FileDescriptor) = 0) then
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_READ_FILE), '%m');
end;
(********************************************************************************************************************************)
function TLocalTreeEngine.WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; Error: PPGError): integer;
-var saved_errno: integer;
begin
Result := fwrite(Buffer, 1, BytesCount, FileDescriptor);
- if Result < BytesCount then begin
- saved_errno := ferror(FileDescriptor);
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error writing to file: %s', g_strerror(saved_errno));
- end;
+ if Result < BytesCount then
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_WRITE_FILE), '%m');
end;
(********************************************************************************************************************************)
function TLocalTreeEngine.CloseFile(const FileDescriptor: TEngineFileDes; Error: PPGError): boolean;
-var saved_errno: integer;
begin
Result := fclose(FileDescriptor) = 0;
- if not Result then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error closing file: %s', g_strerror(saved_errno));
- end;
+ if not Result then
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_CLOSE_FILE), '%m');
end;
(********************************************************************************************************************************)
function TLocalTreeEngine.FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; Error: PPGError): Int64;
-var saved_errno: integer;
begin
Result := fseeko64(FileDescriptor, AbsoluteOffset, SEEK_SET);
- if Result = -1 then begin
- saved_errno := errno;
- g_set_error(Error, G_IO_ERROR, gint(g_io_error_from_errno(saved_errno)), 'Error seeking in file: %s', g_strerror(saved_errno));
- end;
+ if Result = -1 then
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SEEK), '%m');
end;
(********************************************************************************************************************************)
diff --git a/UError.pas b/UError.pas
index 6734367..d557189 100644
--- a/UError.pas
+++ b/UError.pas
@@ -23,54 +23,107 @@ interface
uses glib2, gtk2, Classes, SysUtils, ULibc, GTKForms;
+type TuxcmdErrorEnum = (
+ TUXCMD_ERROR_CANCELLED,
+ TUXCMD_ERROR_EXCEPTION,
+ TUXCMD_ERROR_NOT_SUPPORTED,
+ // Basic IO
+ TUXCMD_ERROR_CHDIR,
+ TUXCMD_ERROR_OPENDIR,
+ TUXCMD_ERROR_STAT,
+ TUXCMD_ERROR_MKDIR,
+ TUXCMD_ERROR_REMOVE,
+ TUXCMD_ERROR_SYMLINK,
+ TUXCMD_ERROR_CHMOD,
+ TUXCMD_ERROR_CHOWN,
+ TUXCMD_ERROR_RENAME,
+ TUXCMD_ERROR_TIMESTAMPS,
+ // File IO
+ TUXCMD_ERROR_OPEN_FILE,
+ TUXCMD_ERROR_READ_FILE,
+ TUXCMD_ERROR_WRITE_FILE,
+ TUXCMD_ERROR_CLOSE_FILE,
+ TUXCMD_ERROR_SEEK,
+ // File copy
+ TUXCMD_ERROR_ALLOC_FAILED,
+ TUXCMD_ERROR_SOURCE_OPEN,
+ TUXCMD_ERROR_TARGET_OPEN,
+ TUXCMD_ERROR_SOURCE_READ,
+ TUXCMD_ERROR_TARGET_WRITE,
+ TUXCMD_ERROR_SOURCE_CLOSE,
+ TUXCMD_ERROR_TARGET_CLOSE
+);
-// Ported from gioerror.h
-
-type GIOErrorEnum = (G_IO_ERROR_FAILED,
- G_IO_ERROR_NOT_FOUND,
- G_IO_ERROR_EXISTS,
- G_IO_ERROR_IS_DIRECTORY,
- G_IO_ERROR_NOT_DIRECTORY,
- G_IO_ERROR_NOT_EMPTY,
- G_IO_ERROR_NOT_REGULAR_FILE,
- G_IO_ERROR_NOT_SYMBOLIC_LINK,
- G_IO_ERROR_NOT_MOUNTABLE_FILE,
- G_IO_ERROR_FILENAME_TOO_LONG,
- G_IO_ERROR_INVALID_FILENAME,
- G_IO_ERROR_TOO_MANY_LINKS,
- G_IO_ERROR_NO_SPACE,
- G_IO_ERROR_INVALID_ARGUMENT,
- G_IO_ERROR_PERMISSION_DENIED,
- G_IO_ERROR_NOT_SUPPORTED,
- G_IO_ERROR_NOT_MOUNTED,
- G_IO_ERROR_ALREADY_MOUNTED,
- G_IO_ERROR_CLOSED,
- G_IO_ERROR_CANCELLED,
- G_IO_ERROR_PENDING,
- G_IO_ERROR_READ_ONLY,
- G_IO_ERROR_CANT_CREATE_BACKUP,
- G_IO_ERROR_WRONG_ETAG,
- G_IO_ERROR_TIMED_OUT,
- G_IO_ERROR_WOULD_RECURSE,
- G_IO_ERROR_BUSY,
- G_IO_ERROR_WOULD_BLOCK,
- G_IO_ERROR_HOST_NOT_FOUND,
- G_IO_ERROR_WOULD_MERGE,
- G_IO_ERROR_FAILED_HANDLED,
- G_IO_ERROR_TOO_MANY_OPEN_FILES,
- G_IO_ERROR_NOT_INITIALIZED,
- G_IO_ERROR_ADDRESS_IN_USE,
- G_IO_ERROR_PARTIAL_INPUT,
- G_IO_ERROR_INVALID_DATA);
+// Ported from gioerror.h, glib-2.83.0
+type GIOErrorEnum = (
+ G_IO_ERROR_FAILED,
+ G_IO_ERROR_NOT_FOUND,
+ G_IO_ERROR_EXISTS,
+ G_IO_ERROR_IS_DIRECTORY,
+ G_IO_ERROR_NOT_DIRECTORY,
+ G_IO_ERROR_NOT_EMPTY,
+ G_IO_ERROR_NOT_REGULAR_FILE,
+ G_IO_ERROR_NOT_SYMBOLIC_LINK,
+ G_IO_ERROR_NOT_MOUNTABLE_FILE,
+ G_IO_ERROR_FILENAME_TOO_LONG,
+ G_IO_ERROR_INVALID_FILENAME,
+ G_IO_ERROR_TOO_MANY_LINKS,
+ G_IO_ERROR_NO_SPACE,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ G_IO_ERROR_PERMISSION_DENIED,
+ G_IO_ERROR_NOT_SUPPORTED,
+ G_IO_ERROR_NOT_MOUNTED,
+ G_IO_ERROR_ALREADY_MOUNTED,
+ G_IO_ERROR_CLOSED,
+ G_IO_ERROR_CANCELLED,
+ G_IO_ERROR_PENDING,
+ G_IO_ERROR_READ_ONLY,
+ G_IO_ERROR_CANT_CREATE_BACKUP,
+ G_IO_ERROR_WRONG_ETAG,
+ G_IO_ERROR_TIMED_OUT,
+ G_IO_ERROR_WOULD_RECURSE,
+ G_IO_ERROR_BUSY,
+ G_IO_ERROR_WOULD_BLOCK,
+ G_IO_ERROR_HOST_NOT_FOUND,
+ G_IO_ERROR_WOULD_MERGE,
+ G_IO_ERROR_FAILED_HANDLED,
+ G_IO_ERROR_TOO_MANY_OPEN_FILES,
+ G_IO_ERROR_NOT_INITIALIZED,
+ G_IO_ERROR_ADDRESS_IN_USE,
+ G_IO_ERROR_PARTIAL_INPUT,
+ G_IO_ERROR_INVALID_DATA,
+ G_IO_ERROR_DBUS_ERROR,
+ G_IO_ERROR_HOST_UNREACHABLE,
+ G_IO_ERROR_NETWORK_UNREACHABLE,
+ G_IO_ERROR_CONNECTION_REFUSED,
+ G_IO_ERROR_PROXY_FAILED,
+ G_IO_ERROR_PROXY_AUTH_FAILED,
+ G_IO_ERROR_PROXY_NEED_AUTH,
+ G_IO_ERROR_PROXY_NOT_ALLOWED,
+ G_IO_ERROR_BROKEN_PIPE,
+// G_IO_ERROR_CONNECTION_CLOSED = G_IO_ERROR_BROKEN_PIPE,
+ G_IO_ERROR_NOT_CONNECTED,
+ G_IO_ERROR_MESSAGE_TOO_LARGE,
+ G_IO_ERROR_NO_SUCH_DEVICE,
+ G_IO_ERROR_DESTINATION_UNSET
+);
+
+const G_IO_ERROR_CONNECTION_CLOSED = G_IO_ERROR_BROKEN_PIPE;
+
+
+function tuxcmd_error_quark: TGQuark;
+function TUXCMD_ERROR: TGQuark;
function g_io_error_quark: TGQuark;
function G_IO_ERROR: TGQuark;
function g_io_error_from_errno(err_no: gint): GIOErrorEnum;
-procedure g_set_error_from_exception(Error: PPGError; E: Exception);
+procedure tuxcmd_set_error_from_exception(Error: PPGError; E: Exception);
procedure ShowError(Parent: TCustomGTKForm; const Text: string; Error: PGError);
+procedure PrefixTuxcmdError(Error: PPGError; const FileName: string);
+procedure VFSToTuxcmdError(Error: PPGError; Operation: TuxcmdErrorEnum);
implementation
@@ -78,6 +131,16 @@ uses UCoreUtils, UGnome;
(********************************************************************************************************************************)
+function tuxcmd_error_quark: TGQuark;
+begin
+ Result := g_quark_from_static_string('tuxcmd-error-quark');
+end;
+
+function TUXCMD_ERROR: TGQuark;
+begin
+ Result := tuxcmd_error_quark;
+end;
+
function g_io_error_quark: TGQuark;
begin
Result := g_quark_from_static_string('g-io-error-quark');
@@ -90,6 +153,11 @@ end;
function g_io_error_from_errno(err_no: gint): GIOErrorEnum;
begin
+ // Prefer native library call
+ if @__g_io_error_from_errno <> nil then begin
+ Result := __g_io_error_from_errno(err_no);
+ Exit;
+ end;
case err_no of
EEXIST: Result := G_IO_ERROR_EXISTS;
EISDIR: Result := G_IO_ERROR_IS_DIRECTORY;
@@ -103,23 +171,40 @@ begin
ENOMEM: Result := G_IO_ERROR_NO_SPACE;
EINVAL: Result := G_IO_ERROR_INVALID_ARGUMENT;
EPERM: Result := G_IO_ERROR_PERMISSION_DENIED;
+ EMLINK: Result := G_IO_ERROR_TOO_MANY_LINKS;
+ ENOMSG: Result := G_IO_ERROR_INVALID_DATA;
+ ENODATA: Result := G_IO_ERROR_INVALID_DATA;
+ EBADMSG: Result := G_IO_ERROR_INVALID_DATA;
ECANCELED: Result := G_IO_ERROR_CANCELLED;
ENOTEMPTY: Result := G_IO_ERROR_NOT_EMPTY;
ENOTSUP: Result := G_IO_ERROR_NOT_SUPPORTED;
+ EPROTONOSUPPORT: Result := G_IO_ERROR_NOT_SUPPORTED;
+ ESOCKTNOSUPPORT: Result := G_IO_ERROR_NOT_SUPPORTED;
+ EPFNOSUPPORT: Result := G_IO_ERROR_NOT_SUPPORTED;
+ EAFNOSUPPORT: Result := G_IO_ERROR_NOT_SUPPORTED;
ETIMEDOUT: Result := G_IO_ERROR_TIMED_OUT;
EBUSY: Result := G_IO_ERROR_BUSY;
EAGAIN: Result := G_IO_ERROR_WOULD_BLOCK;
EMFILE: Result := G_IO_ERROR_TOO_MANY_OPEN_FILES;
EADDRINUSE: Result := G_IO_ERROR_ADDRESS_IN_USE;
+ EHOSTUNREACH: Result := G_IO_ERROR_HOST_UNREACHABLE;
+ ENETUNREACH: Result := G_IO_ERROR_NETWORK_UNREACHABLE;
+ ENETDOWN: Result := G_IO_ERROR_NETWORK_UNREACHABLE;
+ ECONNREFUSED: Result := G_IO_ERROR_CONNECTION_REFUSED;
+ EADDRNOTAVAIL: Result := G_IO_ERROR_CONNECTION_REFUSED;
+ ECONNRESET: Result := G_IO_ERROR_CONNECTION_CLOSED;
+ ENOTCONN: Result := G_IO_ERROR_NOT_CONNECTED;
+ EDESTADDRREQ: Result := G_IO_ERROR_DESTINATION_UNSET;
+ EMSGSIZE: Result := G_IO_ERROR_MESSAGE_TOO_LARGE;
+ ENOTSOCK: Result := G_IO_ERROR_INVALID_ARGUMENT;
else Result := G_IO_ERROR_FAILED;
end;
end;
-
(********************************************************************************************************************************)
-procedure g_set_error_from_exception(Error: PPGError; E: Exception);
+procedure tuxcmd_set_error_from_exception(Error: PPGError; E: Exception);
begin
- g_set_error(Error, G_IO_ERROR, integer(G_IO_ERROR_FAILED), 'Exception raised: %s', PChar(E.Message));
+ g_set_error(Error, TUXCMD_ERROR, integer(TUXCMD_ERROR_EXCEPTION), 'Exception raised: %s', PChar(E.Message));
end;
(********************************************************************************************************************************)
@@ -142,5 +227,72 @@ begin
gtk_widget_destroy (PGtkWidget(Dialog));
end;
+procedure PrefixTuxcmdError(Error: PPGError; const FileName: string);
+begin
+ if (Error = nil) or (Error^ = nil) then Exit;
+ if (Error^.domain <> TUXCMD_ERROR) then Exit;
+ case TuxcmdErrorEnum(Error^.code) of
+ TUXCMD_ERROR_CHDIR: g_prefix_error(Error, 'Error changing directory to ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_OPENDIR: g_prefix_error(Error, 'Error opening directory ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_STAT: g_prefix_error(Error, 'Error getting file info for ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_MKDIR: g_prefix_error(Error, 'Error creating directory ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_REMOVE: g_prefix_error(Error, 'Error deleting ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_SYMLINK: g_prefix_error(Error, 'Error creating symlink ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_CHMOD: g_prefix_error(Error, 'Error changing permissions of ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_CHOWN: g_prefix_error(Error, 'Error changing owner/group of ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_RENAME: g_prefix_error(Error, 'Error renaming file ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_TIMESTAMPS: g_prefix_error(Error, 'Error changing timestamps of ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_OPEN_FILE: g_prefix_error(Error, 'Error opening file ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_READ_FILE: g_prefix_error(Error, 'Error reading file ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_WRITE_FILE: g_prefix_error(Error, 'Error writing file ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_CLOSE_FILE: g_prefix_error(Error, 'Error closing file ''%s'': ', StrToUTF8(PChar(FileName)));
+ TUXCMD_ERROR_SEEK: g_prefix_error(Error, 'Error seeking in file ''%s'': ', StrToUTF8(PChar(FileName)));
+ end;
+end;
+
+procedure VFSToTuxcmdError(Error: PPGError; Operation: TuxcmdErrorEnum);
+var OldError: PGError;
+begin
+ if (Error = nil) or (Error^ = nil) or (Error^.domain <> G_IO_ERROR) then Exit;
+ case GIOErrorEnum(Error^.code) of
+ G_IO_ERROR_FAILED,
+ G_IO_ERROR_NOT_FOUND,
+ G_IO_ERROR_EXISTS,
+ G_IO_ERROR_IS_DIRECTORY,
+ G_IO_ERROR_NOT_DIRECTORY,
+ G_IO_ERROR_NOT_EMPTY,
+ G_IO_ERROR_NOT_REGULAR_FILE,
+ G_IO_ERROR_NOT_SYMBOLIC_LINK,
+ G_IO_ERROR_FILENAME_TOO_LONG,
+ G_IO_ERROR_INVALID_FILENAME,
+ G_IO_ERROR_TOO_MANY_LINKS,
+ G_IO_ERROR_NO_SPACE,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ G_IO_ERROR_PERMISSION_DENIED,
+ G_IO_ERROR_NOT_SUPPORTED,
+// G_IO_ERROR_CLOSED,
+// G_IO_ERROR_CANCELLED,
+// G_IO_ERROR_PENDING,
+ G_IO_ERROR_READ_ONLY,
+ G_IO_ERROR_CANT_CREATE_BACKUP,
+ G_IO_ERROR_WOULD_RECURSE,
+ G_IO_ERROR_BUSY,
+ G_IO_ERROR_WOULD_BLOCK,
+ G_IO_ERROR_WOULD_MERGE,
+// G_IO_ERROR_FAILED_HANDLED,
+ G_IO_ERROR_TOO_MANY_OPEN_FILES,
+ G_IO_ERROR_NOT_INITIALIZED,
+ G_IO_ERROR_PARTIAL_INPUT,
+ G_IO_ERROR_INVALID_DATA,
+ G_IO_ERROR_BROKEN_PIPE,
+ G_IO_ERROR_NO_SUCH_DEVICE: begin
+ OldError := Error^;
+ Error^ := nil;
+ g_set_error(Error, TUXCMD_ERROR, gint(Operation), '%s', OldError^.message);
+ g_free (OldError);
+ end;
+ end;
+end;
+
end.
diff --git a/UGnome.pas b/UGnome.pas
index 2955142..5edab31 100644
--- a/UGnome.pas
+++ b/UGnome.pas
@@ -21,7 +21,7 @@ unit UGnome;
interface
-uses glib2, gdk2, gdk2pixbuf, gtk2, Classes, ULibc,
+uses glib2, gdk2, gdk2pixbuf, gtk2, Classes, ULibc, UError,
GTKForms, GTKControls, GTKStdCtrls, GTKExtCtrls, GTKClasses, GTKDialogs, GTKUtils, GTKConsts,
uVFSprototypes;
@@ -176,7 +176,7 @@ type PGnomeColorPicker = PGtkWidget;
const AFTER_ALL_TABS = -1;
NOT_IN_APP_WINDOWS = -2;
-var libGlib2Handle, libGtk2Handle, libGnome2Handle, libGnomeUI2Handle: Pointer;
+var libGlib2Handle, libGio2Handle, libGtk2Handle, libGnome2Handle, libGnomeUI2Handle: Pointer;
gnome_about_new: function (const name, version, copyright, comments: Pchar; const authors, documenters: PPchar;
const translator_credits: Pchar; logo_pixbuf: PGdkPixbuf): PGtkWidget; cdecl;
{$IFDEF KYLIX}
@@ -212,9 +212,11 @@ var libGlib2Handle, libGtk2Handle, libGnome2Handle, libGnomeUI2Handle: Pointer;
message_format:Pgchar):PGtkWidget; varargs; cdecl;
{$ENDIF}
g_mkdir_with_parents: function (const pathname: PChar; mode: integer): integer; cdecl;
+ __g_io_error_from_errno: function (err_no: gint): GIOErrorEnum; cdecl;
function _gtk_notebook_insert_page(notebook:PGtkNotebook; child:PGtkWidget;tab_label:PGtkWidget; position:gint):gint; cdecl; external gtklib name 'gtk_notebook_insert_page';
+procedure g_prefix_error(err: PPGError; format: Pgchar); varargs; cdecl; external gliblib name 'g_prefix_error';
@@ -1637,17 +1639,26 @@ procedure LoadGnomeLibs;
begin
// Set default values
@gnome_about_new := nil;
+ @gnome_program_init := nil;
+ @libgnome_module_info_get := nil;
+ @libgnomeui_module_info_get := nil;
@gnome_color_picker_new := nil;
@gnome_color_picker_get_i16 := nil;
@gnome_color_picker_set_i16 := nil;
- @libgnomeui_module_info_get := nil;
- @gnome_program_init := nil;
- @libgnome_module_info_get := nil;
@gnome_icon_entry_new := nil;
@gnome_icon_entry_set_pixmap_subdir := nil;
@gnome_icon_entry_get_filename := nil;
@gnome_icon_entry_set_filename := nil;
+ @gnome_date_edit_new := nil;
+ @gnome_date_edit_set_time := nil;
+ @gnome_date_edit_get_time := nil;
@gtk_event_box_set_visible_window := nil;
+ @gtk_icon_size_lookup_for_settings := nil;
+ @gtk_window_set_icon_name := nil;
+ @g_filename_display_name := nil;
+ @gtk_message_dialog_new_with_markup := nil;
+ @g_mkdir_with_parents := nil;
+ @__g_io_error_from_errno := nil;
// Dynamic loading
libGlib2Handle := dlopen('libglib-2.0.so.0', RTLD_LAZY);
@@ -1657,6 +1668,11 @@ begin
@g_mkdir_with_parents := dlsym(libGlib2Handle, 'g_mkdir_with_parents');
DebugMsg(['libglib-2.0.so loaded, @g_filename_display_name = ', @g_filename_display_name]);
end;
+ libGio2Handle := dlopen('libgio-2.0.so.0', RTLD_LAZY);
+ if libGio2Handle = nil then libGio2Handle := dlopen('libgio-2.0.so', RTLD_LAZY);
+ if libGio2Handle <> nil then begin
+ @__g_io_error_from_errno := dlsym(libGio2Handle, 'g_io_error_from_errno');
+ end;
libGtk2Handle := dlopen('libgtk-x11-2.0.so.0', RTLD_LAZY);
if libGtk2Handle = nil then libGtk2Handle := dlopen('libgtk-x11-2.0.so', RTLD_LAZY);
if libGtk2Handle <> nil then begin
diff --git a/vfs/UVFSCore.pas b/vfs/UVFSCore.pas
index e7d63a2..5bf185e 100644
--- a/vfs/UVFSCore.pas
+++ b/vfs/UVFSCore.pas
@@ -136,8 +136,8 @@ type
function GetBlockSize: guint32; override;
procedure SetBlockSize(Value: guint32); override;
- function CopyFileIn(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean; override;
- function CopyFileOut(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean; override;
+ function CopyFileIn(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer; Error: PPGError): boolean; override;
+ function CopyFileOut(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer; Error: PPGError): boolean; override;
function IsOnSameFS(const Path1, Path2: string; FollowSymlinks: boolean): boolean; override;
function TwoSameFiles(const Path1, Path2: string; FollowSymlinks: boolean): boolean; override;
@@ -161,8 +161,8 @@ type
// callbacks here are used for next volume prompts, password prompts (encrypted archives)
function StartCopyOperation(AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
function StopCopyOperation(ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
- function CopyFileOutEx(const SourceFile, DestFile: string; Append: boolean): boolean;
- function CopyFileInEx(const SourceFile, DestFile: string; Append: boolean): boolean;
+ function CopyFileOutEx(const SourceFile, DestFile: string; Append: boolean; Error: PPGError): boolean;
+ function CopyFileInEx(const SourceFile, DestFile: string; Append: boolean; Error: PPGError): boolean;
published
property PluginID: string read GetPluginID;
property ArchiveMode: boolean read FArchiveMode;
@@ -394,7 +394,7 @@ begin
end;
except
on E: Exception do begin
- g_set_error_from_exception(Error, E);
+ tuxcmd_set_error_from_exception(Error, E);
Result := False;
end;
end;
@@ -416,7 +416,7 @@ begin
end;
except
on E: Exception do begin
- g_set_error_from_exception(Error, E);
+ tuxcmd_set_error_from_exception(Error, E);
Result := False;
end;
end;
@@ -465,17 +465,16 @@ end;
function TVFSEngine.GetListing(List: TList; const APath: string; AddDotFiles, FollowSymlinks, AddFullPath: boolean; Error: PPGError): boolean;
var P: PVFSItem;
Item: PDataItem;
- FError: PGError;
begin
DebugMsg(['^^VFS (II): GetListing begin']);
Result := False;
try
if (@FSourcePlugin.FVFSListFirst = nil) or (@FSourcePlugin.FVFSListNext = nil) or (@FSourcePlugin.FVFSListClose = nil) then begin
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'File listing not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'File listing not supported by the VFS module.');
Exit;
end;
- FError := nil;
- P := FSourcePlugin.FVFSListFirst(FGlobs, PChar(APath), FollowSymlinks, AddFullPath, @FError);
+ P := FSourcePlugin.FVFSListFirst(FGlobs, PChar(APath), FollowSymlinks, AddFullPath, Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_OPENDIR);
while (P <> nil) and (BreakProcessingType <> 2) do begin
if (strlen(P^.FName) > 0) and (AddDotFiles or (P^.FName[0] <> '.')) then begin
Item := GetDataItemFromVFSItem(P);
@@ -485,25 +484,24 @@ begin
if P^.FDisplayName <> nil then real_libc_free(P^.FDisplayName);
if P^.sLinkTo <> nil then real_libc_free(P^.sLinkTo);
real_libc_free(P);
- P := FSourcePlugin.FVFSListNext(FGlobs, @FError);
+ P := FSourcePlugin.FVFSListNext(FGlobs, Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_OPENDIR);
end;
- Result := FError = nil;
+ Result := Error^ = nil;
if BreakProcessingType <> 0 then begin
DebugMsg(['^^VFS (WW): GetListing: stopped by BreakProcessing']);
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_CANCELLED), '%s', 'The operation has been cancelled.');
+ if Error^ <> nil then
+ g_error_free(Error^);
+ Error^ := nil;
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_CANCELLED), '%s', 'The operation has been cancelled.');
Result := False;
- end else begin
- if (Error <> nil) and (FError <> nil) then
- Error^ := g_error_copy(FError);
end;
- if FError <> nil then
- g_error_free(FError);
real_libc_free(P);
FSourcePlugin.FVFSListClose(FGlobs, nil);
except
on E: Exception do begin
+ tuxcmd_set_error_from_exception(Error, E);
DebugMsg(['^^VFS (EE): GetListing: Exception: ', E.Message]);
- g_set_error_from_exception(Error, E);
Result := False;
end;
end;
@@ -518,11 +516,12 @@ begin
Result := nil;
if @FSourcePlugin.FVFSFileInfo = nil then begin
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'Querying file info is not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'Querying file info is not supported by the VFS module.');
Exit;
end;
try
P := FSourcePlugin.FVFSFileInfo(FGlobs, PChar(APath), FollowSymlinks, AddFullPath, Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_STAT);
if P <> nil then begin
Result := GetDataItemFromVFSItem(P);
if P^.FName <> nil then real_libc_free(P^.FName);
@@ -533,7 +532,7 @@ begin
except
on E: Exception do begin
DebugMsg(['^^VFS (EE): GetFileInfo: Exception: ', E.Message]);
- g_set_error_from_exception(Error, E);
+ tuxcmd_set_error_from_exception(Error, E);
Result := nil;
end;
end;
@@ -606,10 +605,11 @@ begin
Result := False;
try
Result := FSourcePlugin.FVFSChangeDir(FGlobs, PChar(NewPath), Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_CHDIR);
except
on E: Exception do begin
DebugMsg(['^^VFS (EE): ChangeDir: Exception: ', E.Message]);
- g_set_error_from_exception(Error, E);
+ tuxcmd_set_error_from_exception(Error, E);
Result := False;
end;
end;
@@ -623,13 +623,14 @@ begin
if @FSourcePlugin.FVFSSetCallbacks <> nil then
FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData);
Result := ChangeDir(NewPath, Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_CHDIR);
if @FSourcePlugin.FVFSSetCallbacks <> nil then
FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil);
end;
except
on E: Exception do begin
DebugMsg(['^^VFS (EE): ChangeDirEx: Exception: ', E.Message]);
- g_set_error_from_exception(Error, E);
+ tuxcmd_set_error_from_exception(Error, E);
Result := False;
end;
end;
@@ -674,71 +675,78 @@ end;
function TVFSEngine.MakeDir(const NewDir: string; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSMkDir <> nil then
- Result := FSourcePlugin.FVFSMkDir(FGlobs, PChar(NewDir), Error)
- else begin
+ if @FSourcePlugin.FVFSMkDir <> nil then begin
+ Result := FSourcePlugin.FVFSMkDir(FGlobs, PChar(NewDir), Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_MKDIR);
+ end else begin
Result := False;
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'Creating directories is not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'Creating directories is not supported by the VFS module.');
end;
end;
function TVFSEngine.Remove(const APath: string; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSRemove <> nil then
- Result := FSourcePlugin.FVFSRemove(FGlobs, PChar(APath), Error)
- else begin
+ if @FSourcePlugin.FVFSRemove <> nil then begin
+ Result := FSourcePlugin.FVFSRemove(FGlobs, PChar(APath), Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_REMOVE);
+ end else begin
Result := False;
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'Removing files is not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'Removing files is not supported by the VFS module.');
end;
end;
function TVFSEngine.RenameFile(const SourceFile, DestFile: string; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSRename <> nil then
- Result := FSourcePlugin.FVFSRename(FGlobs, PChar(SourceFile), PChar(DestFile), Error)
- else begin
+ if @FSourcePlugin.FVFSRename <> nil then begin
+ Result := FSourcePlugin.FVFSRename(FGlobs, PChar(SourceFile), PChar(DestFile), Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_RENAME);
+ end else begin
Result := False;
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'Renaming files is not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'Renaming files is not supported by the VFS module.');
end;
end;
function TVFSEngine.MakeSymLink(const NewFileName, PointTo: string; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSMakeSymLink <> nil then
- Result := FSourcePlugin.FVFSMakeSymLink(FGlobs, PChar(NewFileName), PChar(PointTo), Error)
- else begin
+ if @FSourcePlugin.FVFSMakeSymLink <> nil then begin
+ Result := FSourcePlugin.FVFSMakeSymLink(FGlobs, PChar(NewFileName), PChar(PointTo), Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_SYMLINK);
+ end else begin
Result := False;
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'Creating symbolic links is not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'Creating symbolic links is not supported by the VFS module.');
end;
end;
function TVFSEngine.Chmod(const FileName: string; Mode: cuLong; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSChmod <> nil then
- Result := FSourcePlugin.FVFSChmod(FGlobs, PChar(FileName), Mode, Error)
- else begin
+ if @FSourcePlugin.FVFSChmod <> nil then begin
+ Result := FSourcePlugin.FVFSChmod(FGlobs, PChar(FileName), Mode, Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_CHMOD);
+ end else begin
Result := False;
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'Chmod is not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'Chmod is not supported by the VFS module.');
end;
end;
function TVFSEngine.Chown(const FileName: string; UID, GID: cuLong; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSChown <> nil then
- Result := FSourcePlugin.FVFSChown(FGlobs, PChar(FileName), UID, GID, Error)
- else begin
+ if @FSourcePlugin.FVFSChown <> nil then begin
+ Result := FSourcePlugin.FVFSChown(FGlobs, PChar(FileName), UID, GID, Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_CHOWN);
+ end else begin
Result := False;
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'Chown is not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'Chown is not supported by the VFS module.');
end;
end;
function TVFSEngine.ChangeTimes(const APath: string; mtime, atime: time_t; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSChangeTimes <> nil then
- Result := FSourcePlugin.FVFSChangeTimes(FGlobs, PChar(APath), mtime, atime, Error)
- else begin
+ if @FSourcePlugin.FVFSChangeTimes <> nil then begin
+ Result := FSourcePlugin.FVFSChangeTimes(FGlobs, PChar(APath), mtime, atime, Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_TIMESTAMPS);
+ end else begin
Result := False;
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'Changing timestamps is not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'Changing timestamps is not supported by the VFS module.');
end;
end;
@@ -778,48 +786,56 @@ end;
function TVFSEngine.OpenFile(const APath: string; Mode: integer; Error: PPGError): TEngineFileDes;
begin
- if @FSourcePlugin.FVFSOpenFile <> nil then
- Result := FSourcePlugin.FVFSOpenFile(FGlobs, PChar(APath), Mode, Error)
- else begin
+ if @FSourcePlugin.FVFSOpenFile <> nil then begin
+ Result := FSourcePlugin.FVFSOpenFile(FGlobs, PChar(APath), Mode, Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_OPEN_FILE);
+ end else begin
Result := nil;
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'Manual opening files is not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'Manual opening files is not supported by the VFS module.');
end;
end;
function TVFSEngine.ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; Error: PPGError): integer;
begin
- if @FSourcePlugin.FVFSReadFile <> nil then
- Result := FSourcePlugin.FVFSReadFile(FGlobs, FileDescriptor, Buffer, ABlockSize, Error)
- else begin
+ if @FSourcePlugin.FVFSReadFile <> nil then begin
+ Result := FSourcePlugin.FVFSReadFile(FGlobs, FileDescriptor, Buffer, ABlockSize, Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_READ_FILE);
+ end else begin
Result := -1;
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'Manual read is not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'Manual read is not supported by the VFS module.');
end;
end;
function TVFSEngine.WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; Error: PPGError): integer;
begin
- if @FSourcePlugin.FVFSWriteFile <> nil then
- Result := FSourcePlugin.FVFSWriteFile(FGlobs, FileDescriptor, Buffer, BytesCount, Error)
- else begin
+ if @FSourcePlugin.FVFSWriteFile <> nil then begin
+ Result := FSourcePlugin.FVFSWriteFile(FGlobs, FileDescriptor, Buffer, BytesCount, Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_WRITE_FILE);
+ end else begin
Result := -1;
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'Manual write is not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'Manual write is not supported by the VFS module.');
end;
end;
function TVFSEngine.CloseFile(const FileDescriptor: TEngineFileDes; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSCloseFile <> nil then
- Result := FSourcePlugin.FVFSCloseFile(FGlobs, FileDescriptor, nil)
- else Result := False;
+ if @FSourcePlugin.FVFSCloseFile <> nil then begin
+ Result := FSourcePlugin.FVFSCloseFile(FGlobs, FileDescriptor, Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_CLOSE_FILE);
+ end else begin
+ Result := False;
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'Manual closing files is not supported by the VFS module.');
+ end;
end;
function TVFSEngine.FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; Error: PPGError): Int64;
begin
- if @FSourcePlugin.FVFSFileSeek <> nil then
- Result := FSourcePlugin.FVFSFileSeek(FGlobs, FileDescriptor, AbsoluteOffset, Error)
- else begin
+ if @FSourcePlugin.FVFSFileSeek <> nil then begin
+ Result := FSourcePlugin.FVFSFileSeek(FGlobs, FileDescriptor, AbsoluteOffset, Error);
+ VFSToTuxcmdError(Error, TUXCMD_ERROR_SEEK);
+ end else begin
Result := -1;
- g_set_error(Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'Manual seek is not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'Manual seek is not supported by the VFS module.');
end;
end;
@@ -832,73 +848,75 @@ end;
(********************************************************************************************************************************)
-function TVFSEngine.CopyFileIn(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean;
+function TVFSEngine.CopyFileIn(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer; Error: PPGError): boolean;
begin
DebugMsg(['** (WW): deprecated method CopyFileIn called from a TVFSEngine instance!']);
Result := StartCopyOperation(nil, nil, nil, nil);
- Result := Result and CopyFileInEx(SourceFile, DestFile, Append);
+ Result := Result and CopyFileInEx(SourceFile, DestFile, Append, Error);
Result := Result and StopCopyOperation(nil, nil);
end;
-function TVFSEngine.CopyFileOut(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean;
+function TVFSEngine.CopyFileOut(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer; Error: PPGError): boolean;
begin
DebugMsg(['** (WW): deprecated method CopyFileOut called from a TVFSEngine instance!']);
Result := StartCopyOperation(nil, nil, nil, nil);
- Result := Result and CopyFileOutEx(SourceFile, DestFile, Append);
+ Result := Result and CopyFileOutEx(SourceFile, DestFile, Append, Error);
Result := Result and StopCopyOperation(nil, nil);
end;
-function TVFSEngine.CopyFileOutEx(const SourceFile, DestFile: string; Append: boolean): boolean;
-var Error: PGError;
- ACopyProgressCallback: TVFSProgressCallback;
+function TVFSEngine.CopyFileOutEx(const SourceFile, DestFile: string; Append: boolean; Error: PPGError): boolean;
+var ACopyProgressCallback: TVFSProgressCallback;
begin
Result := False;
try
- Error := nil;
if @FSourcePlugin.FVFSCopyToLocal <> nil then
try
- Result := FSourcePlugin.FVFSCopyToLocal(FGlobs, PChar(SourceFile), PChar(DestFile), Append, @Error)
+ Result := FSourcePlugin.FVFSCopyToLocal(FGlobs, PChar(SourceFile), PChar(DestFile), Append, Error)
except
- on E: Exception do g_set_error_from_exception(@Error, E);
+ on E: Exception do tuxcmd_set_error_from_exception(Error, E);
end
else
- g_set_error(@Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'VFSCopyToLocal not supported by the VFS module.');
- if Error <> nil then begin
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'VFSCopyToLocal not supported by the VFS module.');
+ if Error^ <> nil then begin
if FCopyProgressCallback <> nil then begin
@ACopyProgressCallback := FCopyProgressCallback;
- Result := ACopyProgressCallback(0, Error, FCopyCallbackData);
+ Result := ACopyProgressCallback(0, Error^, FCopyCallbackData);
end;
- g_error_free(Error);
end;
except
- on E: Exception do DebugMsg(['*** Exception raised in TVFSEngine.CopyFileOutEx(SourceFile=', SourceFile, ', DestFile=', DestFile, ', Append=', Append,'): (', E.ClassName, '): ', E.Message]);
+ on E: Exception do begin
+ Result := False;
+ tuxcmd_set_error_from_exception(Error, E);
+ DebugMsg(['*** Exception raised in TVFSEngine.CopyFileOutEx(SourceFile=', SourceFile, ', DestFile=', DestFile, ', Append=', Append,'): (', E.ClassName, '): ', E.Message]);
+ end;
end;
end;
-function TVFSEngine.CopyFileInEx(const SourceFile, DestFile: string; Append: boolean): boolean;
-var Error: PGError;
-ACopyProgressCallback: TVFSProgressCallback;
+function TVFSEngine.CopyFileInEx(const SourceFile, DestFile: string; Append: boolean; Error: PPGError): boolean;
+var ACopyProgressCallback: TVFSProgressCallback;
begin
Result := False;
try
- Error := nil;
if @FSourcePlugin.FVFSCopyFromLocal <> nil then
try
- Result := FSourcePlugin.FVFSCopyFromLocal(FGlobs, PChar(SourceFile), PChar(DestFile), Append, @Error)
+ Result := FSourcePlugin.FVFSCopyFromLocal(FGlobs, PChar(SourceFile), PChar(DestFile), Append, Error)
except
- on E: Exception do g_set_error_from_exception(@Error, E);
+ on E: Exception do tuxcmd_set_error_from_exception(Error, E);
end
else
- g_set_error(@Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'VFSCopyFromLocal not supported by the VFS module.');
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'VFSCopyFromLocal not supported by the VFS module.');
if Error <> nil then begin
if FCopyProgressCallback <> nil then begin
@ACopyProgressCallback := FCopyProgressCallback;
- Result := ACopyProgressCallback(0, Error, FCopyCallbackData);
+ Result := ACopyProgressCallback(0, Error^, FCopyCallbackData);
end;
- g_error_free(Error);
end;
except
- on E: Exception do DebugMsg(['*** Exception raised in TVFSEngine.CopyFileInEx(SourceFile=', SourceFile, ', DestFile=', DestFile, ', Append=', Append,'): (', E.ClassName, '): ', E.Message]);
+ on E: Exception do begin
+ Result := False;
+ tuxcmd_set_error_from_exception(Error, E);
+ DebugMsg(['*** Exception raised in TVFSEngine.CopyFileInEx(SourceFile=', SourceFile, ', DestFile=', DestFile, ', Append=', Append,'): (', E.ClassName, '): ', E.Message]);
+ end;
end;
end;
@@ -917,10 +935,10 @@ begin
try
Result := FSourcePlugin.FVFSStartCopyOperation(FGlobs, @Error)
except
- on E: Exception do g_set_error_from_exception(@Error, E);
+ on E: Exception do tuxcmd_set_error_from_exception(@Error, E);
end
else
- g_set_error(@Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'VFSStartCopyOperation not supported by the VFS module.');
+ g_set_error(@Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'VFSStartCopyOperation not supported by the VFS module.');
if Error <> nil then begin
if ProgressCallback <> nil then
Result := ProgressCallback^(0, Error, CallbackData);
@@ -945,10 +963,10 @@ begin
try
Result := FSourcePlugin.FVFSStopCopyOperation(FGlobs, @Error)
except
- on E: Exception do g_set_error_from_exception(@Error, E);
+ on E: Exception do tuxcmd_set_error_from_exception(@Error, E);
end
else
- g_set_error(@Error, G_IO_ERROR, gint(G_IO_ERROR_NOT_SUPPORTED), '%s', 'VFSStopCopyOperation not supported by the VFS module.');
+ g_set_error(@Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_NOT_SUPPORTED), '%s', 'VFSStopCopyOperation not supported by the VFS module.');
if Error <> nil then begin
if ProgressCallback <> nil then
Result := ProgressCallback^(0, Error, CallbackData);