home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional Developers Kit 1992 November / Disc01 / Disc01.mdf / runnable / mmos2 / mmtoolkt / samples / fssht / fsshseek.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-06  |  14.6 KB  |  291 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*                    Copyright (c) IBM Corporation 1992                    */
  4. /*                           All Rights Reserved                            */
  5. /*                                                                          */
  6. /* SOURCE FILE NAME: FSSHSEEK.C                                             */
  7. /*                                                                          */
  8. /* DESCRIPTIVE NAME:  Stream Handler Seek stream routine                    */
  9. /*                                                                          */
  10. /* FUNCTION: Seek a file system stream                                      */
  11. /*                                                                          */
  12. /* ENTRY POINTS: ShcSeek                                                    */
  13. /*                                                                          */
  14. /*************************** END OF SPECIFICATIONS **************************/
  15. #define  INCL_NOPMAPI                  /* no PM include files required */
  16. #define  INCL_DOSSEMAPHORES
  17. #define  INCL_DOSPROCESS
  18. #define  INCL_DOSERRORS
  19. #define  INCL_MMIO
  20. #include <os2.h>
  21. #include <os2me.h>
  22. #include <hhpheap.h>
  23. #include <shi.h>
  24. #include <fssh.h>
  25.  
  26. /************************** START OF SPECIFICATIONS *************************/
  27. /*                                                                          */
  28. /* SUBROUTINE NAME: ShcSeek                                                 */
  29. /*                                                                          */
  30. /* DESCRIPTIVE NAME: Stream Handler Command Seek stream routine.            */
  31. /*                                                                          */
  32. /* FUNCTION: This seeks the specified stream to the position specified by   */
  33. /*   lSeekPoint.  This seek point is qualified by the flags passed to       */
  34. /*   indicate if the seek is from 1) the beginning of the file; 2) from the */
  35. /*   current position in the file; or 3) from the end of the file.          */
  36. /*                                                                          */
  37. /* NOTES:                                                                   */
  38. /*                                                                          */
  39. /* ENTRY POINT: ShcSeek                                                     */
  40. /*   LINKAGE:   CALL NEAR (0:32)                                            */
  41. /*                                                                          */
  42. /* INPUT: Pointer to shc seek parameter block PARM_SEEK containing:         */
  43. /*   ULONG   ulFunction  Handler command function SHC_SEEK                  */
  44. /*   HID     hid         handler ID                                         */
  45. /*   HSTREAM hstream     handle of stream instance                          */
  46. /*   ULONG   ulFlags      Seek flag with following possible Flags:           */
  47. /*                         SPI_SEEK_ABSOLUTE                                */
  48. /*                         SPI_SEEK_RELATIVE                                */
  49. /*                         SPI_SEEK_FROMEND                                 */
  50. /*                         SPI_SEEK_SLAVES                                  */
  51. /*                         SPI_SEEK_MMTIME                                  */
  52. /*                         SPI_SEEK_BYTES                                   */
  53. /*   LONG    lSeekPoint  Seek position. Signed. Seeking from end should be  */
  54. /*                       negative.                                          */
  55. /*                                                                          */
  56. /* EXIT-NORMAL: NO_ERROR (0)                                                */
  57. /*                                                                          */
  58. /* EXIT-ERROR:                                                              */
  59. /*   ERROR_NOT_SEEKABLE_BY_TIME                                             */
  60. /*   ERROR_DATA_ITEM_NOT_SEEKABLE                                           */
  61. /*   ERROR_STREAM_NOT_STOP                                                  */
  62. /*   Errors from the external routines:                                     */
  63. /*     mmioSeek - the extended error code from mmioGetLastError             */
  64. /*     mmioSendMessage (MMIOM_SEEKBYTIME) - extended error code from        */
  65. /*                                          mmioGetLastError                */
  66. /*     ShFindSib - ERROR_INVALID_STREAM, and errors from DosRequestMutexSem */
  67. /*                                                                          */
  68. /* SIDE EFFECTS: The mmio file pointer is positioned to the new location.   */
  69. /*                                                                          */
  70. /* EXTERNAL REFERENCES:                                                     */
  71. /*   ROUTINES:                                                              */
  72. /*     mmioSeek                                                             */
  73. /*     mmioSendMessage                                                      */
  74. /*     mmioGetLastError                                                     */
  75. /*     ShFindSib                                                            */
  76. /*                                                                          */
  77. /*   DATA STRUCTURES: None                                                  */
  78. /*                                                                          */
  79. /*************************** END OF SPECIFICATIONS **************************/
  80.  
  81. RC ShcSeek(pskparm)
  82. PPARM_SEEK pskparm;
  83.  
  84. { /* Start of ShcSeek */
  85.  
  86. RC rc = NO_ERROR;                       // local return code
  87. PSIB psib;                              // Stream instance block
  88. ULONG ulrc;                             // temp rc from special seek
  89. LONG lByteSeekPoint;                    // Seek point in bytes
  90. LONG lAbsFilePos;                       // absolute file position from seek
  91. SHORT sTempFlags;                       // Flags to call mmioseek
  92. BOOL bSeekTried = FALSE;                // have we tried the seek yet?
  93.  
  94.   /*
  95.    * Find our Stream Instance Block
  96.    */
  97.   if (!(rc = ShFindSib(&psib, pskparm->hstream, pskparm->hid)))
  98.     { /* We have SIB */
  99.       //
  100.       // We can only seek when stopped in ready to run state
  101.       //
  102.       if ((psib->ulStatus == SIB_RUNNING) &&
  103.           !(psib->ulActionFlags & SIBACTFLG_THREAD_DEAD))
  104.         { /* Good state */
  105.           //
  106.           // Check if this datatype is phsically seekable. If not just return.
  107.           //
  108.  
  109.           if (!(psib->espcb.spcb.ulHandFlags & SPCBHAND_PHYS_SEEK))
  110.              {
  111.              return(rc);
  112.              }
  113.  
  114.           //
  115.           // Check if this datatype is seekable
  116.           //
  117.  
  118.           if (!(psib->espcb.spcb.ulDataFlags & SPCBDATA_NOSEEK))
  119.  
  120.             //
  121.             // and the psib->espcb.spcb.ulHandFlags field has a value of ?
  122.             // otherwise it this not a physically seekable target.
  123.             //
  124.  
  125.             { /* datatype is seekable */
  126.               //
  127.               // If seek by bytes, just use what's passed.  If not, then it
  128.               //  is in mmtime units.  So we must convert it to bytes first.
  129.               //
  130.               if (pskparm->ulFlags & SPI_SEEK_BYTES)
  131.                 {
  132.                   lByteSeekPoint = pskparm->lSeekPoint;
  133.                 }
  134.               else
  135.                 { /* in mmtime units, need to convert to bytes */
  136.                   //
  137.                   // Check the bytes per unit and mmtime per unit values.
  138.                   // If either are zero then we don't know how to convert the
  139.                   // time units passed into bytes so just call mmioSendMessage
  140.                   // with MMIOM_SEEKBYTIME, to see if the IOProc can figure it out.
  141.                   //
  142.                   if (psib->espcb.spcb.ulBytesPerUnit && psib->espcb.spcb.mmtimePerUnit)
  143.                     {
  144.                       //
  145.                       // Note: The algorithm used will round down the mmtime units
  146.                       //  requested to the next lowest multiple of a Unit.
  147.                       //
  148.                       lByteSeekPoint = psib->espcb.spcb.ulBytesPerUnit *
  149.                                   (pskparm->lSeekPoint / (LONG)psib->espcb.spcb.mmtimePerUnit);
  150.  
  151. #ifdef INLINE_ASM
  152.                       // Check to see if the calculation has overflowed
  153.                       // and caused the seek direction to be reversed.
  154.                       // This part uses in-line assembler to check the
  155.                       // overflow flag, and if it was set, return an error.
  156.                       _asm
  157.                         {
  158.                         jno NOOVERFLOW
  159.                         mov rc, ERROR_LARGE_SEEK_BY_TIME
  160. NOOVERFLOW:
  161.                         }
  162. #endif
  163.                     }
  164.                   else
  165.                     { /* don't know how to convert time to bytes */
  166.  
  167.                       ulrc = mmioSendMessage((HMMIO)psib->ulAssocP1,
  168.                                              MMIOM_SEEKBYTIME,
  169.                                              pskparm->lSeekPoint,
  170.                                              pskparm->ulFlags);
  171.                       //
  172.                       // The error processing is a little tricky for this message since
  173.                       // the IOProc will be handling the message just like a regular
  174.                       // Seek it will return values just as it would for Seek. So
  175.                       // the return value should be the new file position which could be
  176.                       // 0.  If an error occurs then MMIO_ERROR is returned and we need
  177.                       // to call getlasterror for the real error code.
  178.                       // Now, since this is actually being called using mmioSendMessage
  179.                       // it may return MMIO_ERROR for bad handle and the getlasterror
  180.                       // would return MMIO_INVALID_HANDLE.  Also, if the SEEKBYTIME
  181.                       // message is not supported then the mmioSendMessage rc will be
  182.                       // 0, and the getlasterror will be MMIOERR_UNSUPPORTED_MESSAGE.
  183.                       //
  184.                       if ((ulrc == MMIO_ERROR) || (ulrc == 0L))
  185.                         { /* Seek failed */
  186.                           rc = mmioGetLastError((HMMIO)psib->ulAssocP1);
  187.                         } /* Seek failed */
  188.  
  189.                       if ((ulrc == 0L) && (rc == MMIOERR_UNSUPPORTED_MESSAGE))
  190.                         rc = ERROR_NOT_SEEKABLE_BY_TIME;
  191.  
  192.                       bSeekTried = TRUE;
  193.  
  194.                       // Set the absolute file position in mmtime units.
  195.                       // NOTE: This is only implemented for SEEK_FROMEND now.
  196.  
  197.                       if (!rc)
  198.                         {
  199.                         if (pskparm->ulFlags & SPI_SEEK_FROMEND)
  200.                            pskparm->lSeekPoint = ulrc;
  201.                         }
  202.                     } /* don't know how to convert time to bytes */
  203.                 } /* in mmtime units, need to convert to bytes */
  204.  
  205.               if ((!rc) && (!bSeekTried))
  206.                 { /* ok to seek */
  207.                   //
  208.                   // Get rid of all flags but seek origin
  209.                   //
  210.                   sTempFlags = (SHORT)(pskparm->ulFlags &
  211.                                       (SPI_SEEK_RELATIVE+SPI_SEEK_ABSOLUTE+SPI_SEEK_FROMEND));
  212.  
  213.                   lAbsFilePos = mmioSeek((HMMIO)psib->ulAssocP1,
  214.                                          lByteSeekPoint,
  215.                                          sTempFlags);
  216.  
  217.                   if (lAbsFilePos == -1L)
  218.                     { /* Seek failed */
  219.                       rc = mmioGetLastError((HMMIO)psib->ulAssocP1);
  220.                     } /* Seek failed */
  221.                   else
  222.                      {
  223.                      // Seek was OK - set the absolute position in pksparm.
  224.                      // Set the position in either bytes or time, depending
  225.                      // on the seek mode that was requested.
  226.                      // NOTE: This is only implemented for SEEK_FROMEND now.
  227.  
  228.                      if (pskparm->ulFlags & SPI_SEEK_FROMEND)
  229.                         {
  230.  
  231.                         if (pskparm->ulFlags & SPI_SEEK_BYTES)
  232.                            {
  233.                            pskparm->lSeekPoint = lAbsFilePos;
  234.                            }
  235.                         else
  236.                            {
  237.                            //
  238.                            // Check the bytes per unit and mmtime per unit values.
  239.                            // If either are zero then we don't know how to convert
  240.                            // bytes back into time units.
  241.                            //
  242.                            if (psib->espcb.spcb.ulBytesPerUnit && psib->espcb.spcb.mmtimePerUnit)
  243.                               {
  244.                               //
  245.                               // Set the returned seek point to absolute offset in
  246.                               // mmtime units.
  247.                               //
  248.  
  249.                               pskparm->lSeekPoint = (lAbsFilePos / (LONG)psib->espcb.spcb.ulBytesPerUnit)
  250.                                                       * (LONG)psib->espcb.spcb.mmtimePerUnit;
  251.  
  252. #ifdef INLINE_ASM
  253.                               // Check to see if the calculation has overflowed
  254.                               // and caused the seek direction to be reversed.
  255.                               // This part uses in-line assembler to check the
  256.                               // overflow flag, and if it was set, return an error.
  257.                               _asm
  258.                                  {
  259.                                  jno NOTOVERFLOW
  260.                                  mov rc, ERROR_LARGE_SEEK_BY_TIME
  261. NOTOVERFLOW:
  262.                                  }
  263. #endif
  264.                               }
  265.                            else
  266.                               {
  267.                               rc = ERROR_NOT_SEEKABLE_BY_TIME;
  268.                               }
  269.                            }
  270.                         } /* Seek from END */
  271.                      } /* Seek was OK */
  272.                 }  /* ok to seek */
  273.             } /* datatype is seekable */
  274.           else
  275.             {
  276.               rc = ERROR_DATA_ITEM_NOT_SEEKABLE;
  277.             }
  278.         } /* Good state */
  279.       else
  280.         {
  281.           if (psib->ulStatus < SIB_RUNNING)
  282.             rc = ERROR_DATA_ITEM_NOT_SPECIFIED;
  283.           else
  284.             rc = ERROR_INVALID_SEQUENCE;
  285.         }
  286.     } /* We have SIB */
  287.  
  288.   return(rc);
  289.  
  290. } /* End of ShcSeek */
  291.