mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 09:32:00 +01:00 
			
		
		
		
	 df6a2dce00
			
		
	
	
		df6a2dce00
		
	
	
	
	
		
			
			+ codepage support for textrec/filerec and the above routines
  * textrec/filerec now store the filename by default using widechar. It is
    possible to switch back to ansichars using the FPC_ANSI_TEXTFILEREC define.
    In that case, from now on the filename will always be stored in
    DefaultFileSystemEncoding
  * fixed potential buffer overflows and non-null-terminated file names in
    textrec/filerec
  + dodirseparators(pwidechar), changed the dodirseparators(pchar/pwidechar)
    parameters into var-parameters and gave those routines an extra parameter
    that indicates whether the p(wide)char can be changed in place if
    necessary or whether a copy must be made first (avoids us having to make
    all strings always unique everywhere, because they might be changed on
    some platforms via a pchar)
  * do_open/do_erase/do_rename got extra boolean parameters indicating whether
    the passed pchars point to data that can be freely changed (to pass on to
    dodirseparators() if applicable)
  * objects.pp: force assign(pchar) to be called, because
    assign(array[0..255]) cannot choose between pchar and rawbytestring
    versions (and removing the pchar version means that assign(pchar) will
    be mapped to assign(shortstring) in {$h-})
  * fixed up some routines in other units that depend on the format of
    the textrec/filerec.name field
git-svn-id: branches/cpstrrtl@25137 -
		
	
			
		
			
				
	
	
		
			270 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			270 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| {
 | |
|     This file is part of the Free Pascal run time library.
 | |
|     Copyright (c) 2001 by Free Pascal development team
 | |
| 
 | |
|     Low leve file functions
 | |
| 
 | |
|     See the file COPYING.FPC, included in this distribution,
 | |
|     for details about the copyright.
 | |
| 
 | |
|     This program is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | |
| 
 | |
|  **********************************************************************}
 | |
| 
 | |
| {****************************************************************************
 | |
| 
 | |
|                           Low Level File Routines
 | |
| 
 | |
| ****************************************************************************}
 | |
| 
 | |
| procedure do_close(h:thandle);
 | |
| begin
 | |
| { Only three standard handles under real OS/2 }
 | |
|   if h>2 then
 | |
|   begin
 | |
|     InOutRes:=DosClose(h);
 | |
|   end;
 | |
| {$ifdef IODEBUG}
 | |
|   writeln('do_close: handle=', H, ', InOutRes=', InOutRes);
 | |
| {$endif}
 | |
| end;
 | |
| 
 | |
| procedure do_erase(p:Pchar; pchangeable: boolean);
 | |
| var
 | |
|   oldp: pchar;
 | |
| begin
 | |
|   oldp:=p;
 | |
|   DoDirSeparators(p,pchangeable);
 | |
|   inoutres:=DosDelete(p);
 | |
|   if p<>oldp then
 | |
|     freemem(p);
 | |
| end;
 | |
| 
 | |
| procedure do_rename(p1,p2:Pchar; p1changeable, p2changeable: boolean);
 | |
| var
 | |
|   oldp1, oldp2 : pchar;
 | |
| begin
 | |
|   oldp1:=p1;
 | |
|   oldp2:=p2;
 | |
|   DoDirSeparators(p1,p1changeable);
 | |
|   DoDirSeparators(p2,p2changeable);
 | |
|   inoutres:=DosMove(p1, p2);
 | |
|   if p1<>oldp1 then
 | |
|     freemem(p1);
 | |
|   if p2<>oldp2 then
 | |
|     freemem(p2);
 | |
| end;
 | |
| 
 | |
| function do_read(h:thandle;addr:pointer;len:longint):longint;
 | |
| Var
 | |
|   T: cardinal;
 | |
| begin
 | |
| {$ifdef IODEBUG}
 | |
|   write('do_read: handle=', h, ', addr=', ptrint(addr), ', length=', len);
 | |
| {$endif}
 | |
|   InOutRes:=DosRead(H, Addr, Len, T);
 | |
|   do_read:= longint (T);
 | |
| {$ifdef IODEBUG}
 | |
|   writeln(', actual_len=', t, ', InOutRes=', InOutRes);
 | |
| {$endif}
 | |
| end;
 | |
| 
 | |
