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.

331 lines
12 KiB

  1. /***
  2. *fstat.c - return file status info
  3. *
  4. * Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * defines fstat() - return file status info
  8. *
  9. *Revision History:
  10. * 03-??-84 RLB Module created
  11. * 05-??-84 DCW Added register variables
  12. * 05-19-86 SKS Ported to OS/2
  13. * 05-21-87 SKS Cleaned up declarations and include files
  14. * 11-01-87 JCR Multi-thread support
  15. * 12-11-87 JCR Added "_LOAD_DS" to declaration
  16. * 05-25-88 PHG Merged DLL and normal version
  17. * 10-03-88 GJF Adapted for new DOSCALLS.H, DOSTYPES.H.
  18. * 10-04-88 JCR 386: Removed 'far' keyword
  19. * 10-10-88 GJF Made API names match DOSCALLS.H
  20. * 11-07-88 GJF Cleanup, now specific to 386
  21. * 04-13-89 JCR New syscall interface
  22. * 05-23-89 PHG Added mask to ignore network bit when testing handle
  23. * type
  24. * 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention
  25. * 03-12-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
  26. * <cruntime.h>, removed #include <register.h> and fixed
  27. * the copyright. Also, cleaned up the formatting a bit.
  28. * 04-04-90 GJF Removed #include <dos.h>.
  29. * 07-24-90 SBM Removed '32' from API names
  30. * 08-13-90 SBM Compiles cleanly with -W3
  31. * 09-28-90 GJF New-style function declarator.
  32. * 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
  33. * 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
  34. * 01-21-91 GJF ANSI naming.
  35. * 04-26-91 SRW Implemented fstat for _WIN32_ and removed level 3
  36. * warnings.
  37. * 02-13-92 GJF Replaced _nfile by _nhandle for Win32.
  38. * 05-27-92 SKS File Creation and File Last Access timestamps may be 0
  39. * on some file systems (e.g. FAT) in which case the
  40. * File Last Write time should be used instead.
  41. * 06-04-92 SKS Changed comment that used to say "This is a BUG!"
  42. * to explain that this value cannot be computed on
  43. * OS/2 or NT. Only MS-DOS provides this functionality.
  44. * The drive number is not valid for UNC names.
  45. * 06-25-92 GJF Use GetFileInformationByHandle API, also cleaned up
  46. * formatting of Win32 verson [_WIN32_].
  47. * 08-18-92 SKS Add a call to FileTimeToLocalFileTime
  48. * as a temporary fix until _dtoxtime takes UTC
  49. * 08-20-92 GJF Merged two changes above.
  50. * 12-16-92 GJF Win32 GetFileInformationByHandle API doesn't like
  51. * device or pipe handles. Use _S_IFIFO for pipes.
  52. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  53. * 04-06-93 GJF Made computation of file times consistent with _stat().
  54. * 07-21-93 GJF Converted from using __gmtotime_t to __loctotime_t.
  55. * This undoes part of the change made on 04-06-92
  56. * 12-28-94 GJF Added _fstati64.
  57. * 02-15-95 GJF Appended Mac version of source file (somewhat cleaned
  58. * up), with appropriate #ifdef-s.
  59. * 06-11-95 GJF Replaced _osfhnd[] with _osfhnd() (macro referencing
  60. * field in ioinfo struct).
  61. * 06-27-95 GJF Added check that the file handle is open.
  62. * 09-25-95 GJF __loctotime_t now takes a DST flag, pass -1 in this
  63. * slot to indicate DST is undetermined.
  64. * 07-08-96 GJF Replaced defined(_WIN32) with !defined(_MAC), and
  65. * defined(_M_M68K) || defined(_M_MPPC) with
  66. * defined(_MAC). Removed obsolete REG* macros. Also,
  67. * detab-ed and cleaned up the format a bit.
  68. * 12-19-97 GJF Exception-safe locking.
  69. * 05-17-99 PML Remove all Macintosh support.
  70. * 10-27-99 GB Remove #inlcude <dostypes.h>
  71. *
  72. *******************************************************************************/
  73. #include <cruntime.h>
  74. #include <sys/types.h>
  75. #include <sys/stat.h>
  76. #include <errno.h>
  77. #include <msdos.h>
  78. #include <io.h>
  79. #include <internal.h>
  80. #include <stddef.h>
  81. #include <oscalls.h>
  82. #include <stdio.h>
  83. #include <mtdll.h>
  84. #include <time.h>
  85. #define IO_DEVNBR 0x3f
  86. /***
  87. *int _fstat(fildes, buf) - fills supplied buffer with status info
  88. *
  89. *Purpose:
  90. * Fills the supplied buffer with status information on the
  91. * file represented by the specified file designator.
  92. * WARNING: the dev/rdev fields are zero for files. This is
  93. * incompatible with DOS 3 version of this routine.
  94. *
  95. * Note: We cannot directly use the file time stamps returned in the
  96. * BY_HANDLE_FILE_INFORMATION structure. The values are supposedly in
  97. * system time and system time is ambiguously defined (it is UTC for
  98. * Windows NT, local time for Win32S and probably local time for
  99. * Win32C). Therefore, these values must be converted to local time
  100. * before than can be used.
  101. *
  102. *Entry:
  103. * int fildes - file descriptor
  104. * struct stat *buf - buffer to store result in
  105. *
  106. *Exit:
  107. * fills in buffer pointed to by buf
  108. * returns 0 if successful
  109. * returns -1 and sets errno if unsuccessful
  110. *
  111. *Exceptions:
  112. *
  113. *******************************************************************************/
  114. #ifdef _USE_INT64
  115. int __cdecl _fstati64 (
  116. int fildes,
  117. struct _stati64 *buf
  118. )
  119. #else /* ndef _USE_INT64 */
  120. int __cdecl _fstat (
  121. int fildes,
  122. struct _stat *buf
  123. )
  124. #endif /* _USE_INT64 */
  125. {
  126. int isdev; /* 0 for a file, 1 for a device */
  127. int retval = 0; /* assume good return */
  128. BY_HANDLE_FILE_INFORMATION bhfi;
  129. FILETIME LocalFTime;
  130. SYSTEMTIME SystemTime;
  131. if ( ((unsigned)fildes >= (unsigned)_nhandle) ||
  132. !(_osfile(fildes) & FOPEN) )
  133. {
  134. errno = EBADF;
  135. return(-1);
  136. }
  137. #ifdef _MT
  138. /* Lock the file */
  139. _lock_fh(fildes);
  140. __try {
  141. if ( !(_osfile(fildes) & FOPEN) ) {
  142. errno = EBADF;
  143. retval = -1;
  144. goto done;
  145. }
  146. #endif /* _MT */
  147. /* Find out what kind of handle underlies filedes
  148. */
  149. isdev = GetFileType((HANDLE)_osfhnd(fildes)) & ~FILE_TYPE_REMOTE;
  150. if ( isdev != FILE_TYPE_DISK ) {
  151. /* not a disk file. probably a device or pipe
  152. */
  153. if ( (isdev == FILE_TYPE_CHAR) || (isdev == FILE_TYPE_PIPE) ) {
  154. /* treat pipes and devices similarly. no further info is
  155. * available from any API, so set the fields as reasonably
  156. * as possible and return.
  157. */
  158. if ( isdev == FILE_TYPE_CHAR )
  159. buf->st_mode = _S_IFCHR;
  160. else
  161. buf->st_mode = _S_IFIFO;
  162. buf->st_rdev = buf->st_dev = (_dev_t)fildes;
  163. buf->st_nlink = 1;
  164. buf->st_uid = buf->st_gid = buf->st_ino = 0;
  165. buf->st_atime = buf->st_mtime = buf->st_ctime = 0;
  166. if ( isdev == FILE_TYPE_CHAR ) {
  167. #ifdef _USE_INT64
  168. buf->st_size = 0i64;
  169. #else /* ndef _USE_INT64 */
  170. buf->st_size = 0;
  171. #endif /* _USE_INT64 */
  172. }
  173. else {
  174. unsigned long ulAvail;
  175. int rc;
  176. rc = PeekNamedPipe((HANDLE)_osfhnd(fildes),
  177. NULL,
  178. 0,
  179. NULL,
  180. &ulAvail,
  181. NULL);
  182. if (rc) {
  183. buf->st_size = (_off_t)ulAvail;
  184. }
  185. else {
  186. buf->st_size = (_off_t)0;
  187. }
  188. }
  189. goto done;
  190. }
  191. else if ( isdev == FILE_TYPE_UNKNOWN ) {
  192. errno = EBADF;
  193. retval = -1;
  194. goto done; /* join common return code */
  195. }
  196. else {
  197. /* according to the documentation, this cannot happen, but
  198. * play it safe anyway.
  199. */
  200. _dosmaperr(GetLastError());
  201. retval = -1;
  202. goto done;
  203. }
  204. }
  205. /* set the common fields
  206. */
  207. buf->st_ino = buf->st_uid = buf->st_gid = buf->st_mode = 0;
  208. buf->st_nlink = 1;
  209. /* use the file handle to get all the info about the file
  210. */
  211. if ( !GetFileInformationByHandle((HANDLE)_osfhnd(fildes), &bhfi) ) {
  212. _dosmaperr(GetLastError());
  213. retval = -1;
  214. goto done;
  215. }
  216. if ( bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY )
  217. buf->st_mode |= (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6));
  218. else
  219. buf->st_mode |= ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3)
  220. + ((_S_IREAD|_S_IWRITE) >> 6));
  221. /* set file date fields
  222. */
  223. if ( !FileTimeToLocalFileTime( &(bhfi.ftLastWriteTime), &LocalFTime )
  224. || !FileTimeToSystemTime( &LocalFTime, &SystemTime ) )
  225. {
  226. retval = -1;
  227. goto done;
  228. }
  229. buf->st_mtime = __loctotime_t(SystemTime.wYear,
  230. SystemTime.wMonth,
  231. SystemTime.wDay,
  232. SystemTime.wHour,
  233. SystemTime.wMinute,
  234. SystemTime.wSecond,
  235. -1);
  236. if ( bhfi.ftLastAccessTime.dwLowDateTime ||
  237. bhfi.ftLastAccessTime.dwHighDateTime )
  238. {
  239. if ( !FileTimeToLocalFileTime( &(bhfi.ftLastAccessTime),
  240. &LocalFTime ) ||
  241. !FileTimeToSystemTime( &LocalFTime, &SystemTime ) )
  242. {
  243. retval = -1;
  244. goto done;
  245. }
  246. buf->st_atime = __loctotime_t(SystemTime.wYear,
  247. SystemTime.wMonth,
  248. SystemTime.wDay,
  249. SystemTime.wHour,
  250. SystemTime.wMinute,
  251. SystemTime.wSecond,
  252. -1);
  253. }
  254. else
  255. buf->st_atime = buf->st_mtime;
  256. if ( bhfi.ftCreationTime.dwLowDateTime ||
  257. bhfi.ftCreationTime.dwHighDateTime )
  258. {
  259. if ( !FileTimeToLocalFileTime( &(bhfi.ftCreationTime),
  260. &LocalFTime ) ||
  261. !FileTimeToSystemTime( &LocalFTime, &SystemTime ) )
  262. {
  263. retval = -1;
  264. goto done;
  265. }
  266. buf->st_ctime = __loctotime_t(SystemTime.wYear,
  267. SystemTime.wMonth,
  268. SystemTime.wDay,
  269. SystemTime.wHour,
  270. SystemTime.wMinute,
  271. SystemTime.wSecond,
  272. -1);
  273. }
  274. else
  275. buf->st_ctime = buf->st_mtime;
  276. #ifdef _USE_INT64
  277. buf->st_size = ((__int64)(bhfi.nFileSizeHigh)) * (0x100000000i64) +
  278. (__int64)(bhfi.nFileSizeLow);
  279. #else /* ndef _USE_INT64 */
  280. buf->st_size = bhfi.nFileSizeLow;
  281. #endif /* _USE_INT64 */
  282. buf->st_mode |= _S_IFREG;
  283. /* On DOS, this field contains the drive number, but
  284. * the drive number is not available on this platform.
  285. * Also, for UNC network names, there is no drive number.
  286. */
  287. buf->st_rdev = buf->st_dev = 0;
  288. /* Common return code */
  289. done:
  290. #ifdef _MT
  291. ; }
  292. __finally {
  293. _unlock_fh(fildes);
  294. }
  295. #endif /* _MT */
  296. return(retval);
  297. }