Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /****************************************************************************
  2. *
  3. *                            Open Watcom Project
  4. *
  5. *    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
  6. *
  7. *  ========================================================================
  8. *
  9. *    This file contains Original Code and/or Modifications of Original
  10. *    Code as defined in and that are subject to the Sybase Open Watcom
  11. *    Public License version 1.0 (the 'License'). You may not use this file
  12. *    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
  13. *    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
  14. *    provided with the Original Code and Modifications, and is also
  15. *    available at www.sybase.com/developer/opensource.
  16. *
  17. *    The Original Code and all software distributed under the License are
  18. *    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  19. *    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
  20. *    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
  21. *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
  22. *    NON-INFRINGEMENT. Please see the License for the specific language
  23. *    governing rights and limitations under the License.
  24. *
  25. *  ========================================================================
  26. *
  27. * Description:  Implementation of fseek - set stream position.
  28. *
  29. ****************************************************************************/
  30.  
  31.  
  32. #include "variety.h"
  33. #include <stdio.h>
  34. #include <errno.h>
  35. #include <unistd.h>
  36. #include "fileacc.h"
  37. #include "rtdata.h"
  38. #include "seterrno.h"
  39. #include "flush.h"
  40.  
  41.  
  42. static int __update_buffer( long diff, FILE *fp )
  43. {
  44.     /*
  45.       diff is relative to fp->_ptr
  46.       if diff is within the buffer update the pointers and return 0
  47.       otherwise update the pointers and return 1
  48.     */
  49.     if( diff <= fp->_cnt  &&  diff >= (_FP_BASE(fp) - fp->_ptr) ) {
  50.         fp->_flag &= ~(_EOF);
  51.         fp->_ptr += diff;
  52.         fp->_cnt -= diff;
  53.         return( 0 );
  54.     }
  55.     return( 1 );
  56. }
  57.  
  58.  
  59. /*
  60.  * This used to be in __update_buffer(), but we don't want to do this until
  61.  * AFTER we've made certain that lseek() will be a successful one.
  62.  */
  63. static void __reset_buffer( FILE *fp )
  64. {
  65.     fp->_flag &= ~(_EOF);
  66.     fp->_ptr = _FP_BASE(fp);
  67.     fp->_cnt = 0;
  68. }
  69.  
  70.  
  71. _WCRTLINK int fseek( FILE *fp, long offset, int origin )
  72. {
  73.     _ValidFile( fp, -1 );
  74.     _AccessFile( fp );
  75.     /*
  76.       if the file is open for any sort of writing we must ensure that
  77.       the buffer is flushed when dirty so that the integrity of the
  78.       data is preserved.
  79.       if there is an ungotten character in the buffer then the data must
  80.       be discarded to ensure the integrity of the data
  81.     */
  82.     if( fp->_flag & (_WRITE | _UNGET) ) {
  83.         if( fp->_flag & _DIRTY ) {
  84.             /*
  85.               the __flush routine aligns the DOS file pointer with the
  86.               start of the resulting cleared buffer, as such, the SEEK_CUR
  87.               code used for the non-_DIRTY buffer case is not required
  88.             */
  89.             if( __flush( fp ) ) {
  90.                 // assume __flush set the errno value
  91.                 // if erroneous input, override errno value
  92.                 if( origin == SEEK_SET && offset < 0 ) {
  93.                     __set_errno( EINVAL );
  94.                 }
  95.                 _ReleaseFile( fp );
  96.                 return( -1 );
  97.             }
  98.         } else {
  99.             if( origin == SEEK_CUR ) {
  100.                 offset -= fp->_cnt;
  101.             }
  102.             fp->_ptr = _FP_BASE(fp);
  103.             fp->_cnt = 0;
  104.         }
  105.         fp->_flag &= ~(_EOF|_UNGET);
  106.         if( lseek( fileno( fp ), offset, origin ) == -1 ) {
  107.             _ReleaseFile( fp );
  108.             return( -1 );
  109.         }
  110.     } else {
  111.         // file is open for read only,
  112.         // no characters have been ungotten
  113.         // the OS file pointer is at fp->_ptr + fp->_cnt relative to the
  114.         // FILE* buffer
  115.         switch( origin ) {
  116.         case SEEK_CUR:
  117.         {   long    ptr_delta = fp->_cnt;
  118.  
  119.             if( __update_buffer( offset, fp ) ) {
  120.                 offset -= ptr_delta;
  121.                 if( lseek( fileno( fp ), offset, origin ) == -1 ) {
  122.                     _ReleaseFile( fp );
  123.                     return( -1 );
  124.                 }
  125.                 __reset_buffer(fp);
  126.             }
  127.         }   break;
  128.         case SEEK_SET:
  129.         {   long    file_ptr = tell( fileno( fp ) );
  130.  
  131.             file_ptr -= fp->_cnt;
  132.             if( __update_buffer( offset - file_ptr, fp ) ) {
  133.                 if( lseek( fileno( fp ), offset, origin ) == -1 ) {
  134.                     _ReleaseFile( fp );
  135.                     return( -1 );
  136.                 }
  137.                 __reset_buffer(fp);
  138.             }
  139.         }   break;
  140.         case SEEK_END:
  141.             fp->_flag &= ~(_EOF);
  142.             fp->_ptr = _FP_BASE(fp);
  143.             fp->_cnt = 0;
  144.             if( lseek( fileno( fp ), offset, origin ) == -1 ) {
  145.                 _ReleaseFile( fp );
  146.                 return( -1 );
  147.             }
  148.             break;
  149.         default:
  150.             __set_errno( EINVAL );
  151.             _ReleaseFile( fp );
  152.             return( -1 );
  153.         }
  154.     }
  155.     _ReleaseFile( fp );
  156.     return( 0 );            /* indicate success */
  157. }
  158.