diff options
| author | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2009-12-13 14:32:58 +0100 |
|---|---|---|
| committer | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2009-12-13 14:32:58 +0100 |
| commit | 0f7616a007edaa1d19c4672a4fd390c072b1eba6 (patch) | |
| tree | a1524927d8986bb54345c47ded84bb3c2a9559c2 /UEngines.pas | |
| parent | ae0047b8a5fa76ea76c66d8c5c580eba39178755 (diff) | |
| download | tuxcmd-0f7616a007edaa1d19c4672a4fd390c072b1eba6.tar.xz | |
Error system transformation to GErrorv0.6.74
Note that most coreworkers are broken at the moment.
Diffstat (limited to 'UEngines.pas')
| -rw-r--r-- | UEngines.pas | 539 |
1 files changed, 270 insertions, 269 deletions
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; (********************************************************************************************************************************) |
