Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
7.0 KiB

  1. /***
  2. *locking.c - file locking function
  3. *
  4. * Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Defined the _locking() function - file locking and unlocking
  8. *
  9. *Revision History:
  10. * 06-09-89 PHG Module created, based on asm version
  11. * 08-10-89 JCR Changed DOS32FILELOCKS to DOS32SETFILELOCKS
  12. * 03-12-90 GJF Made calling type _CALLTYPE2 (for now), added #include
  13. * <cruntime.h> and fixed the copyright. Also, cleaned up
  14. * the formatting a bit.
  15. * 04-03-90 GJF Now _CALLTYPE1.
  16. * 07-24-90 SBM Removed '32' from API names
  17. * 08-14-90 SBM Compiles cleanly with -W3
  18. * 09-28-90 GJF New-style function declarator.
  19. * 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s.
  20. * It is enough different that there is little point in
  21. * trying to more closely merge the two versions.
  22. * 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
  23. * 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
  24. * 01-16-91 GJF ANSI naming.
  25. * 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_]
  26. * 12-05-91 GJF Fixed usage of [Un]LockFile APIs [_WIN32_].
  27. * 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
  28. * 05-06-92 SRW WIN32 LockFile API changed. [_WIN32_].
  29. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  30. * 09-06-94 CFW Remove Cruiser support.
  31. * 12-03-94 SKS Clean up OS/2 references
  32. * 01-04-95 GJF _WIN32_ -> _WIN32
  33. * 02-15-95 GJF Appended Mac version of source file (somewhat cleaned
  34. * up), with appropriate #ifdef-s.
  35. * 06-27-95 GJF Added check that the file handle is open.
  36. * 07-08-96 GJF Replaced defined(_WIN32) with !defined(_MAC), and
  37. * defined(_M_M68K) || defined(_M_MPPC) with
  38. * defined(_MAC). Also, detab-ed and cleaned up the
  39. * format a bit.
  40. * 12-19-97 GJF Exception-safe locking.
  41. * 05-17-99 PML Remove all Macintosh support.
  42. *
  43. *******************************************************************************/
  44. #include <cruntime.h>
  45. #include <oscalls.h>
  46. #include <errno.h>
  47. #include <sys\locking.h>
  48. #include <io.h>
  49. #include <stdlib.h>
  50. #include <internal.h>
  51. #include <msdos.h>
  52. #include <mtdll.h>
  53. #ifdef _MT
  54. static int __cdecl _locking_lk(int, int, long);
  55. #endif
  56. /***
  57. *int _locking(fh,lmode,nbytes) - file record locking function
  58. *
  59. *Purpose:
  60. * Locks or unlocks nbytes of a specified file
  61. *
  62. * Multi-thread - Must lock/unlock the file handle to prevent
  63. * other threads from working on the file at the same time as us.
  64. * [NOTE: We do NOT release the lock during the 1 second delays
  65. * since some other thread could get in and do something to the
  66. * file. The DOSFILELOCK call locks out other processes, not
  67. * threads, so there is no multi-thread deadlock at the DOS file
  68. * locking level.]
  69. *
  70. *Entry:
  71. * int fh - file handle
  72. * int lmode - locking mode:
  73. * _LK_LOCK/_LK_RLCK -> lock, retry 10 times
  74. * _LK_NBLCK/_LK_N_BRLCK -> lock, don't retry
  75. * _LK_UNLCK -> unlock
  76. * long nbytes - number of bytes to lock/unlock
  77. *
  78. *Exit:
  79. * returns 0 if successful
  80. * returns -1 and sets errno if unsuccessful
  81. *
  82. *Exceptions:
  83. *
  84. *******************************************************************************/
  85. int __cdecl _locking (
  86. int fh,
  87. int lmode,
  88. long nbytes
  89. )
  90. {
  91. #ifdef _MT
  92. int retval;
  93. #else
  94. ULONG dosretval; /* o.s. return code */
  95. LONG lockoffset;
  96. int retry; /* retry count */
  97. #endif
  98. /* validate file handle */
  99. if ( ((unsigned)fh >= (unsigned)_nhandle) ||
  100. !(_osfile(fh) & FOPEN) )
  101. {
  102. /* fh out of range */
  103. errno = EBADF;
  104. _doserrno = 0; /* not an o.s. error */
  105. return -1;
  106. }
  107. #ifdef _MT
  108. _lock_fh(fh); /* acquire file handle lock */
  109. __try {
  110. if ( _osfile(fh) & FOPEN )
  111. retval = _locking_lk(fh, lmode, nbytes);
  112. else {
  113. errno = EBADF;
  114. _doserrno = 0; /* not an o.s. error */
  115. retval = -1;
  116. }
  117. }
  118. __finally {
  119. _unlock_fh(fh);
  120. }
  121. return retval;
  122. }
  123. static int __cdecl _locking_lk (
  124. int fh,
  125. int lmode,
  126. long nbytes
  127. )
  128. {
  129. ULONG dosretval; /* o.s. return code */
  130. LONG lockoffset;
  131. int retry; /* retry count */
  132. #endif /* _MT */
  133. /* obtain current position in file by calling _lseek */
  134. /* Use _lseek_lk as we already own lock */
  135. lockoffset = _lseek_lk(fh, 0L, 1);
  136. if (lockoffset == -1)
  137. return -1;
  138. /* set retry count based on mode */
  139. if (lmode == _LK_LOCK || lmode == _LK_RLCK)
  140. retry = 9; /* retry 9 times */
  141. else
  142. retry = 0; /* don't retry */
  143. /* ask o.s. to lock the file until success or retry count finished */
  144. /* note that the only error possible is a locking violation, since */
  145. /* an invalid handle would have already failed above */
  146. for (;;) {
  147. dosretval = 0;
  148. if (lmode == _LK_UNLCK) {
  149. if ( !(UnlockFile((HANDLE)_get_osfhandle(fh),
  150. lockoffset,
  151. 0L,
  152. nbytes,
  153. 0L))
  154. )
  155. dosretval = GetLastError();
  156. } else {
  157. if ( !(LockFile((HANDLE)_get_osfhandle(fh),
  158. lockoffset,
  159. 0L,
  160. nbytes,
  161. 0L))
  162. )
  163. dosretval = GetLastError();
  164. }
  165. if (retry <= 0 || dosretval == 0)
  166. break; /* exit loop on success or retry exhausted */
  167. Sleep(1000L);
  168. --retry;
  169. }
  170. if (dosretval != 0) {
  171. /* o.s. error occurred -- file was already locked; if a
  172. blocking call, then return EDEADLOCK, otherwise map
  173. error normally */
  174. if (lmode == _LK_LOCK || lmode == _LK_RLCK) {
  175. errno = EDEADLOCK;
  176. _doserrno = dosretval;
  177. }
  178. else {
  179. _dosmaperr(dosretval);
  180. }
  181. return -1;
  182. }
  183. else
  184. return 0;
  185. }