summaryrefslogtreecommitdiff
path: root/UEngines.pas
diff options
context:
space:
mode:
Diffstat (limited to 'UEngines.pas')
-rw-r--r--UEngines.pas140
1 files changed, 84 insertions, 56 deletions
diff --git a/UEngines.pas b/UEngines.pas
index 8a0e9e6..8649a05 100644
--- a/UEngines.pas
+++ b/UEngines.pas
@@ -30,6 +30,11 @@ const omRead = 0;
ConfDefaultDirCreationMask = 755;
+ ConfDefaultOpenFlagsRead = O_RDONLY or O_NOFOLLOW or O_CLOEXEC;
+ ConfDefaultOpenFlagsWrite = O_WRONLY or O_NOFOLLOW or O_CLOEXEC or O_EXCL or O_CREAT or O_TRUNC;
+ ConfDefaultOpenFlagsAppend = O_WRONLY or O_NOFOLLOW or O_CLOEXEC or O_EXCL or O_APPEND;
+
+ ConfDefaultFileCreationMask = S_IRUSR or S_IWUSR or S_IRGRP or S_IROTH;
type
PDataItem = ^TDataItem;
@@ -549,27 +554,27 @@ begin
end;
function TLocalTreeEngine.CopyFileOut(const SourceFile, DestFile: string; Append: boolean; ProgressFunc: TEngineProgressFunc; Sender: Pointer; Error: PPGError): boolean;
-var fsrc, fdest: PFILE;
+var fsrc, fdest: Longint;
Buffer: Pointer;
- BytesDone, BytesRead, BytesWritten: Int64;
+ BytesDone, BytesRead, BytesWritten, BytesRemaining: ssize_t;
begin
Result := False;
BytesDone := 0;
try
// Open source file for reading
- fsrc := fopen64(PChar(SourceFile), 'r');
- if fsrc = nil then begin
+ fsrc := open64(PChar(SourceFile), ConfDefaultOpenFlagsRead, 0);
+ if fsrc < 0 then begin
g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SOURCE_OPEN), '%m');
if @ProgressFunc <> nil then
ProgressFunc(Sender, 0, Error^);
Exit;
end;
// Open target file for writing/appending
- if Append then fdest := fopen64(PChar(DestFile), 'a')
- else fdest := fopen64(PChar(DestFile), 'w');
- if fdest = nil then begin
+ if Append then fdest := open64(PChar(DestFile), ConfDefaultOpenFlagsAppend, 0)
+ else fdest := open64(PChar(DestFile), ConfDefaultOpenFlagsWrite, ConfDefaultFileCreationMask);
+ if fdest < 0 then begin
g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_TARGET_OPEN), '%m');
- fclose(fsrc);
+ libc_close(fsrc);
if @ProgressFunc <> nil then
ProgressFunc(Sender, 0, Error^);
Exit;
@@ -578,17 +583,18 @@ begin
Buffer := malloc(FBlockSize);
if Buffer = nil then begin
g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_ALLOC_FAILED), '%m');
- fclose(fdest);
- fclose(fsrc);
+ libc_close(fdest);
+ libc_close(fsrc);
if @ProgressFunc <> nil then
ProgressFunc(Sender, 0, Error^);
Exit;
end;
- while feof(fsrc) = 0 do begin
+ Result := True;
+ repeat
// Read block
- BytesRead := fread(Buffer, 1, FBlockSize, fsrc);
- if (BytesRead < FBlockSize) and (feof(fsrc) = 0) then begin
+ BytesRead := libc_read(fsrc, Buffer, FBlockSize);
+ if BytesRead < 0 then begin
g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SOURCE_READ), '%m');
Result := False;
if @ProgressFunc <> nil then
@@ -602,41 +608,51 @@ begin
end;
// Write block
- BytesWritten := fwrite(Buffer, 1, BytesRead, fdest);
- if BytesWritten < BytesRead then begin
- g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_TARGET_WRITE), '%m');
- Result := False;
- if @ProgressFunc <> nil then
- ProgressFunc(Sender, BytesDone + BytesRead, Error^);
- Break; // We cannot ignore write errors
+ if BytesRead > 0 then begin
+ BytesRemaining := BytesRead;
+ repeat
+ BytesWritten := libc_write(fdest, Buffer + (BytesRead - BytesRemaining), BytesRemaining);
+ if BytesWritten > 0 then
+ BytesRemaining := BytesRemaining - BytesWritten;
+ until (BytesRemaining = 0) or (BytesWritten <= 0);
+ if BytesWritten < 0 then begin
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_TARGET_WRITE), '%m');
+ Result := False;
+ if @ProgressFunc <> nil then
+ ProgressFunc(Sender, BytesDone + BytesRead, Error^);
+ Break; // We cannot ignore write errors
+ end;
end;
-
+ // BytesRead == 0 means EOF
BytesDone := BytesDone + BytesRead;
- if (@ProgressFunc <> nil) and (not ProgressFunc(Sender, BytesDone, nil)) then
+ if (@ProgressFunc <> nil) and (not ProgressFunc(Sender, BytesDone, nil)) then begin
+ Result := False;
Break;
- end;
- Result := (feof(fsrc) <> 0) and (Error^ = nil);
+ end;
+ until BytesRead <= 0;
libc_free(Buffer);
- if fclose(fdest) <> 0 then begin
- g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_TARGET_CLOSE), '%m');
- Result := False;
- if @ProgressFunc <> nil then
- ProgressFunc(Sender, BytesDone, Error^);
- fclose(fsrc);
- Exit;
- end;
- if fclose(fsrc) <> 0 then begin
- g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SOURCE_CLOSE), '%m');
- Result := False;
- if @ProgressFunc <> nil then
- Result := ProgressFunc(Sender, BytesDone, Error^);
+ if libc_close(fdest) <> 0 then
if Result then begin
- // user has chosen to ignore the error
- g_error_free(Error^);
- Error^ := nil;
- end else Exit;
- end;
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_TARGET_CLOSE), '%m');
+ Result := False;
+ if @ProgressFunc <> nil then
+ ProgressFunc(Sender, BytesDone, Error^);
+ libc_close(fsrc);
+ Exit;
+ end;
+ if libc_close(fsrc) <> 0 then
+ if Result then begin
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SOURCE_CLOSE), '%m');
+ Result := False;
+ if @ProgressFunc <> nil then
+ Result := ProgressFunc(Sender, BytesDone, Error^);
+ if Result then begin
+ // user has chosen to ignore the error
+ g_error_free(Error^);
+ Error^ := nil;
+ end else Exit;
+ end;
except
on E: Exception do begin
Result := False;
@@ -649,6 +665,8 @@ begin
g_error_free(Error^);
Error^ := nil;
end;
+ libc_close(fdest);
+ libc_close(fsrc);
end;
end;
end;
@@ -781,39 +799,49 @@ end;
(********************************************************************************************************************************)
function TLocalTreeEngine.OpenFile(const APath: string; Mode: integer; Error: PPGError): TEngineFileDes;
-var m: PChar;
+var flags, m: Longint;
+ r: Integer;
begin
+ Result := nil;
+ m := 0;
case Mode of
- omRead: m := 'r';
- omWrite: m := 'w';
- omAppend: m := 'a';
- else m := 'r';
+ omRead: flags := ConfDefaultOpenFlagsRead;
+ omWrite: begin
+ flags := ConfDefaultOpenFlagsWrite;
+ m := ConfDefaultFileCreationMask;
+ end;
+ omAppend: flags := ConfDefaultOpenFlagsAppend;
+ else begin
+ g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_OPEN_FILE), 'Invalid file mode %d', Mode);
+ Exit;
+ end;
end;
- Result := fopen64(PChar(APath), m);
- if Result = nil then
- g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_OPEN_FILE), '%m');
+
+ r := open64(PChar(APath), flags, m);
+ if r < 0 then g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_OPEN_FILE), '%m')
+ else Result := Pointer(r);
end;
(********************************************************************************************************************************)
function TLocalTreeEngine.ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; Error: PPGError): integer;
begin
- Result := fread(Buffer, 1, ABlockSize, FileDescriptor);
- if (Result = 0) and (feof(FileDescriptor) = 0) then
+ Result := libc_read(LongInt(FileDescriptor), Buffer, ABlockSize);
+ if Result < 0 then
g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_READ_FILE), '%m');
end;
(********************************************************************************************************************************)
function TLocalTreeEngine.WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; Error: PPGError): integer;
begin
- Result := fwrite(Buffer, 1, BytesCount, FileDescriptor);
- if Result < BytesCount then
+ Result := libc_write(LongInt(FileDescriptor), Buffer, BytesCount);
+ if Result < 0 then
g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_WRITE_FILE), '%m');
end;
(********************************************************************************************************************************)
function TLocalTreeEngine.CloseFile(const FileDescriptor: TEngineFileDes; Error: PPGError): boolean;
begin
- Result := fclose(FileDescriptor) = 0;
+ Result := libc_close(LongInt(FileDescriptor)) = 0;
if not Result then
g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_CLOSE_FILE), '%m');
end;
@@ -821,7 +849,7 @@ end;
(********************************************************************************************************************************)
function TLocalTreeEngine.FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; Error: PPGError): Int64;
begin
- Result := fseeko64(FileDescriptor, AbsoluteOffset, SEEK_SET);
+ Result := lseek64(LongInt(FileDescriptor), AbsoluteOffset, SEEK_SET);
if Result = -1 then
g_set_error(Error, TUXCMD_ERROR, gint(TUXCMD_ERROR_SEEK), '%m');
end;