Leaked source code of windows server 2003
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.

237 lines
7.7 KiB

  1. /***
  2. *chsize.c - change size of a file
  3. *
  4. * Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * contains the _chsize() function - changes the size of a file.
  8. *
  9. *Revision History:
  10. * 03-13-84 RN initial version
  11. * 05-17-86 SKS ported to OS/2
  12. * 07-07-87 JCR Added (_doserrno == 5) check that is in DOS 3.2 version
  13. * 10-29-87 JCR Multi-thread support; also, re-wrote for efficiency
  14. * 12-11-87 JCR Added "_LOAD_DS" to declaration
  15. * 05-25-88 PHG Merged DLL and normal versions
  16. * 10-03-88 GJF Changed DOSNEWSIZE to SYSNEWSIZE
  17. * 10-10-88 GJF Made API names match DOSCALLS.H
  18. * 04-13-89 JCR New syscall interface
  19. * 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention
  20. * 03-12-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
  21. * <cruntime.h>, removed #include <register.h> and fixed
  22. * the copyright. Also, cleaned up the formatting a bit.
  23. * 04-04-90 GJF Added #include <string.h>, removed #include <dos.h>.
  24. * 05-21-90 GJF Fixed stack checking pragma syntax.
  25. * 07-24-90 SBM Replaced <assertm.h> by <assert.h>, removed '32'
  26. * from API names
  27. * 09-28-90 GJF New-style function declarator.
  28. * 12-03-90 GJF Appended Win32 version of the function. It is based
  29. * on the Cruiser version and probably could be merged
  30. * in later (much later).
  31. * 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
  32. * 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo
  33. * 12-28-90 SRW Added _CRUISER_ conditional around check_stack pragma
  34. * 01-16-91 GJF ANSI naming. Also, fixed _chsize_lk parameter decls.
  35. * 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_]
  36. * 04-09-91 PNT Added _MAC_ conditional
  37. * 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
  38. * 05-01-92 GJF Fixed embarrassing bug (didn't work for Win32)!
  39. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  40. * 05-11-93 GJF Replaced BUFSIZ with _INTERNAL_BUFSIZ.
  41. * 09-06-94 CFW Remove Cruiser support.
  42. * 09-06-94 CFW Replace MTHREAD with _MT.
  43. * 01-07-95 CFW Mac merge.
  44. * 02-06-95 CFW assert -> _ASSERTE.
  45. * 06-27-95 GJF Added check that the file handle is open.
  46. * 07-03-96 GJF Replaced defined(_WIN32) with !defined(_MAC), and
  47. * defined(_M_M68K) || defined(_M_MPPC) with
  48. * defined(_MAC). Also, detab-ed and cleaned up the
  49. * format a bit.
  50. * 12-17-97 GJF Exception-safe locking.
  51. * 05-17-99 PML Remove all Macintosh support.
  52. * 06-25-01 BWT Alloc blank buffer off the heap instead of the stack (ntbug: 423988)
  53. *
  54. *******************************************************************************/
  55. #include <cruntime.h>
  56. #include <errno.h>
  57. #include <stdlib.h>
  58. #include <stdio.h>
  59. #include <dbgint.h>
  60. #include <fcntl.h>
  61. #include <msdos.h>
  62. #include <io.h>
  63. #include <string.h>
  64. #include <windows.h>
  65. #include <internal.h>
  66. #include <mtdll.h>
  67. /***
  68. *int _chsize(filedes, size) - change size of a file
  69. *
  70. *Purpose:
  71. * Change file size. Assume file is open for writing, or we can't do it.
  72. * The DOS way to do this is to go to the right spot and write 0 bytes. The
  73. * Xenix way to do this is to make a system call. We write '\0' bytes because
  74. * DOS won't do this for you if you lseek beyond eof, though Xenix will.
  75. *
  76. *Entry:
  77. * int filedes - file handle to change size of
  78. * long size - new size of file
  79. *
  80. *Exit:
  81. * return 0 if successful
  82. * returns -1 and sets errno if fails
  83. *
  84. *Exceptions:
  85. *
  86. *******************************************************************************/
  87. #ifdef _MT
  88. /* define normal version that locks/unlocks, validates fh */
  89. int __cdecl _chsize (
  90. REG1 int filedes,
  91. long size
  92. )
  93. {
  94. int r; /* return value */
  95. if ( ((unsigned)filedes >= (unsigned)_nhandle) ||
  96. !(_osfile(filedes) & FOPEN) )
  97. {
  98. errno = EBADF;
  99. return(-1);
  100. }
  101. _lock_fh(filedes);
  102. __try {
  103. if ( _osfile(filedes) & FOPEN )
  104. r = _chsize_lk(filedes,size);
  105. else {
  106. errno = EBADF;
  107. r = -1;
  108. }
  109. }
  110. __finally {
  111. _unlock_fh(filedes);
  112. }
  113. return r;
  114. }
  115. /* now define version that doesn't lock/unlock, validate fh */
  116. int __cdecl _chsize_lk (
  117. REG1 int filedes,
  118. long size
  119. )
  120. {
  121. long filend;
  122. long extend;
  123. long place;
  124. int cnt;
  125. int oldmode;
  126. int retval = 0; /* assume good return */
  127. #else
  128. /* now define normal version */
  129. int __cdecl _chsize (
  130. REG1 int filedes,
  131. long size
  132. )
  133. {
  134. long filend;
  135. long extend;
  136. long place;
  137. int cnt;
  138. int oldmode;
  139. int retval = 0; /* assume good return */
  140. if ( ((unsigned)filedes >= (unsigned)_nhandle) ||
  141. !(_osfile(filedes) & FOPEN) )
  142. {
  143. errno = EBADF;
  144. return(-1);
  145. }
  146. #endif
  147. _ASSERTE(size >= 0);
  148. /* Get current file position and seek to end */
  149. if ( ((place = _lseek_lk(filedes, 0L, SEEK_CUR)) == -1L) ||
  150. ((filend = _lseek_lk(filedes, 0L, SEEK_END)) == -1L) )
  151. return -1;
  152. extend = size - filend;
  153. /* Grow or shrink the file as necessary */
  154. if (extend > 0L) {
  155. /* extending the file */
  156. char *bl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _INTERNAL_BUFSIZ);
  157. if (!bl) {
  158. errno = ENOMEM;
  159. retval= -1;
  160. } else {
  161. oldmode = _setmode_lk(filedes, _O_BINARY);
  162. /* pad out with nulls */
  163. do {
  164. cnt = (extend >= (long)_INTERNAL_BUFSIZ ) ?
  165. _INTERNAL_BUFSIZ : (int)extend;
  166. if ( (cnt = _write_lk( filedes,
  167. bl,
  168. (extend >= (long)_INTERNAL_BUFSIZ) ?
  169. _INTERNAL_BUFSIZ : (int)extend ))
  170. == -1 )
  171. {
  172. /* Error on write */
  173. if (_doserrno == ERROR_ACCESS_DENIED)
  174. errno = EACCES;
  175. retval = cnt;
  176. break; /* leave write loop */
  177. }
  178. }
  179. while ((extend -= (long)cnt) > 0L);
  180. _setmode_lk(filedes, oldmode);
  181. HeapFree(GetProcessHeap(), 0, bl);
  182. }
  183. /* retval set correctly */
  184. }
  185. else if ( extend < 0L ) {
  186. /* shortening the file */
  187. /*
  188. * Set file pointer to new eof...and truncate it there.
  189. */
  190. _lseek_lk(filedes, size, SEEK_SET);
  191. if ( (retval = SetEndOfFile((HANDLE)_get_osfhandle(filedes)) ?
  192. 0 : -1) == -1 )
  193. {
  194. errno = EACCES;
  195. _doserrno = GetLastError();
  196. }
  197. }
  198. /* else */
  199. /* no file change needed */
  200. /* retval = 0; */
  201. /* Common return code */
  202. _lseek_lk(filedes, place, SEEK_SET);
  203. return retval;
  204. }