~ubuntu-branches/ubuntu/gutsy/audacity/gutsy-backports

« back to all changes in this revision

Viewing changes to lib-src/libsndfile/src/file_io.c

  • Committer: Bazaar Package Importer
  • Author(s): John Dong
  • Date: 2008-02-18 21:58:19 UTC
  • mfrom: (13.1.2 hardy)
  • Revision ID: james.westby@ubuntu.com-20080218215819-tmbcf1rx238r8gdv
Tags: 1.3.4-1.1ubuntu1~gutsy1
Automated backport upload; no source changes.

Show diffs side-by-side

added added

removed removed

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