summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--UChecksum.pas70
-rw-r--r--UChecksumDruid.pas103
-rw-r--r--UConfig.pas4
-rw-r--r--UConnectionManager.pas17
-rw-r--r--UCore.pas119
-rw-r--r--UCoreUtils.pas30
-rw-r--r--UCoreWorkers.pas406
-rw-r--r--UEngines.pas539
-rw-r--r--UError.pas25
-rw-r--r--UMain.pas75
-rw-r--r--UQuickConnect.pas11
-rw-r--r--USearch.pas34
-rw-r--r--vfs/UVFSCore.pas469
-rw-r--r--vfs/uVFSprototypes.pas86
14 files changed, 1085 insertions, 903 deletions
diff --git a/UChecksum.pas b/UChecksum.pas
index b7ef508..0de5fda 100644
--- a/UChecksum.pas
+++ b/UChecksum.pas
@@ -63,7 +63,7 @@ var
implementation
-uses ULocale, UCoreUtils, ULibc, UCore, DateUtils, md5, crc;
+uses ULocale, UCoreUtils, ULibc, UCore, UError, DateUtils, md5, crc;
type TFileListItem = class
public
@@ -198,18 +198,27 @@ end;
function TFChecksum.ProcessFile(FileName: string): boolean;
const ChksumBlockSize = 32768; // Maximum of PByteArray
var FD: TEngineFileDes;
- Error, Count, i, Start: integer;
+ Count, i, Start: integer;
Buffer: Pointer;
s: string;
Stat: PDataItem;
IsMD5: boolean;
+ Error: PGError;
begin
Result := False;
- Stat := Engine.GetFileInfo(FileName, True, True);
+ Error := nil;
+ Stat := Engine.GetFileInfo(FileName, True, True, @Error);
+ if Stat = nil then begin
+ if Error <> nil then begin
+ ShowError(Self, Format('An error occured while opening file ''%s''', [StrToUTF8(ExtractFileName(FileName))]), Error);
+ g_error_free(Error);
+ end;
+ Exit;
+ end;
if (Stat <> nil) and (Stat.Size > 128*1024) then begin
i := integer(Application.MessageBox(Format(LANGTheFileSYouAreTryingToOpenIsQuiteBig, [StrToUTF8(ExtractFileName(FileName))]), [mbYes, mbNo], mbWarning, mbNone, mbNo));
- if (i = integer(mbNo)) or (i = 251) then Exit;
FreeDataItem(Stat);
+ if (i = integer(mbNo)) or (i = 251) then Exit;
end;
IsMD5 := (Pos('MD5', WideUpperCase(ExtractFileName(FileName))) > 0) or ((Pos('SFV', WideUpperCase(ExtractFileName(FileName))) = 0) and (Pos('SUM', WideUpperCase(ExtractFileName(FileName))) > 0));
if IsMD5 then MD5Present := True
@@ -225,20 +234,23 @@ begin
Application.MessageBox(LANGAnErrorOccuredWhileInitializingMemoryBlock, [mbOK], mbError, mbNone, mbOK);
Exit;
end;
- Error := 0;
- FD := Engine.OpenFile(FileName, omRead, Error);
- if Error <> 0 then begin
- Application.MessageBox(Format(LANGAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(ExtractFileName(FileName)), GetErrorString(Error)]), [mbOK], mbError, mbNone, mbOK);
+ FD := Engine.OpenFile(FileName, omRead, @Error);
+ if FD = nil then begin
+ if Error <> nil then begin
+ ShowError(Self, Format('An error occured while opening file ''%s''', [StrToUTF8(ExtractFileName(FileName))]), Error);
+ g_error_free(Error);
+ end;
libc_free(Buffer);
Exit;
end;
s := '';
CommentOpen := True;
repeat
- Count := Engine.ReadFile(FD, Buffer, ChksumBlockSize, Error);
- if Error <> 0 then begin
- Application.MessageBox(Format(LANGAnErrorOccuredWhileReadingFileSS, [StrToUTF8(ExtractFileName(FileName)), GetErrorString(Error)]), [mbOK], mbError, mbNone, mbOK);
- Engine.CloseFile(FD);
+ Count := Engine.ReadFile(FD, Buffer, ChksumBlockSize, @Error);
+ if Error <> nil then begin
+ ShowError(Self, Format('An error occured while reading file ''%s''', [StrToUTF8(ExtractFileName(FileName))]), Error);
+ g_error_free(Error);
+ Engine.CloseFile(FD, nil);
libc_free(Buffer);
Exit;
end;
@@ -259,7 +271,7 @@ begin
if Length(s) > 0 then ProcessLine(s, ExtractFilePath(FileName), IsMD5);
CommentOpen := False;
- Engine.CloseFile(FD);
+ Engine.CloseFile(FD, nil);
libc_free(Buffer);
Result := True;
end;
@@ -270,6 +282,7 @@ var Item: TFileListItem;
S1, S2: string;
i: integer;
Stat: PDataItem;
+ Error: PGError;
begin
TrimCRLFESC(s);
if Length(s) < 1 then Exit;
@@ -312,7 +325,8 @@ begin
Item.Name := ExtractFileName(s2);
Item.FullPath := IncludeTrailingPathDelimiter(Path) + s2;
end;
- Stat := Engine.GetFileInfo(Item.FullPath, True, True);
+ Error := nil;
+ Stat := Engine.GetFileInfo(Item.FullPath, True, True, nil);
if Assigned(Stat) then begin
Item.Size := Stat.Size;
FreeDataItem(Stat);
@@ -373,7 +387,7 @@ end;
procedure TFChecksum.GoProcess;
const ChksumBlockSize = 65536*4;
-var i, Error, Count: integer;
+var i, ErrNum, Count: integer;
FD: TEngineFileDes;
Buffer: Pointer;
MaxSize, OldPos: Int64;
@@ -382,6 +396,7 @@ var i, Error, Count: integer;
CRC: LongWord;
MDContext: TMDContext;
MDDigest: TMDDigest;
+ Error: PGError;
begin
if List.Count = 0 then Exit;
CheckButton.Caption := LANGCheckButtonCaptionStop;
@@ -417,18 +432,21 @@ begin
Data := List[i];
CRC := 0;
if Data.IsMD5 then MDInit(MDContext, MD_VERSION_5);
- Error := 0;
- FD := Engine.OpenFile(Data.FullPath, omRead, Error);
- if Error <> 0 then begin
+ Error := nil;
+ FD := Engine.OpenFile(Data.FullPath, omRead, @Error);
+ if Error <> nil then begin
Data.Status := 3;
+ g_error_free(Error);
Continue;
end;
repeat
- Count := Engine.ReadFile(FD, Buffer, ChksumBlockSize, Error);
- if Error <> 0 then begin
+ Error := nil;
+ Count := Engine.ReadFile(FD, Buffer, ChksumBlockSize, @Error);
+ if Error <> nil then begin
Data.Status := 3;
- Engine.CloseFile(FD);
- Continue;
+ g_error_free(Error);
+ Engine.CloseFile(FD, nil);
+ Break;
end;
if not Data.IsMD5 then CRC := CRC32(CRC, Buffer, Count)
else MDUpdate(MDContext, Buffer^, Count);
@@ -436,7 +454,7 @@ begin
ProgressBar.Text := Format('%d %%', [Trunc(ProgressBar.Fraction * 100)]);
Application.ProcessMessages;
until (Count < ChksumBlockSize) or Stop;
- Engine.CloseFile(FD);
+ Engine.CloseFile(FD, nil);
if Stop then Break;
if not Data.IsMD5 then Data.Status := Ord(not (CRC = Data.CRC)) + 1 else begin
MDFinal(MDContext, MDDigest);
@@ -455,11 +473,11 @@ begin
StatLabel.Caption := LANGChecksumInterrupted;
CheckButton.SetFocus;
end else begin
- Error := 0;
+ ErrNum := 0;
if List.Count > 0 then
for i := 0 to List.Count - 1 do
- if TFileListItem(List[i]).Status <> 1 then Inc(Error);
- StatLabel.Caption := Format(LANGChecksumDOK, [Round(100 * (List.Count - Error) / List.Count)]);
+ if TFileListItem(List[i]).Status <> 1 then Inc(ErrNum);
+ StatLabel.Caption := Format(LANGChecksumDOK, [Round(100 * (List.Count - ErrNum) / List.Count)]);
ActionArea.SetFocus;
end;
StatLabel.UseMarkup := True;
diff --git a/UChecksumDruid.pas b/UChecksumDruid.pas
index 7745fad..fb62775 100644
--- a/UChecksumDruid.pas
+++ b/UChecksumDruid.pas
@@ -76,7 +76,7 @@ var
implementation
-uses ULocale, UCoreUtils, ULibc, UCore, DateUtils, UConfig, StrUtils, md5, crc;
+uses ULocale, UCoreUtils, ULibc, UCore, DateUtils, UConfig, UError, StrUtils, md5, crc;
procedure TFChecksumDruid.FormCreate(Sender: TObject);
@@ -306,19 +306,22 @@ procedure TFChecksumDruid.SetCurrentPage(const Num: integer; const GoingForward:
const Ext: array[boolean] of string = ('.md5', '.sfv');
var s: string;
i: TEngineFileDes;
- Error: integer;
+ Error: PGError;
begin
// A simple test before we can continue
if (CurrentPage = 3) and (not SeparateFileCheckBox.Checked) and GoingForward then begin
- s := UTF8ToStr(FileNameEntry.Text);
- i := Engine.OpenFile(s, omWrite, Error);
- if Error <> 0 then begin
- Application.MessageBox(PGtkWindow(FWidget), Format(LANGCCHKSUMAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(ExtractFileName(s)), GetErrorString(Error)]),
- [mbOK], mbError, mbNone, mbOK);
+ s := ProcessPattern(Engine, StrToUTF8(FileNameEntry.Text), IncludeTrailingPathDelimiter(ExtractFilePath(FileNames[0])), '', False);
+ Error := nil;
+ i := Engine.OpenFile(s, omWrite, @Error);
+ if i = nil then begin
+ if Error <> nil then begin
+ ShowError(Self, Format('An error occured while opening file ''%s''', [StrToUTF8(ExtractFileName(s))]), Error);
+ g_error_free(Error);
+ end;
Exit;
end;
- Engine.CloseFile(i);
- Engine.Remove(s);
+ Engine.CloseFile(i, nil);
+ Engine.Remove(s, nil);
end;
DebugMsg(['TFChecksumDruid.SetCurrentPage: CurrentPage = ', CurrentPage, ', new = ', Num]);
@@ -443,7 +446,7 @@ begin
// Compute maximal size of selected files
MaxSize := 0;
for i := 0 to FileNames.Count - 1 do begin
- Stat := Engine.GetFileInfo(FileNames[i], True, True);
+ Stat := Engine.GetFileInfo(FileNames[i], True, True, nil);
if Assigned(Stat) then begin
Inc(MaxSize, Stat.Size);
FreeDataItem(Stat);
@@ -458,7 +461,7 @@ begin
for i := 0 to FileNames.Count - 1 do begin
ProcessingLabel.Caption := Format(LANGCCHKSUMNowProcessingFileS, [StrToUTF8(ExtractFileName(FileNames[i]))]);
LastValue := Progress.Value;
- Stat := Engine.GetFileInfo(FileNames[i], True, True);
+ Stat := Engine.GetFileInfo(FileNames[i], True, True, nil);
Application.ProcessMessages;
try
if ProcessFile(FileNames[i], SFVRadioButton.Checked, s) then begin
@@ -490,11 +493,12 @@ end;
function TFChecksumDruid.ProcessFile(const FName: string; const IsItSFV: boolean; var HashString: string): boolean;
const ChksumBlockSize = 65536*4;
var FD: TEngineFileDes;
- Error, Count: integer;
+ Count: integer;
Buffer: Pointer;
CRC: LongWord;
MDContext: TMDContext;
MDDigest: TMDDigest;
+ Error: PGError;
begin
HashString := '';
Result := False;
@@ -508,16 +512,21 @@ begin
CRC := 0;
if not IsItSFV then MDInit(MDContext, MD_VERSION_5);
- FD := Engine.OpenFile(FName, omRead, Error);
- if Error <> 0 then begin
- ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(ExtractFileName(FName)), GetErrorString(Error)]);
+ Error := nil;
+ FD := Engine.OpenFile(FName, omRead, @Error);
+ if FD = nil then begin
+ if Error <> nil then begin
+ ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(ExtractFileName(FName)), Error^.message]);
+ g_error_free(Error);
+ end;
Exit;
end;
repeat
- Count := Engine.ReadFile(FD, Buffer, ChksumBlockSize, Error);
- if Error <> 0 then begin
- ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileReadingFileSS, [StrToUTF8(ExtractFileName(FName)), GetErrorString(Error)]);
- Engine.CloseFile(FD);
+ Count := Engine.ReadFile(FD, Buffer, ChksumBlockSize, @Error);
+ if Error <> nil then begin
+ ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileReadingFileSS, [StrToUTF8(ExtractFileName(FName)), Error^.message]);
+ g_error_free(Error);
+ Engine.CloseFile(FD, nil);
Exit;
end;
if IsItSFV then CRC := CRC32(CRC, Buffer, Count)
@@ -527,7 +536,7 @@ begin
Application.ProcessMessages;
CheckStop;
until (Count < ChksumBlockSize) or Stop;
- Engine.CloseFile(FD);
+ Engine.CloseFile(FD, nil);
libc_free(Buffer);
if IsItSFV then HashString := IntToHex(CRC, 8) else
@@ -541,13 +550,18 @@ end;
const ChksumBlockSize = 32768; // Maximum of PByteArray
procedure TFChecksumDruid.WriteLine(const FName, CheckedFName, HashString: string; const IsItSFV, CreateFile, CloseFile: boolean);
-var i, Error, Count: integer;
+var i, Count: integer;
s: string;
+ Error: PGError;
begin
if CreateFile then begin
- FileDes := Engine.OpenFile(FName, omWrite, Error);
- if Error <> 0 then begin
- ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(ExtractFileName(FName)), GetErrorString(Error)]);
+ Error := nil;
+ FileDes := Engine.OpenFile(FName, omWrite, @Error);
+ if FileDes = nil then begin
+ if Error <> nil then begin
+ ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(ExtractFileName(FName)), Error^.message]);
+ g_error_free(Error);
+ end;
Exit;
end;
try
@@ -565,10 +579,12 @@ begin
else s := Format('%s %s'#10, [Trim(AnsiLowerCase(HashString)), ExtractFileName(CheckedFName)]);
for i := 1 to Length(s) do begin
if BufferPos + 1 >= ChksumBlockSize then begin
- Count := Engine.WriteFile(FileDes, Buffer, ChksumBlockSize, Error);
+ Error := nil;
+ Count := Engine.WriteFile(FileDes, Buffer, ChksumBlockSize, @Error);
BufferPos := -1;
- if (Error <> 0) or (Count <> ChksumBlockSize) then begin
- ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileWritingFileSS, [StrToUTF8(ExtractFileName(FName)), GetErrorString(Error)]);
+ if (Error <> nil) { or (Count <> ChksumBlockSize) } then begin
+ ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileWritingFileSS, [StrToUTF8(ExtractFileName(FName)), Error^.message]);
+ g_error_free(Error);
Exit;
end;
end;
@@ -578,25 +594,32 @@ begin
if CloseFile then begin
Inc(BufferPos); // Counting with zero-starting element
- Count := Engine.WriteFile(FileDes, Buffer, BufferPos, Error);
- if (Error <> 0) or (Count <> BufferPos) then begin
- ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileWritingFileSS, [StrToUTF8(ExtractFileName(FName)), GetErrorString(Error)]);
+ Error := nil;
+ Count := Engine.WriteFile(FileDes, Buffer, BufferPos, @Error);
+ if (Error <> nil) { or (Count <> BufferPos) } then begin
+ ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileWritingFileSS, [StrToUTF8(ExtractFileName(FName)), Error^.message]);
+ g_error_free(Error);
Exit;
end;
BufferPos := -1;
- Engine.CloseFile(FileDes);
+ Engine.CloseFile(FileDes, nil);
libc_free(Buffer);
end;
end;
procedure TFChecksumDruid.WriteSFVComment(const FName: string);
-var i, Error, Count: integer;
+var i, Count: integer;
Stat: PDataItem;
s: string;
+ Error: PGError;
begin
- FileDes := Engine.OpenFile(FName, omWrite, Error);
- if Error <> 0 then begin
- ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(ExtractFileName(FName)), GetErrorString(Error)]);
+ Error := nil;
+ FileDes := Engine.OpenFile(FName, omWrite, @Error);
+ if FileDes = nil then begin
+ if Error <> nil then begin
+ ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(ExtractFileName(FName)), Error^.message]);
+ g_error_free(Error);
+ end;
Exit;
end;
try
@@ -613,7 +636,7 @@ begin
'; http://tuxcmd.sourceforge.net/'#13#10'; '#13#10'; /----'#13#10, [ConstAboutVersion, ConstAboutBuildDate,
SysUtils.FormatDateTime('mm.dd.yyyy "at" hh:nn:ss', Now)]);
for i := 0 to FileNames.Count - 1 do begin
- Stat := Engine.GetFileInfo(FileNames[i], True, True);
+ Stat := Engine.GetFileInfo(FileNames[i], True, True, nil);
if Assigned(Stat) then begin
s := s + Format('; %s %s %s'#13#10, [PadRightStr(IntToStr(Stat^.Size), 11),
FormatDate(Stat^.mtime, True, True, 999, 999, 1, '%Y-%m-%d', '%k:%M.%S'), ExtractFileName(FileNames[i])]);
@@ -624,10 +647,12 @@ begin
for i := 1 to Length(s) do begin
if BufferPos + 1 >= ChksumBlockSize then begin
- Count := Engine.WriteFile(FileDes, Buffer, ChksumBlockSize, Error);
+ Error := nil;
+ Count := Engine.WriteFile(FileDes, Buffer, ChksumBlockSize, @Error);
BufferPos := -1;
- if (Error <> 0) or (Count <> ChksumBlockSize) then begin
- ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileWritingFileSS, [StrToUTF8(ExtractFileName(FName)), GetErrorString(Error)]);
+ if (Error <> nil) { or (Count <> ChksumBlockSize) } then begin
+ ErrorLabel.Caption := ErrorLabel.Caption + Format(LANGCCHKSUMAnErrorOccuredWhileWritingFileSS, [StrToUTF8(ExtractFileName(FName)), Error^.message]);
+ g_error_free(Error);
Exit;
end;
end;
diff --git a/UConfig.pas b/UConfig.pas
index a8dc5b6..112ca1d 100644
--- a/UConfig.pas
+++ b/UConfig.pas
@@ -25,8 +25,8 @@ uses Classes, ULocale;
resourcestring
ConstAppTitle = 'Tux Commander';
- ConstAboutVersion = '0.6.73-dev';
- ConstAboutBuildDate = '2009-11-29';
+ ConstAboutVersion = '0.6.74-dev';
+ ConstAboutBuildDate = '2009-12-13';
{$IFDEF FPC}
{$INCLUDE fpcver.inc}
diff --git a/UConnectionManager.pas b/UConnectionManager.pas
index a89147d..7109cc3 100644
--- a/UConnectionManager.pas
+++ b/UConnectionManager.pas
@@ -66,7 +66,7 @@ type
Thread: TOpenConnectionThread;
SourcePanelEngine: TPanelEngine;
ConnectedEngine: TVFSEngine;
- function DoConnectInternal(const URI: string; Engine: TVFSEngine; VFSDialogsParentWindow: PGtkWidget; VFSQuickConnectMode: boolean): boolean;
+ function DoConnectInternal(const URI: string; Engine: TVFSEngine; VFSDialogsParentWindow: PGtkWidget; VFSQuickConnectMode: boolean; Error: PPGError): boolean;
end;
var
@@ -74,7 +74,7 @@ var
implementation
-uses ULocale, UCoreUtils, UConfig, UConnectionProperties, UGnome, UQuickConnect;
+uses ULocale, UCoreUtils, UConfig, UConnectionProperties, UGnome, UQuickConnect, UError;
procedure TFConnectionManager.FormCreate(Sender: TObject);
@@ -539,6 +539,7 @@ var Engine: TVFSEngine;
FActiveConnInfo: TConnMgrItem;
DontShowAgain: boolean;
res: TMessageButton;
+ Error: PGError;
begin
FActiveConnInfo := nil;
if ListView.Selected <> nil then FActiveConnInfo := ListView.Selected.AsPointer(0);
@@ -599,8 +600,10 @@ begin
Engine.Password := FActiveConnInfo.Password;
Engine.PasswordUsed := False;
- if not DoConnectInternal(UTF8ToStr(FActiveConnInfo.GetURI(False)), Engine, FWidget, False) then begin
- if not FSilenceError then Application.MessageBox(PGtkWindow(FWidget), LANGCouldntOpenURI, [mbOK], mbError, mbOK, mbOK);
+ Error := nil;
+ if not DoConnectInternal(UTF8ToStr(FActiveConnInfo.GetURI(False)), Engine, FWidget, False, @Error) then begin
+ if not FSilenceError then
+ ShowError(Self, 'Couldn''t open the URI specified', Error);
ListViewTable.Enabled := True;
CloseButton.Enabled := True;
ConnectButton.Enabled := True;
@@ -609,6 +612,8 @@ begin
StopButton.Enabled := False;
ListView.SetFocus;
Engine.Free;
+ if Error <> nil then
+ g_error_free(Error);
Exit;
end;
@@ -619,7 +624,7 @@ begin
ModalResult := mbOK;
end;
-function TFConnectionManager.DoConnectInternal(const URI: string; Engine: TVFSEngine; VFSDialogsParentWindow: PGtkWidget; VFSQuickConnectMode: boolean): boolean;
+function TFConnectionManager.DoConnectInternal(const URI: string; Engine: TVFSEngine; VFSDialogsParentWindow: PGtkWidget; VFSQuickConnectMode: boolean; Error: PPGError): boolean;
begin
Result := False;
FSilenceError := False;
@@ -658,6 +663,8 @@ begin
end;
until Thread.Finished;
Result := Thread.OpenResult;
+ if Thread.OpenError <> nil then
+ g_propagate_error(Error, Thread.OpenError);
FSilenceError := Thread.VFSCallbackCancelled;
Thread.Free;
Thread := nil;
diff --git a/UCore.pas b/UCore.pas
index 81f6c4d..087999a 100644
--- a/UCore.pas
+++ b/UCore.pas
@@ -46,7 +46,7 @@ procedure GetDirSize(AListView: TGTKListView; Engine: TPanelEngine; DataList: TL
procedure FillDefaultFstabMounterItems;
function CRCGetInfo(FileName: string; Engine: TPanelEngine; var TargetName: string; var TargetCRC: LongWord; var Size: Int64): boolean;
-function WriteCRCFile(Engine: TPanelEngine; TargetFile, SplitFileName: string; const FileSize: Int64; const FileCRC: Longword): boolean;
+function WriteCRCFile(Sender: TObject; Engine: TPanelEngine; TargetFile, SplitFileName: string; const FileSize: Int64; const FileCRC: Longword): boolean;
function ComputeBlockSize(TotalSize: Int64): longint;
@@ -110,7 +110,7 @@ var LeftLocalEngine, RightLocalEngine: TPanelEngine;
implementation
(********************************************************************************************************************************)
uses SysUtils, DateUtils, StrUtils, UConfig, UDirDelete, UOverwrite, ULocale,
- UNewDir, UFileAssoc, USymlink, UCoreClasses, URemoteWait, UMain, UGnome;
+ UNewDir, UFileAssoc, USymlink, UCoreClasses, URemoteWait, UMain, UGnome, UError;
@@ -416,9 +416,11 @@ var DirStage1List, FilesList, DirStage2List: TList;
Item: PDataItem;
ItemSL: PDataItemSL;
ParentDir: string;
+ Error: PGError;
begin
LocalList := TList.Create;
- if Engine.GetListing(LocalList, LocalPath, True, False, True) = 0 then begin
+ Error := nil;
+ if Engine.GetListing(LocalList, LocalPath, True, False, True, @Error) then begin
if not SortForStream then FillDirFiles_sort(LocalList);
for i := 0 to LocalList.Count - 1 do begin
Item := LocalList[i];
@@ -436,8 +438,14 @@ var DirStage1List, FilesList, DirStage2List: TList;
if Item^.IsDir then begin
// Recurse to parent
ParentDir := IncludeTrailingPathDelimiter(string(Item^.FName));
- if Engine.ChangeDir(ParentDir) = 0 then
- FillDirFiles_Recurse(ParentDir, ALevel + 1);
+ Error := nil;
+ if Engine.ChangeDir(ParentDir, @Error) then
+ FillDirFiles_Recurse(ParentDir, ALevel + 1)
+ else begin
+ // * TODO: report and handle errors? we should make sure that user knows some of his data won't be copied
+ DebugMsg(['*** FillDirFiles_Recurse: error changing dir to ''', LocalPath, ''': ', Error^.message]);
+ g_error_free(Error);
+ end;
// Add end stage
ItemSL := DuplicateDataItem(ItemSL);
ItemSL^.Stage1 := False;
@@ -446,6 +454,9 @@ var DirStage1List, FilesList, DirStage2List: TList;
end;
end;
end else begin
+ // * TODO: report and handle errors? we should make sure that user knows some of his data won't be copied
+ DebugMsg(['*** FillDirFiles_Recurse: error getting listing of ''', LocalPath, ''': ', Error^.message]);
+ g_error_free(Error);
// Clear remaining items (in case of error)
for i := 0 to LocalList.Count - 1 do
FreeDataItem(PDataItem(LocalList[i]));
@@ -511,7 +522,8 @@ var ItemSL: PDataItemSL;
begin
ItemSL := malloc(sizeof(TDataItemSL));
memset(ItemSL, 0, sizeof(TDataItemSL));
- ItemSL^.DataItem := Engine.GetFileInfo(APath, False, True);
+ // * TODO: report errors? same way as for FillDirFiles
+ ItemSL^.DataItem := Engine.GetFileInfo(APath, False, True, nil);
ItemSL^.Stage1 := True;
ItemSL^.Level := 1;
Result := ItemSL;
@@ -584,21 +596,13 @@ end;
(********************************************************************************************************************************)
(********************************************************************************************************************************)
function MakeDirectory(ListView: TGTKListView; Engine: TPanelEngine; LeftPanel: boolean; NewDir: string): boolean;
-var Error: integer;
+var Error: PGError;
begin
- Result := False;
- try
- Error := Engine.MakeDir(IncludeTrailingPathDelimiter(Engine.Path) + NewDir);
- if Error <> 0 then begin
- Application.MessageBox(Format(LANGErrorCreatingNewDirectorySInSPanel, [StrToUTF8(NewDir), LANGPanelStrings[LeftPanel], GetErrorString(Error)]), [mbOK], mbError, mbNone, mbOK);
- Exit;
- end;
- Result := True;
- except
- on E: Exception do begin
- Application.MessageBox(Format(LANGErrorCreatingNewDirectorySInSPanelNoPath, [LANGPanelStrings[LeftPanel], E.Message]), [mbOK], mbError, mbNone, mbOK);
- Exit;
- end;
+ Error := nil;
+ Result := Engine.MakeDir(IncludeTrailingPathDelimiter(Engine.Path) + NewDir, @Error);
+ if not Result then begin
+ ShowError(FMain, Format('Error creating new directory ''%s'' in %s panel', [StrToUTF8(NewDir), LANGPanelStrings[LeftPanel]]), Error);
+ g_error_free(Error);
end;
end;
@@ -607,10 +611,11 @@ function CreateSymlink(const FileName, PossibleNewName: string; Engine: TPanelEn
var AFSymLink: TFSymlink;
function HandleCreateSymlink(const OldName, NewName: string): boolean;
- var Res, Response: integer;
+ var Response: integer;
+ Error: PGError;
begin
- Res := Engine.MakeSymLink(NewName, OldName);
- Result := Res = 0;
+ Error := nil;
+ Result := Engine.MakeSymLink(NewName, OldName, @Error);
if not Result then begin
try
FDirDelete := TFDirDelete.Create(AFSymlink);
@@ -618,9 +623,10 @@ var AFSymLink: TFSymlink;
FDirDelete.AddButtons(2);
FDirDelete.Label1.Caption := LANGTheSymbolicLink;
FDirDelete.Label2.Caption := NewName;
- FDirDelete.Label3.Caption := Format(LANGCouldNotBeCreatedS, [GetErrorString(Res)]);
+ FDirDelete.Label3.Caption := Format(LANGCouldNotBeCreatedS, [Error^.message]);
FDirDelete.Label3.Visible := True;
Response := Integer(FDirDelete.Run);
+ g_error_free(Error);
finally
FDirDelete.Free;
end;
@@ -657,10 +663,11 @@ var Data: PDataItem;
AFSymLink: TFSymlink;
function HandleEditSymlink(const ExistingName, PointTo: string): boolean;
- var Res, Response: integer;
+ var Response: integer;
+ Error: PGError;
begin
- Res := Engine.Remove(ExistingName);
- Result := Res = 0;
+ Error := nil;
+ Result := Engine.Remove(ExistingName, @Error);
if not Result then begin
try
FDirDelete := TFDirDelete.Create(AFSymlink);
@@ -668,9 +675,10 @@ var Data: PDataItem;
FDirDelete.AddButtons(2);
FDirDelete.Label1.Caption := LANGTheSymbolicLink;
FDirDelete.Label2.Caption := StrToUTF8(ExistingName);
- FDirDelete.Label3.Caption := Format(LANGCouldNotBeDeletedS, [GetErrorString(Res)]);
+ FDirDelete.Label3.Caption := Format(LANGCouldNotBeDeletedS, [Error^.message]);
FDirDelete.Label3.Visible := True;
Response := Integer(FDirDelete.Run);
+ g_error_free(Error);
finally
FDirDelete.Free;
end;
@@ -679,8 +687,9 @@ var Data: PDataItem;
end;
Exit;
end;
- Res := Engine.MakeSymLink(ExistingName, PointTo);
- Result := Res = 0;
+
+ Error := nil;
+ Result := Engine.MakeSymLink(ExistingName, PointTo, @Error);
if not Result then begin
try
FDirDelete := TFDirDelete.Create(AFSymlink);
@@ -688,9 +697,10 @@ var Data: PDataItem;
FDirDelete.AddButtons(2);
FDirDelete.Label1.Caption := LANGTheSymbolicLink;
FDirDelete.Label2.Caption := StrToUTF8(ExistingName);
- FDirDelete.Label3.Caption := Format(LANGCouldNotBeCreatedS, [GetErrorString(Res)]);
+ FDirDelete.Label3.Caption := Format(LANGCouldNotBeCreatedS, [Error^.message]);
FDirDelete.Label3.Visible := True;
Response := Integer(FDirDelete.Run);
+ g_error_free(Error);
finally
FDirDelete.Free;
end;
@@ -703,7 +713,7 @@ var Data: PDataItem;
begin
Result := False;
- Data := Engine.GetFileInfo(FileName, False, True);
+ Data := Engine.GetFileInfo(FileName, False, True, nil);
if Data = nil then begin
Result := False;
Exit;
@@ -869,10 +879,11 @@ function CRCGetInfo(FileName: string; Engine: TPanelEngine; var TargetName: stri
end;
const CRCBlockSize = 32768;
-var i, Error, Count, Start: integer;
+var i, Count, Start: integer;
FD: TEngineFileDes;
Buffer: Pointer;
s: string;
+ Error: PGError;
begin
Result := False;
if Pos('.', FileName) > 1 then FileName := ChangeFileExt(FileName, '.crc')
@@ -884,15 +895,21 @@ begin
Application.MessageBox(LANGAnErrorOccuredWhileInitializingMemoryBlock, [mbOK], mbError, mbNone, mbOK);
Exit;
end;
- FD := Engine.OpenFile(FileName, omRead, Error);
- if Error <> 0 then Exit;
+ Error := nil;
+ FD := Engine.OpenFile(FileName, omRead, @Error);
+ if Error <> nil then begin
+ g_error_free(nil);
+ Exit;
+ end;
s := '';
repeat
- Count := Engine.ReadFile(FD, Buffer, CRCBlockSize, Error);
- if Error <> 0 then begin
+ Error := nil;
+ Count := Engine.ReadFile(FD, Buffer, CRCBlockSize, @Error);
+ if Error <> nil then begin
libc_free(Buffer);
- Engine.CloseFile(FD);
+ g_error_free(nil);
+ Engine.CloseFile(FD, nil);
Exit;
end;
// processing begins
@@ -911,33 +928,39 @@ begin
until Count < CRCBlockSize;
if Length(s) > 0 then ProcessLine(s);
- Engine.CloseFile(FD);
+ Engine.CloseFile(FD, nil);
libc_free(Buffer);
Result := True;
end;
(********************************************************************************************************************************)
-function WriteCRCFile(Engine: TPanelEngine; TargetFile, SplitFileName: string; const FileSize: Int64; const FileCRC: Longword): boolean;
+function WriteCRCFile(Sender: TObject; Engine: TPanelEngine; TargetFile, SplitFileName: string; const FileSize: Int64; const FileCRC: Longword): boolean;
var FD: TEngineFileDes;
- Error, Count: integer;
+ Count: integer;
s: string;
+ Error: PGError;
begin
Result := False;
if Pos('.', TargetFile) > 1 then TargetFile := ChangeFileExt(TargetFile, '.crc')
else TargetFile := TargetFile + '.crc';
- FD := Engine.OpenFile(TargetFile, omWrite, Error);
- if Error <> 0 then begin
- Application.MessageBox(Format(LANGAnErrorOccuredWhileOpeningFileSS, [TargetFile, GetErrorString(Error)]), [mbOK], mbError, mbNone, mbOK);
+ Error := nil;
+ FD := Engine.OpenFile(TargetFile, omWrite, @Error);
+ if FD = nil then begin
+ if Error <> nil then begin
+ ShowError(TCustomGTKForm(Sender), Format('An error occured while opening file ''%s''', [TargetFile]), Error);
+ g_error_free(Error);
+ end;
Exit;
end;
s := Format('filename=%s'#13#10'size=%d'#13#10'crc32=%s'#13#10, [SplitFileName, FileSize, WideUpperCase(IntToHex(FileCRC, 8))]);
- Count := Engine.WriteFile(FD, @s[1], Length(s), Error);
- if (Error <> 0) or (Count <> Length(s)) then begin
- Application.MessageBox(Format(LANGAnErrorOccuredWhileWritingFileSS, [TargetFile, GetErrorString(Error)]), [mbOK], mbError, mbNone, mbOK);
+ Count := Engine.WriteFile(FD, @s[1], Length(s), @Error);
+ if (Error <> nil) { or (Count <> Length(s)) } then begin
+ ShowError(TCustomGTKForm(Sender), Format('An error occured while writing file ''%s''', [TargetFile]), Error);
+ g_error_free(Error);
Exit;
end;
- Engine.CloseFile(FD);
+ Engine.CloseFile(FD, nil);
Result := True;
end;
diff --git a/UCoreUtils.pas b/UCoreUtils.pas
index f319d44..faf6eb5 100644
--- a/UCoreUtils.pas
+++ b/UCoreUtils.pas
@@ -34,9 +34,6 @@ const ConstERRSpawn = 26;
ConstQuotationCharacters = [' ', '"', '''', '(', ')', ':', '&'];
ConstURIIllegalCharacters = '%:@/';
-function GetErrorString(ErrorNo: integer): string;
-function GetSignalString(SignalNo: integer): string;
-
function FormatSize(Value: Int64; Base: integer; OverrideSizeFormat: integer = -1): string;
function FormatDate(Value: time_t; const FormatTime, FormatDate: boolean; OverrideTimeFormat: integer = -1; OverrideDateFormat: integer = -1; OverrideDateTimeFormat: integer = -1; OverrideCustomDateFormat: string = ''; OverrideCustomTimeFormat: string = ''): string;
function StripDate(Value: time_t): time_t;
@@ -144,24 +141,6 @@ implementation
uses DateUtils, GTKForms, GTKUtils, GTKView, ULocale, UConfig, UCore, UGnome, UMain, UFileAssoc;
(********************************************************************************************************************************)
-function GetErrorString(ErrorNo: integer): string;
-begin
- if ErrorNo >= 0 then Result := StrToUTF8(String(strerror(ErrorNo)))
- else
- case ErrorNo of
- ERRException : Result := LANGUnknownException;
- ERRNoAccess : Result := LANGNoAccess;
- else Result := LANGUnknownError;
- end;
-end;
-
-(********************************************************************************************************************************)
-function GetSignalString(SignalNo: integer): string;
-begin
- Result := StrToUTF8(strsignal(SignalNo));
-end;
-
-(********************************************************************************************************************************)
function FormatFloat64(Value: Int64; Sep: string): string;
var i : integer;
Orig : string;
@@ -1127,13 +1106,18 @@ end;
(********************************************************************************************************************************)
procedure DebugMsg(Params: array of const);
-var
- I: Integer;
+var I: Integer;
+ P: PChar;
begin
if ParamDebug then begin
for I := 0 to High(Params) do
with Params[I] do
case VType of
+ vtPointer: begin
+ P := g_strdup_printf('%p', VPointer);
+ Write(ErrOutput, P);
+ g_free(P);
+ end;
vtInteger: Write(ErrOutput, IntToStr(VInteger));
vtBoolean: Write(ErrOutput, VBoolean);
vtChar: Write(ErrOutput, VChar);
diff --git a/UCoreWorkers.pas b/UCoreWorkers.pas
index 6eabc1e..72dd60f 100644
--- a/UCoreWorkers.pas
+++ b/UCoreWorkers.pas
@@ -26,6 +26,7 @@ type TVFSCallbackThread = class(TThread)
private
FThreadID: __pthread_t;
FCopyProgressFunc: TEngineProgressFunc;
+ // * TODO: move to Create() ?
procedure PrepareExecute; // Call this right after thread has been started
public
AEngine: TPanelEngine;
@@ -143,7 +144,7 @@ type TVFSCallbackThread = class(TThread)
TOpenDirThread = class(TVFSCallbackThread)
private
- function ChangeDir(Engine: TPanelEngine; Path: string; var SelItem: string; const AutoFallBack: boolean): integer;
+ function ChangeDir(Engine: TPanelEngine; Path: string; var SelItem: string; const AutoFallBack: boolean): boolean;
protected
procedure Execute; override;
public
@@ -151,10 +152,11 @@ type TVFSCallbackThread = class(TThread)
ASelItem: string;
AAutoFallBack: boolean;
ADirList: TList;
- ChDirResult, ListingResult, VFSOpenResult: integer;
Finished, CancelIt: boolean;
RunningTime: Int64;
AFullPath, AHighlightItem: string;
+ ChDirResult, ListingResult, VFSOpenResult: boolean;
+ ChDirError, ListingError, VFSOpenError: PGError;
constructor Create;
destructor Destroy; override;
end;
@@ -167,6 +169,7 @@ type TVFSCallbackThread = class(TThread)
URI: string;
Finished: boolean;
OpenResult: boolean;
+ OpenError: PGError;
constructor Create;
destructor Destroy; override;
end;
@@ -349,16 +352,17 @@ begin
password_save^ := VFS_PASSWORD_SAVE_NEVER;
end;
-function vfs_progress_callback(position, max: guint64; user_data: Pointer): gboolean; cdecl;
+// Keep in sync with uVFSprototypes.pas/TVFSProgressCallback
+function vfs_copy_progress_callback(position: guint64; error: PGError; user_data: Pointer): gboolean; cdecl;
begin
// DebugMsg(['VFSCopyCallBackFunc called (iPos = ', iPos, ', iMax = ', iMax, ')']);
Result := True;
if not Assigned(user_data) then Exit;
if Assigned(TVFSCallbackThread(user_data).FCopyProgressFunc) then
try
- Result := TVFSCallbackThread(user_data).FCopyProgressFunc(user_data, position);
+ Result := TVFSCallbackThread(user_data).FCopyProgressFunc(user_data, position, error);
except
- on E: Exception do DebugMsg(['*** Exception raised in vfs_progress_callback(position=', position, ', max=', max, ', user_data=', user_data, '): (', E.ClassName, '): ', E.Message]);
+ on E: Exception do DebugMsg(['*** Exception raised in vfs_copy_progress_callback(position=', position, ', user_data=', user_data, '): (', E.ClassName, '): ', E.Message]);
end;
end;
@@ -729,19 +733,23 @@ end;
procedure DeleteFilesWorker(SenderThread: TWorkerThread);
var SkipAll: boolean;
+ // Return False to break the operation
function HandleDelete(AFileRec: PDataItemSL): boolean;
- var Res, Response: integer;
+ var Response: integer;
+ Res: boolean;
+ Error: PGError;
begin
Result := True;
+ Error := nil;
// 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 := SenderThread.Engine.Remove(String(AFileRec^.DataItem^.FName));
+ Res := SenderThread.Engine.Remove(String(AFileRec^.DataItem^.FName), @Error);
// DebugMsg(['Result : ', Res]);
- if Res <> 0 then
+ if not Res then
if SkipAll then Result := True else
begin
Response := SenderThread.ShowDirDeleteDialog(1, LANGTheFileDirectory, String(AFileRec^.DataItem^.FDisplayName),
- Format(LANGCouldNotBeDeletedS, [GetErrorString(Res)]));
+ Format(LANGCouldNotBeDeletedS, [Error^.message]));
case Response of
1 : Result := True;
3 : begin
@@ -752,6 +760,8 @@ var SkipAll: boolean;
else Result := False;
end;
end;
+ if Error <> nil then
+ g_error_free(Error);
end;
var i: longint;
@@ -766,7 +776,9 @@ begin
with SenderThread do begin
CurrPath := IncludeTrailingPathDelimiter(Engine.Path);
PrepareJobFilesFromPanel(AList, False);
- if Engine.ChangeDir(CurrPath) <> 0 then DebugMsg(['*** WARNING: Cannot change to the origin location, strange behaviour might occur.']);
+ // * TODO: catch the error
+ if not Engine.ChangeDir(CurrPath, nil) then
+ DebugMsg(['*** WARNING: Cannot change to the origin location, strange behaviour might occur.']);
libc_chdir('/');
SetProgress1Params(AList.Count);
@@ -814,7 +826,9 @@ begin
for i := AList.Count - 1 downto 0 do FreeDataItem(PDataItemSL(AList[i]));
AList.Clear;
AList.Free;
- if Engine.ChangeDir(CurrPath) <> 0 then DebugMsg(['*** WARNING: Cannot change to the origin location, strange behaviour might occur.']);
+ // * TODO: catch the error
+ if not Engine.ChangeDir(CurrPath, nil) then
+ DebugMsg(['*** WARNING: Cannot change to the origin location, strange behaviour might occur.']);
end;
SenderThread.FDoneThread := True;
end;
@@ -825,8 +839,8 @@ end;
(********************************************************************************************************************************)
(********************************************************************************************************************************)
- // Return False to break the process
- function CopyFilesWorker_ProgressFunc(Sender: Pointer; BytesDone: Int64): boolean; cdecl;
+ // Keep in sync with UEngines.pas/TEngineProgressFunc
+ function CopyFilesWorker_ProgressFunc(Sender: Pointer; BytesDone: Int64; Error: PGError): boolean; cdecl;
begin
Result := True;
// DebugMsg(['*** CopyFilesWorker: ProgressFunc called (Sender=', QWord(Sender), ', BytesDone=', BytesDone, ')']);
@@ -872,7 +886,8 @@ end;
if ErrorType <> 1 then s3 := StrToUTF8(FileName)
else s3 := '';
- case ShowDirDeleteDialog(3, s, s3, GetErrorString(ErrorNum), s2) of
+ // * TODO: fix error string
+ case ShowDirDeleteDialog(3, s, s3, 'ahoj' { GetErrorString(ErrorNum)} , s2) of
0, 252 : begin // Cancel button, Escape
Result := False;
CancelIt;
@@ -908,25 +923,28 @@ var DefResponse: integer; // Global variables for this function
// Returns True if file was successfully copied, if not, the file will be deleted in LocalCopyFile
function ManualCopyFile(SourceFile, DestFile: string; Append: boolean): boolean;
var fsrc, fdst: TEngineFileDes;
- Error, BSize: integer;
+ BSize: integer;
Buffer: Pointer;
BytesDone, BytesRead, BytesWritten: Int64;
Res: boolean;
+ Error: PGError;
begin
DebugMsg(['ManualCopyFile: ', SourceFile, ' ---> ', DestFile]);
with SenderThread do begin
Result := False;
- Error := 0;
- fsrc := SrcEngine.OpenFile(SourceFile, omRead, Error);
- if Error <> 0 then begin
- CopyFilesWorker_ErrorFunc(SenderThread, 2, Error, SourceFile); // Cannot open source file
+ Error := nil;
+ fsrc := SrcEngine.OpenFile(SourceFile, omRead, @Error);
+ if fsrc = nil then begin
+ // * TODO: set real error, also free it
+ CopyFilesWorker_ErrorFunc(SenderThread, 2, 1 { Error }, SourceFile); // Cannot open source file
Exit;
end;
- if Append then fdst := DestEngine.OpenFile(DestFile, omAppend, Error)
- else fdst := DestEngine.OpenFile(DestFile, omWrite, Error);
- if Error <> 0 then begin
- SrcEngine.CloseFile(fsrc);
- CopyFilesWorker_ErrorFunc(SenderThread, 3, Error, SourceFile); // Cannot open target file
+ if Append then fdst := DestEngine.OpenFile(DestFile, omAppend, @Error)
+ else fdst := DestEngine.OpenFile(DestFile, omWrite, @Error);
+ if fdst = nil then begin
+ // * TODO: set real error, also free it
+ SrcEngine.CloseFile(fsrc, nil);
+ CopyFilesWorker_ErrorFunc(SenderThread, 3, 1 { Error }, SourceFile); // Cannot open target file
Exit;
end;
@@ -944,27 +962,32 @@ var DefResponse: integer; // Global variables for this function
BytesWritten := 0;
repeat
- BytesRead := SrcEngine.ReadFile(fsrc, Buffer, BSize, Error);
- if (BytesRead = 0) and (Error <> 0) then
- Res := CopyFilesWorker_ErrorFunc(SenderThread, 6, Error, SourceFile); // Cannot read from source file
+ BytesRead := SrcEngine.ReadFile(fsrc, Buffer, BSize, @Error);
+ if (BytesRead = 0) and (Error <> nil) then
+ // * TODO: set real error, also free it
+ Res := CopyFilesWorker_ErrorFunc(SenderThread, 6, 1 { Error }, SourceFile); // Cannot read from source file
if BytesRead > 0 then begin
- BytesWritten := DestEngine.WriteFile(fdst, Buffer, BytesRead, Error);
+ Error := nil;
+ BytesWritten := DestEngine.WriteFile(fdst, Buffer, BytesRead, @Error);
if (BytesWritten < BytesRead) then
- Res := CopyFilesWorker_ErrorFunc(SenderThread, 7, Error, DestFile); // Cannot write to source file
+ // * TODO: set real error, also free it
+ Res := CopyFilesWorker_ErrorFunc(SenderThread, 7, 1 { Error }, DestFile); // Cannot write to source file
end;
Inc(BytesDone, BytesRead);
- if not CopyFilesWorker_ProgressFunc(SenderThread, BytesDone) then begin
+ if not CopyFilesWorker_ProgressFunc(SenderThread, BytesDone, nil) then begin
Res := False;
Break;
end;
until (BytesRead = 0) or (BytesWritten < BytesRead);
libc_free(Buffer);
- if DestEngine.CloseFile(fdst) <> 0 then begin
+ // * TODO: set real error, also free it
+ if not DestEngine.CloseFile(fdst, nil) then begin
CopyFilesWorker_ErrorFunc(SenderThread, 4, errno, DestFile); // Cannot close target file
Exit;
end;
- if SrcEngine.CloseFile(fsrc) <> 0 then begin
+ // * TODO: set real error, also free it
+ if not SrcEngine.CloseFile(fsrc, nil) then begin
CopyFilesWorker_ErrorFunc(SenderThread, 5, errno, SourceFile); // Cannot close source file
Exit;
end;
@@ -984,21 +1007,21 @@ var DefResponse: integer; // Global variables for this function
// local -> local
if (SrcEngine is TLocalTreeEngine) and (DestEngine is TLocalTreeEngine)
- then Result := DestEngine.CopyFileIn(SenderThread, SourceFile, DestFile, @CopyFilesWorker_ProgressFunc, @CopyFilesWorker_ErrorFunc, Append)
+ then Result := DestEngine.CopyFileIn(SourceFile, DestFile, Append, @CopyFilesWorker_ProgressFunc, SenderThread)
else
// from local engine to VFS engine
if (SrcEngine is TLocalTreeEngine) and (DestEngine is TVFSEngine) then
begin
AEngine := DestEngine;
- Result := (DestEngine as TVFSEngine).CopyFileInEx(SenderThread, SourceFile, DestFile, @CopyFilesWorker_ErrorFunc, Append);
+ Result := (DestEngine as TVFSEngine).CopyFileInEx(SourceFile, DestFile, Append);
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(SenderThread, SourceFile, DestFile, @CopyFilesWorker_ErrorFunc, Append);
+ Result := (SrcEngine as TVFSEngine).CopyFileOutEx(SourceFile, DestFile, Append);
end
// VFS to VFS (not supported yet)
@@ -1011,11 +1034,14 @@ var DefResponse: integer; // Global variables for this function
// Copy OK? (check size, otherwise delete target file)
if (not Append) and (not Result) then begin
- DataSrc := SrcEngine.GetFileInfo(SourceFile, False, True);
+ // * TODO: check error
+ DataSrc := SrcEngine.GetFileInfo(SourceFile, False, True, nil);
if DataSrc = nil then Exit;
- DataDest := DestEngine.GetFileInfo(DestFile, False, True);
+ // * TODO: check error
+ DataDest := DestEngine.GetFileInfo(DestFile, False, True, nil);
if (DataDest <> nil) and (DataSrc^.Size <> DataDest^.Size) then
- DestEngine.Remove(DestFile);
+ // * TODO: check error
+ DestEngine.Remove(DestFile, nil);
FreeDataItem(DataSrc);
FreeDataItem(DataDest);
end;
@@ -1066,41 +1092,47 @@ var DefResponse: integer; // Global variables for this function
if DataItem^.IsLnk then begin
// Explicit copy the file
if ParamBool3 or (not IsOnSameFS(String(DataItem^.FName), ExtractFileDir(Dst))) then begin
- ErrorKind := DestEngine.MakeSymLink(Dst, String(DataItem^.LnkPointTo));
- if ErrorKind <> 0 then Result := ERRCreateLink;
+ // * TODO: check error
+ ErrorKind := Ord(DestEngine.MakeSymLink(Dst, String(DataItem^.LnkPointTo), nil));
+// if ErrorKind <> 0 then Result := ERRCreateLink;
if not ParamBool3 then begin
- ErrorKind := SrcEngine.Remove(String(DataItem^.FName));
- if ErrorKind <> 0 then Result := ERRRemove;
+ // * TODO: check error
+ ErrorKind := Ord(SrcEngine.Remove(String(DataItem^.FName), nil));
+// if ErrorKind <> 0 then Result := ERRRemove;
end;
end else begin // Move the file
- ErrorKind := DestEngine.RenameFile(String(DataItem^.FName), Dst);
- if ErrorKind <> 0 then Result := ERRCopyMove;
+ // * TODO: check error
+ ErrorKind := Ord(DestEngine.RenameFile(String(DataItem^.FName), Dst, nil));
+// if ErrorKind <> 0 then Result := ERRCopyMove;
end;
end else // is not link
if ParamBool3 then begin // Copy mode
if LocalCopyFile(String(DataItem^.FName), Dst, Append) then begin
if IsOnRO and ConfClearReadOnlyAttr and (DataItem^.Mode and S_IWUSR = 0) then DataItem^.Mode := DataItem^.Mode or S_IWUSR;
- DestEngine.Chmod(Dst, DataItem^.Mode);
- DestEngine.Chown(Dst, DataItem^.UID, DataItem^.GID);
- DestEngine.ChangeTimes(Dst, DataItem^.mtime, DataItem^.atime);
+ // * 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);
end;
end else // Move mode
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']);
- ErrorKind := DestEngine.RenameFile(String(DataItem^.FName), Dst + '_tcmd');
- if ErrorKind = 0 then ErrorKind := DestEngine.RenameFile(Dst + '_tcmd', Dst);
- end else ErrorKind := DestEngine.RenameFile(String(DataItem^.FName), Dst);
- if ErrorKind <> 0 then Result := ERRCopyMove;
+ // * 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;
end else begin
if LocalCopyFile(String(DataItem^.FName), Dst, Append) then begin
if IsOnRO and ConfClearReadOnlyAttr and (DataItem^.Mode and S_IWUSR = 0) then DataItem^.Mode := DataItem^.Mode or S_IWUSR;
- DestEngine.Chmod(Dst, DataItem^.Mode);
- DestEngine.Chown(Dst, DataItem^.UID, DataItem^.GID);
- DestEngine.ChangeTimes(Dst, DataItem^.mtime, DataItem^.atime);
+ // * 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 Cancelled then begin
- ErrorKind := SrcEngine.Remove(String(DataItem^.FName));
- if ErrorKind <> 0 then Result := ERRRemove;
+ ErrorKind := Ord(SrcEngine.Remove(String(DataItem^.FName), nil));
+// if ErrorKind <> 0 then Result := ERRRemove;
end;
end;
end;
@@ -1126,10 +1158,11 @@ var DefResponse: integer; // Global variables for this function
if (not AFileRec^.Stage1) and (ParamBool3 or ((not ParamBool3) and (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;
- DestEngine.Chmod(NewFilePath, DataItem^.Mode);
- DestEngine.Chown(NewFilePath, DataItem^.UID, DataItem^.GID);
- DestEngine.ChangeTimes(NewFilePath, DataItem^.mtime, DataItem^.atime);
- if not ParamBool3 then SrcEngine.Remove(String(DataItem^.FName)); // Remove directory
+ // * 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 not ParamBool3 then SrcEngine.Remove(String(DataItem^.FName), nil); // Remove directory
Exit;
end;
@@ -1142,28 +1175,33 @@ var DefResponse: integer; // Global variables for this function
TwoSameFiles(ExcludeTrailingPathDelimiter(string(AFileRec^.DataItem^.FName)), ExcludeTrailingPathDelimiter(string(AFileRec^.ADestination)), False)) then
begin
DebugMsg(['*** Activating double-rename due to renaming on case-insensitive FS']);
- ErrorKind := DestEngine.RenameFile(string(AFileRec^.DataItem^.FName), ExcludeTrailingPathDelimiter(string(AFileRec^.ADestination)) + '_tcmd');
- if ErrorKind = 0 then ErrorKind := DestEngine.RenameFile(ExcludeTrailingPathDelimiter(string(AFileRec^.ADestination)) + '_tcmd', ExcludeTrailingPathDelimiter(string(AFileRec^.ADestination)));
- end else ErrorKind := DestEngine.RenameFile(string(AFileRec^.DataItem^.FName), string(AFileRec^.ADestination));
- if ErrorKind <> 0 then Res := ERRCopyMove
- else Res := 0;
+ // * 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; }
end else
if not DestEngine.DirectoryExists(NewFilePath, False) then begin
- ErrorKind := DestEngine.MakeDir(NewFilePath);
- if ErrorKind <> 0 then Res := ERRMkDir
- else Res := 0;
+ // * 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 DestEngine.MakeDir(ExtractFileDir(NewFilePath));
+ 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));
if AFileRec^.DataItem^.Size <= 1 then ParamFloat2 := 1 else ParamFloat2 := 100 / (AFileRec^.DataItem^.Size - 1);
- CopyFilesWorker_ProgressFunc(SenderThread, 0);
+ CopyFilesWorker_ProgressFunc(SenderThread, 0, nil);
Res := 0;
if DestEngine.FileExists(NewFilePath, False) and
(not (not ParamBool3 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);
+ // * TODO: check error
+ 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;
@@ -1201,16 +1239,19 @@ var DefResponse: integer; // Global variables for this function
// Remove destination file if exists and should be overwritten
if (Response in [1, 2]) or ((Response = 5) and (Item^.mtime < AFileRec^.DataItem^.mtime)) then begin
- r := DestEngine.Remove(NewFilePath);
+ // * TODO: check error
+ r := ord(DestEngine.Remove(NewFilePath, nil));
while r <> 0 do begin
+ // * TODO: check error
Res := ShowDirDeleteDialog(1, LANGTheFile, StrToUTF8(String(NewFilePath)),
- Format(LANGCouldNotBeDeletedS, [GetErrorString(r)]), LANGCopyError);
+ Format(LANGCouldNotBeDeletedS, ['ahoj' {GetErrorString(r)}]), LANGCopyError);
case Res of
1: begin
Result := True;
Exit;
end;
- 2: r := DestEngine.Remove(NewFilePath);
+ // * TODO: check error
+ 2: r := Ord(DestEngine.Remove(NewFilePath, nil));
0, 124, 255: begin
Result := False;
Exit;
@@ -1226,7 +1267,8 @@ var DefResponse: integer; // Global variables for this function
if (Res <> 0) and (not SkipAll) then begin
if ParamBool3 then cap := LANGCopy
else cap := LANGMove;
- case Res of
+ // * TODO: port to GError
+{ case Res of
ERRCreateLink: begin
s1 := LANGTheSymbolicLink;
if ErrorKind = 0 then s3 := LANGCouldNotBeCreated else
@@ -1250,7 +1292,7 @@ var DefResponse: integer; // Global variables for this function
if ErrorKind = 0 then s3 := '' else
s3 := GetErrorString(ErrorKind);
end;
- end;
+ end; }
Response := ShowDirDeleteDialog(1, s1, StrToUTF8(String(NewFilePath)), s3, cap);
case Response of
1 : Result := True; // Skip
@@ -1396,9 +1438,9 @@ begin
if List.Count > 0 then begin
StartPassed := True;
if SrcEngine is TVFSEngine then
- StartPassed := StartPassed and (SrcEngine as TVFSEngine).StartCopyOperation(SenderThread, @CopyFilesWorker_ErrorFunc, @vfs_ask_question_callback, @vfs_ask_password_callback, @vfs_progress_callback, SenderThread);
+ StartPassed := StartPassed and (SrcEngine as TVFSEngine).StartCopyOperation(@vfs_ask_question_callback, @vfs_ask_password_callback, @vfs_copy_progress_callback, SenderThread);
if DestEngine is TVFSEngine then
- StartPassed := StartPassed and (DestEngine as TVFSEngine).StartCopyOperation(SenderThread, @CopyFilesWorker_ErrorFunc, @vfs_ask_question_callback, @vfs_ask_password_callback, @vfs_progress_callback, SenderThread);
+ StartPassed := StartPassed and (DestEngine as TVFSEngine).StartCopyOperation(@vfs_ask_question_callback, @vfs_ask_password_callback, @vfs_copy_progress_callback, SenderThread);
if StartPassed then
for i := 0 to List.Count - 1 do begin
@@ -1442,9 +1484,9 @@ begin
// We need to ensure these to be called in case of error
if SrcEngine is TVFSEngine then
- (SrcEngine as TVFSEngine).StopCopyOperation(SenderThread, @CopyFilesWorker_ErrorFunc);
+ (SrcEngine as TVFSEngine).StopCopyOperation(@vfs_copy_progress_callback, SenderThread);
if DestEngine is TVFSEngine then
- (DestEngine as TVFSEngine).StopCopyOperation(SenderThread, @CopyFilesWorker_ErrorFunc);
+ (DestEngine as TVFSEngine).StopCopyOperation(@vfs_copy_progress_callback, SenderThread);
end;
// Free the objects
@@ -1452,9 +1494,13 @@ begin
for i := List.Count - 1 downto 0 do FreeDataItem(PDataItemSL(List[i]));
List.Clear;
List.Free;
- if DestEngine.ChangeDir(SaveDestPath) <> 0 then DebugMsg(['*** WARNING: Cannot change to the origin location, strange behaviour might occur.']);
+ // * TODO: check error
+ if not DestEngine.ChangeDir(SaveDestPath, nil) then
+ DebugMsg(['*** WARNING: Cannot change to the origin location, strange behaviour might occur.']);
if SaveSrcPath <> '' then CurrPath := SaveSrcPath;
- if SrcEngine.ChangeDir(CurrPath) <> 0 then DebugMsg(['*** WARNING: Cannot change to the origin location, strange behaviour might occur.']);
+ // * TODO: check error
+ if not SrcEngine.ChangeDir(CurrPath, nil) then
+ DebugMsg(['*** WARNING: Cannot change to the origin location, strange behaviour might occur.']);
end;
SenderThread.FDoneThread := True;
DebugMsg(['(II) CopyFilesWorker: finished']);
@@ -1474,12 +1520,13 @@ procedure MergeFilesWorker(SenderThread: TWorkerThread);
// ParamInt64 = TargetSize
var FD: TEngineFileDes;
- Error, Count, MergeBlockSize: integer;
+ Count, MergeBlockSize: integer;
Buffer: Pointer;
CurrentCRC: LongWord;
PrivateCancel: boolean;
SizeDone: Int64;
TargetName: string;
+ Error: PGError;
function PasteFile(FName: string): boolean;
@@ -1493,21 +1540,26 @@ var FD: TEngineFileDes;
else UpdateCaption1(Format(LANGFromS, [StrToUTF8(FName)]));
UpdateProgress1(0, '0 %');
CommitGUIUpdate;
- Stat := Engine.GetFileInfo(FName, True, True);
+ // * TODO: check error
+ Stat := Engine.GetFileInfo(FName, True, True, nil);
if not Assigned(Stat) then Exit;
SetProgress1Params(Stat^.Size);
FreeDataItem(Stat);
- FDR := Engine.OpenFile(FName, omRead, Error);
- if Error <> 0 then Exit;
+ // * TODO: check error
+ Error := nil;
+ FDR := Engine.OpenFile(FName, omRead, @Error);
+ if FDR = nil then Exit;
repeat
- Count := Engine.ReadFile(FDR, Buffer, MergeBlockSize, Error);
- if Error <> 0 then begin
- Engine.CloseFile(FD);
+ // * TODO: check error
+ Count := Engine.ReadFile(FDR, Buffer, MergeBlockSize, @Error);
+ if Error <> nil then begin
+ Engine.CloseFile(FD, nil);
Exit;
end;
- wCount := Engine.WriteFile(FD, Buffer, Count, Error);
- if (Error <> 0) or (Count <> wCount) then begin
- FCancelMessage := Format(LANGAnErrorOccuredWhileWritingFileSS, [ExtractFileName(TargetName), GetErrorString(Error)]);
+ // * TODO: check error
+ wCount := Engine.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
@@ -1519,7 +1571,8 @@ var FD: TEngineFileDes;
if ParamBool1 then UpdateProgress2(SizeDone, Format('%d %%', [Trunc(SizeDone / FProgress2Max * 100)]));
CommitGUIUpdate;
until (Count < MergeBlockSize) or Cancelled;
- Engine.CloseFile(FDR);
+ // * TODO: set real error, also free it
+ Engine.CloseFile(FDR, nil);
end;
Result := True;
end;
@@ -1541,15 +1594,17 @@ begin
if Engine.FileExists(TargetName, False) then
if ShowMessageBox(Format(LANGTheTargetFileSAlreadyExistsDoYouWantToOverwriteIt, [StrToUTF8(TargetName)]), [mbYes, mbNo], mbQuestion, mbNone, mbNo) = mbYes then
begin
- Error := Engine.Remove(TargetName);
+ // * TODO: check error
+{ Error := Ord(Engine.Remove(TargetName, nil));
if Error <> 0 then begin
FCancelMessage := Format(LANGTheTargetFileSCannotBeRemovedS, [StrToUTF8(ExtractFileName(TargetName)), GetErrorString(Error)]);
FShowCancelMessage := True;
Exit;
- end;
+ end; }
end else Exit;
- Stat := Engine.GetFileInfo(ParamString2, True, True);
+ // * TODO: check error
+ Stat := Engine.GetFileInfo(ParamString2, True, True, nil);
if Assigned(Stat) then MergeBlockSize := ComputeBlockSize(Stat^.Size)
else MergeBlockSize := 65536*4;
FreeDataItem(Stat);
@@ -1561,9 +1616,10 @@ begin
FShowCancelMessage := True;
Exit;
end;
- FD := Engine.OpenFile(TargetName, omWrite, Error);
- if Error <> 0 then begin
- FCancelMessage := Format(LANGAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(TargetName), GetErrorString(Error)]);
+ // * TODO: check error
+ FD := Engine.OpenFile(TargetName, omWrite, @Error);
+ if Error <> nil then begin
+ FCancelMessage := Format(LANGAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(TargetName), Error^.message]);
FShowCancelMessage := True;
libc_free(Buffer);
Exit;
@@ -1600,7 +1656,8 @@ begin
CurrFile := '';
end;
until (SizeDone = ParamInt64) or Cancelled or PrivateCancel {or ((not b) and (not HasInitialCRC))} or (CurrFile = '');
- if (not ParamBool1) and HasFinalCRC then Engine.RenameFile(TargetName, IncludeTrailingPathDelimiter(ExtractFilePath(TargetName)) + TargetFinalName);
+ // * TODO: check error
+ if (not ParamBool1) and HasFinalCRC then Engine.RenameFile(TargetName, IncludeTrailingPathDelimiter(ExtractFilePath(TargetName)) + TargetFinalName, nil);
if Cancelled and (not PrivateCancel) then begin
FCancelMessage := LANGUserCancelled;
FShowCancelMessage := True;
@@ -1611,7 +1668,8 @@ 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);
- Engine.CloseFile(FD);
+ // * TODO: set real error, also free it
+ Engine.CloseFile(FD, nil);
end;
libc_free(Buffer);
SenderThread.FDoneThread := True;
@@ -1630,7 +1688,7 @@ procedure SplitFilesWorker(SenderThread: TWorkerThread);
const SplitBlockSize = 65536*4;
var FD: TEngineFileDes;
- Error: integer;
+ Error: PGError;
FileCRC: LongWord;
Buffer: Pointer;
PrivateCancel: boolean;
@@ -1645,9 +1703,10 @@ var FD: TEngineFileDes;
Result := False;
Written := 0;
with SenderThread do begin
- FDW := Engine.OpenFile(TargetFile, omWrite, Error);
+ // * TODO: check error
+ FDW := Engine.OpenFile(TargetFile, omWrite, @Error);
DebugMsg(['-- Opening file ', ExtractFileName(TargetFile), ', PartSize = ', PartSize]);
- if Error <> 0 then Exit;
+ if Error <> nil then Exit;
if ParamInt64 > 0 then begin
UpdateCaption2(Format(LANGToS, [StrToUTF8(TargetFile)]));
SetProgress1Params(PartSize);
@@ -1655,30 +1714,37 @@ var FD: TEngineFileDes;
end else UpdateCaption1(Format(LANGToS, [StrToUTF8(TargetFile)]));
CommitGUIUpdate;
repeat
- DebugMsg(['Seek to ', Engine.FileSeek(FD, SizeDone + Written, Error), ', Written = ', Written]);
+ // * TODO: check error
+ DebugMsg(['Seek to ', Engine.FileSeek(FD, SizeDone + Written, @Error), ', Written = ', Written]);
if Written + SplitBlockSize > PartSize then bl := PartSize - Written
else bl := SplitBlockSize;
- Count := Engine.ReadFile(FD, Buffer, bl, Error);
- if (Error <> 0) or (Count <> bl) then begin
- Engine.CloseFile(FDW);
- DebugMsg(['Read Error: ', GetErrorString(Error), ', Count = ', Count, ', bl = ', bl]);
- if (Count <> bl) and (Error = 0) then Error := EIO;
+ // * TODO: check error
+ Count := Engine.ReadFile(FD, Buffer, bl, @Error);
+ if (Error <> nil) or (Count <> bl) then begin
+ // * TODO: set real error, also free it
+ Engine.CloseFile(FDW, nil);
+ DebugMsg(['Read Error: ', Error^.message, ', Count = ', Count, ', bl = ', bl]);
+// if (Count <> bl) and (Error = 0) then Error := EIO;
Exit;
end;
- wCount := Engine.WriteFile(FDW, Buffer, Count, Error);
+ // * TODO: check error
+ wCount := Engine.WriteFile(FDW, Buffer, Count, @Error);
Inc(Written, wCount);
FileCRC := CRC32(FileCRC, Buffer, wCount);
- if (Error <> 0) or (Count <> wCount) then begin
- Engine.CloseFile(FDW);
- DebugMsg(['Write Error: ', GetErrorString(Error), ', Count = ', Count, ', wCount = ', wCount]);
- if (wCount <> Count) and (Error = 0) then Error := ENOSPC;
+ if (Error <> nil) or (Count <> wCount) then begin
+ // * TODO: set real error, also free it
+ Engine.CloseFile(FDW, nil);
+ // * TODO: check error
+ DebugMsg(['Write Error: ', Error^.message, ', Count = ', Count, ', wCount = ', wCount]);
+// if (wCount <> Count) and (Error = 0) then Error := ENOSPC;
Exit;
end;
UpdateProgress1(FProgress1Pos + wCount, Format('%d %%', [Trunc((FProgress1Pos + wCount) / FProgress1Max * 100)]));
if ParamInt64 > 0 then UpdateProgress2(FProgress2Pos + wCount, Format('%d %%', [Trunc((FProgress2Pos + wCount) / FProgress2Max * 100)]));
CommitGUIUpdate;
until (Written = PartSize) or Cancelled or PrivateCancel;
- Engine.CloseFile(FDW);
+ // * TODO: set real error, also free it
+ Engine.CloseFile(FDW, nil);
end;
DebugMsg(['-- Closing file ', ExtractFileName(TargetFile), ', PartSize = ', PartSize, ', Written = ', Written]);
Result := True;
@@ -1721,7 +1787,8 @@ var i: integer;
xx: string;
begin
with SenderThread do begin
- Stat := Engine.GetFileInfo(ParamString1, True, True);
+ // * TODO: check error
+ Stat := Engine.GetFileInfo(ParamString1, True, True, nil);
if not Assigned(Stat) then begin
FCancelMessage := Format(LANGCannotOpenFileS, [StrToUTF8(ParamString1)]);
FShowCancelMessage := True;
@@ -1746,9 +1813,10 @@ begin
FShowCancelMessage := True;
Exit;
end;
- FD := Engine.OpenFile(ParamString1, omRead, Error);
- if Error <> 0 then begin
- FCancelMessage := Format(LANGAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(ParamString1), GetErrorString(Error)]);
+ // * TODO: check error
+ FD := Engine.OpenFile(ParamString1, omRead, @Error);
+ if Error <> nil then begin
+ FCancelMessage := Format(LANGAnErrorOccuredWhileOpeningFileSS, [StrToUTF8(ParamString1), Error^.message]);
libc_free(Buffer);
Exit;
end;
@@ -1777,7 +1845,8 @@ begin
for i := List.Count - 1 downto 0 do
FreeDataItem(PDataItem(List[i]));
List.Clear;
- Error := Engine.GetListing(List, FilePath, ConfShowDotFiles, False, False);
+ // * TODO: check error
+{ Error := Engine.GetListing(List, FilePath, ConfShowDotFiles, False, False, nil);
if (Error = 0) and (List.Count > 0) then begin
st := '';
if List.Count < 6 then begin
@@ -1790,19 +1859,20 @@ 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);
end;
- end;
+ end; }
except end;
// Test for target file existence
if Engine.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
- Error := Engine.Remove(IncludeTrailingPathDelimiter(FilePath) + FileName);
+ // * TODO: check error
+{ Error := Engine.Remove(IncludeTrailingPathDelimiter(FilePath) + FileName);
if Error <> 0 then begin
FCancelMessage := Format(LANGTheTargetFileSCannotBeRemovedS, [StrToUTF8(IncludeTrailingPathDelimiter(FilePath) + FileName), GetErrorString(Error)]);
FShowCancelMessage := True;
PrivateCancel := True;
Break;
- end;
+ end; }
end else begin
PrivateCancel := True;
Break;
@@ -1815,7 +1885,7 @@ begin
if (CurrSize >= 512) and (TDF >= CurrSize) then begin
b := WriteSplitPart(IncludeTrailingPathDelimiter(FilePath) + FileName, CurrSize, ws);
if (not b) and (ParamInt64 > 0) then begin
- FCancelMessage := Format(LANGAnErrorOccuredWhileOperationS, [GetErrorString(Error)]);
+ FCancelMessage := Format(LANGAnErrorOccuredWhileOperationS, [Error^.message]);
FShowCancelMessage := True;
PrivateCancel := True;
Break;
@@ -1845,14 +1915,15 @@ begin
Engine.GetFileSystemInfo(FilePath, x, TDF, xx);
if (TDF < 512) and (not NewDiskQuestion) then Break;
until (TDF >= 512) or PrivateCancel or Cancelled;
- if WriteCRCFile(Engine, IncludeTrailingPathDelimiter(FilePath) + FileName, OriginalFName, SizeDone, FileCRC)
+ if WriteCRCFile(ProgressForm, Engine, IncludeTrailingPathDelimiter(FilePath) + FileName, OriginalFName, SizeDone, FileCRC)
then ShowMessageBox(Format(LANGSplitOfSSucceeded, [StrToUTF8(OriginalFName)]), [mbOK], mbInfo, mbNone, mbOK)
else begin
FCancelMessage := Format(LANGSplitOfSFailed, [StrToUTF8(OriginalFName)]);
FShowCancelMessage := True;
end;
end;
- Engine.CloseFile(FD);
+ // * TODO: set real error, also free it
+ Engine.CloseFile(FD, nil);
end;
if List.Count > 0 then
for i := List.Count - 1 downto 0 do
@@ -1874,7 +1945,8 @@ procedure ChmodFilesWorker(SenderThread: TWorkerThread);
var SkipAll: boolean;
function HandleChmod(AFileRec: PDataItemSL): boolean;
- var Res, Response: integer;
+ var Response: integer;
+ Res: boolean;
begin
Result := True;
with SenderThread do begin
@@ -1882,13 +1954,15 @@ var SkipAll: boolean;
if AFileRec^.DataItem^.IsDir and ParamBool1 and AFileRec^.Stage1 and (not AFileRec^.DataItem^.IsLnk) then Exit;
if (not AFileRec^.DataItem^.IsDir) and ParamBool1 and (ParamInt1 = 1) then Exit; // Directories only
if AFileRec^.DataItem^.IsDir and ParamBool1 and (ParamInt1 = 2) then Exit; // Files only
- Res := Engine.Chmod(String(AFileRec^.DataItem^.FName), ParamCardinal1);
+ // * TODO: check error
+ Res := Engine.Chmod(String(AFileRec^.DataItem^.FName), ParamCardinal1, nil);
// DebugMsg(['Result : ', Res]);
- if Res <> 0 then
+ if not Res then
if SkipAll then Result := True else
begin
+ // * TODO: check error
Response := ShowDirDeleteDialog(1, LANGTheFileDirectory, String(AFileRec^.DataItem^.FDisplayName), Format(LANGCouldNotBeChmoddedS,
- [GetErrorString(Res)]), LANGDialogChangePermissions);
+ ['ahoj' {GetErrorString(Res)}]), LANGDialogChangePermissions);
case Response of
1 : Result := True;
3 : begin
@@ -1953,20 +2027,23 @@ procedure ChownFilesWorker(SenderThread: TWorkerThread);
var SkipAll: boolean;
function HandleChown(AFileRec: PDataItemSL): boolean;
- var Res, Response: integer;
+ var Response: integer;
+ Res: boolean;
begin
Result := True;
with SenderThread do begin
// 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 ParamBool1 and AFileRec^.Stage1 and (not AFileRec^.DataItem^.IsLnk)) or
((not AFileRec^.DataItem^.IsDir) and ParamBool1) then Exit;
- Res := Engine.Chown(String(AFileRec^.DataItem^.FName), ParamCardinal1, ParamCardinal2);
+ // * TODO: check error
+ Res := Engine.Chown(String(AFileRec^.DataItem^.FName), ParamCardinal1, ParamCardinal2, nil);
// DebugMsg(['Result : ', Res]);
- if Res <> 0 then
+ if not Res then
if SkipAll then Result := True else
begin
+ // * TODO: check error
Response := ShowDirDeleteDialog(1, LANGTheFileDirectory, String(AFileRec^.DataItem^.FDisplayName), Format(LANGCouldNotBeChownedS,
- [GetErrorString(Res)]), LANGDialogChangeOwner);
+ ['ahoj' {GetErrorString(Res)}]), LANGDialogChangeOwner);
case Response of
1 : Result := True;
3 : begin
@@ -2060,19 +2137,28 @@ begin
FreeOnTerminate := False;
Finished := False;
CancelIt := False;
- ChDirResult := 0;
- ListingResult := 0;
- VFSOpenResult := 0;
+ ChDirResult := False;
+ ListingResult := False;
+ VFSOpenResult := False;
+ ChDirError := nil;
+ ListingError := nil;
+ VFSOpenError := nil;
RunningTime := 0;
end;
destructor TOpenDirThread.Destroy;
begin
+ if VFSOpenError <> nil then
+ g_error_free(VFSOpenError);
+ if ChDirError <> nil then
+ g_error_free(ChDirError);
+ if ListingError <> nil then
+ g_error_free(ListingError);
inherited Destroy;
end;
(********************************************************************************************************************************)
-function TOpenDirThread.ChangeDir(Engine: TPanelEngine; Path: string; var SelItem: string; const AutoFallBack: boolean): integer;
+function TOpenDirThread.ChangeDir(Engine: TPanelEngine; Path: string; var SelItem: string; const AutoFallBack: boolean): boolean;
procedure GoUp(var NewPath: string);
var x: integer;
@@ -2087,8 +2173,8 @@ function TOpenDirThread.ChangeDir(Engine: TPanelEngine; Path: string; var SelIte
end;
var APath: string;
- Error : integer;
begin
+ Result := False;
try
APath := Engine.Path;
if Path = '..' then GoUp(APath)
@@ -2102,28 +2188,19 @@ begin
end;
// AutoFallback loop
- if Engine is TVFSEngine
- then Error := (Engine as TVFSEngine).ChangeDirEx(APath, @vfs_ask_question_callback, @vfs_ask_password_callback, nil, Self)
- else Error := Engine.ChangeDir(APath);
-
- while AutoFallback and (Error <> 0) and (APath <> '/') do begin
- GoUp(APath);
+ repeat
if Engine is TVFSEngine
- then Error := (Engine as TVFSEngine).ChangeDirEx(APath, @vfs_ask_question_callback, @vfs_ask_password_callback, nil, Self)
- else Error := Engine.ChangeDir(APath);
- end;
- // Going on...
- if Error <> 0 then begin
- Result := Error;
- DebugMsg(['*** UCore.ChangeDir: error during Engine.ChangeDir: ', GetErrorString(Error)]);
- Exit;
- end;
- Engine.Path := APath;
- Result := 0;
+ 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);
+ until Result or (not AutoFallback) or (Length(APath) <= 1);
+ if Result then
+ Engine.Path := APath;
except
on E: Exception do begin
+ Result := False;
DebugMsg(['*** Exception raised in UCore.ChangeDir (', E.ClassName, '): ', E.Message]);
- Result := 1;
end;
end;
end;
@@ -2143,13 +2220,13 @@ begin
xEngine.SavePath := AEngine.Path;
// AEngine must be set here since VFSOpenEx callbacks will reference it
AEngine := xEngine;
- VFSOpenResult := (AEngine as TVFSEngine).VFSOpenEx(AFullPath, @vfs_ask_question_callback, @vfs_ask_password_callback, nil, Self);
- end else VFSOpenResult := 0;
+ VFSOpenResult := (AEngine as TVFSEngine).VFSOpenEx(AFullPath, @vfs_ask_question_callback, @vfs_ask_password_callback, nil, Self, @VFSOpenError);
+ end else VFSOpenResult := True;
- if (VFSOpenResult = 0) and (not CancelIt) then begin
+ if VFSOpenResult and (not CancelIt) then begin
ChDirResult := ChangeDir(AEngine, APath, ASelItem, AAutoFallBack);
- if (ChDirResult = 0) and (not CancelIt) then
- ListingResult := AEngine.GetListing(ADirList, AEngine.GetPath, ConfShowDotFiles, True, False);
+ if ChDirResult and (not CancelIt) then
+ ListingResult := AEngine.GetListing(ADirList, AEngine.GetPath, ConfShowDotFiles, True, False, @ListingError);
end;
except
on E: Exception do DebugMsg(['*** Exception raised in TOpenDirThread.Execute (', E.ClassName, '): ', E.Message]);
@@ -2171,6 +2248,7 @@ begin
FreeOnTerminate := False;
Finished := False;
OpenResult := False;
+ OpenError := nil;
end;
destructor TOpenConnectionThread.Destroy;
@@ -2182,7 +2260,7 @@ procedure TOpenConnectionThread.Execute;
begin
PrepareExecute;
try
- OpenResult := (AEngine as TVFSEngine).VFSOpenURI(URI, @vfs_ask_question_callback, @vfs_ask_password_callback, nil, Self);
+ OpenResult := (AEngine as TVFSEngine).VFSOpenURI(URI, @vfs_ask_question_callback, @vfs_ask_password_callback, nil, Self, @OpenError);
finally
Finished := True;
end;
diff --git a/UEngines.pas b/UEngines.pas
index a8f1923..66dd9ea 100644
--- a/UEngines.pas
+++ b/UEngines.pas
@@ -24,14 +24,7 @@ interface
uses glib2, gdk2, Classes, ULibc;
-const ERRException = -1;
- ERRNoAccess = -2;
- ERRCreateLink = -3;
- ERRCopyMove = -4;
- ERRRemove = -5;
- ERRMkDIr = -6;
-
- omRead = 0;
+const omRead = 0;
omWrite = 1;
omAppend = 2;
@@ -66,8 +59,12 @@ type
ForceMove, IsOnRO: boolean;
end;
- TEngineProgressFunc = function (Sender: Pointer; BytesDone: Int64): boolean; cdecl; // Return False to break the copy process
- TEngineErrorFunc = function (Sender: Pointer; ErrorType, ErrorNum: integer; FileName: string): boolean; cdecl; // Return
+ // Progress callback, return False to break the copy process
+ // If an Error is set, returning True means to ignore error (don't delete broken file if possible)
+ // If an Error is set, BytesDone may contain random value
+ // Do not free Error, it belongs to the copy operation
+ TEngineProgressFunc = function (Sender: Pointer; BytesDone: Int64; Error: PGError): boolean; cdecl;
+ // * TODO: file handle
TEngineFileDes = pointer;
TPanelEngine = class
@@ -79,10 +76,10 @@ type
constructor Create;
destructor Destroy; override;
- function GetListing(List: TList; const APath: string; AddDotFiles, FollowSymlinks, AddFullPath: boolean): integer; virtual; abstract; // Returns errorcode
- function GetFileInfo(const APath: string; FollowSymlinks, AddFullPath: boolean): PDataItem; virtual; abstract;
+ function GetListing(List: TList; const APath: string; AddDotFiles, FollowSymlinks, AddFullPath: boolean; Error: PPGError): boolean; virtual; abstract;
+ function GetFileInfo(const APath: string; FollowSymlinks, AddFullPath: boolean; Error: PPGError): PDataItem; virtual; abstract;
- function ChangeDir(const NewPath: string): integer; virtual; abstract; // Returns errorcode
+ function ChangeDir(const NewPath: string; Error: PPGError): boolean; virtual; abstract;
function GetPath: string; virtual; abstract;
procedure SetPath(Value: string); virtual; abstract;
@@ -95,28 +92,28 @@ type
function FileCanRun(const FileName: string): boolean; virtual; abstract;
// Operations
- function MakeDir(const NewDir: string): integer; virtual; abstract; // Returns errorcode
- function Remove(const APath: string): integer; virtual; abstract; // Returns errorcode
- function MakeSymLink(const NewFileName, PointTo: string): integer; virtual; abstract; // Returns errorcode
- function Chmod(const FileName: string; Mode: cuLong): integer; virtual; abstract; // Returns errorcode
- function Chown(const FileName: string; UID, GID: cuLong): integer; virtual; abstract; // Returns errorcode
- function RenameFile(const SourceFile, DestFile: string): integer; virtual; abstract; // Returns errorcode
- function ChangeTimes(const APath: string; mtime, atime: time_t): integer; virtual; abstract; // Returns errorcode
+ function MakeDir(const NewDir: string; Error: PPGError): boolean; virtual; abstract;
+ function Remove(const APath: string; Error: PPGError): boolean; virtual; abstract;
+ function MakeSymLink(const NewFileName, PointTo: string; Error: PPGError): boolean; virtual; abstract;
+ function Chmod(const FileName: string; Mode: cuLong; Error: PPGError): boolean; virtual; abstract;
+ function Chown(const FileName: string; UID, GID: cuLong; Error: PPGError): boolean; virtual; abstract;
+ function RenameFile(const SourceFile, DestFile: string; Error: PPGError): boolean; virtual; abstract;
+ function ChangeTimes(const APath: string; mtime, atime: time_t; Error: PPGError): boolean; virtual; abstract;
// Copy-related routines
function GetBlockSize: guint32; virtual; abstract;
procedure SetBlockSize(Value: guint32); virtual; abstract;
- function CopyFileIn(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; virtual; abstract; // returns True if file is successfully copied
- function CopyFileOut(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; virtual; abstract; // returns True if file is successfully copied
+ 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 IsOnSameFS(const Path1, Path2: string; FollowSymlinks: boolean): boolean; virtual; abstract;
function TwoSameFiles(const Path1, Path2: string; FollowSymlinks: boolean): boolean; virtual; abstract;
// Separate file read/write routines, not supported on most backends
- function OpenFile(const APath: string; Mode: integer; var Error: integer): TEngineFileDes; virtual; abstract; // Returns filedescriptor
- function ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; var Error: integer): integer; virtual; abstract; // Returns number of bytes read
- function WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; var Error: integer): integer; virtual; abstract; // Returns number of bytes written
- function CloseFile(const FileDescriptor: TEngineFileDes): integer; virtual; abstract; // Returns errorcode
- function FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; var Error: integer): Int64; virtual; abstract; // Returns errorcode
+ function OpenFile(const APath: string; Mode: integer; Error: PPGError): TEngineFileDes; virtual; abstract; // Returns filedescriptor
+ function ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; Error: PPGError): integer; virtual; abstract; // Returns number of bytes read
+ function WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; Error: PPGError): integer; virtual; abstract; // Returns number of bytes written
+ function CloseFile(const FileDescriptor: TEngineFileDes; Error: PPGError): boolean; virtual; abstract;
+ function FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; Error: PPGError): Int64; virtual; abstract;
published
property Path: string read GetPath write SetPath;
property BlockSize: guint32 read GetBlockSize write SetBlockSize;
@@ -130,10 +127,10 @@ type
constructor Create;
destructor Destroy; override;
- function GetListing(List: TList; const APath: string; AddDotFiles, FollowSymlinks, AddFullPath: boolean): integer; override;
- function GetFileInfo(const APath: string; FollowSymlinks, AddFullPath: boolean): PDataItem; override;
+ function GetListing(List: TList; const APath: string; AddDotFiles, FollowSymlinks, AddFullPath: boolean; Error: PPGError): boolean; override;
+ function GetFileInfo(const APath: string; FollowSymlinks, AddFullPath: boolean; Error: PPGError): PDataItem; override;
- function ChangeDir(const NewPath: string): integer; override;
+ function ChangeDir(const NewPath: string; Error: PPGError): boolean; override;
function GetPath: string; override;
procedure SetPath(Value: string); override;
@@ -145,29 +142,26 @@ type
function IsOnROMedium(const FileName: string): boolean; override;
function FileCanRun(const FileName: string): boolean; override;
- function MakeDir(const NewDir: string): integer; override;
- function Remove(const APath: string): integer; override;
- function MakeSymLink(const NewFileName, PointTo: string): integer; override;
- function Chmod(const FileName: string; Mode: cuLong): integer; override;
- function Chown(const FileName: string; UID, GID: cuLong): integer; override;
- function RenameFile(const SourceFile, DestFile: string): integer; override;
- function ChangeTimes(const APath: string; mtime, atime: time_t): integer; override;
+ function MakeDir(const NewDir: string; Error: PPGError): boolean; override;
+ function Remove(const APath: string; Error: PPGError): boolean; override;
+ function MakeSymLink(const NewFileName, PointTo: string; Error: PPGError): boolean; override;
+ function Chmod(const FileName: string; Mode: cuLong; Error: PPGError): boolean; override;
+ function Chown(const FileName: string; UID, GID: cuLong; Error: PPGError): boolean; override;
+ function RenameFile(const SourceFile, DestFile: string; Error: PPGError): boolean; override;
+ function ChangeTimes(const APath: string; mtime, atime: time_t; Error: PPGError): boolean; override;
function GetBlockSize: guint32; override;
procedure SetBlockSize(Value: guint32); override;
- function CopyFileIn(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; override;
- function CopyFileOut(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; 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 IsOnSameFS(const Path1, Path2: string; FollowSymlinks: boolean): boolean; override;
function TwoSameFiles(const Path1, Path2: string; FollowSymlinks: boolean): boolean; override;
- function OpenFile(const APath: string; Mode: integer; var Error: integer): TEngineFileDes; override;
- function ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; var Error: integer): integer; override;
- function WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; var Error: integer): integer; override;
- function CloseFile(const FileDescriptor: TEngineFileDes): integer; override;
- function FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; var Error: integer): Int64; override;
-
- // Local extra functions
- function CopyFile(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
+ function OpenFile(const APath: string; Mode: integer; Error: PPGError): TEngineFileDes; override;
+ function ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; Error: PPGError): integer; override;
+ function WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; Error: PPGError): integer; override;
+ function CloseFile(const FileDescriptor: TEngineFileDes; Error: PPGError): boolean; override;
+ function FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; Error: PPGError): Int64; override;
published
property Path;
property BlockSize;
@@ -182,7 +176,7 @@ function DuplicateDataItem(DataItem: PDataItemSL): PDataItemSL; overload;
implementation
-uses SysUtils, UCoreUtils, UGnome;
+uses SysUtils, UCoreUtils, UGnome, UError;
(********************************************************************************************************************************)
constructor TPanelEngine.Create;
@@ -235,26 +229,31 @@ begin
end;
end;
-function TLocalTreeEngine.GetListing(List: TList; const APath: string; AddDotFiles, FollowSymlinks, AddFullPath: boolean): integer;
+function TLocalTreeEngine.GetListing(List: TList; const APath: string; AddDotFiles, FollowSymlinks, AddFullPath: boolean; Error: PPGError): boolean;
var Item: PDataItem;
Handle: PDIR;
DirEnt: PDirent64;
Buf: PChar;
+ saved_errno: integer;
+ FError: PGError;
begin
- Result := 0;
+ Result := False;
try
if libc_chdir(PChar(APath)) <> 0 then begin
- Result := errno;
- DebugMsg(['*** TLocalTreeEngine.GetListing(APath=', APath, '): chdir error: ', strerror(Result)]);
+ 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)]);
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));
DebugMsg(['*** TLocalTreeEngine.GetListing(APath=', APath, '): opendir() handle == NULL: ', strerror(errno)]);
- Result := ERRNoAccess;
Exit;
end;
+ FError := nil;
repeat
DirEnt := readdir64(Handle);
if (DirEnt <> nil) and (DirEnt^.d_name[0] <> #0) then begin
@@ -262,32 +261,37 @@ begin
if (Buf <> '.') and (Buf <> '..') and (strlen(Buf) > 0) and
(AddDotFiles or (Buf[0] <> '.')) then
begin
- Item := GetFileInfo(IncludeTrailingPathDelimiter(APath) + string(Buf), FollowSymlinks, AddFullPath);
+ Item := GetFileInfo(IncludeTrailingPathDelimiter(APath) + string(Buf), FollowSymlinks, AddFullPath, @FError);
List.Add(Item);
end;
end;
- until DirEnt = nil;
- // TODO: check errno?
+ until (DirEnt = nil) or (FError <> nil);
closedir(Handle);
+
+ if FError <> nil then g_propagate_error(Error, FError)
+ else Result := True;
except
on E: Exception do begin
- Result := ERRException;
+ Result := False;
DebugMsg(['*** TLocalTreeEngine.GetListing(APath=', APath, ') -Exception: ', E.Message]);
Exit;
end;
end;
end;
-function TLocalTreeEngine.GetFileInfo(const APath: string; FollowSymlinks, AddFullPath: boolean): PDataItem;
+function TLocalTreeEngine.GetFileInfo(const APath: string; FollowSymlinks, AddFullPath: boolean; Error: PPGError): PDataItem;
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
- DebugMsg(['*** TLocalTreeEngine.GetFileInfo(APath=', APath, '): Error reading file via lstat64: ', strerror(errno)]);
+ 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)]);
libc_free(StatBuf);
Result := nil;
Exit;
@@ -342,19 +346,23 @@ begin
Result := Item;
end;
-function TLocalTreeEngine.ChangeDir(const NewPath: string): integer;
+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
- Result := errno;
+ 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));
Exit;
end;
Handle := opendir(PChar(APath));
- if not Assigned(Handle) then begin
- Result := ERRNoAccess;
+ 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));
Exit;
end;
{ if not Assigned(readdir(Handle)) then begin
@@ -362,13 +370,14 @@ begin
Exit;
end; }
if closedir(Handle) <> 0 then begin
- Result := ERRNoAccess;
+ 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));
Exit;
end;
- Result := 0;
+ Result := True;
except
on E: Exception do begin
- Result := ERRException;
+ Result := False;
DebugMsg(['*** TLocalTreeEngine.ChangeDir(APath=', APath, ') -Exception: ', E.Message]);
Exit;
end;
@@ -376,26 +385,6 @@ begin
end;
(********************************************************************************************************************************)
-function TLocalTreeEngine.MakeDir(const NewDir: string): integer;
-begin
-// DebugMsg(['(II) TLocalTreeEngine.MakeDir: begin']);
- Result := __mkdir(PChar(NewDir), OctalToAttr(ConfDefaultDirCreationMask));
-// DebugMsg(['(II) TLocalTreeEngine.MakeDir: Result = ', Result]);
-// if Result <> 0 then Result := errno;
-
- if Result <> 0 then try
- if Self.DirectoryExists(NewDir, False) or (g_mkdir_with_parents(PChar(NewDir), OctalToAttr(ConfDefaultDirCreationMask)) <> 0) {ForceDirectories(NewDir))}
- then Result := errno
- else Result := 0;
- except
- Result := -1;
- DebugMsg(['(II) TLocalTreeEngine.MakeDir: Exception']);
- end;
-
-// DebugMsg(['(II) TLocalTreeEngine.MakeDir: end']);
-end;
-
-(********************************************************************************************************************************)
function TLocalTreeEngine.GetDirSize(const APath: string): Int64;
function InternalGetDirSize(APath: string): Int64;
@@ -447,157 +436,202 @@ begin
end;
(********************************************************************************************************************************)
-function TLocalTreeEngine.Remove(const APath: string): integer;
+function TLocalTreeEngine.MakeDir(const NewDir: string; Error: PPGError): boolean;
+var saved_errno: integer;
begin
- Result := libc_remove(PChar(ExcludeTrailingPathDelimiter(APath)));
- if Result <> 0 then Result := errno;
+ 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;
+ 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));
+ end else Result := True;
+end;
-function TLocalTreeEngine.CopyFileIn(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
+(********************************************************************************************************************************)
+function TLocalTreeEngine.MakeSymLink(const NewFileName, PointTo: string; Error: PPGError): boolean;
+var saved_errno: integer;
begin
- Result := CopyFile(Sender, SourceFile, DestFile, ProgressFunc, ErrorFunc, Append);
+ 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));
+ end else Result := True;
end;
-function TLocalTreeEngine.CopyFileOut(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
+(********************************************************************************************************************************)
+function TLocalTreeEngine.Chmod(const FileName: string; Mode: cuLong; Error: PPGError): boolean;
+var saved_errno: integer;
begin
- Result := CopyFile(Sender, SourceFile, DestFile, ProgressFunc, ErrorFunc, Append);
+ 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));
+ end else Result := True;
end;
-function TLocalTreeEngine.CopyFile(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
-var fsrc, fdest: PFILE;
- BytesDone, BytesRead: Int64;
-// offset: __off_t;
+(********************************************************************************************************************************)
+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));
+ 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));
+ end else Result := True;
+end;
- // Used due to sendfile bug while copying from NTFS and some 2.6.x kernels
- function OldCopyRoutine: boolean;
- var Buffer: Pointer;
- BytesWritten: Int64;
- Res: boolean;
- begin
- Result := False;
- Res := True;
- try
-// DebugMsg(['*** Using old copy function due to bug in sendfile']);
-// WriteLn('x1');
- Buffer := malloc(FBlockSize);
-// WriteLn('x2');
- if Buffer = nil then begin
- ErrorFunc(Sender, 1, errno, SourceFile); // Memory allocation failed
-// libc_free(Buffer);
+(********************************************************************************************************************************)
+function TLocalTreeEngine.ChangeTimes(const APath: string; mtime, atime: time_t; Error: PPGError): boolean;
+var timebuf: Putimbuf;
+ saved_errno: integer;
+begin
+ Result := False;
+ try
+ timebuf := malloc(sizeof(Tutimbuf));
+ memset(timebuf, 0, sizeof(Tutimbuf));
+ 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));
+ end else Result := True;
+ libc_free(timebuf);
+ except
+ on E: Exception do DebugMsg(['*** Exception raised in TLocalTreeEngine.ChangeTimes(APath=', APath, '): (', E.ClassName, '): ', E.Message]);
+ end;
+end;
+
+(********************************************************************************************************************************)
+
+function TLocalTreeEngine.CopyFileIn(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean;
+begin
+ Result := CopyFileOut(SourceFile, DestFile, Append, ProgressFunc, Sender);
+end;
+
+function TLocalTreeEngine.CopyFileOut(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean;
+var fsrc, fdest: PFILE;
+ Buffer: Pointer;
+ BytesDone, BytesRead, BytesWritten: Int64;
+ Ignore: boolean;
+ saved_errno: integer;
+ Error: PGError;
+begin
+ Result := False;
+ Error := nil;
+ 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;
Exit;
end;
- memset(Buffer, 0, FBlockSize);
+ // 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;
+ fclose(fsrc);
+ Exit;
+ end;
+
+ BytesDone := 0;
+ Buffer := malloc(FBlockSize);
-// WriteLn('x3');
while feof(fsrc) = 0 do begin
-// WriteLn('x4');
+ Error := nil;
+
+ // Read block
BytesRead := fread(Buffer, 1, FBlockSize, fsrc);
if (BytesRead < FBlockSize) and (feof(fsrc) = 0) then begin
- Res := ErrorFunc(Sender, 6, errno, SourceFile); // Cannot read from source file
- Break;
+ 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;
end;
-// WriteLn('x5');
+
+ // Write block
BytesWritten := fwrite(Buffer, 1, BytesRead, fdest);
if BytesWritten < BytesRead then begin
- Res := ErrorFunc(Sender, 7, ferror(fdest), DestFile); // Cannot write to source file
- Break;
+ 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;
+ Break; // We cannot ignore write errors
end;
+
Inc(BytesDone, BytesRead);
-// WriteLn('x6');
- try
- if Assigned(ProgressFunc) and (not ProgressFunc(Sender, BytesDone)) then begin
- Res := False;
+ if (@ProgressFunc <> nil) and (not ProgressFunc(Sender, BytesDone, nil)) then
Break;
- end;
- except
- on E: Exception do DebugMsg(['*** ProgressFunc ! Exception raised in TLocalTreeEngine.CopyFile.OldCopyRoutine(Sender=', DWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]);
- end;
-// WriteLn('x7');
end;
-// WriteLn('x8');
+ Result := feof(fsrc) <> 0;
libc_free(Buffer);
-// WriteLn('x9');
- Result := Res;
- except
- on E: Exception do DebugMsg(['*** Exception raised in TLocalTreeEngine.CopyFile.OldCopyRoutine(Sender=', DWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]);
- end;
- end;
-(*
- function NewCopyRoutine: boolean;
- var Res: boolean;
- StatBuf: Pstat64;
- begin
- try
- Res := True;
- repeat
- DebugMsg(['Copy(sendfile): offset = ', offset, ', BytesDone = ', BytesDone, ', ftell(fsrc) = ', ftell(fsrc)]);
- BytesRead := sendfile(fileno(fdest), fileno(fsrc), offset, FBlockSize);
- if BytesRead = -1 then begin
- if errno = EINVAL then begin
- Result := OldCopyRoutine;
- Exit;
- end else Res := ErrorFunc(Sender, 6, errno, SourceFile); // Cannot read from source file
- Break;
+
+ if fclose(fdest) <> 0 then begin
+ fclose(fsrc);
+ 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;
- Inc(BytesDone, BytesRead);
- if Assigned(ProgressFunc) and (not ProgressFunc(Sender, BytesDone)) then begin
- Res := False;
- Break;
+ Exit;
+ end;
+ if fclose(fsrc) <> 0 then begin
+ 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;
- until BytesRead < FBlockSize;
-
- StatBuf := malloc(sizeof(Tstat64));
- memset(StatBuf, 0, sizeof(Tstat64));
- if lstat64(PChar(SourceFile), StatBuf) <> 0 then begin
- DebugMsg(['*** TLocalTreeEngine.CopyFile.NewCopyRoutine(Sender=', DWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): Error reading file via lstat64: ', strerror(errno)]);
- Res := ErrorFunc(Sender, 6, errno, SourceFile);
- end else
- if (BytesDone < StatBuf^.st_size) and Res then
- Res := ErrorFunc(Sender, 6, errno, SourceFile);
- libc_free(StatBuf);
- Result := Res;
- except
- on E: Exception do DebugMsg(['*** Exception raised in TLocalTreeEngine.CopyFile.NewCopyRoutine(Sender=', DWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]);
+ Exit;
end;
- end;
-*)
-begin
- Result := False;
- try
- fsrc := fopen64(PChar(SourceFile), 'r');
- if fsrc = nil then begin
- ErrorFunc(Sender, 2, errno, SourceFile); // Cannot open source file
- Exit;
- end;
- if Append then fdest := fopen64(PChar(DestFile), 'a')
- else fdest := fopen64(PChar(DestFile), 'w');
- if fdest = nil then begin
- fclose(fsrc);
- ErrorFunc(Sender, 3, errno, DestFile); // Cannot open target file
- Exit;
- end;
-
- BytesDone := 0;
-// offset := 0;
-
- Result := OldCopyRoutine;
-
- if fclose(fdest) <> 0 then begin
- fclose(fsrc);
- ErrorFunc(Sender, 4, errno, DestFile); // Cannot close target file
- Exit;
- end;
- if fclose(fsrc) <> 0 then begin
- ErrorFunc(Sender, 5, errno, SourceFile); // Cannot close source file
- Exit;
- end;
except
- on E: Exception do DebugMsg(['*** Exception raised in TLocalTreeEngine.CopyFile(Sender=', DWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]);
+ on E: Exception do DebugMsg(['*** Exception raised in TLocalTreeEngine.CopyFile(Sender=', Sender, ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]);
end;
-// DebugMsg(['(II) TLocalTreeEngine.CopyFile: finished']);
end;
(********************************************************************************************************************************)
@@ -624,28 +658,6 @@ begin
end;
(********************************************************************************************************************************)
-function TLocalTreeEngine.MakeSymLink(const NewFileName, PointTo: string): integer;
-begin
-// DebugMsg(['TLocalTreeEngine.MakeSymLink(NewFileName = "', NewFileName, '", PointTo = "', PointTo, '"']);
- Result := symlink(PChar(PointTo), PChar(NewFileName));
- if Result <> 0 then Result := errno;
-end;
-
-(********************************************************************************************************************************)
-function TLocalTreeEngine.Chmod(const FileName: string; Mode: cuLong): integer;
-begin
- Result := libc_chmod(PChar(FileName), Mode);
- if Result <> 0 then Result := errno;
-end;
-
-(********************************************************************************************************************************)
-function TLocalTreeEngine.Chown(const FileName: string; UID, GID: cuLong): integer;
-begin
- Result := libc_chown(PChar(FileName), UID, GID);
- if Result <> 0 then Result := errno;
-end;
-
-(********************************************************************************************************************************)
procedure TLocalTreeEngine.BreakProcessing(ProcessingKind: integer);
begin
BreakProcessingType := ProcessingKind;
@@ -698,31 +710,6 @@ begin
end;
(********************************************************************************************************************************)
-function TLocalTreeEngine.RenameFile(const SourceFile, DestFile: string): integer;
-begin
- Result := libc_rename(PChar(SourceFile), PChar(DestFile));
- if Result <> 0 then Result := errno;
-end;
-
-(********************************************************************************************************************************)
-function TLocalTreeEngine.ChangeTimes(const APath: string; mtime, atime: time_t): integer;
-var timebuf: Putimbuf;
-begin
- Result := errno;
- try
- timebuf := malloc(sizeof(Tutimbuf));
- memset(timebuf, 0, sizeof(Tutimbuf));
- timebuf^.actime := atime;
- timebuf^.modtime := mtime;
- Result := utime(PChar(APath), timebuf);
- if Result <> 0 then Result := errno;
- libc_free(timebuf);
- except
- on E: Exception do DebugMsg(['*** Exception raised in TLocalTreeEngine.ChangeTimes(APath=', APath, '): (', E.ClassName, '): ', E.Message]);
- end;
-end;
-
-(********************************************************************************************************************************)
procedure TLocalTreeEngine.GetFileSystemInfo(const APath: string; var FSSize, FSFree: Int64; var FSName: string);
var Stat: Pstatfs64;
fd: PFILE;
@@ -774,10 +761,10 @@ begin
end;
(********************************************************************************************************************************)
-function TLocalTreeEngine.OpenFile(const APath: string; Mode: integer; var Error: integer): TEngineFileDes;
+function TLocalTreeEngine.OpenFile(const APath: string; Mode: integer; Error: PPGError): TEngineFileDes;
var m: PChar;
+ saved_errno: integer;
begin
- Error := 0;
case Mode of
omRead: m := 'r';
omWrite: m := 'w';
@@ -785,40 +772,54 @@ begin
else m := 'r';
end;
Result := fopen64(PChar(APath), m);
- if Result = nil then Error := errno;
+ 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;
end;
(********************************************************************************************************************************)
-function TLocalTreeEngine.ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; var Error: integer): integer;
+function TLocalTreeEngine.ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; Error: PPGError): integer;
+var saved_errno: integer;
begin
- Error := 0;
Result := fread(Buffer, 1, ABlockSize, FileDescriptor);
- if (Result = 0) and (feof(FileDescriptor) = 0) then Error := errno;
+ 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;
end;
(********************************************************************************************************************************)
-function TLocalTreeEngine.WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; var Error: integer): integer;
+function TLocalTreeEngine.WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; Error: PPGError): integer;
+var saved_errno: integer;
begin
- Error := 0;
-{ Result := __write(fileno(FileDescriptor), Buffer^, BytesCount);
- if Result < BytesCount then Error := errno; }
Result := fwrite(Buffer, 1, BytesCount, FileDescriptor);
- if Result < BytesCount then Error := ferror(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;
end;
(********************************************************************************************************************************)
-function TLocalTreeEngine.CloseFile(const FileDescriptor: TEngineFileDes): integer;
+function TLocalTreeEngine.CloseFile(const FileDescriptor: TEngineFileDes; Error: PPGError): boolean;
+var saved_errno: integer;
begin
- Result := fclose(FileDescriptor);
- if Result <> 0 then Result := errno;
+ 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;
end;
(********************************************************************************************************************************)
-function TLocalTreeEngine.FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; var Error: integer): Int64;
+function TLocalTreeEngine.FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; Error: PPGError): Int64;
+var saved_errno: integer;
begin
- Error := 0;
Result := fseeko64(FileDescriptor, AbsoluteOffset, SEEK_SET);
- if Result = -1 then Error := errno;
+ 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;
end;
(********************************************************************************************************************************)
diff --git a/UError.pas b/UError.pas
index cf722e3..57250a8 100644
--- a/UError.pas
+++ b/UError.pas
@@ -21,7 +21,7 @@ unit UError;
interface
-uses glib2, gdk2, Classes, ULibc;
+uses glib2, gtk2, Classes, ULibc, GTKForms;
// Ported from gioerror.h
@@ -68,6 +68,8 @@ function G_IO_ERROR: TGQuark;
function g_io_error_from_errno(err_no: gint): GIOErrorEnum;
+procedure ShowError(Parent: TCustomGTKForm; const Text: string; Error: PGError);
+
implementation
uses SysUtils, UCoreUtils, UGnome;
@@ -111,5 +113,26 @@ begin
end;
end;
+
+(********************************************************************************************************************************)
+procedure ShowError(Parent: TCustomGTKForm; const Text: string; Error: PGError);
+var Dialog: PGtkWidget;
+ error_str: PChar;
+begin
+ if Error <> nil then error_str := Error^.message
+ else error_str := '';
+ if @gtk_message_dialog_new_with_markup <> nil
+ then dialog := gtk_message_dialog_new_with_markup (PGtkWindow(Parent.FWidget), GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ '<span size="large" weight="ultrabold">%s</span>'#10#10'%s',
+ PChar(Text), error_str)
+ else dialog := gtk_message_dialog_new (PGtkWindow(Parent.FWidget), GTK_DIALOG_MODAL or GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
+ '%s'#10#10'%s', PChar(Text), error_str);
+ gtk_window_set_title (PGtkWindow(dialog), '');
+ gtk_dialog_run (PGtkDialog(Dialog));
+ gtk_widget_destroy (PGtkWidget(Dialog));
+end;
+
end.
diff --git a/UMain.pas b/UMain.pas
index 8066949..1767a24 100644
--- a/UMain.pas
+++ b/UMain.pas
@@ -265,7 +265,7 @@ uses ULibc,
UPreferences, UViewer, UToolTips, UMounterPrefs, UColumns,
UTestPlugin, UConnectionManager, USearch, UProperties,
URemoteWait, URunFromVFS, uVFSprototypes, UQuickConnect,
- UConnectionProperties;
+ UConnectionProperties, UError;
@@ -1125,7 +1125,8 @@ procedure TFMain.FormClose(Sender: TObject; var Action: TCloseAction);
if not Assigned(Engine.ParentEngine) or (not (Engine is TVFSEngine)) then Exit;
Result := Engine.ParentEngine;
CheckForUnsavedConnection(Engine as TVFSEngine, False);
- if not TVFSEngine(Engine).VFSClose then DebugMsg(['Error closing the engine...']);
+ if not TVFSEngine(Engine).VFSClose(nil) then
+ DebugMsg(['Error closing the engine...']);
Engine.Free;
end;
@@ -1170,7 +1171,7 @@ begin
if b then begin
if (not LeftPanelNotebook.Visible) and (LeftPanelEngine is TVFSEngine) then begin
while LeftPanelEngine is TVFSEngine do s := CloseVFS(True, True);
- if LeftPanelEngine is TLocalTreeEngine then LeftPanelEngine.ChangeDir(s);
+ if LeftPanelEngine is TLocalTreeEngine then LeftPanelEngine.ChangeDir(s, nil);
end else
for i := 0 to LeftTabEngines.Count - 1 do
if (TPanelEngine(LeftTabEngines[i]) <> nil) and (TPanelEngine(LeftTabEngines[i]) is TVFSEngine) then
@@ -1189,7 +1190,7 @@ begin
if (not RightPanelNotebook.Visible) and (RightPanelEngine is TVFSEngine) then begin
while RightPanelEngine is TVFSEngine do s := CloseVFS(False, True);
- if RightPanelEngine is TLocalTreeEngine then RightPanelEngine.ChangeDir(s);
+ if RightPanelEngine is TLocalTreeEngine then RightPanelEngine.ChangeDir(s, nil);
end else
for i := 0 to RightTabEngines.Count - 1 do
if (TPanelEngine(RightTabEngines[i]) <> nil) and (TPanelEngine(RightTabEngines[i]) is TVFSEngine) then
@@ -1872,26 +1873,25 @@ begin
HiliString1 := '';
HiliString2 := '';
end;
- if OpenDirThread.VFSOpenResult <> 0 then begin
+ if not OpenDirThread.VFSOpenResult then begin
// Silence the error if password dialog has been cancelled
if not OpenDirThread.VFSCallbackCancelled then
- Application.MessageBox(LANGCouldntOpenURIArchive, [mbOK], mbError, mbOK, mbOK);
+ ShowError(Self, LANGCouldntOpenURIArchive, OpenDirThread.VFSOpenError);
DebugMsg(['TFMain.ChangingDir: Freeing thread...']);
OpenDirThread.Free;
end else
- if OpenDirThread.ChDirResult <> 0 then begin
- if not OpenDirThread.VFSCallbackCancelled then begin
- // Drop the error message if one of the callback dialogs were cancelled
- if OpenDirThread.ChDirResult = 1 then Application.MessageBox(Format(LANGErrorGettingListingForSPanelNoPath, [LANGPanelStrings[LeftPanel], 'Exception']), [mbOK], mbError, mbNone, mbOK)
- else Application.MessageBox(Format(LANGErrorGettingListingForSPanel, [LANGPanelStrings[LeftPanel], GetErrorString(OpenDirThread.ChDirResult), NewPath]), [mbOK], mbError, mbNone, mbOK);
- end;
+ if not OpenDirThread.ChDirResult then begin
+ // Drop the error message if one of the callback dialogs were cancelled
+ if not OpenDirThread.VFSCallbackCancelled then
+ ShowError(Self, 'Error changing directory', OpenDirThread.ChDirError);
+ DebugMsg(['TFMain.ChangingDir: Freeing thread...']);
+ OpenDirThread.Free;
+ end else
+ if not OpenDirThread.ListingResult then begin
+ ShowError(Self, Format('Error getting listing for %s panel', [LANGPanelStrings[LeftPanel]]), OpenDirThread.ListingError);
DebugMsg(['TFMain.ChangingDir: Freeing thread...']);
OpenDirThread.Free;
end else begin
- if OpenDirThread.ListingResult <> 0 then begin
- Application.MessageBox(Format(LANGErrorGettingListingForSPanel, [LANGPanelStrings[LeftPanel], GetErrorString(OpenDirThread.ListingResult), Engine.Path]), [mbOK], mbError, mbNone, mbOK);
- Exit;
- end;
s := OpenDirThread.ASelItem;
Engine := OpenDirThread.AEngine; // set current Engine from the thread (might have been modified due to VFS)
if LeftPanel then LeftPanelEngine := Engine
@@ -3607,7 +3607,7 @@ var s: string;
// AViewer: TViewerThread;
AViewer: TFViewer;
begin
- Stat := Engine.GetFileInfo(Filename, True, True);
+ Stat := Engine.GetFileInfo(Filename, True, True, nil);
if Assigned(Stat) and (Stat^.Size > ConfEditViewFileSizeLimit) and
(Application.MessageBox(LANGTheFileYouAreTryingToOpenIsQuiteBig, [mbYes, mbNo], mbWarning, mbNone, mbNo) = mbNo)
then begin
@@ -3710,7 +3710,7 @@ begin
DebugMsg(['Some strange error occured...']);
Exit;
end;
- Stat := Engine.GetFileInfo(Path, True, True);
+ Stat := Engine.GetFileInfo(Path, True, True, nil);
if Assigned(Stat) and Stat^.IsExecutable then begin
b := True;
if Engine is TVFSEngine then b := HandleRunFromArchive(Path, Engine, Command, FileTypeDesc, False); // not a local engine, extract to local first
@@ -4084,7 +4084,7 @@ begin
if AFile <> '' then
try
FChmod := TFChmod.Create(Self);
- Stat := Engine.GetFileInfo(IncludeTrailingPathDelimiter(Engine.Path) + AFile, True, True);
+ Stat := Engine.GetFileInfo(IncludeTrailingPathDelimiter(Engine.Path) + AFile, True, True, nil);
if not Assigned(Stat) then Exit;
UsrManager := TUserManager.Create;
try
@@ -4182,7 +4182,7 @@ begin
if AFile <> '' then
try
FChown := TFChown.Create(Self);
- Stat := Engine.GetFileInfo(IncludeTrailingPathDelimiter(Engine.Path) + AFile, True, True);
+ Stat := Engine.GetFileInfo(IncludeTrailingPathDelimiter(Engine.Path) + AFile, True, True, nil);
if not Assigned(Stat) then Exit;
FChown.AssignMode(Stat^.Mode, AFile, Stat^.UID, Stat^.GID);
if FChown.Run = mbOK then begin
@@ -4320,6 +4320,7 @@ var Item: TGTKMenuItem;
UpDir, Found: boolean;
i, j: integer;
Assoc: TFileAssoc;
+ Error: PGError;
begin
ClearPopupMenu(FilePopupMenu);
if LeftLastFocused then begin
@@ -4333,9 +4334,11 @@ begin
if Assigned(AListView.Selected) and Assigned(AListView.Selected.Data) and (not PDataItem(AListView.Selected.Data)^.UpDir)
then FileName := FileName + PDataItem(AListView.Selected.Data)^.FName;
ShortFName := ExtractFileName(ExcludeTrailingPathDelimiter(FileName));
- DataItem := Engine.GetFileInfo(FileName, True, True);
+ Error := nil;
+ DataItem := Engine.GetFileInfo(FileName, True, True, @Error);
if not Assigned(DataItem) then begin
- DebugMsg(['Error: File data not assigned. Bug ???! FileName = ', FileName]);
+ DebugMsg(['Error: File data not assigned. Bug ???! FileName = ', FileName, ', Error = ', Error^.message]);
+ g_error_free(Error);
Exit;
end;
UpDir := PDataItem(AListView.Selected.Data)^.UpDir;
@@ -4480,7 +4483,8 @@ var Engine: TPanelEngine;
DataItem: PDataItem;
AListView: TGTKListView;
FileName, ShortFName, s: string;
- Error: integer;
+ SpawnError: integer;
+ Error: PGError;
b: boolean;
begin
try
@@ -4501,9 +4505,11 @@ begin
if Assigned(AListView.Selected) and Assigned(AListView.Selected.Data) and (not PDataItem(AListView.Selected.Data)^.UpDir)
then FileName := FileName + PDataItem(AListView.Selected.Data)^.FName;
ShortFName := ExtractFileName(ExcludeTrailingPathDelimiter(FileName));
- DataItem := Engine.GetFileInfo(FileName, True, True);
+ Error := nil;
+ DataItem := Engine.GetFileInfo(FileName, True, True, @Error);
if not Assigned(DataItem) then begin
- DebugMsg(['Error: File data not assigned. Bug ???! FileName = ', FileName]);
+ DebugMsg(['Error: File data not assigned. Bug ???! FileName = ', FileName, ', Error = ', Error^.message]);
+ g_error_free(Error);
Exit;
end;
@@ -4514,7 +4520,7 @@ begin
if Engine is TVFSEngine then b := HandleRunFromArchive(FileName, Engine, '', '', False); // not a local engine, extract to local first
if b then begin
libc_chdir(PChar(ExtractFilePath(FileName)));
- b := ExecuteProgram(QuoteStr(FileName), ExtractFilePath(FileName), True, False, Error);
+ b := ExecuteProgram(QuoteStr(FileName), ExtractFilePath(FileName), True, False, SpawnError);
libc_chdir(PChar('/'));
end else b := True; // Mask cancelled extraction from VFS
if not b then Application.MessageBox(LANGErrorExecutingCommand, [mbOK], mbError, mbNone, mbOK);
@@ -4531,7 +4537,7 @@ begin
if b then begin
libc_chdir(PChar(ExtractFilePath(FileName)));
b := ExecuteProgram(s, ExtractFilePath(FileName), TAssocAction((Sender as TGTKMenuItem).Data).AutodetectGUI,
- TAssocAction((Sender as TGTKMenuItem).Data).RunInTerminal, Error);
+ TAssocAction((Sender as TGTKMenuItem).Data).RunInTerminal, SpawnError);
libc_chdir(PChar('/'));
end else b := True; // Mask cancelled extraction from VFS
if not b then Application.MessageBox(Format(LANGCannotExecuteSPleaseCheckTheConfiguration, [FileName]), [mbOK], mbError, mbNone, mbOK);
@@ -5392,7 +5398,7 @@ begin
FTestPlugin := TFTestPlugin.Create(Self);
if (FTestPlugin.Run = mbOK) and (PluginList.Count > 0) then begin
Engine := TVFSEngine.Create(PluginList[FTestPlugin.PluginOptionMenu.ItemIndex]);
- if not Engine.VFSOpenURI(FTestPlugin.CommandEntry.Text, nil, nil, nil, nil) then begin
+ if not Engine.VFSOpenURI(FTestPlugin.CommandEntry.Text, nil, nil, nil, nil, nil) then begin
Application.MessageBox(LANGCouldntOpenURI, [mbOK], mbError, mbOK, mbOK);
Exit;
end;
@@ -5728,7 +5734,8 @@ begin
try
xEngine := Engine;
Engine := xEngine.ParentEngine;
- if not TVFSEngine(xEngine).VFSClose then DebugMsg(['Error closing the engine...']);
+ if not TVFSEngine(xEngine).VFSClose(nil) then
+ DebugMsg(['Error closing the engine...']);
xEngine.Free;
except end;
@@ -5756,7 +5763,8 @@ begin
if (i <> TabNo) and (not CheckForUnsavedConnection(Engine as TVFSEngine, False)) then Exit;
xEngine := Engine;
Engine := xEngine.ParentEngine;
- if not TVFSEngine(xEngine).VFSClose then DebugMsg(['Error closing the engine...']);
+ if not TVFSEngine(xEngine).VFSClose(nil) then
+ DebugMsg(['Error closing the engine...']);
xEngine.Free;
except end;
end;
@@ -6072,7 +6080,8 @@ begin
if not SuppressRefresh then
ChangingDir(LeftPanel, Engine.SavePath, Engine.ParentEngine.LastHighlightItem, Engine.ParentEngine.LastHighlightItem, False, True);
- if not TVFSEngine(Engine).VFSClose then DebugMsg(['Error closing the engine...']);
+ if not TVFSEngine(Engine).VFSClose(nil) then
+ DebugMsg(['Error closing the engine...']);
Engine.Free;
end;
@@ -6368,7 +6377,7 @@ begin
if AFile <> '' then
try
FProperties := TFProperties.Create(Self);
- Stat := Engine.GetFileInfo(IncludeTrailingPathDelimiter(Engine.Path) + AFile, True, True);
+ Stat := Engine.GetFileInfo(IncludeTrailingPathDelimiter(Engine.Path) + AFile, True, True, nil);
if not Assigned(Stat) then Exit;
// FProperties.AssignMode(Stat^.Mode, AFile, Stat^.UID, Stat^.GID);
FProperties.DisplayFileName := AFile;
@@ -6493,7 +6502,7 @@ begin
Result := False;
try
if not BypassDialog then begin
- Stat := Engine.GetFileInfo(APath, True, True);
+ Stat := Engine.GetFileInfo(APath, True, True, nil);
FRunFromVFS := TFRunFromVFS.Create(Self);
FRunFromVFS.FileNameLabel2.Caption := Format('%s<span weight="ultrabold"> </span>', [StrToUTF8(APath)]);
if FileTypeDesc = '' then FileTypeDesc := LANGHandleRunFromArchive_FileTypeDesc_Unknown;
diff --git a/UQuickConnect.pas b/UQuickConnect.pas
index e6d7d5f..89a2439 100644
--- a/UQuickConnect.pas
+++ b/UQuickConnect.pas
@@ -63,7 +63,7 @@ var
implementation
-uses ULocale, UCoreUtils, UConfig, UConnectionProperties, UGnome, uVFSprototypes;
+uses ULocale, UCoreUtils, UConfig, UConnectionProperties, UGnome, UError, uVFSprototypes;
procedure TFQuickConnect.FormCreate(Sender: TObject);
@@ -273,6 +273,7 @@ var Engine: TVFSEngine;
URI, Scheme: string;
DontShowAgain: boolean;
res: TMessageButton;
+ Error: PGError;
begin
if ConnectionManager <> nil then AFConnectionManager := ConnectionManager
else AFConnectionManager := TFConnectionManager.Create(Self);
@@ -332,8 +333,10 @@ begin
URI := URIComboBox.Entry.Text;
Engine.Password := URIRipPassword(URI, True);
- if not AFConnectionManager.DoConnectInternal(URI, Engine, FWidget, True) then begin
- if not AFConnectionManager.FSilenceError then Application.MessageBox(PGtkWindow(FWidget), LANGCouldntOpenURI, [mbOK], mbError, mbOK, mbOK);
+ Error := nil;
+ if not AFConnectionManager.DoConnectInternal(URI, Engine, FWidget, True, @Error) then begin
+ if not AFConnectionManager.FSilenceError then
+ ShowError(Self, 'Couldn''t open the URI specified', Error);
Table.Enabled := True;
CloseButton.Enabled := True;
ConnectButton.Enabled := True;
@@ -342,6 +345,8 @@ begin
StopButton.Enabled := False;
URIComboBox.Entry.SetFocus;
Engine.Free;
+ if Error <> nil then
+ g_error_free(Error);
Exit;
end;
diff --git a/USearch.pas b/USearch.pas
index 9794e4c..edf4403 100644
--- a/USearch.pas
+++ b/USearch.pas
@@ -594,7 +594,7 @@ begin
if b then begin
DebugMsg(['Found plugin ''', Plugin.ModuleID, ''', trying to open the archive ''', archive, '''']);
AEngine := TVFSEngine.Create(Plugin);
- b := b and ((AEngine as TVFSEngine).VFSOpenEx(archive, nil, nil, nil, nil) = 0);
+ b := b and (AEngine as TVFSEngine).VFSOpenEx(archive, nil, nil, nil, nil, nil);
end;
end;
end else begin
@@ -603,7 +603,8 @@ begin
end;
if b then FMain.EditViewFileInternal(Self, string(PDataItem(FileList.Selected.AsPointer(0))^.FDisplayName), AEngine, True, False)
else Application.MessageBox(Format(LANGCannotLoadFile, [string(PDataItem(FileList.Selected.AsPointer(0))^.FDisplayName)]), [mbOK], mbError, mbNone, mbOK);
- if AEngine is TVFSEngine then (AEngine as TVFSEngine).VFSClose;
+ if AEngine is TVFSEngine then
+ (AEngine as TVFSEngine).VFSClose(nil);
AEngine.Free;
end;
@@ -829,7 +830,8 @@ begin
Processing := False;
Stop := False;
if FileList.Items.Count > 0 then FileList.SetFocus;
- if Engine.ChangeDir(OldDir) <> 0 then DebugMsg(['DoSearch: cannot change back to saved directory']);
+ if not Engine.ChangeDir(OldDir, nil) then
+ DebugMsg(['DoSearch: cannot change back to saved directory']);
// Enable the UI
Table1.Enabled := True;
@@ -904,7 +906,7 @@ var LocalList: TList;
Data: PDataItem;
Plugin: TVFSPlugin;
xEngine: TVFSEngine;
- VFSOpenResult: integer;
+ VFSOpenResult: boolean;
begin
try
if CancelIt then Exit;
@@ -915,9 +917,9 @@ begin
CurrentDir := StartDir;
GUIMutex.Release;
- if FEngine.ChangeDir(StartDir) <> 0 then Exit;
+ if not FEngine.ChangeDir(StartDir, nil) then Exit;
LocalList := TList.Create;
- if FEngine.GetListing(LocalList, StartDir, True, True, False) = 0 then begin
+ if FEngine.GetListing(LocalList, StartDir, True, True, False, nil) then begin
// Processing...
StartDir := IncludeTrailingPathDelimiter(StartDir);
@@ -991,10 +993,11 @@ begin
xEngine.ParentEngine := FEngine;
xEngine.SavePath := StartDir + FileName;
FEngine := xEngine;
- VFSOpenResult := (FEngine as TVFSEngine).VFSOpenEx(IncludeTrailingPathDelimiter(StartDir) + FileName, nil, nil, nil, nil);
- if (VFSOpenResult = 0) and (not CancelIt) then DoRecurse('/');
+ VFSOpenResult := (FEngine as TVFSEngine).VFSOpenEx(IncludeTrailingPathDelimiter(StartDir) + FileName, nil, nil, nil, nil, nil);
+ if VFSOpenResult and (not CancelIt) then DoRecurse('/');
FEngine := FEngine.ParentEngine;
- if not (xEngine as TVFSEngine).VFSClose then DebugMsg(['Error closing the engine...']);
+ if not (xEngine as TVFSEngine).VFSClose(nil) then
+ DebugMsg(['Error closing the engine...']);
xEngine.Free;
end;
end;
@@ -1011,22 +1014,21 @@ end;
function TSearchThread.FindText(FileName: string): boolean;
const BlockSize = 65536;
var fd: TEngineFileDes;
- i, Error, Read, Pos: integer;
+ i, Read, Pos: integer;
Buffer: PByteArray;
x: boolean;
begin
Result := False;
try
- Error := 0;
Buffer := malloc(BlockSize);
if Buffer = nil then Exit;
memset(Buffer, 0, BlockSize);
- fd := FEngine.OpenFile(FileName, omRead, Error);
- if (fd = nil) or (Error <> 0) then Exit;
+ fd := FEngine.OpenFile(FileName, omRead, nil);
+ if fd = nil then Exit;
Pos := 1;
repeat
- Read := FEngine.ReadFile(fd, Buffer, BlockSize, Error);
+ Read := FEngine.ReadFile(fd, Buffer, BlockSize, nil);
if Read > 0 then
for i := 0 to Read - 1 do begin
if FCaseSensitiveStrings then x := Buffer^[i] = byte(FStringFind[Pos])
@@ -1035,7 +1037,7 @@ begin
Inc(Pos);
if Pos > Length(FStringFind) then begin
Result := True;
- FEngine.CloseFile(fd);
+ FEngine.CloseFile(fd, nil);
libc_free(Buffer);
Exit;
end;
@@ -1045,7 +1047,7 @@ begin
// DebugMsg(['Read : ', Read, ' bytes.']);
if CancelIt then Break;
until Read < BlockSize;
- FEngine.CloseFile(fd);
+ FEngine.CloseFile(fd, nil);
libc_free(Buffer);
except
end;
diff --git a/vfs/UVFSCore.pas b/vfs/UVFSCore.pas
index cf3e36a..d875b83 100644
--- a/vfs/UVFSCore.pas
+++ b/vfs/UVFSCore.pas
@@ -97,6 +97,8 @@ type
FBlockSize: Cardinal;
FArchiveMode: boolean;
FArchivePath: string;
+ FCopyProgressCallback: PVFSProgressCallback;
+ FCopyCallbackData: Pointer;
function GetPluginID: string;
function GetDataItemFromVFSItem(P: PVFSItem): PDataItem;
function GetArchiveStreamingType: boolean;
@@ -109,10 +111,10 @@ type
constructor Create(SourcePlugin: TVFSPlugin);
destructor Destroy; override;
- function GetListing(List: TList; const APath: string; AddDotFiles, FollowSymlinks, AddFullPath: boolean): integer; override;
- function GetFileInfo(const APath: string; FollowSymlinks, AddFullPath: boolean): PDataItem; override;
+ function GetListing(List: TList; const APath: string; AddDotFiles, FollowSymlinks, AddFullPath: boolean; Error: PPGError): boolean; override;
+ function GetFileInfo(const APath: string; FollowSymlinks, AddFullPath: boolean; Error: PPGError): PDataItem; override;
- function ChangeDir(const NewPath: string): integer; override;
+ function ChangeDir(const NewPath: string; Error: PPGError): boolean; override;
function GetPath: string; override;
procedure SetPath(Value: string); override;
@@ -124,32 +126,32 @@ type
function IsOnROMedium(const FileName: string): boolean; override;
function FileCanRun(const FileName: string): boolean; override;
- function MakeDir(const NewDir: string): integer; override;
- function Remove(const APath: string): integer; override;
- function MakeSymLink(const NewFileName, PointTo: string): integer; override;
- function Chmod(const FileName: string; Mode: cuLong): integer; override;
- function Chown(const FileName: string; UID, GID: cuLong): integer; override;
- function RenameFile(const SourceFile, DestFile: string): integer; override;
- function ChangeTimes(const APath: string; mtime, atime: time_t): integer; override;
+ function MakeDir(const NewDir: string; Error: PPGError): boolean; override;
+ function Remove(const APath: string; Error: PPGError): boolean; override;
+ function MakeSymLink(const NewFileName, PointTo: string; Error: PPGError): boolean; override;
+ function Chmod(const FileName: string; Mode: cuLong; Error: PPGError): boolean; override;
+ function Chown(const FileName: string; UID, GID: cuLong; Error: PPGError): boolean; override;
+ function RenameFile(const SourceFile, DestFile: string; Error: PPGError): boolean; override;
+ function ChangeTimes(const APath: string; mtime, atime: time_t; Error: PPGError): boolean; override;
function GetBlockSize: guint32; override;
procedure SetBlockSize(Value: guint32); override;
- function CopyFileIn(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; override;
- function CopyFileOut(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; 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 IsOnSameFS(const Path1, Path2: string; FollowSymlinks: boolean): boolean; override;
function TwoSameFiles(const Path1, Path2: string; FollowSymlinks: boolean): boolean; override;
- function OpenFile(const APath: string; Mode: integer; var Error: integer): TEngineFileDes; override;
- function ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; var Error: integer): integer; override;
- function WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; var Error: integer): integer; override;
- function CloseFile(const FileDescriptor: TEngineFileDes): integer; override;
- function FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; var Error: integer): Int64; override;
+ function OpenFile(const APath: string; Mode: integer; Error: PPGError): TEngineFileDes; override;
+ function ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; Error: PPGError): integer; override;
+ function WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; Error: PPGError): integer; override;
+ function CloseFile(const FileDescriptor: TEngineFileDes; Error: PPGError): boolean; override;
+ function FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; Error: PPGError): Int64; override;
// VFS additions
- function VFSOpenURI(const URI: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
- function VFSOpenEx(const OpenFile: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): TVFSResult;
- function VFSClose: boolean;
- function ChangeDirEx(const NewPath: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): integer;
+ function VFSOpenURI(const URI: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer; Error: PPGError): boolean;
+ function VFSOpenEx(const OpenFile: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer; Error: PPGError): boolean;
+ function VFSClose(Error: PPGError): boolean;
+ function ChangeDirEx(const NewPath: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer; Error: PPGError): boolean;
function GetPathURI: string;
@@ -157,10 +159,10 @@ type
procedure ResetPassword;
// callbacks here are used for next volume prompts, password prompts (encrypted archives)
- function StartCopyOperation(Sender: Pointer; ErrorFunc: TEngineErrorFunc; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
- function StopCopyOperation(Sender: Pointer; ErrorFunc: TEngineErrorFunc): boolean;
- function CopyFileInEx(Sender: Pointer; const SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
- function CopyFileOutEx(Sender: Pointer; const SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
+ 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;
published
property PluginID: string read GetPluginID;
property ArchiveMode: boolean read FArchiveMode;
@@ -176,7 +178,7 @@ var PluginList: TList;
implementation
-uses SysUtils, UConfig, ULocale;
+uses SysUtils, UConfig, ULocale, UError;
const ConstGlobalModulePath1 = '/usr/lib/tuxcmd';
@@ -359,6 +361,8 @@ begin
RemoveFileOnClose := '';
OpenedFromQuickConnect := False;
CustomPluginIDSave := '';
+ FCopyProgressCallback := nil;
+ FCopyCallbackData := nil;
if @FSourcePlugin.FVFSNew <> nil then FGlobs := FSourcePlugin.FVFSNew(@VFSLogFunc);
end;
@@ -375,13 +379,13 @@ begin
end;
end;
-function TVFSEngine.VFSOpenURI(const URI: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
+function TVFSEngine.VFSOpenURI(const URI: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer; Error: PPGError): boolean;
begin
Result := False;
if (FGlobs <> nil) and (@FSourcePlugin.FVFSOpenURI <> nil) then begin
if @FSourcePlugin.FVFSSetCallbacks <> nil then
FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData);
- Result := FSourcePlugin.FVFSOpenURI(FGlobs, PChar(URI)) = cVFS_OK;
+ Result := FSourcePlugin.FVFSOpenURI(FGlobs, PChar(URI), Error);
FArchiveMode := False;
FArchivePath := '';
if @FSourcePlugin.FVFSSetCallbacks <> nil then
@@ -389,27 +393,27 @@ begin
end;
end;
-function TVFSEngine.VFSOpenEx(const OpenFile: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): TVFSResult;
+function TVFSEngine.VFSOpenEx(const OpenFile: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer; Error: PPGError): boolean;
begin
- Result := cVFS_OK;
+ Result := False;
if (FGlobs <> nil) and (@FSourcePlugin.FVFSOpenArchive <> nil) then begin
if @FSourcePlugin.FVFSSetCallbacks <> nil then
FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData);
- Result := FSourcePlugin.FVFSOpenArchive(FGlobs, PChar(OpenFile));
+ Result := FSourcePlugin.FVFSOpenArchive(FGlobs, PChar(OpenFile), Error);
FArchiveMode := True;
- if Result = cVFS_OK then FArchivePath := OpenFile
- else FArchivePath := '';
+ if Result then FArchivePath := OpenFile
+ else FArchivePath := '';
if @FSourcePlugin.FVFSSetCallbacks <> nil then
FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil);
end;
end;
(********************************************************************************************************************************)
-function TVFSEngine.VFSClose: boolean;
+function TVFSEngine.VFSClose(Error: PPGError): boolean;
begin
Result := False;
- if (FGlobs <> nil) and (@FSourcePlugin.FVFSClose <> nil)
- then Result := FSourcePlugin.FVFSClose(FGlobs) = cVFS_OK;
+ if (FGlobs <> nil) and (@FSourcePlugin.FVFSClose <> nil) then
+ Result := FSourcePlugin.FVFSClose(FGlobs, Error);
end;
function TVFSEngine.GetDataItemFromVFSItem(P: PVFSItem): PDataItem;
@@ -444,30 +448,21 @@ begin
Result := Item;
end;
-function TVFSEngine.GetListing(List: TList; const APath: string; AddDotFiles, FollowSymlinks, AddFullPath: boolean): integer;
+function TVFSEngine.GetListing(List: TList; const APath: string; AddDotFiles, FollowSymlinks, AddFullPath: boolean; Error: PPGError): boolean;
var P: PVFSItem;
Item: PDataItem;
- Res: integer;
+ FError: PGError;
begin
DebugMsg(['^^VFS (II): GetListing begin']);
- Result := 0;
+ Result := False;
try
- if @FSourcePlugin.FVFSListFirst = nil then begin
- Result := ERRNoAccess;
- Exit;
- end;
- P := real_libc_malloc(sizeof(TVFSItem));
- memset(P, 0, sizeof(TVFSItem));
- Res := FSourcePlugin.FVFSListFirst(FGlobs, PChar(APath), P, FollowSymlinks, AddFullPath);
- if Res <> cVFS_OK then begin
- FSourcePlugin.FVFSListClose(FGlobs);
- if Res = cVFS_Not_More_Files then Result := 0
- else Result := Res;
- real_libc_free(P);
+ 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.');
Exit;
end;
-
- repeat
+ FError := nil;
+ P := FSourcePlugin.FVFSListFirst(FGlobs, PChar(APath), FollowSymlinks, AddFullPath, @FError);
+ while (P <> nil) and (BreakProcessingType <> 2) do begin
if (strlen(P^.FName) > 0) and (AddDotFiles or (P^.FName[0] <> '.')) then begin
Item := GetDataItemFromVFSItem(P);
List.Add(Item);
@@ -475,14 +470,22 @@ begin
if P^.FName <> nil then real_libc_free(P^.FName);
if P^.FDisplayName <> nil then real_libc_free(P^.FDisplayName);
if P^.sLinkTo <> nil then real_libc_free(P^.sLinkTo);
- memset(P, 0, sizeof(TVFSItem));
- Res := FSourcePlugin.FVFSListNext(FGlobs, P);
- until (Res <> cVFS_OK) or (BreakProcessingType = 2);
- if BreakProcessingType <> 0 then DebugMsg(['^^VFS (WW): GetListing: stopped by BreakProcessing']);
-
+ real_libc_free(P);
+ P := FSourcePlugin.FVFSListNext(FGlobs, @FError);
+ end;
+ Result := FError = 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.');
+ 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);
- if Res <> cVFS_Not_More_Files then Result := Res;
+ FSourcePlugin.FVFSListClose(FGlobs, nil);
except
on E: Exception do
DebugMsg(['^^VFS (EE): GetListing: Exception: ', E.Message]);
@@ -491,18 +494,19 @@ begin
DebugMsg(['^^VFS (II): GetListing end.']);
end;
-function TVFSEngine.GetFileInfo(const APath: string; FollowSymlinks, AddFullPath: boolean): PDataItem;
+function TVFSEngine.GetFileInfo(const APath: string; FollowSymlinks, AddFullPath: boolean; Error: PPGError): PDataItem;
var P: PVFSItem;
- Res: integer;
begin
DebugMsg(['^^VFS (II): GetFileInfo begin']);
Result := nil;
- if @FSourcePlugin.FVFSFileInfo = nil then Exit;
+
+ 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.');
+ Exit;
+ end;
try
- P := real_libc_malloc(sizeof(TVFSItem));
- memset(P, 0, sizeof(TVFSItem));
- Res := FSourcePlugin.FVFSFileInfo(FGlobs, PChar(APath), P, FollowSymlinks, AddFullPath);
- if Res = cVFS_OK then
+ P := FSourcePlugin.FVFSFileInfo(FGlobs, PChar(APath), FollowSymlinks, AddFullPath, Error);
+ if P <> nil then
Result := GetDataItemFromVFSItem(P);
if P^.FName <> nil then real_libc_free(P^.FName);
if P^.FDisplayName <> nil then real_libc_free(P^.FDisplayName);
@@ -527,13 +531,12 @@ begin
AFSSize := -1;
AFSFree := -1;
AFSName := nil;
- if FSourcePlugin.FVFSGetFileSystemInfo(FGlobs, PChar(APath), @AFSSize, @AFSFree, @AFSName) = cVFS_OK then begin
- FSSize := AFSSize;
- FSFree := AFSFree;
- if AFSName <> nil then begin
- FSName := string(AFSName);
- real_libc_free(AFSName);
- end;
+ FSourcePlugin.FVFSGetFileSystemInfo(FGlobs, PChar(APath), @AFSSize, @AFSFree, @AFSName);
+ FSSize := AFSSize;
+ FSFree := AFSFree;
+ if AFSName <> nil then begin
+ FSName := string(AFSName);
+ real_libc_free(AFSName);
end;
end;
end;
@@ -546,7 +549,7 @@ end;
function TVFSEngine.FileCanRun(const FileName: string): boolean;
var Item: PDataItem;
begin
- Item := GetFileInfo(FileName, True, True);
+ Item := GetFileInfo(FileName, True, True, nil);
Result := (Item <> nil) and Item^.IsExecutable;
FreeDataItem(Item);
end;
@@ -577,26 +580,23 @@ begin
end;
end;
-function TVFSEngine.ChangeDir(const NewPath: string): integer;
+function TVFSEngine.ChangeDir(const NewPath: string; Error: PPGError): boolean;
begin
- DebugMsg(['^^VFS (II): ChangeDir begin']);
- Result := 0;
+ Result := False;
try
- Result := FSourcePlugin.FVFSChangeDir(FGlobs, PChar(NewPath));
-// Sleep(3000);
+ Result := FSourcePlugin.FVFSChangeDir(FGlobs, PChar(NewPath), Error);
except
on E: Exception do DebugMsg(['^^VFS (EE): ChangeDir: Exception: ', E.Message]);
end;
- DebugMsg(['^^VFS (II): ChangeDir end.']);
end;
-function TVFSEngine.ChangeDirEx(const NewPath: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): integer;
+function TVFSEngine.ChangeDirEx(const NewPath: string; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer; Error: PPGError): boolean;
begin
- Result := ERRNoAccess;
+ Result := False;
if (FGlobs <> nil) and (@FSourcePlugin.FVFSChangeDir <> nil) then begin
if @FSourcePlugin.FVFSSetCallbacks <> nil then
FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData);
- Result := ChangeDir(NewPath);
+ Result := ChangeDir(NewPath, Error);
if @FSourcePlugin.FVFSSetCallbacks <> nil then
FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil);
end;
@@ -604,7 +604,7 @@ end;
procedure TVFSEngine.SetPath(Value: string);
begin
- ChangeDir(Value);
+ ChangeDir(Value, nil);
end;
function TVFSEngine.FileExists(const FileName: string; FollowSymlinks: boolean): boolean;
@@ -614,9 +614,8 @@ begin
if (FGlobs = nil) or (@FSourcePlugin.FVFSFileInfo = nil) then
Exit;
try
- P := real_libc_malloc(sizeof(TVFSItem));
- memset(P, 0, sizeof(TVFSItem));
- Result := FSourcePlugin.FVFSFileInfo(FGlobs, PChar(FileName), P, FollowSymlinks, False) = cVFS_OK;
+ P := FSourcePlugin.FVFSFileInfo(FGlobs, PChar(FileName), FollowSymlinks, False, nil);
+ Result := P <> nil;
real_libc_free(P);
except
on E: Exception do
@@ -626,16 +625,13 @@ end;
function TVFSEngine.DirectoryExists(const FileName: string; FollowSymlinks: boolean): boolean;
var P: PVFSItem;
- Res: integer;
begin
Result := False;
if (FGlobs = nil) or (@FSourcePlugin.FVFSFileInfo = nil) then
Exit;
try
- P := real_libc_malloc(sizeof(TVFSItem));
- memset(P, 0, sizeof(TVFSItem));
- Res := FSourcePlugin.FVFSFileInfo(FGlobs, PChar(FileName), P, FollowSymlinks, False);
- Result := (Res = cVFS_OK) and (TVFSItemType(P^.ItemType) = vDirectory);
+ P := FSourcePlugin.FVFSFileInfo(FGlobs, PChar(FileName), FollowSymlinks, False, nil);
+ Result := (P <> nil) and (TVFSItemType(P^.ItemType) = vDirectory);
real_libc_free(P);
except
on E: Exception do
@@ -643,46 +639,74 @@ begin
end;
end;
-function TVFSEngine.MakeDir(const NewDir: string): integer;
+function TVFSEngine.MakeDir(const NewDir: string; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSMkDir <> nil then Result := FSourcePlugin.FVFSMkDir(FGlobs, PChar(NewDir))
- else Result := cVFS_Failed;
+ if @FSourcePlugin.FVFSMkDir <> nil then
+ Result := FSourcePlugin.FVFSMkDir(FGlobs, PChar(NewDir), Error)
+ 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.');
+ end;
end;
-function TVFSEngine.Remove(const APath: string): integer;
+function TVFSEngine.Remove(const APath: string; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSRemove <> nil then Result := FSourcePlugin.FVFSRemove(FGlobs, PChar(APath))
- else Result := cVFS_Failed;
+ if @FSourcePlugin.FVFSRemove <> nil then
+ Result := FSourcePlugin.FVFSRemove(FGlobs, PChar(APath), Error)
+ 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.');
+ end;
end;
-function TVFSEngine.RenameFile(const SourceFile, DestFile: string): integer;
+function TVFSEngine.RenameFile(const SourceFile, DestFile: string; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSRename <> nil then Result := FSourcePlugin.FVFSRename(FGlobs, PChar(SourceFile), PChar(DestFile))
- else Result := cVFS_Failed;
+ if @FSourcePlugin.FVFSRename <> nil then
+ Result := FSourcePlugin.FVFSRename(FGlobs, PChar(SourceFile), PChar(DestFile), Error)
+ 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.');
+ end;
end;
-function TVFSEngine.MakeSymLink(const NewFileName, PointTo: string): integer;
+function TVFSEngine.MakeSymLink(const NewFileName, PointTo: string; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSMakeSymLink <> nil then Result := FSourcePlugin.FVFSMakeSymLink(FGlobs, PChar(NewFileName), PChar(PointTo))
- else Result := cVFS_Failed;
+ if @FSourcePlugin.FVFSMakeSymLink <> nil then
+ Result := FSourcePlugin.FVFSMakeSymLink(FGlobs, PChar(NewFileName), PChar(PointTo), Error)
+ 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.');
+ end;
end;
-function TVFSEngine.Chmod(const FileName: string; Mode: cuLong): integer;
+function TVFSEngine.Chmod(const FileName: string; Mode: cuLong; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSChmod <> nil then Result := FSourcePlugin.FVFSChmod(FGlobs, PChar(FileName), Mode)
- else Result := cVFS_Failed;
+ if @FSourcePlugin.FVFSChmod <> nil then
+ Result := FSourcePlugin.FVFSChmod(FGlobs, PChar(FileName), Mode, Error)
+ 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.');
+ end;
end;
-function TVFSEngine.Chown(const FileName: string; UID, GID: cuLong): integer;
+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)
- else Result := cVFS_Failed;
+ if @FSourcePlugin.FVFSChown <> nil then
+ Result := FSourcePlugin.FVFSChown(FGlobs, PChar(FileName), UID, GID, Error)
+ 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.');
+ end;
end;
-function TVFSEngine.ChangeTimes(const APath: string; mtime, atime: time_t): integer;
+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)
- else Result := cVFS_Failed;
+ if @FSourcePlugin.FVFSChangeTimes <> nil then
+ Result := FSourcePlugin.FVFSChangeTimes(FGlobs, PChar(APath), mtime, atime, Error)
+ 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.');
+ end;
end;
function TVFSEngine.GetDirSize(const APath: string): Int64;
@@ -719,46 +743,51 @@ begin
else Result := True;
end;
-function TVFSEngine.OpenFile(const APath: string; Mode: integer; var Error: integer): TEngineFileDes;
-var i: integer;
+function TVFSEngine.OpenFile(const APath: string; Mode: integer; Error: PPGError): TEngineFileDes;
begin
- if @FSourcePlugin.FVFSOpenFile <> nil then begin
- Result := FSourcePlugin.FVFSOpenFile(FGlobs, PChar(APath), Mode, @i);
- Error := i;
- end else Result := nil;
+ if @FSourcePlugin.FVFSOpenFile <> nil then
+ Result := FSourcePlugin.FVFSOpenFile(FGlobs, PChar(APath), Mode, Error)
+ 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.');
+ end;
end;
-function TVFSEngine.ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; var Error: integer): integer;
-var i: integer;
+function TVFSEngine.ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; Error: PPGError): integer;
begin
- if @FSourcePlugin.FVFSReadFile <> nil then begin
- Result := FSourcePlugin.FVFSReadFile(FGlobs, FileDescriptor, Buffer, ABlockSize, @i);
- Error := i;
- end else Result := -1;
+ if @FSourcePlugin.FVFSReadFile <> nil then
+ Result := FSourcePlugin.FVFSReadFile(FGlobs, FileDescriptor, Buffer, ABlockSize, Error)
+ 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.');
+ end;
end;
-function TVFSEngine.WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; var Error: integer): integer;
-var i: integer;
+function TVFSEngine.WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; Error: PPGError): integer;
begin
- if @FSourcePlugin.FVFSWriteFile <> nil then begin
- Result := FSourcePlugin.FVFSWriteFile(FGlobs, FileDescriptor, Buffer, BytesCount, @i);
- Error := i;
- end else Result := -1;
+ if @FSourcePlugin.FVFSWriteFile <> nil then
+ Result := FSourcePlugin.FVFSWriteFile(FGlobs, FileDescriptor, Buffer, BytesCount, Error)
+ 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.');
+ end;
end;
-function TVFSEngine.CloseFile(const FileDescriptor: TEngineFileDes): integer;
+function TVFSEngine.CloseFile(const FileDescriptor: TEngineFileDes; Error: PPGError): boolean;
begin
- if @FSourcePlugin.FVFSCloseFile <> nil then Result := FSourcePlugin.FVFSCloseFile(FGlobs, FileDescriptor)
- else Result := 0;
+ if @FSourcePlugin.FVFSCloseFile <> nil then
+ Result := FSourcePlugin.FVFSCloseFile(FGlobs, FileDescriptor, nil)
+ else Result := False;
end;
-function TVFSEngine.FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; var Error: integer): Int64;
-var i: integer;
+function TVFSEngine.FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; Error: PPGError): Int64;
begin
- if @FSourcePlugin.FVFSFileSeek <> nil then begin
- Result := FSourcePlugin.FVFSFileSeek(FGlobs, FileDescriptor, AbsoluteOffset, @i);
- Error := i;
- end else Result := -1;
+ if @FSourcePlugin.FVFSFileSeek <> nil then
+ Result := FSourcePlugin.FVFSFileSeek(FGlobs, FileDescriptor, AbsoluteOffset, Error)
+ 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.');
+ end;
end;
function TVFSEngine.TwoSameFiles(const Path1, Path2: string; FollowSymlinks: boolean): boolean;
@@ -770,129 +799,123 @@ end;
(********************************************************************************************************************************)
-function TVFSEngine.CopyFileIn(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
+function TVFSEngine.CopyFileIn(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean;
begin
- Result := StartCopyOperation(Sender, ErrorFunc, nil, nil, nil, nil);
- Result := Result and CopyFileInEx(Sender, SourceFile, DestFile, ErrorFunc, Append);
- Result := Result and StopCopyOperation(Sender, ErrorFunc);
+ 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 StopCopyOperation(nil, nil);
end;
-function TVFSEngine.CopyFileOut(Sender: Pointer; const SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
+function TVFSEngine.CopyFileOut(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer): boolean;
begin
- Result := StartCopyOperation(Sender, ErrorFunc, nil, nil, nil, nil);
- Result := Result and CopyFileInEx(Sender, SourceFile, DestFile, ErrorFunc, Append);
- Result := Result and StopCopyOperation(Sender, ErrorFunc);
+ 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 StopCopyOperation(nil, nil);
end;
-function TVFSEngine.CopyFileOutEx(Sender: Pointer; const SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
-var Res: TVFSResult;
+function TVFSEngine.CopyFileOutEx(const SourceFile, DestFile: string; Append: boolean): boolean;
+var Error: PGError;
+ ACopyProgressCallback: TVFSProgressCallback;
begin
Result := False;
try
- if @FSourcePlugin.FVFSCopyToLocal <> nil then begin
- try
- Res := FSourcePlugin.FVFSCopyToLocal(FGlobs, PChar(SourceFile), PChar(DestFile), Append);
- except
- on E: Exception do begin
- DebugMsg(['*** Exception raised in TVFSEngine.CopyFileOut(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]);
- Res := cVFS_WriteErr;
- end;
+ Error := nil;
+ if @FSourcePlugin.FVFSCopyToLocal <> nil then
+ Result := FSourcePlugin.FVFSCopyToLocal(FGlobs, PChar(SourceFile), PChar(DestFile), Append, @Error)
+ 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
+ if FCopyProgressCallback <> nil then begin
+ @ACopyProgressCallback := FCopyProgressCallback;
+ Result := ACopyProgressCallback(0, Error, FCopyCallbackData);
end;
- Result := Res = cVFS_OK;
- // * TODO: Port to GError
- if (Res <> cVFS_OK) and Assigned(ErrorFunc) then
- case Res of
- cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, SourceFile);
- cVFS_WriteErr: Result := ErrorFunc(Sender, 7, 0, DestFile);
- cVFS_mallocFailed: ErrorFunc(Sender, 1, 0, SourceFile);
- cVFS_Cancelled: ErrorFunc(Sender, 0, 0, SourceFile);
- end;
- end else Result := False;
+ g_error_free(Error);
+ end;
except
- on E: Exception do DebugMsg(['*** Exception raised in TVFSEngine.CopyFileOut(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]);
+ on E: Exception do begin
+ DebugMsg(['*** Exception raised in TVFSEngine.CopyFileOutEx(SourceFile=', SourceFile, ', DestFile=', DestFile, ', Append=', Append,'): (', E.ClassName, '): ', E.Message]);
+ Result := False;
+ end;
end;
end;
-function TVFSEngine.CopyFileInEx(Sender: Pointer; const SourceFile, DestFile: string; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean;
-var Res: TVFSResult;
+function TVFSEngine.CopyFileInEx(const SourceFile, DestFile: string; Append: boolean): boolean;
+var Error: PGError;
+ACopyProgressCallback: TVFSProgressCallback;
begin
Result := False;
try
- if @FSourcePlugin.FVFSCopyFromLocal <> nil then begin
- try
- Res := FSourcePlugin.FVFSCopyFromLocal(FGlobs, PChar(SourceFile), PChar(DestFile), Append);
- except
- on E: Exception do begin
- DebugMsg(['*** Exception raised in TVFSEngine.CopyFileIn(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]);
- Res := cVFS_WriteErr;
- end;
+ Error := nil;
+ if @FSourcePlugin.FVFSCopyFromLocal <> nil then
+ Result := FSourcePlugin.FVFSCopyFromLocal(FGlobs, PChar(SourceFile), PChar(DestFile), Append, @Error)
+ else
+ g_set_error(@Error, G_IO_ERROR, gint(G_IO_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);
end;
- Result := Res = cVFS_OK;
- // * TODO: Port to GError
- if (Res <> cVFS_OK) and Assigned(ErrorFunc) then
- case Res of
- cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, SourceFile);
- cVFS_WriteErr: Result := ErrorFunc(Sender, 7, 0, DestFile);
- cVFS_mallocFailed: ErrorFunc(Sender, 1, 0, SourceFile);
- cVFS_Cancelled: ErrorFunc(Sender, 0, 0, SourceFile);
- end;
- end else Result := False;
+ g_error_free(Error);
+ end;
except
- on E: Exception do DebugMsg(['*** Exception raised in TVFSEngine.CopyFileIn(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]);
+ on E: Exception do begin
+ DebugMsg(['*** Exception raised in TVFSEngine.CopyFileInEx(SourceFile=', SourceFile, ', DestFile=', DestFile, ', Append=', Append,'): (', E.ClassName, '): ', E.Message]);
+ Result := False;
+ end;
end;
end;
-function TVFSEngine.StartCopyOperation(Sender: Pointer; ErrorFunc: TEngineErrorFunc; AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
-var Res: TVFSResult;
+function TVFSEngine.StartCopyOperation(AskQuestionCallback: PVFSAskQuestionCallback; AskPasswordCallback: PVFSAskPasswordCallback; ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
+var Error: PGError;
begin
Result := not ArchiveMode;
try
if @FSourcePlugin.FVFSSetCallbacks <> nil then
FSourcePlugin.FVFSSetCallbacks(FGlobs, AskQuestionCallback, AskPasswordCallback, ProgressCallback, CallbackData);
+ FCopyProgressCallback := ProgressCallback;
+ FCopyCallbackData := CallbackData;
if ArchiveMode then begin
- if @FSourcePlugin.FVFSStartCopyOperation <> nil then begin
- Res := FSourcePlugin.FVFSStartCopyOperation(FGlobs);
- Result := Res = cVFS_OK;
- // * TODO: Port to GError
- if (Res <> cVFS_OK) and Assigned(ErrorFunc) then
- case Res of
- cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, 'StartCopyOperation');
- cVFS_WriteErr: Result := ErrorFunc(Sender, 7, 0, 'StartCopyOperation');
- cVFS_mallocFailed: ErrorFunc(Sender, 1, 0, 'StartCopyOperation');
- cVFS_Cancelled: ErrorFunc(Sender, 0, 0, 'StartCopyOperation');
- end;
- end else
- ErrorFunc(Sender, 2, 0, 'StartCopyOperation not supported');
+ Error := nil;
+ if @FSourcePlugin.FVFSStartCopyOperation <> nil then
+ Result := FSourcePlugin.FVFSStartCopyOperation(FGlobs, @Error)
+ else
+ g_set_error(@Error, G_IO_ERROR, gint(G_IO_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);
+ g_error_free(Error);
+ end;
end;
except
- on E: Exception do DebugMsg(['*** Exception raised in TVFSEngine.StartCopyOperation(Sender=', QWord(Sender), '): (', E.ClassName, '): ', E.Message]);
+ on E: Exception do DebugMsg(['*** Exception raised in TVFSEngine.StartCopyOperation(CallbackData=', CallbackData, '): (', E.ClassName, '): ', E.Message]);
end;
end;
-function TVFSEngine.StopCopyOperation(Sender: Pointer; ErrorFunc: TEngineErrorFunc): boolean;
-var Res: TVFSResult;
+function TVFSEngine.StopCopyOperation(ProgressCallback: PVFSProgressCallback; CallbackData: Pointer): boolean;
+var Error: PGError;
begin
Result := not ArchiveMode;
try
if @FSourcePlugin.FVFSSetCallbacks <> nil then
FSourcePlugin.FVFSSetCallbacks(FGlobs, nil, nil, nil, nil);
if ArchiveMode then begin
- if @FSourcePlugin.FVFSStopCopyOperation <> nil then begin
- Res := FSourcePlugin.FVFSStopCopyOperation(FGlobs);
- Result := Res = cVFS_OK;
- // * TODO: Port to GError
- if (Res <> cVFS_OK) and Assigned(ErrorFunc) then
- case Res of
- cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, 'StopCopyOperation');
- cVFS_WriteErr: Result := ErrorFunc(Sender, 7, 0, 'StopCopyOperation');
- cVFS_mallocFailed: ErrorFunc(Sender, 1, 0, 'StopCopyOperation');
- cVFS_Cancelled: ErrorFunc(Sender, 0, 0, 'StopCopyOperation');
- end;
- end else
- ErrorFunc(Sender, 5, 0, 'StopCopyOperation not supported');
+ Error := nil;
+ if @FSourcePlugin.FVFSStopCopyOperation <> nil then
+ Result := FSourcePlugin.FVFSStopCopyOperation(FGlobs, @Error)
+ else
+ g_set_error(@Error, G_IO_ERROR, gint(G_IO_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);
+ g_error_free(Error);
+ end;
end;
+ FCopyProgressCallback := nil;
+ FCopyCallbackData := nil;
except
- on E: Exception do DebugMsg(['*** Exception raised in TVFSEngine.StopCopyOperation(Sender=', QWord(Sender), '): (', E.ClassName, '): ', E.Message]);
+ on E: Exception do DebugMsg(['*** Exception raised in TVFSEngine.StopCopyOperation(CallbackData=', CallbackData, '): (', E.ClassName, '): ', E.Message]);
end;
end;
diff --git a/vfs/uVFSprototypes.pas b/vfs/uVFSprototypes.pas
index 8beacdd..9ed0844 100644
--- a/vfs/uVFSprototypes.pas
+++ b/vfs/uVFSprototypes.pas
@@ -36,24 +36,7 @@ uses glib2;
const
cVFSVersion = 5; // current version of the VFS API
- // Error codes (TVFSResult)
- cVFS_OK = 0;
- cVFS_Failed = 1; // also No such file
- cVFS_Cancelled = 2;
- cVFS_Not_Supported = 3;
- cVFS_Not_More_Files = 4; // returned while directory listing
- cVFS_ReadErr = 5;
- cVFS_WriteErr = 6; // also ReadOnlyFileSystem
- cVFS_LoginFailed = 7;
- cVFS_PermissionDenied = 8;
- cVFS_NoSpaceLeft = 9;
- cVFS_mallocFailed = 10;
- cVFS_BadPassword = 11;
- cVFS_MissingVolume = 12;
- cVFS_CorruptedArchive = 13;
-
-
- // Open modes (for VFSOpenFile function)
+ // Open modes (for VFSOpenFile function)
cVFS_OpenRead = 0;
cVFS_OpenWrite = 1;
cVFS_OpenAppend = 2;
@@ -76,8 +59,6 @@ const
type
- TVFSResult = longint;
-
// Plugin private data for each connection/instance
TVFSGlobs = Pointer;
@@ -94,7 +75,6 @@ type
TVFSItemType = (vRegular=0, vChardev=1, vBlockdev=2, vDirectory=3, vFifo=4, vSock=5, vOther=6);
-
PVFSItem = ^TVFSItem;
TVFSItem = record
FName: PChar;
@@ -149,10 +129,14 @@ type
password_save: PVFSPasswordSave;
user_data: Pointer): gboolean; cdecl;
- // Return False to break the operation
+ // Progress callback, return False to break the copy process
+ // If an Error is set, returning True means to ignore error (don't delete broken file if possible)
+ // If an Error is set, Position may contain random value
+ // Do not free Error, it belongs to the copy operation
PVFSProgressCallback = ^TVFSProgressCallback;
+ // Keep in sync with UCoreWorkers.pas/vfs_progress_callback
TVFSProgressCallback = function (position: guint64;
- max: guint64;
+ error: PGError;
user_data: Pointer): gboolean; cdecl;
type
@@ -192,33 +176,33 @@ type
// Opens specified archive. This will also switch engine into an archiving mode
- TVFSOpenArchive = function (g:TVFSGlobs; const sName: PChar): TVFSResult; cdecl;
+ TVFSOpenArchive = function (g:TVFSGlobs; const sName: PChar; Error: PPGError): gboolean; cdecl;
// Opens specified network location. This will also switch engine into a networking mode
// In case of URI, do not supply password encoded in the string; plugin will automatically spawn the TVFSAskPasswordCallback callback when needed
- TVFSOpenURI = function (g:TVFSGlobs; const sURI: PChar): TVFSResult; cdecl;
+ TVFSOpenURI = function (g:TVFSGlobs; const sURI: PChar; Error: PPGError): gboolean; cdecl;
// Closes the file or connection to the server
- TVFSClose = function (g:TVFSGlobs): TVFSResult; cdecl;
+ TVFSClose = function (g:TVFSGlobs; Error: PPGError): gboolean; cdecl;
// These functions serves for listing contents of a directory
// Before calling VFSListFirst, it is recommended to change target directory (VFSChangeDir) to check it really exists
// First call the VFSListFirst function and then repeat call of VFSListNext until it returns NULL.
// Then call VFSListClose to make cleanup
- TVFSListFirst = function (g:TVFSGlobs; const sDir: PChar; VFSItem: PVFSItem; FollowSymlinks, AddFullPath: gboolean): TVFSResult; cdecl;
- TVFSListNext = function (g:TVFSGlobs; VFSItem: PVFSItem): TVFSResult; cdecl;
- TVFSListClose = function (g:TVFSGlobs): TVFSResult; cdecl;
+ TVFSListFirst = function (g:TVFSGlobs; const sDir: PChar; FollowSymlinks, AddFullPath: gboolean; Error: PPGError): PVFSItem; cdecl;
+ TVFSListNext = function (g:TVFSGlobs; Error: PPGError): PVFSItem; cdecl;
+ TVFSListClose = function (g:TVFSGlobs; Error: PPGError): gboolean; cdecl;
// Gets a single info item without need to list a whole directory
- TVFSFileInfo = function (g:TVFSGlobs; const AFileName: PChar; VFSItem: PVFSItem; FollowSymlinks, AddFullPath: gboolean): TVFSResult; cdecl;
+ TVFSFileInfo = function (g:TVFSGlobs; const AFileName: PChar; FollowSymlinks, AddFullPath: gboolean; Error: PPGError): PVFSItem; cdecl;
// Try to change directory, checks real access
- TVFSChangeDir = function (g:TVFSGlobs; const NewPath: PChar): TVFSResult; cdecl;
+ TVFSChangeDir = function (g:TVFSGlobs; const NewPath: PChar; Error: PPGError): gboolean; cdecl;
// Returns current working path, tuxcmd will take care of memory deallocation
TVFSGetPath = function (g:TVFSGlobs): PChar; cdecl;
// Returns the current working path in the URI form, tuxcmd will take care of memory deallocation
TVFSGetPathURI = function (g:TVFSGlobs): PChar; cdecl;
// Gets filesystem info; tuxcmd will take care of memory deallocation
- TVFSGetFileSystemInfo = function (g:TVFSGlobs; const APath: PChar; FSSize, FSFree: PInt64; FSLabel: PPChar): TVFSResult; cdecl;
+ TVFSGetFileSystemInfo = procedure (g:TVFSGlobs; const APath: PChar; FSSize, FSFree: PInt64; FSLabel: PPChar); cdecl;
TVFSIsOnSameFS = function (g:TVFSGlobs; const Path1, Path2: PChar; FollowSymlinks: gboolean): gboolean; cdecl;
// Checks if the two files are simmilar (used to test the case-insensitive filesystem - or hardlinks)
TVFSTwoSameFiles = function (g:TVFSGlobs; const Path1, Path2: PChar; FollowSymlinks: gboolean): gboolean; cdecl;
@@ -228,34 +212,34 @@ type
TVFSBreakGetDirSize = procedure (g:TVFSGlobs); cdecl;
// Operations
- TVFSMkDir = function (g:TVFSGlobs; const sDirName: PChar): TVFSResult; cdecl;
+ TVFSMkDir = function (g:TVFSGlobs; const sDirName: PChar; Error: PPGError): gboolean; cdecl;
// Rename/Move, the two files/directories have to be on the same filesystem (do manual copy and delete otherway)
- TVFSRename = function (g:TVFSGlobs; const sSrcName, sDstName: PChar): TVFSResult; cdecl;
+ TVFSRename = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; Error: PPGError): gboolean; cdecl;
// Removes file/directory (empty only!)
- TVFSRemove = function (g:TVFSGlobs; const APath: PChar): TVFSResult; cdecl;
- TVFSMakeSymLink = function (g:TVFSGlobs; const NewFileName, PointTo: PChar): TVFSResult; cdecl;
+ TVFSRemove = function (g:TVFSGlobs; const APath: PChar; Error: PPGError): gboolean; cdecl;
+ TVFSMakeSymLink = function (g:TVFSGlobs; const NewFileName, PointTo: PChar; Error: PPGError): gboolean; cdecl;
// Mode is classic unix format (glibc) - a bit mask
- TVFSChmod = function (g:TVFSGlobs; const FileName: PChar; Mode: guint32): TVFSResult; cdecl;
- TVFSChown = function (g:TVFSGlobs; const FileName: PChar; UID, GID: guint32): TVFSResult; cdecl;
+ TVFSChmod = function (g:TVFSGlobs; const FileName: PChar; Mode: guint32; Error: PPGError): gboolean; cdecl;
+ TVFSChown = function (g:TVFSGlobs; const FileName: PChar; UID, GID: guint32; Error: PPGError): gboolean; cdecl;
// Changes times for the file/directory - mtime and atime are __time_t parameters (glibc)
- TVFSChangeTimes = function (g:TVFSGlobs; const APath: PChar; mtime, atime: guint32): TVFSResult; cdecl;
+ TVFSChangeTimes = function (g:TVFSGlobs; const APath: PChar; mtime, atime: guint32; Error: PPGError): gboolean; cdecl;
// Performs the copy process from inside of module to local filesystem
// (thus sSrcName is a path from inside of module and sDstName is path in the local filesystem where the file should be copied)
// Note: if you need to transfer a file between two VFS modules, you need to do it manually -
// - either first copy to local FS or use the Open, Read, Write functions of the module (NOTE: both VFS modules have to support these functions)
- TVFSCopyToLocal = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; Append: gboolean): TVFSResult; cdecl;
+ TVFSCopyToLocal = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; Append: gboolean; Error: PPGError): gboolean; cdecl;
// Performs the copy process from local filesystem into the module
- TVFSCopyFromLocal = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; Append: gboolean): TVFSResult; cdecl;
- // Start the copy operation - open the archive and prepare internal structures
- TVFSStartCopyOperation = function (g:TVFSGlobs): TVFSResult; cdecl;
- // Stop the copy operation - close the archive and free memory
- TVFSStopCopyOperation = function (g:TVFSGlobs): TVFSResult; cdecl;
+ TVFSCopyFromLocal = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; Append: gboolean; Error: PPGError): gboolean; cdecl;
+ // Start the copy operation - open the archive and prepare internal structures (called only in archive mode)
+ TVFSStartCopyOperation = function (g:TVFSGlobs; Error: PPGError): gboolean; cdecl;
+ // Stop the copy operation - close the archive and free memory (called only in archive mode)
+ TVFSStopCopyOperation = function (g:TVFSGlobs; Error: PPGError): gboolean; cdecl;
// TODO: Prototype function for packing new files into archive
- TVFSPack = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; CompressionLevel: integer; const Password: PChar): TVFSResult; cdecl;
+ TVFSPack = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; CompressionLevel: integer; const Password: PChar; Error: PPGError): gboolean; cdecl;
// TODO: not implemented at all
@@ -263,14 +247,14 @@ type
// There is a TVFSFileDes object which identifies the processed file (filedescriptor)
// All these functions needs a pointer to an int variable to store the error code
// NOTE: not all modules could support this set of functions due to its design (unable to set a solid block size)
- TVFSOpenFile = function (g:TVFSGlobs; const APath: PChar; Mode: integer; Error: Pinteger): TVFSFileDes; cdecl;
+ TVFSOpenFile = function (g:TVFSGlobs; const APath: PChar; Mode: integer; Error: PPGError): TVFSFileDes; cdecl;
// Opens a file or creates new (the values for the Mode parameter are described above) and returns the assigned filedescriptor
- TVFSReadFile = function (g:TVFSGlobs; const FileDescriptor: TVFSFileDes; Buffer: Pointer; ABlockSize: integer; Error: Pinteger): integer; cdecl;
+ TVFSReadFile = function (g:TVFSGlobs; const FileDescriptor: TVFSFileDes; Buffer: Pointer; ABlockSize: integer; Error: PPGError): integer; cdecl;
// Returns number of bytes read; the buffer needs to be allocated by a blocksize (set it by VFSSetBlockSize function)
- TVFSWriteFile = function (g:TVFSGlobs; const FileDescriptor: TVFSFileDes; Buffer: Pointer; BytesCount: integer; Error: Pinteger): integer; cdecl;
+ TVFSWriteFile = function (g:TVFSGlobs; const FileDescriptor: TVFSFileDes; Buffer: Pointer; BytesCount: integer; Error: PPGError): integer; cdecl;
// Returns number of bytes written
- TVFSCloseFile = function (g:TVFSGlobs; const FileDescriptor: TVFSFileDes): TVFSResult; cdecl;
- TVFSFileSeek = function (g:TVFSGlobs; const FileDescriptor: TVFSFileDes; const AbsoluteOffset: Int64; Error: Pinteger): Int64; cdecl;
+ TVFSCloseFile = function (g:TVFSGlobs; const FileDescriptor: TVFSFileDes; Error: PPGError): gboolean; cdecl;
+ TVFSFileSeek = function (g:TVFSGlobs; const FileDescriptor: TVFSFileDes; const AbsoluteOffset: Int64; Error: PPGError): Int64; cdecl;
// Sets the position in the file from the start and returns real current position