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.

259 lines
8.4 KiB

  1. /***
  2. *fstat64.c - return file status info
  3. *
  4. * Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * defines _fstat64() - return file status info
  8. *
  9. *Revision History:
  10. * 06-02-98 GJF Created.
  11. * 11-10-99 GB Made modifications to take care of DST.
  12. *
  13. *******************************************************************************/
  14. #include <cruntime.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <errno.h>
  18. #include <msdos.h>
  19. #include <io.h>
  20. #include <internal.h>
  21. #include <stddef.h>
  22. #include <oscalls.h>
  23. #include <stdio.h>
  24. #include <mtdll.h>
  25. #include <time.h>
  26. #define IO_DEVNBR 0x3f
  27. /*
  28. * Number of 100 nanosecond units from 1/1/1601 to 1/1/1970
  29. */
  30. #define EPOCH_BIAS 116444736000000000i64
  31. /***
  32. *int _fstat64(fildes, buf) - fills supplied buffer with status info
  33. *
  34. *Purpose:
  35. * Fills the supplied buffer with status information on the
  36. * file represented by the specified file designator.
  37. * WARNING: the dev/rdev fields are zero for files. This is
  38. * incompatible with DOS 3 version of this routine.
  39. *
  40. * Note: Unlike fstat, _fstat64 uses the UTC time values returned in the
  41. * BY_HANDLE_FILE_INFORMATION struct. This means the time values will
  42. * always be correct on NTFS, but may be wrong on FAT file systems for
  43. * file times whose DST state is different from the current DST state
  44. * (this an NT bug).
  45. *
  46. *Entry:
  47. * int fildes - file descriptor
  48. * struct _stat64 *buf - buffer to store result in
  49. *
  50. *Exit:
  51. * fills in buffer pointed to by buf
  52. * returns 0 if successful
  53. * returns -1 and sets errno if unsuccessful
  54. *
  55. *Exceptions:
  56. *
  57. *******************************************************************************/
  58. int __cdecl _fstat64 (
  59. int fildes,
  60. struct __stat64 *buf
  61. )
  62. {
  63. int isdev; /* 0 for a file, 1 for a device */
  64. int retval = 0; /* assume good return */
  65. BY_HANDLE_FILE_INFORMATION bhfi;
  66. FILETIME LocalFTime;
  67. SYSTEMTIME SystemTime;
  68. if ( ((unsigned)fildes >= (unsigned)_nhandle) ||
  69. !(_osfile(fildes) & FOPEN) )
  70. {
  71. errno = EBADF;
  72. return(-1);
  73. }
  74. #ifdef _MT
  75. /* Lock the file */
  76. _lock_fh(fildes);
  77. __try {
  78. if ( !(_osfile(fildes) & FOPEN) ) {
  79. errno = EBADF;
  80. retval = -1;
  81. goto done;
  82. }
  83. #endif /* _MT */
  84. /* Find out what kind of handle underlies filedes
  85. */
  86. isdev = GetFileType((HANDLE)_osfhnd(fildes)) & ~FILE_TYPE_REMOTE;
  87. if ( isdev != FILE_TYPE_DISK ) {
  88. /* not a disk file. probably a device or pipe
  89. */
  90. if ( (isdev == FILE_TYPE_CHAR) || (isdev == FILE_TYPE_PIPE) ) {
  91. /* treat pipes and devices similarly. no further info is
  92. * available from any API, so set the fields as reasonably
  93. * as possible and return.
  94. */
  95. if ( isdev == FILE_TYPE_CHAR )
  96. buf->st_mode = _S_IFCHR;
  97. else
  98. buf->st_mode = _S_IFIFO;
  99. buf->st_rdev = buf->st_dev = (_dev_t)fildes;
  100. buf->st_nlink = 1;
  101. buf->st_uid = buf->st_gid = buf->st_ino = 0;
  102. buf->st_atime = buf->st_mtime = buf->st_ctime = 0;
  103. if ( isdev == FILE_TYPE_CHAR ) {
  104. buf->st_size = 0i64;
  105. }
  106. else {
  107. unsigned long ulAvail;
  108. int rc;
  109. rc = PeekNamedPipe((HANDLE)_osfhnd(fildes),
  110. NULL,
  111. 0,
  112. NULL,
  113. &ulAvail,
  114. NULL);
  115. if (rc) {
  116. buf->st_size = (_off_t)ulAvail;
  117. }
  118. else {
  119. buf->st_size = (_off_t)0;
  120. }
  121. }
  122. goto done;
  123. }
  124. else if ( isdev == FILE_TYPE_UNKNOWN ) {
  125. errno = EBADF;
  126. retval = -1;
  127. goto done; /* join common return code */
  128. }
  129. else {
  130. /* according to the documentation, this cannot happen, but
  131. * play it safe anyway.
  132. */
  133. _dosmaperr(GetLastError());
  134. retval = -1;
  135. goto done;
  136. }
  137. }
  138. /* set the common fields
  139. */
  140. buf->st_ino = buf->st_uid = buf->st_gid = buf->st_mode = 0;
  141. buf->st_nlink = 1;
  142. /* use the file handle to get all the info about the file
  143. */
  144. if ( !GetFileInformationByHandle((HANDLE)_osfhnd(fildes), &bhfi) ) {
  145. _dosmaperr(GetLastError());
  146. retval = -1;
  147. goto done;
  148. }
  149. if ( bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY )
  150. buf->st_mode |= (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6));
  151. else
  152. buf->st_mode |= ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3)
  153. + ((_S_IREAD|_S_IWRITE) >> 6));
  154. /* set file date fields
  155. */
  156. if ( !FileTimeToLocalFileTime( &(bhfi.ftLastWriteTime), &LocalFTime )
  157. || !FileTimeToSystemTime( &LocalFTime, &SystemTime ) )
  158. {
  159. retval = -1;
  160. goto done;
  161. }
  162. buf->st_mtime = __loctotime64_t(SystemTime.wYear,
  163. SystemTime.wMonth,
  164. SystemTime.wDay,
  165. SystemTime.wHour,
  166. SystemTime.wMinute,
  167. SystemTime.wSecond,
  168. -1);
  169. if ( bhfi.ftLastAccessTime.dwLowDateTime ||
  170. bhfi.ftLastAccessTime.dwHighDateTime )
  171. {
  172. if ( !FileTimeToLocalFileTime( &(bhfi.ftLastAccessTime),
  173. &LocalFTime ) ||
  174. !FileTimeToSystemTime( &LocalFTime, &SystemTime ) )
  175. {
  176. retval = -1;
  177. goto done;
  178. }
  179. buf->st_atime = __loctotime64_t(SystemTime.wYear,
  180. SystemTime.wMonth,
  181. SystemTime.wDay,
  182. SystemTime.wHour,
  183. SystemTime.wMinute,
  184. SystemTime.wSecond,
  185. -1);
  186. }
  187. else
  188. buf->st_atime = buf->st_mtime;
  189. if ( bhfi.ftCreationTime.dwLowDateTime ||
  190. bhfi.ftCreationTime.dwHighDateTime )
  191. {
  192. if ( !FileTimeToLocalFileTime( &(bhfi.ftCreationTime),
  193. &LocalFTime ) ||
  194. !FileTimeToSystemTime( &LocalFTime, &SystemTime ) )
  195. {
  196. retval = -1;
  197. goto done;
  198. }
  199. buf->st_ctime = __loctotime64_t(SystemTime.wYear,
  200. SystemTime.wMonth,
  201. SystemTime.wDay,
  202. SystemTime.wHour,
  203. SystemTime.wMinute,
  204. SystemTime.wSecond,
  205. -1);
  206. }
  207. else
  208. buf->st_ctime = buf->st_mtime;
  209. buf->st_size = ((__int64)(bhfi.nFileSizeHigh)) * (0x100000000i64) +
  210. (__int64)(bhfi.nFileSizeLow);
  211. buf->st_mode |= _S_IFREG;
  212. /* On DOS, this field contains the drive number, but
  213. * the drive number is not available on this platform.
  214. * Also, for UNC network names, there is no drive number.
  215. */
  216. buf->st_rdev = buf->st_dev = 0;
  217. /* Common return code */
  218. done:
  219. #ifdef _MT
  220. ; }
  221. __finally {
  222. _unlock_fh(fildes);
  223. }
  224. #endif /* _MT */
  225. return(retval);
  226. }