FreeBASIC
0.91.0
Main Page
Data Structures
Files
File List
Globals
dev_file_open.c
Go to the documentation of this file.
1
/* file device */
2
3
#include "
fb.h
"
4
5
static
FB_FILE_HOOKS
hooks_dev_file
= {
6
fb_DevFileEof
,
7
fb_DevFileClose
,
8
fb_DevFileSeek
,
9
fb_DevFileTell
,
10
fb_DevFileRead
,
11
fb_DevFileReadWstr
,
12
fb_DevFileWrite
,
13
fb_DevFileWriteWstr
,
14
fb_DevFileLock
,
15
fb_DevFileUnlock
,
16
fb_DevFileReadLine
,
17
fb_DevFileReadLineWstr
,
18
NULL
,
19
fb_DevFileFlush
20
};
21
22
void
fb_hSetFileBufSize
( FILE *fp )
23
{
24
/* change the default buffer size */
25
setvbuf( fp,
NULL
, _IOFBF,
FB_FILE_BUFSIZE
);
26
/* Note: setvbuf() is only allowed to be called before doing any I/O
27
with that FILE handle */
28
}
29
30
int
fb_DevFileOpen
(
FB_FILE
*
handle
,
const
char
*
filename
,
size_t
fname_len )
31
{
32
FILE *fp =
NULL
;
33
char
*openmask;
34
char
*fname;
35
36
FB_LOCK
();
37
38
fname = (
char
*) alloca(fname_len + 1);
39
memcpy(fname, filename, fname_len);
40
fname[fname_len] = 0;
41
42
/* Convert directory separators to whatever the current platform supports */
43
fb_hConvertPath
( fname );
44
45
handle->
hooks
= &
hooks_dev_file
;
46
47
openmask =
NULL
;
48
switch
( handle->
mode
)
49
{
50
case
FB_FILE_MODE_APPEND
:
51
/* will create the file if it doesn't exist */
52
openmask =
"ab"
;
53
break
;
54
55
case
FB_FILE_MODE_INPUT
:
56
/* will fail if file doesn't exist */
57
openmask =
"rt"
;
58
break
;
59
60
case
FB_FILE_MODE_OUTPUT
:
61
/* will create the file if it doesn't exist */
62
openmask =
"wb"
;
63
break
;
64
65
case
FB_FILE_MODE_BINARY
:
66
case
FB_FILE_MODE_RANDOM
:
67
68
switch
( handle->
access
)
69
{
70
case
FB_FILE_ACCESS_WRITE
:
71
openmask =
"wb"
;
72
break
;
73
case
FB_FILE_ACCESS_READ
:
74
openmask =
"rb"
;
75
break
;
76
default
:
77
/* w+ would erase the contents */
78
openmask =
"r+b"
;
79
break
;
80
}
81
}
82
83
if
( openmask ==
NULL
)
84
{
85
FB_UNLOCK
();
86
return
fb_ErrorSetNum
(
FB_RTERROR_ILLEGALFUNCTIONCALL
);
87
}
88
89
handle->
size
= -1;
90
91
switch
(handle->
mode
)
92
{
93
case
FB_FILE_MODE_BINARY
:
94
case
FB_FILE_MODE_RANDOM
:
95
/* try opening */
96
if
( (fp = fopen( fname, openmask )) ==
NULL
)
97
{
98
/* if file was not found and in READ/WRITE (or ANY) mode,
99
* create it */
100
if
( handle->
access
==
FB_FILE_ACCESS_ANY
101
|| handle->
access
==
FB_FILE_ACCESS_READWRITE
)
102
{
103
fp = fopen( fname,
"w+b"
);
104
105
/* if file could not be created and in ANY mode, try opening as read-only */
106
if
( (fp ==
NULL
) && (handle->
access
==
FB_FILE_ACCESS_ANY
) ) {
107
fp = fopen( fname,
"rb"
);
108
if
(fp !=
NULL
) {
109
// don't forget to set the effective access mode ...
110
handle->
access
=
FB_FILE_ACCESS_READ
;
111
}
112
}
113
}
114
115
if
( fp ==
NULL
)
116
{
117
FB_UNLOCK
();
118
return
fb_ErrorSetNum
(
FB_RTERROR_FILENOTFOUND
);
119
}
120
}
121
122
fb_hSetFileBufSize
( fp );
123
break
;
124
125
/* special case, fseek() is unreliable in text-mode, so the file size
126
must be calculated in binary mode - bin mode can't be used for text
127
input because newlines must be converted, and EOF char (27) handled */
128
case
FB_FILE_MODE_INPUT
:
129
/* try opening in binary mode */
130
if
( (fp = fopen( fname,
"rb"
)) ==
NULL
)
131
{
132
FB_UNLOCK
();
133
return
fb_ErrorSetNum
(
FB_RTERROR_FILENOTFOUND
);
134
}
135
136
fb_hSetFileBufSize
( fp );
137
138
/* calc file size */
139
handle->
size
=
fb_DevFileGetSize
( fp,
FB_FILE_MODE_INPUT
, handle->
encod
,
FALSE
);
140
if
( handle->
size
== -1 )
141
{
142
fclose( fp );
143
FB_UNLOCK
();
144
return
fb_ErrorSetNum
(
FB_RTERROR_ILLEGALFUNCTIONCALL
);
145
}
146
147
/* now reopen it in text-mode */
148
if
( (fp = freopen( fname, openmask, fp )) ==
NULL
)
149
{
150
FB_UNLOCK
();
151
return
fb_ErrorSetNum
(
FB_RTERROR_FILENOTFOUND
);
152
}
153
154
fb_hSetFileBufSize
( fp );
155
156
/* skip BOM, if any */
157
fb_hDevFileSeekStart
( fp,
FB_FILE_MODE_INPUT
, handle->
encod
,
FALSE
);
158
159
break
;
160
161
default
:
162
/* try opening */
163
if
( (fp = fopen( fname, openmask )) ==
NULL
)
164
{
165
FB_UNLOCK
();
166
return
fb_ErrorSetNum
(
FB_RTERROR_FILENOTFOUND
);
167
}
168
169
fb_hSetFileBufSize
( fp );
170
}
171
172
if
( handle->
size
== -1 )
173
{
174
/* calc file size */
175
handle->
size
=
fb_DevFileGetSize
( fp, handle->
mode
, handle->
encod
,
TRUE
);
176
if
( handle->
size
== -1 )
177
{
178
fclose( fp );
179
FB_UNLOCK
();
180
return
fb_ErrorSetNum
(
FB_RTERROR_ILLEGALFUNCTIONCALL
);
181
}
182
}
183
184
handle->
opaque
= fp;
185
if
(handle->
access
==
FB_FILE_ACCESS_ANY
)
186
handle->
access
=
FB_FILE_ACCESS_READWRITE
;
187
188
/* We just need this for TAB(n) and SPC(n) */
189
if
( strcasecmp( fname,
"CON"
)==0 )
190
handle->
type
=
FB_FILE_TYPE_CONSOLE
;
191
192
FB_UNLOCK
();
193
194
return
fb_ErrorSetNum
(
FB_RTERROR_OK
);
195
}
rtlib
dev_file_open.c
Generated on Thu Jan 23 2014 19:40:08 for FreeBASIC by
1.8.4