summaryrefslogtreecommitdiff
path: root/rtl/sinclairql/sysfile.inc
blob: ecaf72c3f678b0efa0d1d72db08706a5f8f8e6cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
{
    This file is part of the Free Pascal run time library.
    Copyright (c) 2020 by Free Pascal development team

    Low level file functions for the Sinclair QL

    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
               All these functions can set InOutRes on errors
****************************************************************************}

{ close a file from the handle value }
procedure do_close(handle : longint);
begin
  Error2InOutRes(io_close(handle));
end;

{ delete a file, given its name }
procedure do_erase(p : pchar; pchangeable: boolean);
begin
  Error2InOutRes(io_delet(p));
end;


procedure do_rename(p1,p2 : pchar; p1changeable, p2changeable: boolean);
begin
end;


function do_write(h: longint; addr: pointer; len: longint) : longint;
var
  res: longint;
begin
  do_write:=0;
  res:=io_sstrg(h, -1, addr, len);
  if res < 0 then
    Error2InOutRes(res)
  else
    do_write:=res;
end;


function do_read(h: longint; addr: pointer; len: longint) : longint;
var
  res: longint;
begin
  do_read := 0;
  res := io_fline(h, -1, addr, len);
  if res = ERR_EF then
    res := 0;
  if res < 0 then
    Error2InOutRes(res)
  else
    do_read := res;
end;


function do_filepos(handle: longint): longint;
var
  res: longint;
  pos: longint;
begin
  do_filepos := 0;
  pos := 0;
  res := fs_posre(handle, pos);
  if res = ERR_EF then
    res := 0;
  if (res < 0) then
    Error2InOutRes(res)
  else
    do_filepos := pos;
end;


procedure do_seek(handle, pos: longint);
var
  res: longint;
begin
  res := fs_posab(handle, pos);
  if res = ERR_EF then
    res := 0;
  if (res < 0) then
    Error2InOutRes(res);
end;


{ The maximum length of a QL file is 2^31 - 64 bytes ($7FFFFFC0)
  so the maximum offset is that, minus 1. ($7fffffBF) }

const
  MAX_QL_FILE_LENGTH = $7FFFFFBF;

function do_seekend(handle: longint): longint;
var
  res: longint;
  pos: longint;
begin
  do_seekend:=-1;
  pos:=MAX_QL_FILE_LENGTH;
  res:=fs_posab(handle, pos);
  if res = ERR_EF then
    res := 0;
  if res < 0 then
    Error2InOutRes(res)
  else
    do_seekend := pos;
end;


function do_filesize(handle: longint): longint;
var
  res: longint;
  header: array [0..$39] of byte;
begin
  do_filesize := 0;
  res := fs_headr(handle, @header, $40);
  if res < 0 then
    Error2InOutRes(res)
  else
    do_filesize := plongint(@header[0])^;
end;


{ truncate at a given position }
procedure do_truncate(handle, pos: longint);
begin
  do_seek(handle, pos);
  fs_truncate(handle);
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
  res: longint;
  openMode: longint;
begin
  openMode:=Q_OPEN;

  { 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;

  { 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;

  { empty name is special }
  if p[0]=#0 then begin
    case filerec(f).mode of
      fminput :
        filerec(f).handle:=StdInputHandle;
      fmappend,
      fmoutput : begin
        filerec(f).handle:=StdOutputHandle;
        filerec(f).mode:=fmOutput; {fool fmappend}
      end;
    end;
    exit;
  end;

  { rewrite (create a new file) }
  if (flags and $1000)<>0 then openMode:=Q_OPEN_OVER;

  res:=io_open(p,openMode);

  if res < 0 then
    begin
      Error2InOutRes(res);
      filerec(f).mode:=fmClosed;
      exit;
    end
  else
    filerec(f).handle:=res;

  { 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;
end;


function do_isdevice(handle: thandle): boolean;
begin
  do_isdevice:=false;
end;