cannam@85
|
1 /*
|
cannam@85
|
2 ** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
cannam@85
|
3 ** Copyright (C) 2003 Ross Bencina <rbencina@iprimus.com.au>
|
cannam@85
|
4 **
|
cannam@85
|
5 ** This program is free software; you can redistribute it and/or modify
|
cannam@85
|
6 ** it under the terms of the GNU Lesser General Public License as published by
|
cannam@85
|
7 ** the Free Software Foundation; either version 2.1 of the License, or
|
cannam@85
|
8 ** (at your option) any later version.
|
cannam@85
|
9 **
|
cannam@85
|
10 ** This program is distributed in the hope that it will be useful,
|
cannam@85
|
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
cannam@85
|
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
cannam@85
|
13 ** GNU Lesser General Public License for more details.
|
cannam@85
|
14 **
|
cannam@85
|
15 ** You should have received a copy of the GNU Lesser General Public License
|
cannam@85
|
16 ** along with this program; if not, write to the Free Software
|
cannam@85
|
17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
cannam@85
|
18 */
|
cannam@85
|
19
|
cannam@85
|
20 /*
|
cannam@85
|
21 ** The file is split into three sections as follows:
|
cannam@85
|
22 ** - The top section (USE_WINDOWS_API == 0) for Linux, Unix and MacOSX
|
cannam@85
|
23 ** systems (including Cygwin).
|
cannam@85
|
24 ** - The middle section (USE_WINDOWS_API == 1) for microsoft windows
|
cannam@85
|
25 ** (including MinGW) using the native windows API.
|
cannam@85
|
26 ** - A legacy windows section which attempted to work around grevious
|
cannam@85
|
27 ** bugs in microsoft's POSIX implementation.
|
cannam@85
|
28 */
|
cannam@85
|
29
|
cannam@85
|
30 /*
|
cannam@85
|
31 ** The header file sfconfig.h MUST be included before the others to ensure
|
cannam@85
|
32 ** that large file support is enabled correctly on Unix systems.
|
cannam@85
|
33 */
|
cannam@85
|
34
|
cannam@85
|
35 #include "sfconfig.h"
|
cannam@85
|
36
|
cannam@85
|
37 #include <stdio.h>
|
cannam@85
|
38 #include <stdlib.h>
|
cannam@85
|
39
|
cannam@85
|
40 #if HAVE_UNISTD_H
|
cannam@85
|
41 #include <unistd.h>
|
cannam@85
|
42 #endif
|
cannam@85
|
43
|
cannam@85
|
44 #if (HAVE_DECL_S_IRGRP == 0)
|
cannam@85
|
45 #include <sf_unistd.h>
|
cannam@85
|
46 #endif
|
cannam@85
|
47
|
cannam@85
|
48 #include <string.h>
|
cannam@85
|
49 #include <fcntl.h>
|
cannam@85
|
50 #include <errno.h>
|
cannam@85
|
51 #include <sys/stat.h>
|
cannam@85
|
52
|
cannam@85
|
53 #include "sndfile.h"
|
cannam@85
|
54 #include "common.h"
|
cannam@85
|
55
|
cannam@85
|
56 #define SENSIBLE_SIZE (0x40000000)
|
cannam@85
|
57
|
cannam@85
|
58 /*
|
cannam@85
|
59 ** Neat solution to the Win32/OS2 binary file flage requirement.
|
cannam@85
|
60 ** If O_BINARY isn't already defined by the inclusion of the system
|
cannam@85
|
61 ** headers, set it to zero.
|
cannam@85
|
62 */
|
cannam@85
|
63 #ifndef O_BINARY
|
cannam@85
|
64 #define O_BINARY 0
|
cannam@85
|
65 #endif
|
cannam@85
|
66
|
cannam@85
|
67 static void psf_log_syserr (SF_PRIVATE *psf, int error) ;
|
cannam@85
|
68
|
cannam@85
|
69 #if (USE_WINDOWS_API == 0)
|
cannam@85
|
70
|
cannam@85
|
71 /*------------------------------------------------------------------------------
|
cannam@85
|
72 ** Win32 stuff at the bottom of the file. Unix and other sensible OSes here.
|
cannam@85
|
73 */
|
cannam@85
|
74
|
cannam@85
|
75 static int psf_close_fd (int fd) ;
|
cannam@85
|
76 static int psf_open_fd (PSF_FILE * pfile) ;
|
cannam@85
|
77 static sf_count_t psf_get_filelen_fd (int fd) ;
|
cannam@85
|
78
|
cannam@85
|
79 int
|
cannam@85
|
80 psf_fopen (SF_PRIVATE *psf)
|
cannam@85
|
81 {
|
cannam@85
|
82 psf->error = 0 ;
|
cannam@85
|
83 psf->file.filedes = psf_open_fd (&psf->file) ;
|
cannam@85
|
84
|
cannam@85
|
85 if (psf->file.filedes == - SFE_BAD_OPEN_MODE)
|
cannam@85
|
86 { psf->error = SFE_BAD_OPEN_MODE ;
|
cannam@85
|
87 psf->file.filedes = -1 ;
|
cannam@85
|
88 return psf->error ;
|
cannam@85
|
89 } ;
|
cannam@85
|
90
|
cannam@85
|
91 if (psf->file.filedes == -1)
|
cannam@85
|
92 psf_log_syserr (psf, errno) ;
|
cannam@85
|
93
|
cannam@85
|
94 return psf->error ;
|
cannam@85
|
95 } /* psf_fopen */
|
cannam@85
|
96
|
cannam@85
|
97 int
|
cannam@85
|
98 psf_fclose (SF_PRIVATE *psf)
|
cannam@85
|
99 { int retval ;
|
cannam@85
|
100
|
cannam@85
|
101 if (psf->virtual_io)
|
cannam@85
|
102 return 0 ;
|
cannam@85
|
103
|
cannam@85
|
104 if (psf->file.do_not_close_descriptor)
|
cannam@85
|
105 { psf->file.filedes = -1 ;
|
cannam@85
|
106 return 0 ;
|
cannam@85
|
107 } ;
|
cannam@85
|
108
|
cannam@85
|
109 if ((retval = psf_close_fd (psf->file.filedes)) == -1)
|
cannam@85
|
110 psf_log_syserr (psf, errno) ;
|
cannam@85
|
111
|
cannam@85
|
112 psf->file.filedes = -1 ;
|
cannam@85
|
113
|
cannam@85
|
114 return retval ;
|
cannam@85
|
115 } /* psf_fclose */
|
cannam@85
|
116
|
cannam@85
|
117 int
|
cannam@85
|
118 psf_open_rsrc (SF_PRIVATE *psf)
|
cannam@85
|
119 {
|
cannam@85
|
120 if (psf->rsrc.filedes > 0)
|
cannam@85
|
121 return 0 ;
|
cannam@85
|
122
|
cannam@85
|
123 /* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */
|
cannam@85
|
124 snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s/rsrc", psf->file.path.c) ;
|
cannam@85
|
125 psf->error = SFE_NO_ERROR ;
|
cannam@85
|
126 if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
|
cannam@85
|
127 { psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
|
cannam@85
|
128 if (psf->rsrclength > 0 || (psf->rsrc.mode & SFM_WRITE))
|
cannam@85
|
129 return SFE_NO_ERROR ;
|
cannam@85
|
130 psf_close_fd (psf->rsrc.filedes) ;
|
cannam@85
|
131 psf->rsrc.filedes = -1 ;
|
cannam@85
|
132 } ;
|
cannam@85
|
133
|
cannam@85
|
134 if (psf->rsrc.filedes == - SFE_BAD_OPEN_MODE)
|
cannam@85
|
135 { psf->error = SFE_BAD_OPEN_MODE ;
|
cannam@85
|
136 return psf->error ;
|
cannam@85
|
137 } ;
|
cannam@85
|
138
|
cannam@85
|
139 /*
|
cannam@85
|
140 ** Now try for a resource fork stored as a separate file in the same
|
cannam@85
|
141 ** directory, but preceded with a dot underscore.
|
cannam@85
|
142 */
|
cannam@85
|
143 snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s._%s", psf->file.dir.c, psf->file.name.c) ;
|
cannam@85
|
144 psf->error = SFE_NO_ERROR ;
|
cannam@85
|
145 if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
|
cannam@85
|
146 { psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
|
cannam@85
|
147 return SFE_NO_ERROR ;
|
cannam@85
|
148 } ;
|
cannam@85
|
149
|
cannam@85
|
150 /*
|
cannam@85
|
151 ** Now try for a resource fork stored in a separate file in the
|
cannam@85
|
152 ** .AppleDouble/ directory.
|
cannam@85
|
153 */
|
cannam@85
|
154 snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s.AppleDouble/%s", psf->file.dir.c, psf->file.name.c) ;
|
cannam@85
|
155 psf->error = SFE_NO_ERROR ;
|
cannam@85
|
156 if ((psf->rsrc.filedes = psf_open_fd (&psf->rsrc)) >= 0)
|
cannam@85
|
157 { psf->rsrclength = psf_get_filelen_fd (psf->rsrc.filedes) ;
|
cannam@85
|
158 return SFE_NO_ERROR ;
|
cannam@85
|
159 } ;
|
cannam@85
|
160
|
cannam@85
|
161 /* No resource file found. */
|
cannam@85
|
162 if (psf->rsrc.filedes == -1)
|
cannam@85
|
163 psf_log_syserr (psf, errno) ;
|
cannam@85
|
164
|
cannam@85
|
165 psf->rsrc.filedes = -1 ;
|
cannam@85
|
166
|
cannam@85
|
167 return psf->error ;
|
cannam@85
|
168 } /* psf_open_rsrc */
|
cannam@85
|
169
|
cannam@85
|
170 sf_count_t
|
cannam@85
|
171 psf_get_filelen (SF_PRIVATE *psf)
|
cannam@85
|
172 { sf_count_t filelen ;
|
cannam@85
|
173
|
cannam@85
|
174 if (psf->virtual_io)
|
cannam@85
|
175 return psf->vio.get_filelen (psf->vio_user_data) ;
|
cannam@85
|
176
|
cannam@85
|
177 filelen = psf_get_filelen_fd (psf->file.filedes) ;
|
cannam@85
|
178
|
cannam@85
|
179 if (filelen == -1)
|
cannam@85
|
180 { psf_log_syserr (psf, errno) ;
|
cannam@85
|
181 return (sf_count_t) -1 ;
|
cannam@85
|
182 } ;
|
cannam@85
|
183
|
cannam@85
|
184 if (filelen == -SFE_BAD_STAT_SIZE)
|
cannam@85
|
185 { psf->error = SFE_BAD_STAT_SIZE ;
|
cannam@85
|
186 return (sf_count_t) -1 ;
|
cannam@85
|
187 } ;
|
cannam@85
|
188
|
cannam@85
|
189 switch (psf->file.mode)
|
cannam@85
|
190 { case SFM_WRITE :
|
cannam@85
|
191 filelen = filelen - psf->fileoffset ;
|
cannam@85
|
192 break ;
|
cannam@85
|
193
|
cannam@85
|
194 case SFM_READ :
|
cannam@85
|
195 if (psf->fileoffset > 0 && psf->filelength > 0)
|
cannam@85
|
196 filelen = psf->filelength ;
|
cannam@85
|
197 break ;
|
cannam@85
|
198
|
cannam@85
|
199 case SFM_RDWR :
|
cannam@85
|
200 /*
|
cannam@85
|
201 ** Cannot open embedded files SFM_RDWR so we don't need to
|
cannam@85
|
202 ** subtract psf->fileoffset. We already have the answer we
|
cannam@85
|
203 ** need.
|
cannam@85
|
204 */
|
cannam@85
|
205 break ;
|
cannam@85
|
206
|
cannam@85
|
207 default :
|
cannam@85
|
208 /* Shouldn't be here, so return error. */
|
cannam@85
|
209 filelen = -1 ;
|
cannam@85
|
210 } ;
|
cannam@85
|
211
|
cannam@85
|
212 return filelen ;
|
cannam@85
|
213 } /* psf_get_filelen */
|
cannam@85
|
214
|
cannam@85
|
215 int
|
cannam@85
|
216 psf_close_rsrc (SF_PRIVATE *psf)
|
cannam@85
|
217 { psf_close_fd (psf->rsrc.filedes) ;
|
cannam@85
|
218 psf->rsrc.filedes = -1 ;
|
cannam@85
|
219 return 0 ;
|
cannam@85
|
220 } /* psf_close_rsrc */
|
cannam@85
|
221
|
cannam@85
|
222 int
|
cannam@85
|
223 psf_set_stdio (SF_PRIVATE *psf)
|
cannam@85
|
224 { int error = 0 ;
|
cannam@85
|
225
|
cannam@85
|
226 switch (psf->file.mode)
|
cannam@85
|
227 { case SFM_RDWR :
|
cannam@85
|
228 error = SFE_OPEN_PIPE_RDWR ;
|
cannam@85
|
229 break ;
|
cannam@85
|
230
|
cannam@85
|
231 case SFM_READ :
|
cannam@85
|
232 psf->file.filedes = 0 ;
|
cannam@85
|
233 break ;
|
cannam@85
|
234
|
cannam@85
|
235 case SFM_WRITE :
|
cannam@85
|
236 psf->file.filedes = 1 ;
|
cannam@85
|
237 break ;
|
cannam@85
|
238
|
cannam@85
|
239 default :
|
cannam@85
|
240 error = SFE_BAD_OPEN_MODE ;
|
cannam@85
|
241 break ;
|
cannam@85
|
242 } ;
|
cannam@85
|
243 psf->filelength = 0 ;
|
cannam@85
|
244
|
cannam@85
|
245 return error ;
|
cannam@85
|
246 } /* psf_set_stdio */
|
cannam@85
|
247
|
cannam@85
|
248 void
|
cannam@85
|
249 psf_set_file (SF_PRIVATE *psf, int fd)
|
cannam@85
|
250 { psf->file.filedes = fd ;
|
cannam@85
|
251 } /* psf_set_file */
|
cannam@85
|
252
|
cannam@85
|
253 int
|
cannam@85
|
254 psf_file_valid (SF_PRIVATE *psf)
|
cannam@85
|
255 { return (psf->file.filedes >= 0) ? SF_TRUE : SF_FALSE ;
|
cannam@85
|
256 } /* psf_set_file */
|
cannam@85
|
257
|
cannam@85
|
258 sf_count_t
|
cannam@85
|
259 psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
|
cannam@85
|
260 { sf_count_t current_pos, new_position ;
|
cannam@85
|
261
|
cannam@85
|
262 if (psf->virtual_io)
|
cannam@85
|
263 return psf->vio.seek (offset, whence, psf->vio_user_data) ;
|
cannam@85
|
264
|
cannam@85
|
265 current_pos = psf_ftell (psf) ;
|
cannam@85
|
266
|
cannam@85
|
267 switch (whence)
|
cannam@85
|
268 { case SEEK_SET :
|
cannam@85
|
269 offset += psf->fileoffset ;
|
cannam@85
|
270 break ;
|
cannam@85
|
271
|
cannam@85
|
272 case SEEK_END :
|
cannam@85
|
273 if (psf->file.mode == SFM_WRITE)
|
cannam@85
|
274 { new_position = lseek (psf->file.filedes, offset, whence) ;
|
cannam@85
|
275
|
cannam@85
|
276 if (new_position < 0)
|
cannam@85
|
277 psf_log_syserr (psf, errno) ;
|
cannam@85
|
278
|
cannam@85
|
279 return new_position - psf->fileoffset ;
|
cannam@85
|
280 } ;
|
cannam@85
|
281
|
cannam@85
|
282 /* Transform SEEK_END into a SEEK_SET, ie find the file
|
cannam@85
|
283 ** length add the requested offset (should be <= 0) to
|
cannam@85
|
284 ** get the offset wrt the start of file.
|
cannam@85
|
285 */
|
cannam@85
|
286 whence = SEEK_SET ;
|
cannam@85
|
287 offset = lseek (psf->file.filedes, 0, SEEK_END) + offset ;
|
cannam@85
|
288 break ;
|
cannam@85
|
289
|
cannam@85
|
290 case SEEK_CUR :
|
cannam@85
|
291 /* Translate a SEEK_CUR into a SEEK_SET. */
|
cannam@85
|
292 offset += current_pos ;
|
cannam@85
|
293 whence = SEEK_SET ;
|
cannam@85
|
294 break ;
|
cannam@85
|
295
|
cannam@85
|
296 default :
|
cannam@85
|
297 /* We really should not be here. */
|
cannam@85
|
298 psf_log_printf (psf, "psf_fseek : whence is %d *****.\n", whence) ;
|
cannam@85
|
299 return 0 ;
|
cannam@85
|
300 } ;
|
cannam@85
|
301
|
cannam@85
|
302 if (current_pos != offset)
|
cannam@85
|
303 new_position = lseek (psf->file.filedes, offset, whence) ;
|
cannam@85
|
304 else
|
cannam@85
|
305 new_position = offset ;
|
cannam@85
|
306
|
cannam@85
|
307 if (new_position < 0)
|
cannam@85
|
308 psf_log_syserr (psf, errno) ;
|
cannam@85
|
309
|
cannam@85
|
310 new_position -= psf->fileoffset ;
|
cannam@85
|
311
|
cannam@85
|
312 return new_position ;
|
cannam@85
|
313 } /* psf_fseek */
|
cannam@85
|
314
|
cannam@85
|
315 sf_count_t
|
cannam@85
|
316 psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
cannam@85
|
317 { sf_count_t total = 0 ;
|
cannam@85
|
318 ssize_t count ;
|
cannam@85
|
319
|
cannam@85
|
320 if (psf->virtual_io)
|
cannam@85
|
321 return psf->vio.read (ptr, bytes*items, psf->vio_user_data) / bytes ;
|
cannam@85
|
322
|
cannam@85
|
323 items *= bytes ;
|
cannam@85
|
324
|
cannam@85
|
325 /* Do this check after the multiplication above. */
|
cannam@85
|
326 if (items <= 0)
|
cannam@85
|
327 return 0 ;
|
cannam@85
|
328
|
cannam@85
|
329 while (items > 0)
|
cannam@85
|
330 { /* Break the read down to a sensible size. */
|
cannam@85
|
331 count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ;
|
cannam@85
|
332
|
cannam@85
|
333 count = read (psf->file.filedes, ((char*) ptr) + total, (size_t) count) ;
|
cannam@85
|
334
|
cannam@85
|
335 if (count == -1)
|
cannam@85
|
336 { if (errno == EINTR)
|
cannam@85
|
337 continue ;
|
cannam@85
|
338
|
cannam@85
|
339 psf_log_syserr (psf, errno) ;
|
cannam@85
|
340 break ;
|
cannam@85
|
341 } ;
|
cannam@85
|
342
|
cannam@85
|
343 if (count == 0)
|
cannam@85
|
344 break ;
|
cannam@85
|
345
|
cannam@85
|
346 total += count ;
|
cannam@85
|
347 items -= count ;
|
cannam@85
|
348 } ;
|
cannam@85
|
349
|
cannam@85
|
350 if (psf->is_pipe)
|
cannam@85
|
351 psf->pipeoffset += total ;
|
cannam@85
|
352
|
cannam@85
|
353 return total / bytes ;
|
cannam@85
|
354 } /* psf_fread */
|
cannam@85
|
355
|
cannam@85
|
356 sf_count_t
|
cannam@85
|
357 psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
cannam@85
|
358 { sf_count_t total = 0 ;
|
cannam@85
|
359 ssize_t count ;
|
cannam@85
|
360
|
cannam@85
|
361 if (psf->virtual_io)
|
cannam@85
|
362 return psf->vio.write (ptr, bytes*items, psf->vio_user_data) / bytes ;
|
cannam@85
|
363
|
cannam@85
|
364 items *= bytes ;
|
cannam@85
|
365
|
cannam@85
|
366 /* Do this check after the multiplication above. */
|
cannam@85
|
367 if (items <= 0)
|
cannam@85
|
368 return 0 ;
|
cannam@85
|
369
|
cannam@85
|
370 while (items > 0)
|
cannam@85
|
371 { /* Break the writes down to a sensible size. */
|
cannam@85
|
372 count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : items ;
|
cannam@85
|
373
|
cannam@85
|
374 count = write (psf->file.filedes, ((const char*) ptr) + total, count) ;
|
cannam@85
|
375
|
cannam@85
|
376 if (count == -1)
|
cannam@85
|
377 { if (errno == EINTR)
|
cannam@85
|
378 continue ;
|
cannam@85
|
379
|
cannam@85
|
380 psf_log_syserr (psf, errno) ;
|
cannam@85
|
381 break ;
|
cannam@85
|
382 } ;
|
cannam@85
|
383
|
cannam@85
|
384 if (count == 0)
|
cannam@85
|
385 break ;
|
cannam@85
|
386
|
cannam@85
|
387 total += count ;
|
cannam@85
|
388 items -= count ;
|
cannam@85
|
389 } ;
|
cannam@85
|
390
|
cannam@85
|
391 if (psf->is_pipe)
|
cannam@85
|
392 psf->pipeoffset += total ;
|
cannam@85
|
393
|
cannam@85
|
394 return total / bytes ;
|
cannam@85
|
395 } /* psf_fwrite */
|
cannam@85
|
396
|
cannam@85
|
397 sf_count_t
|
cannam@85
|
398 psf_ftell (SF_PRIVATE *psf)
|
cannam@85
|
399 { sf_count_t pos ;
|
cannam@85
|
400
|
cannam@85
|
401 if (psf->virtual_io)
|
cannam@85
|
402 return psf->vio.tell (psf->vio_user_data) ;
|
cannam@85
|
403
|
cannam@85
|
404 if (psf->is_pipe)
|
cannam@85
|
405 return psf->pipeoffset ;
|
cannam@85
|
406
|
cannam@85
|
407 pos = lseek (psf->file.filedes, 0, SEEK_CUR) ;
|
cannam@85
|
408
|
cannam@85
|
409 if (pos == ((sf_count_t) -1))
|
cannam@85
|
410 { psf_log_syserr (psf, errno) ;
|
cannam@85
|
411 return -1 ;
|
cannam@85
|
412 } ;
|
cannam@85
|
413
|
cannam@85
|
414 return pos - psf->fileoffset ;
|
cannam@85
|
415 } /* psf_ftell */
|
cannam@85
|
416
|
cannam@85
|
417 static int
|
cannam@85
|
418 psf_close_fd (int fd)
|
cannam@85
|
419 { int retval ;
|
cannam@85
|
420
|
cannam@85
|
421 if (fd < 0)
|
cannam@85
|
422 return 0 ;
|
cannam@85
|
423
|
cannam@85
|
424 while ((retval = close (fd)) == -1 && errno == EINTR)
|
cannam@85
|
425 /* Do nothing. */ ;
|
cannam@85
|
426
|
cannam@85
|
427 return retval ;
|
cannam@85
|
428 } /* psf_close_fd */
|
cannam@85
|
429
|
cannam@85
|
430 sf_count_t
|
cannam@85
|
431 psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf)
|
cannam@85
|
432 { sf_count_t k = 0 ;
|
cannam@85
|
433 sf_count_t count ;
|
cannam@85
|
434
|
cannam@85
|
435 while (k < bufsize - 1)
|
cannam@85
|
436 { count = read (psf->file.filedes, &(buffer [k]), 1) ;
|
cannam@85
|
437
|
cannam@85
|
438 if (count == -1)
|
cannam@85
|
439 { if (errno == EINTR)
|
cannam@85
|
440 continue ;
|
cannam@85
|
441
|
cannam@85
|
442 psf_log_syserr (psf, errno) ;
|
cannam@85
|
443 break ;
|
cannam@85
|
444 } ;
|
cannam@85
|
445
|
cannam@85
|
446 if (count == 0 || buffer [k++] == '\n')
|
cannam@85
|
447 break ;
|
cannam@85
|
448 } ;
|
cannam@85
|
449
|
cannam@85
|
450 buffer [k] = 0 ;
|
cannam@85
|
451
|
cannam@85
|
452 return k ;
|
cannam@85
|
453 } /* psf_fgets */
|
cannam@85
|
454
|
cannam@85
|
455 int
|
cannam@85
|
456 psf_is_pipe (SF_PRIVATE *psf)
|
cannam@85
|
457 { struct stat statbuf ;
|
cannam@85
|
458
|
cannam@85
|
459 if (psf->virtual_io)
|
cannam@85
|
460 return SF_FALSE ;
|
cannam@85
|
461
|
cannam@85
|
462 if (fstat (psf->file.filedes, &statbuf) == -1)
|
cannam@85
|
463 { psf_log_syserr (psf, errno) ;
|
cannam@85
|
464 /* Default to maximum safety. */
|
cannam@85
|
465 return SF_TRUE ;
|
cannam@85
|
466 } ;
|
cannam@85
|
467
|
cannam@96
|
468 if (S_ISFIFO (statbuf.st_mode) /*|| S_ISSOCK (statbuf.st_mode) */)
|
cannam@85
|
469 return SF_TRUE ;
|
cannam@85
|
470
|
cannam@85
|
471 return SF_FALSE ;
|
cannam@85
|
472 } /* psf_is_pipe */
|
cannam@85
|
473
|
cannam@85
|
474 static sf_count_t
|
cannam@85
|
475 psf_get_filelen_fd (int fd)
|
cannam@85
|
476 { struct stat statbuf ;
|
cannam@85
|
477
|
cannam@85
|
478 /*
|
cannam@85
|
479 ** Sanity check.
|
cannam@85
|
480 ** If everything is OK, this will be optimised out.
|
cannam@85
|
481 */
|
cannam@85
|
482 if (sizeof (statbuf.st_size) == 4 && sizeof (sf_count_t) == 8)
|
cannam@85
|
483 return (sf_count_t) -SFE_BAD_STAT_SIZE ;
|
cannam@85
|
484
|
cannam@85
|
485 if (fstat (fd, &statbuf) == -1)
|
cannam@85
|
486 return (sf_count_t) -1 ;
|
cannam@85
|
487
|
cannam@85
|
488 return statbuf.st_size ;
|
cannam@85
|
489 } /* psf_get_filelen_fd */
|
cannam@85
|
490
|
cannam@85
|
491 int
|
cannam@85
|
492 psf_ftruncate (SF_PRIVATE *psf, sf_count_t len)
|
cannam@85
|
493 { int retval ;
|
cannam@85
|
494
|
cannam@85
|
495 /* Returns 0 on success, non-zero on failure. */
|
cannam@85
|
496 if (len < 0)
|
cannam@85
|
497 return -1 ;
|
cannam@85
|
498
|
cannam@85
|
499 if ((sizeof (off_t) < sizeof (sf_count_t)) && len > 0x7FFFFFFF)
|
cannam@85
|
500 return -1 ;
|
cannam@85
|
501
|
cannam@85
|
502 retval = ftruncate (psf->file.filedes, len) ;
|
cannam@85
|
503
|
cannam@85
|
504 if (retval == -1)
|
cannam@85
|
505 psf_log_syserr (psf, errno) ;
|
cannam@85
|
506
|
cannam@85
|
507 return retval ;
|
cannam@85
|
508 } /* psf_ftruncate */
|
cannam@85
|
509
|
cannam@85
|
510 void
|
cannam@85
|
511 psf_init_files (SF_PRIVATE *psf)
|
cannam@85
|
512 { psf->file.filedes = -1 ;
|
cannam@85
|
513 psf->rsrc.filedes = -1 ;
|
cannam@85
|
514 psf->file.savedes = -1 ;
|
cannam@85
|
515 } /* psf_init_files */
|
cannam@85
|
516
|
cannam@85
|
517 void
|
cannam@85
|
518 psf_use_rsrc (SF_PRIVATE *psf, int on_off)
|
cannam@85
|
519 {
|
cannam@85
|
520 if (on_off)
|
cannam@85
|
521 { if (psf->file.filedes != psf->rsrc.filedes)
|
cannam@85
|
522 { psf->file.savedes = psf->file.filedes ;
|
cannam@85
|
523 psf->file.filedes = psf->rsrc.filedes ;
|
cannam@85
|
524 } ;
|
cannam@85
|
525 }
|
cannam@85
|
526 else if (psf->file.filedes == psf->rsrc.filedes)
|
cannam@85
|
527 psf->file.filedes = psf->file.savedes ;
|
cannam@85
|
528
|
cannam@85
|
529 return ;
|
cannam@85
|
530 } /* psf_use_rsrc */
|
cannam@85
|
531
|
cannam@85
|
532 static int
|
cannam@85
|
533 psf_open_fd (PSF_FILE * pfile)
|
cannam@85
|
534 { int fd, oflag, mode ;
|
cannam@85
|
535
|
cannam@85
|
536 /*
|
cannam@85
|
537 ** Sanity check. If everything is OK, this test and the printfs will
|
cannam@85
|
538 ** be optimised out. This is meant to catch the problems caused by
|
cannam@85
|
539 ** "sfconfig.h" being included after <stdio.h>.
|
cannam@85
|
540 */
|
cannam@85
|
541 if (sizeof (off_t) != sizeof (sf_count_t))
|
cannam@85
|
542 { puts ("\n\n*** Fatal error : sizeof (off_t) != sizeof (sf_count_t)") ;
|
cannam@85
|
543 puts ("*** This means that libsndfile was not configured correctly.\n") ;
|
cannam@85
|
544 exit (1) ;
|
cannam@85
|
545 } ;
|
cannam@85
|
546
|
cannam@85
|
547 switch (pfile->mode)
|
cannam@85
|
548 { case SFM_READ :
|
cannam@85
|
549 oflag = O_RDONLY | O_BINARY ;
|
cannam@85
|
550 mode = 0 ;
|
cannam@85
|
551 break ;
|
cannam@85
|
552
|
cannam@85
|
553 case SFM_WRITE :
|
cannam@85
|
554 oflag = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
|
cannam@85
|
555 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
|
cannam@85
|
556 break ;
|
cannam@85
|
557
|
cannam@85
|
558 case SFM_RDWR :
|
cannam@85
|
559 oflag = O_RDWR | O_CREAT | O_BINARY ;
|
cannam@85
|
560 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ;
|
cannam@85
|
561 break ;
|
cannam@85
|
562
|
cannam@85
|
563 default :
|
cannam@85
|
564 return - SFE_BAD_OPEN_MODE ;
|
cannam@85
|
565 break ;
|
cannam@85
|
566 } ;
|
cannam@85
|
567
|
cannam@85
|
568 if (mode == 0)
|
cannam@85
|
569 fd = open (pfile->path.c, oflag) ;
|
cannam@85
|
570 else
|
cannam@85
|
571 fd = open (pfile->path.c, oflag, mode) ;
|
cannam@85
|
572
|
cannam@85
|
573 return fd ;
|
cannam@85
|
574 } /* psf_open_fd */
|
cannam@85
|
575
|
cannam@85
|
576 static void
|
cannam@85
|
577 psf_log_syserr (SF_PRIVATE *psf, int error)
|
cannam@85
|
578 {
|
cannam@85
|
579 /* Only log an error if no error has been set yet. */
|
cannam@85
|
580 if (psf->error == 0)
|
cannam@85
|
581 { psf->error = SFE_SYSTEM ;
|
cannam@85
|
582 snprintf (psf->syserr, sizeof (psf->syserr), "System error : %s.", strerror (error)) ;
|
cannam@85
|
583 } ;
|
cannam@85
|
584
|
cannam@85
|
585 return ;
|
cannam@85
|
586 } /* psf_log_syserr */
|
cannam@85
|
587
|
cannam@85
|
588 void
|
cannam@85
|
589 psf_fsync (SF_PRIVATE *psf)
|
cannam@85
|
590 {
|
cannam@85
|
591 #if HAVE_FSYNC
|
cannam@85
|
592 if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
cannam@85
|
593 fsync (psf->file.filedes) ;
|
cannam@85
|
594 #else
|
cannam@85
|
595 psf = NULL ;
|
cannam@85
|
596 #endif
|
cannam@85
|
597 } /* psf_fsync */
|
cannam@85
|
598
|
cannam@85
|
599 #elif USE_WINDOWS_API
|
cannam@85
|
600
|
cannam@85
|
601 /* Win32 file i/o functions implemented using native Win32 API */
|
cannam@85
|
602
|
cannam@85
|
603 #include <windows.h>
|
cannam@85
|
604 #include <io.h>
|
cannam@85
|
605
|
cannam@85
|
606 static int psf_close_handle (HANDLE handle) ;
|
cannam@85
|
607 static HANDLE psf_open_handle (PSF_FILE * pfile) ;
|
cannam@85
|
608 static sf_count_t psf_get_filelen_handle (HANDLE handle) ;
|
cannam@85
|
609
|
cannam@85
|
610 /* USE_WINDOWS_API */ int
|
cannam@85
|
611 psf_fopen (SF_PRIVATE *psf)
|
cannam@85
|
612 {
|
cannam@85
|
613 psf->error = 0 ;
|
cannam@85
|
614 psf->file.handle = psf_open_handle (&psf->file) ;
|
cannam@85
|
615
|
cannam@85
|
616 if (psf->file.handle == NULL)
|
cannam@85
|
617 psf_log_syserr (psf, GetLastError ()) ;
|
cannam@85
|
618
|
cannam@85
|
619 return psf->error ;
|
cannam@85
|
620 } /* psf_fopen */
|
cannam@85
|
621
|
cannam@85
|
622 /* USE_WINDOWS_API */ int
|
cannam@85
|
623 psf_fclose (SF_PRIVATE *psf)
|
cannam@85
|
624 { int retval ;
|
cannam@85
|
625
|
cannam@85
|
626 if (psf->virtual_io)
|
cannam@85
|
627 return 0 ;
|
cannam@85
|
628
|
cannam@85
|
629 if (psf->file.do_not_close_descriptor)
|
cannam@85
|
630 { psf->file.handle = NULL ;
|
cannam@85
|
631 return 0 ;
|
cannam@85
|
632 } ;
|
cannam@85
|
633
|
cannam@85
|
634 if ((retval = psf_close_handle (psf->file.handle)) == -1)
|
cannam@85
|
635 psf_log_syserr (psf, GetLastError ()) ;
|
cannam@85
|
636
|
cannam@85
|
637 psf->file.handle = NULL ;
|
cannam@85
|
638
|
cannam@85
|
639 return retval ;
|
cannam@85
|
640 } /* psf_fclose */
|
cannam@85
|
641
|
cannam@85
|
642 /* USE_WINDOWS_API */ int
|
cannam@85
|
643 psf_open_rsrc (SF_PRIVATE *psf)
|
cannam@85
|
644 {
|
cannam@85
|
645 if (psf->rsrc.handle != NULL)
|
cannam@85
|
646 return 0 ;
|
cannam@85
|
647
|
cannam@85
|
648 /* Test for MacOSX style resource fork on HPFS or HPFS+ filesystems. */
|
cannam@85
|
649 snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s/rsrc", psf->file.path.c) ;
|
cannam@85
|
650 psf->error = SFE_NO_ERROR ;
|
cannam@85
|
651 if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL)
|
cannam@85
|
652 { psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ;
|
cannam@85
|
653 return SFE_NO_ERROR ;
|
cannam@85
|
654 } ;
|
cannam@85
|
655
|
cannam@85
|
656 /*
|
cannam@85
|
657 ** Now try for a resource fork stored as a separate file in the same
|
cannam@85
|
658 ** directory, but preceded with a dot underscore.
|
cannam@85
|
659 */
|
cannam@85
|
660 snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s._%s", psf->file.dir.c, psf->file.name.c) ;
|
cannam@85
|
661 psf->error = SFE_NO_ERROR ;
|
cannam@85
|
662 if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL)
|
cannam@85
|
663 { psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ;
|
cannam@85
|
664 return SFE_NO_ERROR ;
|
cannam@85
|
665 } ;
|
cannam@85
|
666
|
cannam@85
|
667 /*
|
cannam@85
|
668 ** Now try for a resource fork stored in a separate file in the
|
cannam@85
|
669 ** .AppleDouble/ directory.
|
cannam@85
|
670 */
|
cannam@85
|
671 snprintf (psf->rsrc.path.c, sizeof (psf->rsrc.path.c), "%s.AppleDouble/%s", psf->file.dir.c, psf->file.name.c) ;
|
cannam@85
|
672 psf->error = SFE_NO_ERROR ;
|
cannam@85
|
673 if ((psf->rsrc.handle = psf_open_handle (&psf->rsrc)) != NULL)
|
cannam@85
|
674 { psf->rsrclength = psf_get_filelen_handle (psf->rsrc.handle) ;
|
cannam@85
|
675 return SFE_NO_ERROR ;
|
cannam@85
|
676 } ;
|
cannam@85
|
677
|
cannam@85
|
678 /* No resource file found. */
|
cannam@85
|
679 if (psf->rsrc.handle == NULL)
|
cannam@85
|
680 psf_log_syserr (psf, GetLastError ()) ;
|
cannam@85
|
681
|
cannam@85
|
682 psf->rsrc.handle = NULL ;
|
cannam@85
|
683
|
cannam@85
|
684 return psf->error ;
|
cannam@85
|
685 } /* psf_open_rsrc */
|
cannam@85
|
686
|
cannam@85
|
687 /* USE_WINDOWS_API */ sf_count_t
|
cannam@85
|
688 psf_get_filelen (SF_PRIVATE *psf)
|
cannam@85
|
689 { sf_count_t filelen ;
|
cannam@85
|
690
|
cannam@85
|
691 if (psf->virtual_io)
|
cannam@85
|
692 return psf->vio.get_filelen (psf->vio_user_data) ;
|
cannam@85
|
693
|
cannam@85
|
694 filelen = psf_get_filelen_handle (psf->file.handle) ;
|
cannam@85
|
695
|
cannam@85
|
696 if (filelen == -1)
|
cannam@85
|
697 { psf_log_syserr (psf, errno) ;
|
cannam@85
|
698 return (sf_count_t) -1 ;
|
cannam@85
|
699 } ;
|
cannam@85
|
700
|
cannam@85
|
701 if (filelen == -SFE_BAD_STAT_SIZE)
|
cannam@85
|
702 { psf->error = SFE_BAD_STAT_SIZE ;
|
cannam@85
|
703 return (sf_count_t) -1 ;
|
cannam@85
|
704 } ;
|
cannam@85
|
705
|
cannam@85
|
706 switch (psf->file.mode)
|
cannam@85
|
707 { case SFM_WRITE :
|
cannam@85
|
708 filelen = filelen - psf->fileoffset ;
|
cannam@85
|
709 break ;
|
cannam@85
|
710
|
cannam@85
|
711 case SFM_READ :
|
cannam@85
|
712 if (psf->fileoffset > 0 && psf->filelength > 0)
|
cannam@85
|
713 filelen = psf->filelength ;
|
cannam@85
|
714 break ;
|
cannam@85
|
715
|
cannam@85
|
716 case SFM_RDWR :
|
cannam@85
|
717 /*
|
cannam@85
|
718 ** Cannot open embedded files SFM_RDWR so we don't need to
|
cannam@85
|
719 ** subtract psf->fileoffset. We already have the answer we
|
cannam@85
|
720 ** need.
|
cannam@85
|
721 */
|
cannam@85
|
722 break ;
|
cannam@85
|
723
|
cannam@85
|
724 default :
|
cannam@85
|
725 /* Shouldn't be here, so return error. */
|
cannam@85
|
726 filelen = -1 ;
|
cannam@85
|
727 } ;
|
cannam@85
|
728
|
cannam@85
|
729 return filelen ;
|
cannam@85
|
730 } /* psf_get_filelen */
|
cannam@85
|
731
|
cannam@85
|
732 /* USE_WINDOWS_API */ void
|
cannam@85
|
733 psf_init_files (SF_PRIVATE *psf)
|
cannam@85
|
734 { psf->file.handle = NULL ;
|
cannam@85
|
735 psf->rsrc.handle = NULL ;
|
cannam@85
|
736 psf->file.hsaved = NULL ;
|
cannam@85
|
737 } /* psf_init_files */
|
cannam@85
|
738
|
cannam@85
|
739 /* USE_WINDOWS_API */ void
|
cannam@85
|
740 psf_use_rsrc (SF_PRIVATE *psf, int on_off)
|
cannam@85
|
741 {
|
cannam@85
|
742 if (on_off)
|
cannam@85
|
743 { if (psf->file.handle != psf->rsrc.handle)
|
cannam@85
|
744 { psf->file.hsaved = psf->file.handle ;
|
cannam@85
|
745 psf->file.handle = psf->rsrc.handle ;
|
cannam@85
|
746 } ;
|
cannam@85
|
747 }
|
cannam@85
|
748 else if (psf->file.handle == psf->rsrc.handle)
|
cannam@85
|
749 psf->file.handle = psf->file.hsaved ;
|
cannam@85
|
750
|
cannam@85
|
751 return ;
|
cannam@85
|
752 } /* psf_use_rsrc */
|
cannam@85
|
753
|
cannam@85
|
754 /* USE_WINDOWS_API */ static HANDLE
|
cannam@85
|
755 psf_open_handle (PSF_FILE * pfile)
|
cannam@85
|
756 { DWORD dwDesiredAccess ;
|
cannam@85
|
757 DWORD dwShareMode ;
|
cannam@85
|
758 DWORD dwCreationDistribution ;
|
cannam@85
|
759 HANDLE handle ;
|
cannam@85
|
760
|
cannam@85
|
761 switch (pfile->mode)
|
cannam@85
|
762 { case SFM_READ :
|
cannam@85
|
763 dwDesiredAccess = GENERIC_READ ;
|
cannam@85
|
764 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE ;
|
cannam@85
|
765 dwCreationDistribution = OPEN_EXISTING ;
|
cannam@85
|
766 break ;
|
cannam@85
|
767
|
cannam@85
|
768 case SFM_WRITE :
|
cannam@85
|
769 dwDesiredAccess = GENERIC_WRITE ;
|
cannam@85
|
770 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE ;
|
cannam@85
|
771 dwCreationDistribution = CREATE_ALWAYS ;
|
cannam@85
|
772 break ;
|
cannam@85
|
773
|
cannam@85
|
774 case SFM_RDWR :
|
cannam@85
|
775 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE ;
|
cannam@85
|
776 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE ;
|
cannam@85
|
777 dwCreationDistribution = OPEN_ALWAYS ;
|
cannam@85
|
778 break ;
|
cannam@85
|
779
|
cannam@85
|
780 default :
|
cannam@85
|
781 return NULL ;
|
cannam@85
|
782 } ;
|
cannam@85
|
783
|
cannam@85
|
784 if (pfile->use_wchar)
|
cannam@85
|
785 handle = CreateFileW (
|
cannam@85
|
786 pfile->path.wc, /* pointer to name of the file */
|
cannam@85
|
787 dwDesiredAccess, /* access (read-write) mode */
|
cannam@85
|
788 dwShareMode, /* share mode */
|
cannam@85
|
789 0, /* pointer to security attributes */
|
cannam@85
|
790 dwCreationDistribution, /* how to create */
|
cannam@85
|
791 FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */
|
cannam@85
|
792 NULL /* handle to file with attributes to copy */
|
cannam@85
|
793 ) ;
|
cannam@85
|
794 else
|
cannam@85
|
795 handle = CreateFile (
|
cannam@85
|
796 pfile->path.c, /* pointer to name of the file */
|
cannam@85
|
797 dwDesiredAccess, /* access (read-write) mode */
|
cannam@85
|
798 dwShareMode, /* share mode */
|
cannam@85
|
799 0, /* pointer to security attributes */
|
cannam@85
|
800 dwCreationDistribution, /* how to create */
|
cannam@85
|
801 FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */
|
cannam@85
|
802 NULL /* handle to file with attributes to copy */
|
cannam@85
|
803 ) ;
|
cannam@85
|
804
|
cannam@85
|
805 if (handle == INVALID_HANDLE_VALUE)
|
cannam@85
|
806 return NULL ;
|
cannam@85
|
807
|
cannam@85
|
808 return handle ;
|
cannam@85
|
809 } /* psf_open_handle */
|
cannam@85
|
810
|
cannam@85
|
811 /* USE_WINDOWS_API */ static void
|
cannam@85
|
812 psf_log_syserr (SF_PRIVATE *psf, int error)
|
cannam@85
|
813 { LPVOID lpMsgBuf ;
|
cannam@85
|
814
|
cannam@85
|
815 /* Only log an error if no error has been set yet. */
|
cannam@85
|
816 if (psf->error == 0)
|
cannam@85
|
817 { psf->error = SFE_SYSTEM ;
|
cannam@85
|
818
|
cannam@85
|
819 FormatMessage (
|
cannam@85
|
820 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
cannam@85
|
821 NULL,
|
cannam@85
|
822 error,
|
cannam@85
|
823 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
|
cannam@85
|
824 (LPTSTR) &lpMsgBuf,
|
cannam@85
|
825 0,
|
cannam@85
|
826 NULL
|
cannam@85
|
827 ) ;
|
cannam@85
|
828
|
cannam@85
|
829 snprintf (psf->syserr, sizeof (psf->syserr), "System error : %s", (char*) lpMsgBuf) ;
|
cannam@85
|
830 LocalFree (lpMsgBuf) ;
|
cannam@85
|
831 } ;
|
cannam@85
|
832
|
cannam@85
|
833 return ;
|
cannam@85
|
834 } /* psf_log_syserr */
|
cannam@85
|
835
|
cannam@85
|
836
|
cannam@85
|
837 /* USE_WINDOWS_API */ int
|
cannam@85
|
838 psf_close_rsrc (SF_PRIVATE *psf)
|
cannam@85
|
839 { psf_close_handle (psf->rsrc.handle) ;
|
cannam@85
|
840 psf->rsrc.handle = NULL ;
|
cannam@85
|
841 return 0 ;
|
cannam@85
|
842 } /* psf_close_rsrc */
|
cannam@85
|
843
|
cannam@85
|
844
|
cannam@85
|
845 /* USE_WINDOWS_API */ int
|
cannam@85
|
846 psf_set_stdio (SF_PRIVATE *psf)
|
cannam@85
|
847 { HANDLE handle = NULL ;
|
cannam@85
|
848 int error = 0 ;
|
cannam@85
|
849
|
cannam@85
|
850 switch (psf->file.mode)
|
cannam@85
|
851 { case SFM_RDWR :
|
cannam@85
|
852 error = SFE_OPEN_PIPE_RDWR ;
|
cannam@85
|
853 break ;
|
cannam@85
|
854
|
cannam@85
|
855 case SFM_READ :
|
cannam@85
|
856 handle = GetStdHandle (STD_INPUT_HANDLE) ;
|
cannam@85
|
857 psf->file.do_not_close_descriptor = 1 ;
|
cannam@85
|
858 break ;
|
cannam@85
|
859
|
cannam@85
|
860 case SFM_WRITE :
|
cannam@85
|
861 handle = GetStdHandle (STD_OUTPUT_HANDLE) ;
|
cannam@85
|
862 psf->file.do_not_close_descriptor = 1 ;
|
cannam@85
|
863 break ;
|
cannam@85
|
864
|
cannam@85
|
865 default :
|
cannam@85
|
866 error = SFE_BAD_OPEN_MODE ;
|
cannam@85
|
867 break ;
|
cannam@85
|
868 } ;
|
cannam@85
|
869
|
cannam@85
|
870 psf->file.handle = handle ;
|
cannam@85
|
871 psf->filelength = 0 ;
|
cannam@85
|
872
|
cannam@85
|
873 return error ;
|
cannam@85
|
874 } /* psf_set_stdio */
|
cannam@85
|
875
|
cannam@85
|
876 /* USE_WINDOWS_API */ void
|
cannam@85
|
877 psf_set_file (SF_PRIVATE *psf, int fd)
|
cannam@85
|
878 { HANDLE handle ;
|
cannam@85
|
879 intptr_t osfhandle ;
|
cannam@85
|
880
|
cannam@85
|
881 osfhandle = _get_osfhandle (fd) ;
|
cannam@85
|
882 handle = (HANDLE) osfhandle ;
|
cannam@85
|
883
|
cannam@85
|
884 psf->file.handle = handle ;
|
cannam@85
|
885 } /* psf_set_file */
|
cannam@85
|
886
|
cannam@85
|
887 /* USE_WINDOWS_API */ int
|
cannam@85
|
888 psf_file_valid (SF_PRIVATE *psf)
|
cannam@85
|
889 { if (psf->file.handle == NULL)
|
cannam@85
|
890 return SF_FALSE ;
|
cannam@85
|
891 if (psf->file.handle == INVALID_HANDLE_VALUE)
|
cannam@85
|
892 return SF_FALSE ;
|
cannam@85
|
893 return SF_TRUE ;
|
cannam@85
|
894 } /* psf_set_file */
|
cannam@85
|
895
|
cannam@85
|
896 /* USE_WINDOWS_API */ sf_count_t
|
cannam@85
|
897 psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
|
cannam@85
|
898 { sf_count_t new_position ;
|
cannam@85
|
899 LONG lDistanceToMove, lDistanceToMoveHigh ;
|
cannam@85
|
900 DWORD dwMoveMethod ;
|
cannam@85
|
901 DWORD dwResult, dwError ;
|
cannam@85
|
902
|
cannam@85
|
903 if (psf->virtual_io)
|
cannam@85
|
904 return psf->vio.seek (offset, whence, psf->vio_user_data) ;
|
cannam@85
|
905
|
cannam@85
|
906 switch (whence)
|
cannam@85
|
907 { case SEEK_SET :
|
cannam@85
|
908 offset += psf->fileoffset ;
|
cannam@85
|
909 dwMoveMethod = FILE_BEGIN ;
|
cannam@85
|
910 break ;
|
cannam@85
|
911
|
cannam@85
|
912 case SEEK_END :
|
cannam@85
|
913 dwMoveMethod = FILE_END ;
|
cannam@85
|
914 break ;
|
cannam@85
|
915
|
cannam@85
|
916 default :
|
cannam@85
|
917 dwMoveMethod = FILE_CURRENT ;
|
cannam@85
|
918 break ;
|
cannam@85
|
919 } ;
|
cannam@85
|
920
|
cannam@85
|
921 lDistanceToMove = (DWORD) (offset & 0xFFFFFFFF) ;
|
cannam@85
|
922 lDistanceToMoveHigh = (DWORD) ((offset >> 32) & 0xFFFFFFFF) ;
|
cannam@85
|
923
|
cannam@85
|
924 dwResult = SetFilePointer (psf->file.handle, lDistanceToMove, &lDistanceToMoveHigh, dwMoveMethod) ;
|
cannam@85
|
925
|
cannam@85
|
926 if (dwResult == 0xFFFFFFFF)
|
cannam@85
|
927 dwError = GetLastError () ;
|
cannam@85
|
928 else
|
cannam@85
|
929 dwError = NO_ERROR ;
|
cannam@85
|
930
|
cannam@85
|
931 if (dwError != NO_ERROR)
|
cannam@85
|
932 { psf_log_syserr (psf, dwError) ;
|
cannam@85
|
933 return -1 ;
|
cannam@85
|
934 } ;
|
cannam@85
|
935
|
cannam@85
|
936 new_position = (dwResult + ((__int64) lDistanceToMoveHigh << 32)) - psf->fileoffset ;
|
cannam@85
|
937
|
cannam@85
|
938 return new_position ;
|
cannam@85
|
939 } /* psf_fseek */
|
cannam@85
|
940
|
cannam@85
|
941 /* USE_WINDOWS_API */ sf_count_t
|
cannam@85
|
942 psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
cannam@85
|
943 { sf_count_t total = 0 ;
|
cannam@85
|
944 ssize_t count ;
|
cannam@85
|
945 DWORD dwNumberOfBytesRead ;
|
cannam@85
|
946
|
cannam@85
|
947 if (psf->virtual_io)
|
cannam@85
|
948 return psf->vio.read (ptr, bytes*items, psf->vio_user_data) / bytes ;
|
cannam@85
|
949
|
cannam@85
|
950 items *= bytes ;
|
cannam@85
|
951
|
cannam@85
|
952 /* Do this check after the multiplication above. */
|
cannam@85
|
953 if (items <= 0)
|
cannam@85
|
954 return 0 ;
|
cannam@85
|
955
|
cannam@85
|
956 while (items > 0)
|
cannam@85
|
957 { /* Break the writes down to a sensible size. */
|
cannam@85
|
958 count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ;
|
cannam@85
|
959
|
cannam@85
|
960 if (ReadFile (psf->file.handle, ((char*) ptr) + total, count, &dwNumberOfBytesRead, 0) == 0)
|
cannam@85
|
961 { psf_log_syserr (psf, GetLastError ()) ;
|
cannam@85
|
962 break ;
|
cannam@85
|
963 }
|
cannam@85
|
964 else
|
cannam@85
|
965 count = dwNumberOfBytesRead ;
|
cannam@85
|
966
|
cannam@85
|
967 if (count == 0)
|
cannam@85
|
968 break ;
|
cannam@85
|
969
|
cannam@85
|
970 total += count ;
|
cannam@85
|
971 items -= count ;
|
cannam@85
|
972 } ;
|
cannam@85
|
973
|
cannam@85
|
974 if (psf->is_pipe)
|
cannam@85
|
975 psf->pipeoffset += total ;
|
cannam@85
|
976
|
cannam@85
|
977 return total / bytes ;
|
cannam@85
|
978 } /* psf_fread */
|
cannam@85
|
979
|
cannam@85
|
980 /* USE_WINDOWS_API */ sf_count_t
|
cannam@85
|
981 psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
cannam@85
|
982 { sf_count_t total = 0 ;
|
cannam@85
|
983 ssize_t count ;
|
cannam@85
|
984 DWORD dwNumberOfBytesWritten ;
|
cannam@85
|
985
|
cannam@85
|
986 if (psf->virtual_io)
|
cannam@85
|
987 return psf->vio.write (ptr, bytes * items, psf->vio_user_data) / bytes ;
|
cannam@85
|
988
|
cannam@85
|
989 items *= bytes ;
|
cannam@85
|
990
|
cannam@85
|
991 /* Do this check after the multiplication above. */
|
cannam@85
|
992 if (items <= 0)
|
cannam@85
|
993 return 0 ;
|
cannam@85
|
994
|
cannam@85
|
995 while (items > 0)
|
cannam@85
|
996 { /* Break the writes down to a sensible size. */
|
cannam@85
|
997 count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ;
|
cannam@85
|
998
|
cannam@85
|
999 if (WriteFile (psf->file.handle, ((const char*) ptr) + total, count, &dwNumberOfBytesWritten, 0) == 0)
|
cannam@85
|
1000 { psf_log_syserr (psf, GetLastError ()) ;
|
cannam@85
|
1001 break ;
|
cannam@85
|
1002 }
|
cannam@85
|
1003 else
|
cannam@85
|
1004 count = dwNumberOfBytesWritten ;
|
cannam@85
|
1005
|
cannam@85
|
1006 if (count == 0)
|
cannam@85
|
1007 break ;
|
cannam@85
|
1008
|
cannam@85
|
1009 total += count ;
|
cannam@85
|
1010 items -= count ;
|
cannam@85
|
1011 } ;
|
cannam@85
|
1012
|
cannam@85
|
1013 if (psf->is_pipe)
|
cannam@85
|
1014 psf->pipeoffset += total ;
|
cannam@85
|
1015
|
cannam@85
|
1016 return total / bytes ;
|
cannam@85
|
1017 } /* psf_fwrite */
|
cannam@85
|
1018
|
cannam@85
|
1019 /* USE_WINDOWS_API */ sf_count_t
|
cannam@85
|
1020 psf_ftell (SF_PRIVATE *psf)
|
cannam@85
|
1021 { sf_count_t pos ;
|
cannam@85
|
1022 LONG lDistanceToMoveLow, lDistanceToMoveHigh ;
|
cannam@85
|
1023 DWORD dwResult, dwError ;
|
cannam@85
|
1024
|
cannam@85
|
1025 if (psf->virtual_io)
|
cannam@85
|
1026 return psf->vio.tell (psf->vio_user_data) ;
|
cannam@85
|
1027
|
cannam@85
|
1028 if (psf->is_pipe)
|
cannam@85
|
1029 return psf->pipeoffset ;
|
cannam@85
|
1030
|
cannam@85
|
1031 lDistanceToMoveLow = 0 ;
|
cannam@85
|
1032 lDistanceToMoveHigh = 0 ;
|
cannam@85
|
1033
|
cannam@85
|
1034 dwResult = SetFilePointer (psf->file.handle, lDistanceToMoveLow, &lDistanceToMoveHigh, FILE_CURRENT) ;
|
cannam@85
|
1035
|
cannam@85
|
1036 if (dwResult == 0xFFFFFFFF)
|
cannam@85
|
1037 dwError = GetLastError () ;
|
cannam@85
|
1038 else
|
cannam@85
|
1039 dwError = NO_ERROR ;
|
cannam@85
|
1040
|
cannam@85
|
1041 if (dwError != NO_ERROR)
|
cannam@85
|
1042 { psf_log_syserr (psf, dwError) ;
|
cannam@85
|
1043 return -1 ;
|
cannam@85
|
1044 } ;
|
cannam@85
|
1045
|
cannam@85
|
1046 pos = (dwResult + ((__int64) lDistanceToMoveHigh << 32)) ;
|
cannam@85
|
1047
|
cannam@85
|
1048 return pos - psf->fileoffset ;
|
cannam@85
|
1049 } /* psf_ftell */
|
cannam@85
|
1050
|
cannam@85
|
1051 /* USE_WINDOWS_API */ static int
|
cannam@85
|
1052 psf_close_handle (HANDLE handle)
|
cannam@85
|
1053 { if (handle == NULL)
|
cannam@85
|
1054 return 0 ;
|
cannam@85
|
1055
|
cannam@85
|
1056 if (CloseHandle (handle) == 0)
|
cannam@85
|
1057 return -1 ;
|
cannam@85
|
1058
|
cannam@85
|
1059 return 0 ;
|
cannam@85
|
1060 } /* psf_close_handle */
|
cannam@85
|
1061
|
cannam@85
|
1062 /* USE_WINDOWS_API */ sf_count_t
|
cannam@85
|
1063 psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf)
|
cannam@85
|
1064 { sf_count_t k = 0 ;
|
cannam@85
|
1065 sf_count_t count ;
|
cannam@85
|
1066 DWORD dwNumberOfBytesRead ;
|
cannam@85
|
1067
|
cannam@85
|
1068 while (k < bufsize - 1)
|
cannam@85
|
1069 { if (ReadFile (psf->file.handle, &(buffer [k]), 1, &dwNumberOfBytesRead, 0) == 0)
|
cannam@85
|
1070 { psf_log_syserr (psf, GetLastError ()) ;
|
cannam@85
|
1071 break ;
|
cannam@85
|
1072 }
|
cannam@85
|
1073 else
|
cannam@85
|
1074 { count = dwNumberOfBytesRead ;
|
cannam@85
|
1075 /* note that we only check for '\n' not other line endings such as CRLF */
|
cannam@85
|
1076 if (count == 0 || buffer [k++] == '\n')
|
cannam@85
|
1077 break ;
|
cannam@85
|
1078 } ;
|
cannam@85
|
1079 } ;
|
cannam@85
|
1080
|
cannam@85
|
1081 buffer [k] = 0 ;
|
cannam@85
|
1082
|
cannam@85
|
1083 return k ;
|
cannam@85
|
1084 } /* psf_fgets */
|
cannam@85
|
1085
|
cannam@85
|
1086 /* USE_WINDOWS_API */ int
|
cannam@85
|
1087 psf_is_pipe (SF_PRIVATE *psf)
|
cannam@85
|
1088 {
|
cannam@85
|
1089 if (psf->virtual_io)
|
cannam@85
|
1090 return SF_FALSE ;
|
cannam@85
|
1091
|
cannam@85
|
1092 if (GetFileType (psf->file.handle) == FILE_TYPE_DISK)
|
cannam@85
|
1093 return SF_FALSE ;
|
cannam@85
|
1094
|
cannam@85
|
1095 /* Default to maximum safety. */
|
cannam@85
|
1096 return SF_TRUE ;
|
cannam@85
|
1097 } /* psf_is_pipe */
|
cannam@85
|
1098
|
cannam@85
|
1099 /* USE_WINDOWS_API */ sf_count_t
|
cannam@85
|
1100 psf_get_filelen_handle (HANDLE handle)
|
cannam@85
|
1101 { sf_count_t filelen ;
|
cannam@85
|
1102 DWORD dwFileSizeLow, dwFileSizeHigh, dwError = NO_ERROR ;
|
cannam@85
|
1103
|
cannam@85
|
1104 dwFileSizeLow = GetFileSize (handle, &dwFileSizeHigh) ;
|
cannam@85
|
1105
|
cannam@85
|
1106 if (dwFileSizeLow == 0xFFFFFFFF)
|
cannam@85
|
1107 dwError = GetLastError () ;
|
cannam@85
|
1108
|
cannam@85
|
1109 if (dwError != NO_ERROR)
|
cannam@85
|
1110 return (sf_count_t) -1 ;
|
cannam@85
|
1111
|
cannam@85
|
1112 filelen = dwFileSizeLow + ((__int64) dwFileSizeHigh << 32) ;
|
cannam@85
|
1113
|
cannam@85
|
1114 return filelen ;
|
cannam@85
|
1115 } /* psf_get_filelen_handle */
|
cannam@85
|
1116
|
cannam@85
|
1117 /* USE_WINDOWS_API */ void
|
cannam@85
|
1118 psf_fsync (SF_PRIVATE *psf)
|
cannam@85
|
1119 { FlushFileBuffers (psf->file.handle) ;
|
cannam@85
|
1120 } /* psf_fsync */
|
cannam@85
|
1121
|
cannam@85
|
1122
|
cannam@85
|
1123 /* USE_WINDOWS_API */ int
|
cannam@85
|
1124 psf_ftruncate (SF_PRIVATE *psf, sf_count_t len)
|
cannam@85
|
1125 { int retval = 0 ;
|
cannam@85
|
1126 LONG lDistanceToMoveLow, lDistanceToMoveHigh ;
|
cannam@85
|
1127 DWORD dwResult, dwError = NO_ERROR ;
|
cannam@85
|
1128
|
cannam@85
|
1129 /* This implementation trashes the current file position.
|
cannam@85
|
1130 ** should it save and restore it? what if the current position is past
|
cannam@85
|
1131 ** the new end of file?
|
cannam@85
|
1132 */
|
cannam@85
|
1133
|
cannam@85
|
1134 /* Returns 0 on success, non-zero on failure. */
|
cannam@85
|
1135 if (len < 0)
|
cannam@85
|
1136 return 1 ;
|
cannam@85
|
1137
|
cannam@85
|
1138 lDistanceToMoveLow = (DWORD) (len & 0xFFFFFFFF) ;
|
cannam@85
|
1139 lDistanceToMoveHigh = (DWORD) ((len >> 32) & 0xFFFFFFFF) ;
|
cannam@85
|
1140
|
cannam@85
|
1141 dwResult = SetFilePointer (psf->file.handle, lDistanceToMoveLow, &lDistanceToMoveHigh, FILE_BEGIN) ;
|
cannam@85
|
1142
|
cannam@85
|
1143 if (dwResult == 0xFFFFFFFF)
|
cannam@85
|
1144 dwError = GetLastError () ;
|
cannam@85
|
1145
|
cannam@85
|
1146 if (dwError != NO_ERROR)
|
cannam@85
|
1147 { retval = -1 ;
|
cannam@85
|
1148 psf_log_syserr (psf, dwError) ;
|
cannam@85
|
1149 }
|
cannam@85
|
1150 else
|
cannam@85
|
1151 { /* Note: when SetEndOfFile is used to extend a file, the contents of the
|
cannam@85
|
1152 ** new portion of the file is undefined. This is unlike chsize(),
|
cannam@85
|
1153 ** which guarantees that the new portion of the file will be zeroed.
|
cannam@85
|
1154 ** Not sure if this is important or not.
|
cannam@85
|
1155 */
|
cannam@85
|
1156 if (SetEndOfFile (psf->file.handle) == 0)
|
cannam@85
|
1157 { retval = -1 ;
|
cannam@85
|
1158 psf_log_syserr (psf, GetLastError ()) ;
|
cannam@85
|
1159 } ;
|
cannam@85
|
1160 } ;
|
cannam@85
|
1161
|
cannam@85
|
1162 return retval ;
|
cannam@85
|
1163 } /* psf_ftruncate */
|
cannam@85
|
1164
|
cannam@85
|
1165
|
cannam@85
|
1166 #else
|
cannam@85
|
1167 /* Win32 file i/o functions implemented using Unix-style file i/o API */
|
cannam@85
|
1168
|
cannam@85
|
1169 /* Win32 has a 64 file offset seek function:
|
cannam@85
|
1170 **
|
cannam@85
|
1171 ** __int64 _lseeki64 (int handle, __int64 offset, int origin) ;
|
cannam@85
|
1172 **
|
cannam@85
|
1173 ** It also has a 64 bit fstat function:
|
cannam@85
|
1174 **
|
cannam@85
|
1175 ** int fstati64 (int, struct _stati64) ;
|
cannam@85
|
1176 **
|
cannam@85
|
1177 ** but the fscking thing doesn't work!!!!! The file size parameter returned
|
cannam@85
|
1178 ** by this function is only valid up until more data is written at the end of
|
cannam@85
|
1179 ** the file. That makes this function completely 100% useless.
|
cannam@85
|
1180 */
|
cannam@85
|
1181
|
cannam@85
|
1182 #include <io.h>
|
cannam@85
|
1183 #include <direct.h>
|
cannam@85
|
1184
|
cannam@85
|
1185 /* Win32 */ int
|
cannam@85
|
1186 psf_fopen (SF_PRIVATE *psf, const char *pathname, int open_mode)
|
cannam@85
|
1187 { int oflag, mode ;
|
cannam@85
|
1188
|
cannam@85
|
1189 switch (open_mode)
|
cannam@85
|
1190 { case SFM_READ :
|
cannam@85
|
1191 oflag = O_RDONLY | O_BINARY ;
|
cannam@85
|
1192 mode = 0 ;
|
cannam@85
|
1193 break ;
|
cannam@85
|
1194
|
cannam@85
|
1195 case SFM_WRITE :
|
cannam@85
|
1196 oflag = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
|
cannam@85
|
1197 mode = S_IRUSR | S_IWUSR | S_IRGRP ;
|
cannam@85
|
1198 break ;
|
cannam@85
|
1199
|
cannam@85
|
1200 case SFM_RDWR :
|
cannam@85
|
1201 oflag = O_RDWR | O_CREAT | O_BINARY ;
|
cannam@85
|
1202 mode = S_IRUSR | S_IWUSR | S_IRGRP ;
|
cannam@85
|
1203 break ;
|
cannam@85
|
1204
|
cannam@85
|
1205 default :
|
cannam@85
|
1206 psf->error = SFE_BAD_OPEN_MODE ;
|
cannam@85
|
1207 return -1 ;
|
cannam@85
|
1208 break ;
|
cannam@85
|
1209 } ;
|
cannam@85
|
1210
|
cannam@85
|
1211 if (mode == 0)
|
cannam@85
|
1212 psf->file.filedes = open (pathname, oflag) ;
|
cannam@85
|
1213 else
|
cannam@85
|
1214 psf->file.filedes = open (pathname, oflag, mode) ;
|
cannam@85
|
1215
|
cannam@85
|
1216 if (psf->file.filedes == -1)
|
cannam@85
|
1217 psf_log_syserr (psf, errno) ;
|
cannam@85
|
1218
|
cannam@85
|
1219 return psf->file.filedes ;
|
cannam@85
|
1220 } /* psf_fopen */
|
cannam@85
|
1221
|
cannam@85
|
1222 /* Win32 */ sf_count_t
|
cannam@85
|
1223 psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence)
|
cannam@85
|
1224 { sf_count_t new_position ;
|
cannam@85
|
1225
|
cannam@85
|
1226 if (psf->virtual_io)
|
cannam@85
|
1227 return psf->vio.seek (offset, whence, psf->vio_user_data) ;
|
cannam@85
|
1228
|
cannam@85
|
1229 switch (whence)
|
cannam@85
|
1230 { case SEEK_SET :
|
cannam@85
|
1231 offset += psf->fileoffset ;
|
cannam@85
|
1232 break ;
|
cannam@85
|
1233
|
cannam@85
|
1234 case SEEK_END :
|
cannam@85
|
1235 if (psf->file.mode == SFM_WRITE)
|
cannam@85
|
1236 { new_position = _lseeki64 (psf->file.filedes, offset, whence) ;
|
cannam@85
|
1237
|
cannam@85
|
1238 if (new_position < 0)
|
cannam@85
|
1239 psf_log_syserr (psf, errno) ;
|
cannam@85
|
1240
|
cannam@85
|
1241 return new_position - psf->fileoffset ;
|
cannam@85
|
1242 } ;
|
cannam@85
|
1243
|
cannam@85
|
1244 /* Transform SEEK_END into a SEEK_SET, ie find the file
|
cannam@85
|
1245 ** length add the requested offset (should be <= 0) to
|
cannam@85
|
1246 ** get the offset wrt the start of file.
|
cannam@85
|
1247 */
|
cannam@85
|
1248 whence = SEEK_SET ;
|
cannam@85
|
1249 offset = _lseeki64 (psf->file.filedes, 0, SEEK_END) + offset ;
|
cannam@85
|
1250 break ;
|
cannam@85
|
1251
|
cannam@85
|
1252 default :
|
cannam@85
|
1253 /* No need to do anything about SEEK_CUR. */
|
cannam@85
|
1254 break ;
|
cannam@85
|
1255 } ;
|
cannam@85
|
1256
|
cannam@85
|
1257 /*
|
cannam@85
|
1258 ** Bypass weird Win32-ism if necessary.
|
cannam@85
|
1259 ** _lseeki64() returns an "invalid parameter" error if called with the
|
cannam@85
|
1260 ** offset == 0 and whence == SEEK_CUR.
|
cannam@85
|
1261 *** Use the _telli64() function instead.
|
cannam@85
|
1262 */
|
cannam@85
|
1263 if (offset == 0 && whence == SEEK_CUR)
|
cannam@85
|
1264 new_position = _telli64 (psf->file.filedes) ;
|
cannam@85
|
1265 else
|
cannam@85
|
1266 new_position = _lseeki64 (psf->file.filedes, offset, whence) ;
|
cannam@85
|
1267
|
cannam@85
|
1268 if (new_position < 0)
|
cannam@85
|
1269 psf_log_syserr (psf, errno) ;
|
cannam@85
|
1270
|
cannam@85
|
1271 new_position -= psf->fileoffset ;
|
cannam@85
|
1272
|
cannam@85
|
1273 return new_position ;
|
cannam@85
|
1274 } /* psf_fseek */
|
cannam@85
|
1275
|
cannam@85
|
1276 /* Win32 */ sf_count_t
|
cannam@85
|
1277 psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
cannam@85
|
1278 { sf_count_t total = 0 ;
|
cannam@85
|
1279 ssize_t count ;
|
cannam@85
|
1280
|
cannam@85
|
1281 if (psf->virtual_io)
|
cannam@85
|
1282 return psf->vio.read (ptr, bytes*items, psf->vio_user_data) / bytes ;
|
cannam@85
|
1283
|
cannam@85
|
1284 items *= bytes ;
|
cannam@85
|
1285
|
cannam@85
|
1286 /* Do this check after the multiplication above. */
|
cannam@85
|
1287 if (items <= 0)
|
cannam@85
|
1288 return 0 ;
|
cannam@85
|
1289
|
cannam@85
|
1290 while (items > 0)
|
cannam@85
|
1291 { /* Break the writes down to a sensible size. */
|
cannam@85
|
1292 count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ;
|
cannam@85
|
1293
|
cannam@85
|
1294 count = read (psf->file.filedes, ((char*) ptr) + total, (size_t) count) ;
|
cannam@85
|
1295
|
cannam@85
|
1296 if (count == -1)
|
cannam@85
|
1297 { if (errno == EINTR)
|
cannam@85
|
1298 continue ;
|
cannam@85
|
1299
|
cannam@85
|
1300 psf_log_syserr (psf, errno) ;
|
cannam@85
|
1301 break ;
|
cannam@85
|
1302 } ;
|
cannam@85
|
1303
|
cannam@85
|
1304 if (count == 0)
|
cannam@85
|
1305 break ;
|
cannam@85
|
1306
|
cannam@85
|
1307 total += count ;
|
cannam@85
|
1308 items -= count ;
|
cannam@85
|
1309 } ;
|
cannam@85
|
1310
|
cannam@85
|
1311 return total / bytes ;
|
cannam@85
|
1312 } /* psf_fread */
|
cannam@85
|
1313
|
cannam@85
|
1314 /* Win32 */ sf_count_t
|
cannam@85
|
1315 psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf)
|
cannam@85
|
1316 { sf_count_t total = 0 ;
|
cannam@85
|
1317 ssize_t count ;
|
cannam@85
|
1318
|
cannam@85
|
1319 if (psf->virtual_io)
|
cannam@85
|
1320 return psf->vio.write (ptr, bytes*items, psf->vio_user_data) / bytes ;
|
cannam@85
|
1321
|
cannam@85
|
1322 items *= bytes ;
|
cannam@85
|
1323
|
cannam@85
|
1324 /* Do this check after the multiplication above. */
|
cannam@85
|
1325 if (items <= 0)
|
cannam@85
|
1326 return 0 ;
|
cannam@85
|
1327
|
cannam@85
|
1328 while (items > 0)
|
cannam@85
|
1329 { /* Break the writes down to a sensible size. */
|
cannam@85
|
1330 count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : items ;
|
cannam@85
|
1331
|
cannam@85
|
1332 count = write (psf->file.filedes, ((const char*) ptr) + total, count) ;
|
cannam@85
|
1333
|
cannam@85
|
1334 if (count == -1)
|
cannam@85
|
1335 { if (errno == EINTR)
|
cannam@85
|
1336 continue ;
|
cannam@85
|
1337
|
cannam@85
|
1338 psf_log_syserr (psf, errno) ;
|
cannam@85
|
1339 break ;
|
cannam@85
|
1340 } ;
|
cannam@85
|
1341
|
cannam@85
|
1342 if (count == 0)
|
cannam@85
|
1343 break ;
|
cannam@85
|
1344
|
cannam@85
|
1345 total += count ;
|
cannam@85
|
1346 items -= count ;
|
cannam@85
|
1347 } ;
|
cannam@85
|
1348
|
cannam@85
|
1349 return total / bytes ;
|
cannam@85
|
1350 } /* psf_fwrite */
|
cannam@85
|
1351
|
cannam@85
|
1352 /* Win32 */ sf_count_t
|
cannam@85
|
1353 psf_ftell (SF_PRIVATE *psf)
|
cannam@85
|
1354 { sf_count_t pos ;
|
cannam@85
|
1355
|
cannam@85
|
1356 if (psf->virtual_io)
|
cannam@85
|
1357 return psf->vio.tell (psf->vio_user_data) ;
|
cannam@85
|
1358
|
cannam@85
|
1359 pos = _telli64 (psf->file.filedes) ;
|
cannam@85
|
1360
|
cannam@85
|
1361 if (pos == ((sf_count_t) -1))
|
cannam@85
|
1362 { psf_log_syserr (psf, errno) ;
|
cannam@85
|
1363 return -1 ;
|
cannam@85
|
1364 } ;
|
cannam@85
|
1365
|
cannam@85
|
1366 return pos - psf->fileoffset ;
|
cannam@85
|
1367 } /* psf_ftell */
|
cannam@85
|
1368
|
cannam@85
|
1369 /* Win32 */ int
|
cannam@85
|
1370 psf_fclose (SF_PRIVATE *psf)
|
cannam@85
|
1371 { int retval ;
|
cannam@85
|
1372
|
cannam@85
|
1373 while ((retval = close (psf->file.filedes)) == -1 && errno == EINTR)
|
cannam@85
|
1374 /* Do nothing. */ ;
|
cannam@85
|
1375
|
cannam@85
|
1376 if (retval == -1)
|
cannam@85
|
1377 psf_log_syserr (psf, errno) ;
|
cannam@85
|
1378
|
cannam@85
|
1379 psf->file.filedes = -1 ;
|
cannam@85
|
1380
|
cannam@85
|
1381 return retval ;
|
cannam@85
|
1382 } /* psf_fclose */
|
cannam@85
|
1383
|
cannam@85
|
1384 /* Win32 */ sf_count_t
|
cannam@85
|
1385 psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf)
|
cannam@85
|
1386 { sf_count_t k = 0 ;
|
cannam@85
|
1387 sf_count_t count ;
|
cannam@85
|
1388
|
cannam@85
|
1389 while (k < bufsize - 1)
|
cannam@85
|
1390 { count = read (psf->file.filedes, &(buffer [k]), 1) ;
|
cannam@85
|
1391
|
cannam@85
|
1392 if (count == -1)
|
cannam@85
|
1393 { if (errno == EINTR)
|
cannam@85
|
1394 continue ;
|
cannam@85
|
1395
|
cannam@85
|
1396 psf_log_syserr (psf, errno) ;
|
cannam@85
|
1397 break ;
|
cannam@85
|
1398 } ;
|
cannam@85
|
1399
|
cannam@85
|
1400 if (count == 0 || buffer [k++] == '\n')
|
cannam@85
|
1401 break ;
|
cannam@85
|
1402 } ;
|
cannam@85
|
1403
|
cannam@85
|
1404 buffer [k] = 0 ;
|
cannam@85
|
1405
|
cannam@85
|
1406 return k ;
|
cannam@85
|
1407 } /* psf_fgets */
|
cannam@85
|
1408
|
cannam@85
|
1409 /* Win32 */ int
|
cannam@85
|
1410 psf_is_pipe (SF_PRIVATE *psf)
|
cannam@85
|
1411 { struct stat statbuf ;
|
cannam@85
|
1412
|
cannam@85
|
1413 if (psf->virtual_io)
|
cannam@85
|
1414 return SF_FALSE ;
|
cannam@85
|
1415
|
cannam@85
|
1416 /* Not sure if this works. */
|
cannam@85
|
1417 if (fstat (psf->file.filedes, &statbuf) == -1)
|
cannam@85
|
1418 { psf_log_syserr (psf, errno) ;
|
cannam@85
|
1419 /* Default to maximum safety. */
|
cannam@85
|
1420 return SF_TRUE ;
|
cannam@85
|
1421 } ;
|
cannam@85
|
1422
|
cannam@85
|
1423 /* These macros are defined in Win32/unistd.h. */
|
cannam@85
|
1424 if (S_ISFIFO (statbuf.st_mode) || S_ISSOCK (statbuf.st_mode))
|
cannam@85
|
1425 return SF_TRUE ;
|
cannam@85
|
1426
|
cannam@85
|
1427 return SF_FALSE ;
|
cannam@85
|
1428 } /* psf_checkpipe */
|
cannam@85
|
1429
|
cannam@85
|
1430 /* Win32 */ sf_count_t
|
cannam@85
|
1431 psf_get_filelen (SF_PRIVATE *psf)
|
cannam@85
|
1432 {
|
cannam@85
|
1433 #if 0
|
cannam@85
|
1434 /*
|
cannam@85
|
1435 ** Windoze is SOOOOO FUCKED!!!!!!!
|
cannam@85
|
1436 ** This code should work but doesn't. Why?
|
cannam@85
|
1437 ** Code below does work.
|
cannam@85
|
1438 */
|
cannam@85
|
1439 struct _stati64 statbuf ;
|
cannam@85
|
1440
|
cannam@85
|
1441 if (_fstati64 (psf->file.filedes, &statbuf))
|
cannam@85
|
1442 { psf_log_syserr (psf, errno) ;
|
cannam@85
|
1443 return (sf_count_t) -1 ;
|
cannam@85
|
1444 } ;
|
cannam@85
|
1445
|
cannam@85
|
1446 return statbuf.st_size ;
|
cannam@85
|
1447 #else
|
cannam@85
|
1448 sf_count_t current, filelen ;
|
cannam@85
|
1449
|
cannam@85
|
1450 if (psf->virtual_io)
|
cannam@85
|
1451 return psf->vio.get_filelen (psf->vio_user_data) ;
|
cannam@85
|
1452
|
cannam@85
|
1453 if ((current = _telli64 (psf->file.filedes)) < 0)
|
cannam@85
|
1454 { psf_log_syserr (psf, errno) ;
|
cannam@85
|
1455 return (sf_count_t) -1 ;
|
cannam@85
|
1456 } ;
|
cannam@85
|
1457
|
cannam@85
|
1458 /*
|
cannam@85
|
1459 ** Lets face it, windoze if FUBAR!!!
|
cannam@85
|
1460 **
|
cannam@85
|
1461 ** For some reason, I have to call _lseeki64() TWICE to get to the
|
cannam@85
|
1462 ** end of the file.
|
cannam@85
|
1463 **
|
cannam@85
|
1464 ** This might have been avoided if windows had implemented the POSIX
|
cannam@85
|
1465 ** standard function fsync() but NO, that would have been too easy.
|
cannam@85
|
1466 **
|
cannam@85
|
1467 ** I am VERY close to saying that windoze will no longer be supported
|
cannam@85
|
1468 ** by libsndfile and changing the license to GPL at the same time.
|
cannam@85
|
1469 */
|
cannam@85
|
1470
|
cannam@85
|
1471 _lseeki64 (psf->file.filedes, 0, SEEK_END) ;
|
cannam@85
|
1472
|
cannam@85
|
1473 if ((filelen = _lseeki64 (psf->file.filedes, 0, SEEK_END)) < 0)
|
cannam@85
|
1474 { psf_log_syserr (psf, errno) ;
|
cannam@85
|
1475 return (sf_count_t) -1 ;
|
cannam@85
|
1476 } ;
|
cannam@85
|
1477
|
cannam@85
|
1478 if (filelen > current)
|
cannam@85
|
1479 _lseeki64 (psf->file.filedes, current, SEEK_SET) ;
|
cannam@85
|
1480
|
cannam@85
|
1481 switch (psf->file.mode)
|
cannam@85
|
1482 { case SFM_WRITE :
|
cannam@85
|
1483 filelen = filelen - psf->fileoffset ;
|
cannam@85
|
1484 break ;
|
cannam@85
|
1485
|
cannam@85
|
1486 case SFM_READ :
|
cannam@85
|
1487 if (psf->fileoffset > 0 && psf->filelength > 0)
|
cannam@85
|
1488 filelen = psf->filelength ;
|
cannam@85
|
1489 break ;
|
cannam@85
|
1490
|
cannam@85
|
1491 case SFM_RDWR :
|
cannam@85
|
1492 /*
|
cannam@85
|
1493 ** Cannot open embedded files SFM_RDWR so we don't need to
|
cannam@85
|
1494 ** subtract psf->fileoffset. We already have the answer we
|
cannam@85
|
1495 ** need.
|
cannam@85
|
1496 */
|
cannam@85
|
1497 break ;
|
cannam@85
|
1498
|
cannam@85
|
1499 default :
|
cannam@85
|
1500 filelen = 0 ;
|
cannam@85
|
1501 } ;
|
cannam@85
|
1502
|
cannam@85
|
1503 return filelen ;
|
cannam@85
|
1504 #endif
|
cannam@85
|
1505 } /* psf_get_filelen */
|
cannam@85
|
1506
|
cannam@85
|
1507 /* Win32 */ int
|
cannam@85
|
1508 psf_ftruncate (SF_PRIVATE *psf, sf_count_t len)
|
cannam@85
|
1509 { int retval ;
|
cannam@85
|
1510
|
cannam@85
|
1511 /* Returns 0 on success, non-zero on failure. */
|
cannam@85
|
1512 if (len < 0)
|
cannam@85
|
1513 return 1 ;
|
cannam@85
|
1514
|
cannam@85
|
1515 /* The global village idiots at micorsoft decided to implement
|
cannam@85
|
1516 ** nearly all the required 64 bit file offset functions except
|
cannam@85
|
1517 ** for one, truncate. The fscking morons!
|
cannam@85
|
1518 **
|
cannam@85
|
1519 ** This is not 64 bit file offset clean. Somone needs to clean
|
cannam@85
|
1520 ** this up.
|
cannam@85
|
1521 */
|
cannam@85
|
1522 if (len > 0x7FFFFFFF)
|
cannam@85
|
1523 return -1 ;
|
cannam@85
|
1524
|
cannam@85
|
1525 retval = chsize (psf->file.filedes, len) ;
|
cannam@85
|
1526
|
cannam@85
|
1527 if (retval == -1)
|
cannam@85
|
1528 psf_log_syserr (psf, errno) ;
|
cannam@85
|
1529
|
cannam@85
|
1530 return retval ;
|
cannam@85
|
1531 } /* psf_ftruncate */
|
cannam@85
|
1532
|
cannam@85
|
1533
|
cannam@85
|
1534 static void
|
cannam@85
|
1535 psf_log_syserr (SF_PRIVATE *psf, int error)
|
cannam@85
|
1536 {
|
cannam@85
|
1537 /* Only log an error if no error has been set yet. */
|
cannam@85
|
1538 if (psf->error == 0)
|
cannam@85
|
1539 { psf->error = SFE_SYSTEM ;
|
cannam@85
|
1540 snprintf (psf->syserr, sizeof (psf->syserr), "System error : %s", strerror (error)) ;
|
cannam@85
|
1541 } ;
|
cannam@85
|
1542
|
cannam@85
|
1543 return ;
|
cannam@85
|
1544 } /* psf_log_syserr */
|
cannam@85
|
1545
|
cannam@85
|
1546 #endif
|
cannam@85
|
1547
|