123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- {
- 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.
- **********************************************************************}
- { Keep Track of open files }
- const
- max_files = 50;
- var
- openfiles : array [0..max_files-1] of boolean;
- {$ifdef SYSTEMDEBUG}
- opennames : array [0..max_files-1] of pchar;
- const
- free_closed_names : boolean = true;
- {$endif SYSTEMDEBUG}
- {****************************************************************************
- Low level File Routines
- ****************************************************************************}
- procedure do_close(handle : thandle);
- var
- regs : trealregs;
- begin
- if Handle<=4 then
- exit;
- regs.realebx:=handle;
- if handle<max_files then
- begin
- openfiles[handle]:=false;
- {$ifdef SYSTEMDEBUG}
- if assigned(opennames[handle]) and free_closed_names then
- begin
- sysfreememsize(opennames[handle],strlen(opennames[handle])+1);
- opennames[handle]:=nil;
- end;
- {$endif SYSTEMDEBUG}
- end;
- regs.realeax:=$3e00;
- sysrealintr($21,regs);
- if (regs.realflags and carryflag) <> 0 then
- GetInOutRes(lo(regs.realeax));
- end;
- procedure do_erase(p : pchar; pchangeable: boolean);
- var
- regs : trealregs;
- oldp : pchar;
- begin
- oldp:=p;
- DoDirSeparators(p,pchangeable);
- syscopytodos(longint(p),strlen(p)+1);
- regs.realedx:=tb_offset;
- regs.realds:=tb_segment;
- if LFNSupport then
- regs.realeax:=$7141
- else
- regs.realeax:=$4100;
- regs.realesi:=0;
- regs.realecx:=0;
- sysrealintr($21,regs);
- if (regs.realflags and carryflag) <> 0 then
- GetInOutRes(lo(regs.realeax));
- if p<>oldp then
- freemem(p);
- end;
- procedure do_rename(p1,p2 : pchar; p1changeable, p2changeable: boolean);
- var
- regs : trealregs;
- oldp1, oldp2 : pchar;
- begin
- oldp1:=p1;
- oldp2:=p2;
- DoDirSeparators(p1,p1changeable);
- DoDirSeparators(p2,p2changeable);
- if strlen(p1)+strlen(p2)+3>tb_size then
- HandleError(217);
- sysseg_move(get_ds,longint(p2),dos_selector,tb,strlen(p2)+1);
- sysseg_move(get_ds,longint(p1),dos_selector,tb+strlen(p2)+2,strlen(p1)+1);
- regs.realedi:=tb_offset;
- regs.realedx:=tb_offset + strlen(p2)+2;
- regs.realds:=tb_segment;
- regs.reales:=tb_segment;
- if LFNSupport then
- regs.realeax:=$7156
- else
- regs.realeax:=$5600;
- regs.realecx:=$ff; { attribute problem here ! }
- sysrealintr($21,regs);
- if (regs.realflags and carryflag) <> 0 then
- GetInOutRes(lo(regs.realeax));
- if p1<>oldp1 then
- freemem(p1);
- if p2<>oldp2 then
- freemem(p2);
- end;
- function do_write(h:thandle;addr:pointer;len : longint) : longint;
- var
- regs : trealregs;
- size,
- writesize : longint;
- begin
- writesize:=0;
- while len > 0 do
- begin
- if len>tb_size then
- size:=tb_size
- else
- size:=len;
- syscopytodos(ptrint(addr)+writesize,size);
- regs.realecx:=size;
- regs.realedx:=tb_offset;
- regs.realds:=tb_segment;
- regs.realebx:=h;
- regs.realeax:=$4000;
- sysrealintr($21,regs);
- if (regs.realflags and carryflag) <> 0 then
- begin
- GetInOutRes(lo(regs.realeax));
- exit(writesize);
- end;
- inc(writesize,lo(regs.realeax));
- dec(len,lo(regs.realeax));
- { stop when not the specified size is written }
- if lo(regs.realeax)<size then
- break;
- end;
- Do_Write:=WriteSize;
- end;
- function do_read(h:thandle;addr:pointer;len : longint) : longint;
- var
- regs : trealregs;
- size,
- readsize : longint;
- begin
- readsize:=0;
- while len > 0 do
- begin
- if len>tb_size then
- size:=tb_size
- else
- size:=len;
- regs.realecx:=size;
- regs.realedx:=tb_offset;
- regs.realds:=tb_segment;
- regs.realebx:=h;
- regs.realeax:=$3f00;
- sysrealintr($21,regs);
- if (regs.realflags and carryflag) <> 0 then
- begin
- GetInOutRes(lo(regs.realeax));
- do_read:=0;
- exit;
- end;
- syscopyfromdos(ptrint(addr)+readsize,lo(regs.realeax));
- inc(readsize,lo(regs.realeax));
- dec(len,lo(regs.realeax));
- { stop when not the specified size is read }
- if lo(regs.realeax)<size then
- break;
- end;
- do_read:=readsize;
- end;
- function do_filepos(handle : thandle) : longint;
- var
- regs : trealregs;
- begin
- regs.realebx:=handle;
- regs.realecx:=0;
- regs.realedx:=0;
- regs.realeax:=$4201;
- sysrealintr($21,regs);
- if (regs.realflags and carryflag) <> 0 then
- Begin
- GetInOutRes(lo(regs.realeax));
- do_filepos:=0;
- end
- else
- do_filepos:=lo(regs.realedx) shl 16+lo(regs.realeax);
- end;
- procedure do_seek(handle:thandle;pos : longint);
- var
- regs : trealregs;
- begin
- regs.realebx:=handle;
- regs.realecx:=pos shr 16;
- regs.realedx:=pos and $ffff;
- regs.realeax:=$4200;
- sysrealintr($21,regs);
- if (regs.realflags and carryflag) <> 0 then
- GetInOutRes(lo(regs.realeax));
- end;
- function do_seekend(handle:thandle):longint;
- var
- regs : trealregs;
- begin
- regs.realebx:=handle;
- regs.realecx:=0;
- regs.realedx:=0;
- regs.realeax:=$4202;
- sysrealintr($21,regs);
- if (regs.realflags and carryflag) <> 0 then
- Begin
- GetInOutRes(lo(regs.realeax));
- do_seekend:=0;
- end
- else
- do_seekend:=lo(regs.realedx) shl 16+lo(regs.realeax);
- end;
- function do_filesize(handle : thandle) : longint;
- var
- aktfilepos : longint;
- begin
- aktfilepos:=do_filepos(handle);
- do_filesize:=do_seekend(handle);
- do_seek(handle,aktfilepos);
- end;
- { truncate at a given position }
- procedure do_truncate (handle:thandle;pos:longint);
- var
- regs : trealregs;
- begin
- do_seek(handle,pos);
- regs.realecx:=0;
- regs.realedx:=tb_offset;
- regs.realds:=tb_segment;
- regs.realebx:=handle;
- regs.realeax:=$4000;
- sysrealintr($21,regs);
- if (regs.realflags and carryflag) <> 0 then
- GetInOutRes(lo(regs.realeax));
- end;
- const
- FileHandleCount : longint = 20;
- function Increase_file_handle_count : boolean;
- var
- regs : trealregs;
- begin
- Inc(FileHandleCount,10);
- regs.realebx:=FileHandleCount;
- regs.realeax:=$6700;
- sysrealintr($21,regs);
- if (regs.realflags and carryflag) <> 0 then
- begin
- Increase_file_handle_count:=false;
- Dec (FileHandleCount, 10);
- end
- else
- Increase_file_handle_count:=true;
- end;
- function dos_version : word;
- var
- regs : trealregs;
- begin
- regs.realeax := $3000;
- sysrealintr($21,regs);
- dos_version := regs.realeax
- 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
- regs : trealregs;
- action : longint;
- 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;
- action:=$1;
- { convert filemode to filerec modes }
- case (flags 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
- action:=$12; {create file function}
- { empty name is special }
- 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;
- DoDirSeparators(p,pchangeable);
- { real dos call }
- syscopytodos(longint(p),strlen(p)+1);
- {$ifndef RTLLITE}
- if LFNSupport then
- begin
- regs.realeax := $716c; { Use LFN Open/Create API }
- regs.realedx := action; { action if file does/doesn't exist }
- regs.realesi := tb_offset;
- regs.realebx := $2000 + (flags and $ff); { file open mode }
- end
- else
- {$endif RTLLITE}
- begin
- if (action and $00f0) <> 0 then
- regs.realeax := $3c00 { Map to Create/Replace API }
- else
- regs.realeax := $3d00 + (flags and $ff); { Map to Open_Existing API }
- regs.realedx := tb_offset;
- end;
- regs.realds := tb_segment;
- regs.realecx := $20; { file attributes }
- sysrealintr($21,regs);
- {$ifndef RTLLITE}
- if (regs.realflags and carryflag) <> 0 then
- if lo(regs.realeax)=4 then
- if Increase_file_handle_count then
- begin
- { Try again }
- if LFNSupport then
- begin
- regs.realeax := $716c; {Use LFN Open/Create API}
- regs.realedx := action; {action if file does/doesn't exist}
- regs.realesi := tb_offset;
- regs.realebx := $2000 + (flags and $ff); {file open mode}
- end
- else
- begin
- if (action and $00f0) <> 0 then
- regs.realeax := $3c00 {Map to Create/Replace API}
- else
- regs.realeax := $3d00 + (flags and $ff); {Map to Open API}
- regs.realedx := tb_offset;
- end;
- regs.realds := tb_segment;
- regs.realecx := $20; {file attributes}
- sysrealintr($21,regs);
- end;
- {$endif RTLLITE}
- if (regs.realflags and carryflag) <> 0 then
- begin
- GetInOutRes(lo(regs.realeax));
- if oldp<>p then
- freemem(p);
- FileRec(f).mode:=fmclosed;
- exit;
- end
- else
- begin
- filerec(f).handle:=lo(regs.realeax);
- {$ifndef RTLLITE}
- { for systems that have more then 20 by default ! }
- if lo(regs.realeax)>FileHandleCount then
- FileHandleCount:=lo(regs.realeax);
- {$endif RTLLITE}
- end;
- if lo(regs.realeax)<max_files then
- begin
- {$ifdef SYSTEMDEBUG}
- if openfiles[lo(regs.realeax)] and
- assigned(opennames[lo(regs.realeax)]) then
- begin
- Writeln(stderr,'file ',opennames[lo(regs.realeax)],'(',lo(regs.realeax),') not closed but handle reused!');
- sysfreememsize(opennames[lo(regs.realeax)],strlen(opennames[lo(regs.realeax)])+1);
- end;
- {$endif SYSTEMDEBUG}
- openfiles[lo(regs.realeax)]:=true;
- {$ifdef SYSTEMDEBUG}
- opennames[lo(regs.realeax)] := sysgetmem(strlen(p)+1);
- move(p^,opennames[lo(regs.realeax)]^,strlen(p)+1);
- {$endif SYSTEMDEBUG}
- end;
- { append mode }
- if ((flags and $100) <> 0) and
- (FileRec (F).Handle <> UnusedHandle) then
- begin
- do_seekend(filerec(f).handle);
- filerec(f).mode:=fmoutput; {fool fmappend}
- end;
- if oldp<>p then
- freemem(p);
- end;
- function do_isdevice(handle:THandle):boolean;
- var
- regs : trealregs;
- begin
- regs.realebx:=handle;
- regs.realeax:=$4400;
- sysrealintr($21,regs);
- do_isdevice:=(regs.realedx and $80)<>0;
- if (regs.realflags and carryflag) <> 0 then
- GetInOutRes(lo(regs.realeax));
- end;
|