📄 file_io.c
字号:
return error ;} /* psf_set_stdio *//* Win32 */ voidpsf_set_file (SF_PRIVATE *psf, int fd){ HANDLE handle ; long osfhandle ; osfhandle = _get_osfhandle (fd) ; handle = (HANDLE) osfhandle ; if (GetFileType (handle) == FILE_TYPE_DISK) psf->filedes = (int) handle ; else psf->filedes = fd ;} /* psf_set_file *//* Win32 */ intpsf_filedes_valid (SF_PRIVATE *psf){ return (((HANDLE) psf->filedes) != INVALID_HANDLE_VALUE) ? SF_TRUE : SF_FALSE ;} /* psf_set_file *//* Win32 */ sf_count_tpsf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence){ sf_count_t new_position ; LONG lDistanceToMove, lDistanceToMoveHigh ; DWORD dwMoveMethod ; DWORD dwResult, dwError ; switch (whence) { case SEEK_SET : offset += psf->fileoffset ; dwMoveMethod = FILE_BEGIN ; break ; case SEEK_END : dwMoveMethod = FILE_END ; break ; default : dwMoveMethod = FILE_CURRENT ; break ; } ; lDistanceToMove = (DWORD) (offset & 0xFFFFFFFF) ; lDistanceToMoveHigh = (DWORD) ((offset >> 32) & 0xFFFFFFFF) ; dwResult = SetFilePointer ((HANDLE) psf->filedes, lDistanceToMove, &lDistanceToMoveHigh, dwMoveMethod) ; if (dwResult == 0xFFFFFFFF) dwError = GetLastError () ; else dwError = NO_ERROR ; if (dwError != NO_ERROR) { psf_log_syserr (psf, dwError) ; return -1 ; } ; new_position = (dwResult + ((__int64) lDistanceToMoveHigh << 32)) - psf->fileoffset ; return new_position ;} /* psf_fseek *//* Win32 */ sf_count_tpsf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf){ sf_count_t total = 0 ; ssize_t count ; DWORD dwNumberOfBytesRead ; items *= bytes ; /* Do this check after the multiplication above. */ if (items <= 0) return 0 ; while (items > 0) { /* Break the writes down to a sensible size. */ count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ; if (ReadFile ((HANDLE) psf->filedes, ((char*) ptr) + total, count, &dwNumberOfBytesRead, 0) == 0) { psf_log_syserr (psf, GetLastError ()) ; break ; } else count = dwNumberOfBytesRead ; if (count == 0) break ; total += count ; items -= count ; } ; if (psf->is_pipe) psf->pipeoffset += total ; return total / bytes ;} /* psf_fread *//* Win32 */ sf_count_tpsf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf){ sf_count_t total = 0 ; ssize_t count ; DWORD dwNumberOfBytesWritten ; items *= bytes ; /* Do this check after the multiplication above. */ if (items <= 0) return 0 ; while (items > 0) { /* Break the writes down to a sensible size. */ count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ; if (WriteFile ((HANDLE) psf->filedes, ((const char*) ptr) + total, count, &dwNumberOfBytesWritten, 0) == 0) { psf_log_syserr (psf, GetLastError ()) ; break ; } else count = dwNumberOfBytesWritten ; if (count == 0) break ; total += count ; items -= count ; } ; if (psf->is_pipe) psf->pipeoffset += total ; return total / bytes ;} /* psf_fwrite *//* Win32 */ sf_count_tpsf_ftell (SF_PRIVATE *psf){ sf_count_t pos ; LONG lDistanceToMoveLow, lDistanceToMoveHigh ; DWORD dwResult, dwError ; if (psf->is_pipe) return psf->pipeoffset ; lDistanceToMoveLow = 0 ; lDistanceToMoveHigh = 0 ; dwResult = SetFilePointer ((HANDLE) psf->filedes, lDistanceToMoveLow, &lDistanceToMoveHigh, FILE_CURRENT) ; if (dwResult == 0xFFFFFFFF) dwError = GetLastError () ; else dwError = NO_ERROR ; if (dwError != NO_ERROR) { psf_log_syserr (psf, dwError) ; return -1 ; } ; pos = (dwResult + ((__int64) lDistanceToMoveHigh << 32)) ; return pos - psf->fileoffset ;} /* psf_ftell *//* Win32 */ intpsf_close_fd (int fd){ if (CloseHandle ((HANDLE) fd) == 0) return -1 ; return 0 ;} /* psf_close_fd *//* Win32 */ sf_count_tpsf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf){ sf_count_t k = 0 ; sf_count_t count ; DWORD dwNumberOfBytesRead ; while (k < bufsize - 1) { if (ReadFile ((HANDLE) psf->filedes, &(buffer [k]), 1, &dwNumberOfBytesRead, 0) == 0) { psf_log_syserr (psf, GetLastError ()) ; break ; } else { count = dwNumberOfBytesRead ; /* note that we only check for '\n' not other line endings such as CRLF */ if (count == 0 || buffer [k++] == '\n') break ; } ; } ; buffer [k] = 0 ; return k ;} /* psf_fgets *//* Win32 */ intpsf_is_pipe (SF_PRIVATE *psf){ if (GetFileType ((HANDLE) psf->filedes) == FILE_TYPE_DISK) return SF_FALSE ; /* Default to maximum safety. */ return SF_TRUE ;} /* psf_is_pipe *//* Win32 */ sf_count_tpsf_get_filelen_fd (int fd){ sf_count_t filelen ; DWORD dwFileSizeLow, dwFileSizeHigh, dwError = NO_ERROR ; dwFileSizeLow = GetFileSize ((HANDLE) fd, &dwFileSizeHigh) ; if (dwFileSizeLow == 0xFFFFFFFF) dwError = GetLastError () ; if (dwError != NO_ERROR) return (sf_count_t) -1 ; filelen = dwFileSizeLow + ((__int64) dwFileSizeHigh << 32) ; return filelen ;} /* psf_get_filelen_fd *//* Win32 */ intpsf_ftruncate (SF_PRIVATE *psf, sf_count_t len){ int retval = 0 ; LONG lDistanceToMoveLow, lDistanceToMoveHigh ; DWORD dwResult, dwError = NO_ERROR ; /* This implementation trashes the current file position. ** should it save and restore it? what if the current position is past ** the new end of file? */ /* Returns 0 on success, non-zero on failure. */ if (len < 0) return 1 ; lDistanceToMoveLow = (DWORD) (len & 0xFFFFFFFF) ; lDistanceToMoveHigh = (DWORD) ((len >> 32) & 0xFFFFFFFF) ; dwResult = SetFilePointer ((HANDLE) psf->filedes, lDistanceToMoveLow, &lDistanceToMoveHigh, FILE_BEGIN) ; if (dwResult == 0xFFFFFFFF) dwError = GetLastError () ; if (dwError != NO_ERROR) { retval = -1 ; psf_log_syserr (psf, dwError) ; } else { /* Note: when SetEndOfFile is used to extend a file, the contents of the ** new portion of the file is undefined. This is unlike chsize(), ** which guarantees that the new portion of the file will be zeroed. ** Not sure if this is important or not. */ if (SetEndOfFile ((HANDLE) psf->filedes) == 0) { retval = -1 ; psf_log_syserr (psf, GetLastError ()) ; } ; } ; return retval ;} /* psf_ftruncate */#else/* Win32 file i/o functions implemented using Unix-style file i/o API *//* Win32 has a 64 file offset seek function:**** __int64 _lseeki64 (int handle, __int64 offset, int origin) ;**** It also has a 64 bit fstat function:**** int fstati64 (int, struct _stati64) ;**** but the fscking thing doesn't work!!!!! The file size parameter returned** by this function is only valid up until more data is written at the end of** the file. That makes this function completely 100% useless.*/#include <io.h>#include <direct.h>#ifndef HAVE_SSIZE_Ttypedef long ssize_t ;#endif/* Win32 */ intpsf_fopen (SF_PRIVATE *psf, const char *pathname, int open_mode){ int oflag, mode ; switch (open_mode) { case SFM_READ : oflag = O_RDONLY | O_BINARY ; mode = 0 ; break ; case SFM_WRITE : oflag = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ; mode = S_IRUSR | S_IWUSR | S_IRGRP ; break ; case SFM_RDWR : oflag = O_RDWR | O_CREAT | O_BINARY ; mode = S_IRUSR | S_IWUSR | S_IRGRP ; break ; default : psf->error = SFE_BAD_OPEN_MODE ; return -1 ; break ; } ; if (mode == 0) psf->filedes = open (pathname, oflag) ; else psf->filedes = open (pathname, oflag, mode) ; if (psf->filedes == -1) psf_log_syserr (psf, errno) ; return psf->filedes ;} /* psf_fopen *//* Win32 */ sf_count_tpsf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence){ sf_count_t new_position ; switch (whence) { case SEEK_SET : offset += psf->fileoffset ; break ; case SEEK_END : if (psf->mode == SFM_WRITE) { new_position = _lseeki64 (psf->filedes, offset, whence) ; if (new_position < 0) psf_log_syserr (psf, errno) ; return new_position - psf->fileoffset ; } ; /* Transform SEEK_END into a SEEK_SET, ie find the file ** length add the requested offset (should be <= 0) to ** get the offset wrt the start of file. */ whence = SEEK_SET ; offset = _lseeki64 (psf->filedes, 0, SEEK_END) + offset ; break ; default : /* No need to do anything about SEEK_CUR. */ break ; } ; /* ** Bypass weird Win32-ism if necessary. ** _lseeki64() returns an "invalid parameter" error if called with the ** offset == 0 and whence == SEEK_CUR. *** Use the _telli64() function instead. */ if (offset == 0 && whence == SEEK_CUR) new_position = _telli64 (psf->filedes) ; else new_position = _lseeki64 (psf->filedes, offset, whence) ; if (new_position < 0) psf_log_syserr (psf, errno) ; new_position -= psf->fileoffset ; return new_position ;} /* psf_fseek *//* Win32 */ sf_count_tpsf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf){ sf_count_t total = 0 ; ssize_t count ; items *= bytes ; /* Do this check after the multiplication above. */ if (items <= 0) return 0 ; while (items > 0) { /* Break the writes down to a sensible size. */ count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ; count = read (psf->filedes, ((char*) ptr) + total, (size_t) count) ; if (count == -1) { if (errno == EINTR) continue ; psf_log_syserr (psf, errno) ; break ; } ; if (count == 0) break ; total += count ; items -= count ; } ; return total / bytes ;} /* psf_fread *//* Win32 */ sf_count_tpsf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf){ sf_count_t total = 0 ; ssize_t count ; items *= bytes ; /* Do this check after the multiplication above. */ if (items <= 0) return 0 ; while (items > 0) { /* Break the writes down to a sensible size. */ count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : items ; count = write (psf->filedes, ((const char*) ptr) + total, count) ; if (count == -1) { if (errno == EINTR) continue ; psf_log_syserr (psf, errno) ; break ; } ; if (count == 0) break ; total += count ; items -= count ; } ; return total / bytes ;} /* psf_fwrite *//* Win32 */ sf_count_tpsf_ftell (SF_PRIVATE *psf){ sf_count_t pos ; pos = _telli64 (psf->filedes) ; if (pos == ((sf_count_t) -1)) { psf_log_syserr (psf, errno) ; return -1 ; } ; return pos - psf->fileoffset ;} /* psf_ftell *//* Win32 */ intpsf_fclose (SF_PRIVATE *psf){ int retval ; while ((retval = close (psf->filedes)) == -1 && errno == EINTR) /* Do nothing. */ ; if (retval == -1) psf_log_syserr (psf, errno) ; psf->filedes = -1 ; return retval ;} /* psf_fclose *//* Win32 */ sf_count_tpsf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf){ sf_count_t k = 0 ; sf_count_t count ; while (k < bufsize - 1) { count = read (psf->filedes, &(buffer [k]), 1) ; if (count == -1) { if (errno == EINTR) continue ; psf_log_syserr (psf, errno) ; break ; } ; if (count == 0 || buffer [k++] == '\n') break ; } ; buffer [k] = 0 ; return k ;} /* psf_fgets *//* Win32 */ intpsf_is_pipe (SF_PRIVATE *psf){ struct stat statbuf ; /* Not sure if this works. */ if (fstat (psf->filedes, &statbuf) == -1) { psf_log_syserr (psf, errno) ; /* Default to maximum safety. */ return SF_TRUE ; } ; /* These macros are defined in Win32/unistd.h. */ if (S_ISFIFO (statbuf.st_mode) || S_ISSOCK (statbuf.st_mode)) return SF_TRUE ; return SF_FALSE ;} /* psf_checkpipe *//* Win32 */ sf_count_tpsf_get_filelen (SF_PRIVATE *psf){#if 0 /* ** Windoze is SOOOOO FUCKED!!!!!!! ** This code should work but doesn't. Why? ** Code below does work. */ struct _stati64 statbuf ; if (_fstati64 (psf->filedes, &statbuf)) { psf_log_syserr (psf, errno) ; return (sf_count_t) -1 ; } ; return statbuf.st_size ;#else sf_count_t current, filelen ; if ((current = _telli64 (psf->filedes)) < 0) { psf_log_syserr (psf, errno) ; return (sf_count_t) -1 ; } ; /* ** Lets face it, windoze if FUBAR!!! ** ** For some reason, I have to call _lseeki64() TWICE to get to the ** end of the file. ** ** This might have been avoided if windows had implemented the POSIX ** standard function fsync() but NO, that would have been too easy. ** ** I am VERY close to saying that windoze will no longer be supported ** by libsndfile and changing the license to GPL at the same time. */ _lseeki64 (psf->filedes, 0, SEEK_END) ; if ((filelen = _lseeki64 (psf->filedes, 0, SEEK_END)) < 0) { psf_log_syserr (psf, errno) ; return (sf_count_t) -1 ; } ; if (filelen > current) _lseeki64 (psf->filedes, current, SEEK_SET) ; switch (psf->mode) { case SFM_WRITE : filelen = filelen - psf->fileoffset ; break ; case SFM_READ : if (psf->fileoffset > 0 && psf->filelength > 0) filelen = psf->filelength ; break ; case SFM_RDWR : /* ** Cannot open embedded files SFM_RDWR so we don't need to ** subtract psf->fileoffset. We already have the answer we ** need. */ break ; default : filelen = 0 ; } ; return filelen ;#endif} /* psf_get_filelen *//* Win32 */ intpsf_ftruncate (SF_PRIVATE *psf, sf_count_t len){ int retval ; /* Returns 0 on success, non-zero on failure. */ if (len < 0) return 1 ; /* The global village idiots at micorsoft decided to implement ** nearly all the required 64 bit file offset functions except ** for one, truncate. The fscking morons! ** ** This is not 64 bit file offset clean. Somone needs to clean ** this up. */ if (len > 0x7FFFFFFF) return -1 ; retval = chsize (psf->filedes, len) ; if (retval == -1) psf_log_syserr (psf, errno) ; return retval ;} /* psf_ftruncate */static voidpsf_log_syserr (SF_PRIVATE *psf, int error){ /* Only log an error if no error has been set yet. */ if (psf->error == 0) { psf->error = SFE_SYSTEM ; LSF_SNPRINTF (psf->syserr, sizeof (psf->syserr), "System error : %s", strerror (error)) ; } ; return ;} /* psf_log_syserr */#endif/*** Do not edit or modify anything in this comment block.** The arch-tag line is a file identity tag for the GNU Arch** revision control system.**** arch-tag: 749740d7-ecc7-47bd-8cf7-600f31d32e6d*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -