FreeBASIC  0.91.0
dev_file_open.c
Go to the documentation of this file.
1 /* file device */
2 
3 #include "fb.h"
4 
18  NULL,
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  {
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 
61  /* will create the file if it doesn't exist */
62  openmask = "wb";
63  break;
64 
67 
68  switch( handle->access )
69  {
71  openmask = "wb";
72  break;
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();
87  }
88 
89  handle->size = -1;
90 
91  switch (handle->mode)
92  {
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();
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();
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();
145  }
146 
147  /* now reopen it in text-mode */
148  if( (fp = freopen( fname, openmask, fp )) == NULL )
149  {
150  FB_UNLOCK();
152  }
153 
154  fb_hSetFileBufSize( fp );
155 
156  /* skip BOM, if any */
158 
159  break;
160 
161  default:
162  /* try opening */
163  if( (fp = fopen( fname, openmask )) == NULL )
164  {
165  FB_UNLOCK();
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();
181  }
182  }
183 
184  handle->opaque = fp;
185  if (handle->access == FB_FILE_ACCESS_ANY)
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 }