| function do_write(h:thandle;addr:pointer;len:longint) : longint;
 | |
| Var
 | |
|   T: cardinal;
 | |
| begin
 | |
| {$ifdef IODEBUG}
 | |
|   write('do_write: handle=', h, ', addr=', ptrint(addr), ', length=', len);
 | |
| {$endif}
 | |
|   InOutRes:=DosWrite(H, Addr, Len, T);
 | |
|   do_write:= longint (T);
 | |
| {$ifdef IODEBUG}
 | |
|   writeln(', actual_len=', t, ', InOutRes=', InOutRes);
 | |
| {$endif}
 | |
| end;
 | |
| 
 | |
| function Do_FilePos (Handle: THandle): int64;
 | |
| var
 | |
|   PosActual: int64;
 | |
| begin
 | |
|   InOutRes := Sys_DosSetFilePtrL (Handle, 0, 1, PosActual);
 | |
|   Do_FilePos := PosActual;
 | |
| {$ifdef IODEBUG}
 | |
|   writeln('do_filepos: handle=', Handle, ', actual_pos=', PosActual, ', InOutRes=', InOutRes);
 | |
| {$endif}
 | |
| end;
 | |
| 
 | |
| procedure Do_Seek (Handle: THandle; Pos: int64);
 | |
| var
 | |
|   PosActual: int64;
 | |
| begin
 | |
|   InOutRes:=Sys_DosSetFilePtrL(Handle, Pos, 0 {ZeroBased}, PosActual);
 | |
| {$ifdef IODEBUG}
 | |
|   writeln('do_seek: handle=', Handle, ', pos=', pos, ', actual_pos=', PosActual, ', InOutRes=', InOutRes);
 | |
| {$endif}
 | |
| end;
 | |
| 
 | |
| function Do_SeekEnd (Handle: THandle): int64;
 | |
| var
 | |
|   PosActual: int64;
 | |
| begin
 | |
|   InOutRes := Sys_DosSetFilePtrL (Handle, 0, 2 {EndBased}, PosActual);
 | |
|   Do_SeekEnd := PosActual;
 | |
| {$ifdef IODEBUG}
 | |
|   writeln('do_seekend: handle=', Handle, ', actual_pos=', PosActual, ', InOutRes=', InOutRes);
 | |
| {$endif}
 | |
| end;
 | |
| 
 | |
| function Do_FileSize (Handle: THandle): int64;
 | |
| var
 | |
|   AktFilePos: int64;
 | |
| begin
 | |
|   AktFilePos := Do_FilePos (Handle);
 | |
|   Do_FileSize := Do_SeekEnd (Handle);
 | |
|   Do_Seek (Handle, AktFilePos);
 | |
| end;
 | |
| 
 | |
| procedure Do_Truncate (Handle: THandle; Pos: int64);
 | |
| begin
 | |
|   InOutRes := Sys_DosSetFileSizeL (Handle, Pos);
 | |
|   Do_SeekEnd (Handle);
 | |
| end;
 | |
| 
 | |
| 
 | |
| const
 | |
|     FileHandleCount: cardinal = 20;
 | |
| 
 | |
| function Increase_File_Handle_Count: boolean;
 | |
| var Err: word;
 | |
|     L1: longint;
 | |
|     L2: cardinal;
 | |
| begin
 | |
|   L1 := 10;
 | |
|   if DosSetRelMaxFH (L1, L2) <> 0 then
 | |
|     Increase_File_Handle_Count := false
 | |
|   else
 | |
|     if L2 > FileHandleCount then
 | |
|     begin
 | |
|       FileHandleCount := L2;
 | |
|       Increase_File_Handle_Count := true;
 | |
|     end
 | |
|     else
 | |
|       Increase_File_Handle_Count := false;
 | |
| end;
 | |
| 
 | |
| procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
 | |
| {
 | |
|   filerec and textrec have both handle and mode as the first items so
 | |
|   they could use the same routine for opening/creating.
 | |
| 
 | |
|   when (flags and $100)   the file will be append
 | |
|   when (flags and $1000)  the file will be truncate/rewritten
 | |
|   when (flags and $10000) there is no check for close (needed for textfiles)
 | |
| }
 | |
| var
 | |
|   Action, Attrib, OpenFlags, FM: Cardinal;
 | |
|   oldp : pchar;
 | |
| begin
 | |
