annotate src/libsndfile-1.0.25/src/file_io.c @ 138:eb184393b244

Rebuild with DW2 exception handling to match Qt
author Chris Cannam <cannam@all-day-breakfast.com>
date Thu, 27 Oct 2016 10:26:57 +0100
parents 39797f8363b6
children
rev   line source
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