diff options
Diffstat (limited to 'UEngines.pas')
| -rw-r--r-- | UEngines.pas | 140 |
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; |