| 
 | |
|   // close first if opened
 | |
|   if ((flags and $10000)=0) then
 | |
|   begin
 | |
|     case filerec(f).mode of
 | |
|       fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
 | |
|       fmclosed:;
 | |
|     else
 | |
|       begin
 | |
|         inoutres:=102; {not assigned}
 | |
|         exit;
 | |
|       end;
 | |
|     end;
 | |
|   end;
 | |
| 
 | |
|   // reset file handle
 | |
|   filerec(f).handle := UnusedHandle;
 | |
| 
 | |
|   Attrib:=0;
 | |
|   OpenFlags:=0;
 | |
| 
 | |
|   // convert filesharing
 | |
|   FM := Flags and $FF and not (8);
 | |
| (* DenyNone if sharing not specified. *)
 | |
|   if FM and 112 = 0 then
 | |
|     FM := FM or 64;
 | |
|   // convert filemode to filerec modes and access mode
 | |
|   case (FM and 3) of
 | |
|     0: filerec(f).mode:=fminput;
 | |
|     1: filerec(f).mode:=fmoutput;
 | |
|     2: filerec(f).mode:=fminout;
 | |
|   end;
 | |
| 
 | |
|   if (flags and $1000)<>0 then
 | |
|     OpenFlags:=OpenFlags or 2 {doOverwrite} or 16 {doCreate} // Create/overwrite
 | |
|   else
 | |
|     OpenFlags:=OpenFlags or 1 {doOpen}; // Open existing
 | |
| 
 | |
|   // Handle Std I/O
 | |
|   if p[0]=#0 then
 | |
|   begin
 | |
|     case FileRec(f).mode of
 | |
|       fminput :
 | |
|         FileRec(f).Handle:=StdInputHandle;
 | |
|       fminout, // this is set by rewrite
 | |
|       fmoutput :
 | |
|         FileRec(f).Handle:=StdOutputHandle;
 | |
|       fmappend :
 | |
|         begin
 | |
|           FileRec(f).Handle:=StdOutputHandle;
 | |
|           FileRec(f).mode:=fmoutput; // fool fmappend
 | |
|         end;
 | |
|     end;
 | |
|     exit;
 | |
|   end;
 | |
| 
 | |
|   oldp:=p;
 | |
|   // convert unix slashes to normal slashes
 | |
|   DoDirSeparators(p,pchangeable);
 | |
|   Attrib:=32 {faArchive};
 | |
| 
 | |
|   InOutRes:=Sys_DosOpenL(p, FileRec(F).Handle, Action, 0, Attrib, OpenFlags, FM, nil);
 | |
| 
 | |
|   // If too many open files try to set more file handles and open again
 | |
|   if (InOutRes = 4) then
 | |
|     if Increase_File_Handle_Count then
 | |
|       InOutRes:=Sys_DosOpenL(p, FileRec(F).Handle, Action, 0, Attrib, OpenFlags, FM, nil);
 | |
| 
 | |
|   If InOutRes<>0 then FileRec(F).Handle:=UnusedHandle;
 | |
| 
 | |
|   // If Handle created -> make some things
 | |
|   if (FileRec(F).Handle <> UnusedHandle) then
 | |
|   begin
 | |
| 
 | |
|     // Move to end of file for Append command
 | |
|     if ((Flags and $100) <> 0) then
 | |
|     begin
 | |
|       do_seekend(FileRec(F).Handle);
 | |
|       FileRec(F).Mode := fmOutput;
 | |
|     end;
 | |
| 
 | |
|   end;
 | |
| 
 | |
|   if oldp<>p then
 | |
|     freemem(p);
 | |
| 
 | |
| {$ifdef IODEBUG}
 | |
|   writeln('do_open,', filerec(f).handle, ',', filerec(f).name, ',', filerec(f).mode, ', InOutRes=', InOutRes);
 | |
| {$endif}
 | |
| end;
 | |
| 
 | |
| function do_isdevice (Handle: THandle): boolean;
 | |
| var
 | |
|   HT, Attr: cardinal;
 | |
| begin
 | |
|   do_isdevice:=false;
 | |
|   If DosQueryHType(Handle, HT, Attr)<>0 then exit;
 | |
|   if ht=1 then do_isdevice:=true;
 | |
| end;
 | |
| {$ASMMODE ATT}
 |