home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / lseek.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  8KB  |  273 lines

  1. /***
  2. *lseek.c - change file position
  3. *
  4. *       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines _lseek() - move the file pointer
  8. *
  9. *******************************************************************************/
  10.  
  11. #ifndef _MAC
  12.  
  13.  
  14. #include <cruntime.h>
  15. #include <oscalls.h>
  16. #include <mtdll.h>
  17. #include <io.h>
  18. #include <internal.h>
  19. #include <stdlib.h>
  20. #include <errno.h>
  21. #include <msdos.h>
  22. #include <stdio.h>
  23.  
  24. /***
  25. *long _lseek(fh,pos,mthd) - move the file pointer
  26. *
  27. *Purpose:
  28. *       Moves the file pointer associated with fh to a new position.
  29. *       The new position is pos bytes (pos may be negative) away
  30. *       from the origin specified by mthd.
  31. *
  32. *       If mthd == SEEK_SET, the origin in the beginning of file
  33. *       If mthd == SEEK_CUR, the origin is the current file pointer position
  34. *       If mthd == SEEK_END, the origin is the end of the file
  35. *
  36. *       Multi-thread:
  37. *       _lseek()    = locks/unlocks the file
  38. *       _lseek_lk() = does NOT lock/unlock the file (it is assumed that
  39. *                     the caller has the aquired the file lock,if needed).
  40. *
  41. *Entry:
  42. *       int fh - file handle to move file pointer on
  43. *       long pos - position to move to, relative to origin
  44. *       int mthd - specifies the origin pos is relative to (see above)
  45. *
  46. *Exit:
  47. *       returns the offset, in bytes, of the new position from the beginning
  48. *       of the file.
  49. *       returns -1L (and sets errno) if fails.
  50. *       Note that seeking beyond the end of the file is not an error.
  51. *       (although seeking before the beginning is.)
  52. *
  53. *Exceptions:
  54. *
  55. *******************************************************************************/
  56.  
  57. #ifdef _MT
  58.  
  59. /* define locking/validating lseek */
  60. long __cdecl _lseek (
  61.         int fh,
  62.         long pos,
  63.         int mthd
  64.         )
  65. {
  66.         int r;
  67.  
  68.         /* validate fh */
  69.         if ( ((unsigned)fh >= (unsigned)_nhandle) ||
  70.              !(_osfile(fh) & FOPEN) )
  71.         {
  72.                 /* bad file handle */
  73.                 errno = EBADF;
  74.                 _doserrno = 0;  /* not o.s. error */
  75.                 return -1;
  76.         }
  77.  
  78.         _lock_fh(fh);                   /* lock file handle */
  79.         r = _lseek_lk(fh, pos, mthd);   /* seek */
  80.         _unlock_fh(fh);                 /* unlock file handle */
  81.  
  82.         return r;
  83. }
  84.  
  85. /* define core _lseek -- doesn't lock or validate fh */
  86. long __cdecl _lseek_lk (
  87.         int fh,
  88.         long pos,
  89.         int mthd
  90.         )
  91. {
  92.         ULONG newpos;                   /* new file position */
  93.         ULONG dosretval;                /* o.s. return value */
  94.         HANDLE osHandle;        /* o.s. handle value */
  95.  
  96. #else  /* _MT */
  97.  
  98. /* define normal _lseek */
  99. long __cdecl _lseek (
  100.         int fh,
  101.         long pos,
  102.         int mthd
  103.         )
  104. {
  105.         ULONG newpos;                   /* new file position */
  106.         ULONG dosretval;                /* o.s. return value */
  107.         HANDLE osHandle;        /* o.s. handle value */
  108.  
  109.         /* validate fh */
  110.         if ( ((unsigned)fh >= (unsigned)_nhandle) ||
  111.              !(_osfile(fh) & FOPEN) )
  112.         {
  113.                 /* bad file handle */
  114.                 errno = EBADF;
  115.                 _doserrno = 0;  /* not o.s. error */
  116.                 return -1;
  117.         }
  118.  
  119. #endif  /* _MT */
  120.  
  121.         /* tell o.s. to seek */
  122.  
  123. #if SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END
  124.     #error Xenix and Win32 seek constants not compatible
  125. #endif  /* SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END */
  126.         if ((osHandle = (HANDLE)_get_osfhandle(fh)) == (HANDLE)-1)
  127.         {
  128.             errno = EBADF;
  129.             return -1;
  130.         }
  131.  
  132.         if ((newpos = SetFilePointer(osHandle, pos, NULL, mthd)) == -1)
  133.                 dosretval = GetLastError();
  134.         else
  135.                 dosretval = 0;
  136.  
  137.         if (dosretval) {
  138.                 /* o.s. error */
  139.                 _dosmaperr(dosretval);
  140.                 return -1;
  141.         }
  142.  
  143.         _osfile(fh) &= ~FEOFLAG;        /* clear the ctrl-z flag on the file */
  144.         return newpos;                  /* return */
  145. }
  146.  
  147.  
  148. #else  /* _MAC */
  149.  
  150.  
  151. #include <cruntime.h>
  152. #include <io.h>
  153. #include <internal.h>
  154. #include <stdlib.h>
  155. #include <errno.h>
  156. #include <memory.h>
  157. #include <msdos.h>
  158. #include <stdio.h>
  159. #include <string.h>
  160. #include <macos\files.h>
  161. #include <macos\errors.h>
  162.  
  163. /***
  164. *long _lseek(fh,pos,mthd) - move the file pointer
  165. *
  166. *Purpose:
  167. *       Moves the file pointer associated with fh to a new position.
  168. *       The new position is pos bytes (pos may be negative) away
  169. *       from the origin specified by mthd.
  170. *
  171. *       If mthd == SEEK_SET, the origin in the beginning of file
  172. *       If mthd == SEEK_CUR, the origin is the current file pointer position
  173. *       If mthd == SEEK_END, the origin is the end of the file
  174. *
  175. *Entry:
  176. *       int fh - file handle to move file pointer on
  177. *       long pos - position to move to, relative to origin
  178. *       int mthd - specifies the origin pos is relative to (see above)
  179. *
  180. *Exit:
  181. *       returns the offset, in bytes, of the new position from the beginning
  182. *       of the file.
  183. *       returns -1L (and sets errno) if fails.
  184. *       Note that seeking beyond the end of the file is not an error.
  185. *  Seeking beyond end of file extends the file to that length.
  186. *       (although seeking before the beginning is.)
  187. *
  188. *Exceptions:
  189. *
  190. *******************************************************************************/
  191.  
  192. long __cdecl _lseek (
  193.         int fh,
  194.         long pos,
  195.         int mthd
  196.         )
  197. {
  198.  
  199.         ParamBlockRec parm;
  200.         OSErr osErr;
  201.  
  202.         /* validate handle */
  203.         if ( (unsigned)fh >= (unsigned)_nfile ||
  204.              !(_osfile[fh] & FOPEN) ||
  205.              _osfile[fh] & FDEV )
  206.         {
  207.                 /* out of range -- return error */
  208.                 errno = EBADF;
  209.                 _macerrno = 0;
  210.                 return -1;
  211.         }
  212.  
  213.         switch (mthd)
  214.         {
  215.                 case SEEK_SET:
  216.                         osErr = 0;
  217.                         break;
  218.  
  219.                 case SEEK_CUR:
  220.                         memset(&parm, '\0', sizeof(ParamBlockRec));
  221.                         parm.ioParam.ioRefNum = _osfhnd[fh];
  222.                         osErr = PBGetFPosSync(&parm);
  223.                         pos += parm.ioParam.ioPosOffset;
  224.                         break;
  225.  
  226.                 case SEEK_END:
  227.                         memset(&parm, '\0', sizeof(ParamBlockRec));
  228.                         parm.ioParam.ioRefNum = _osfhnd[fh];
  229.                         osErr = PBGetEOFSync(&parm);
  230.                         pos += (long)parm.ioParam.ioMisc;
  231.                         break;
  232.  
  233.                 default:
  234.                         errno = EINVAL;
  235.                         return -1;
  236.         }
  237.  
  238.         if (!osErr)
  239.         {
  240.                 memset(&parm, '\0', sizeof(ParamBlockRec));
  241.                 parm.ioParam.ioRefNum = _osfhnd[fh];
  242.                 parm.ioParam.ioPosMode = fsFromStart;
  243.                 parm.ioParam.ioPosOffset = pos;
  244.                 osErr = PBSetFPosSync(&parm);
  245.                 if (osErr == eofErr)
  246.                 {
  247.                         /* extend file if positioning beyond EOF */
  248.                         memset(&parm, '\0', sizeof(ParamBlockRec));
  249.                         parm.ioParam.ioRefNum = _osfhnd[fh];
  250.                         (long)parm.ioParam.ioMisc = pos;
  251.                         osErr = PBSetEOFSync(&parm);
  252.                         if (!osErr)
  253.                         {
  254.                                 memset(&parm, '\0', sizeof(ParamBlockRec));
  255.                                 parm.ioParam.ioPosMode = fsFromStart;
  256.                                 parm.ioParam.ioRefNum = _osfhnd[fh];
  257.                                 parm.ioParam.ioPosOffset = pos;
  258.                                 osErr = PBSetFPosSync(&parm);
  259.                         }
  260.                 }
  261.         }
  262.         if (osErr)
  263.         {
  264.                 _dosmaperr(osErr);
  265.                 return -1;
  266.         }
  267.  
  268.         return parm.ioParam.ioPosOffset;
  269. }
  270.  
  271.  
  272. #endif  /* _MAC */
  273.