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.

280 lines
9.0 KiB

  1. /***
  2. *stat64.c - get file status
  3. *
  4. * Copyright (c) 1998-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * defines _stat64() - get file status
  8. *
  9. *Revision History:
  10. * 06-02-98 GJF Created.
  11. * 11-10-99 GB Made changes so as 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 <ctype.h>
  19. #include <msdos.h>
  20. #include <oscalls.h>
  21. #include <string.h>
  22. #include <internal.h>
  23. #include <stdlib.h>
  24. #include <direct.h>
  25. #include <mbstring.h>
  26. #include <tchar.h>
  27. #define ISSLASH(a) ((a) == _T('\\') || (a) == _T('/'))
  28. /*
  29. * Number of 100 nanosecond units from 1/1/1601 to 1/1/1970
  30. */
  31. #define EPOCH_BIAS 116444736000000000i64
  32. #ifdef _UNICODE
  33. #define __tdtoxmode __wdtoxmode
  34. #else /* ndef _UNICODE */
  35. #define __tdtoxmode __dtoxmode
  36. #endif /* _UNICODE */
  37. /*
  38. * Local routine which returns true if the argument is a UNC name
  39. * specifying the root name of a share, such as '\\server\share\'.
  40. */
  41. static int IsRootUNCName(const _TSCHAR *path);
  42. extern unsigned short __cdecl __tdtoxmode(int, const _TSCHAR *);
  43. /***
  44. *int _stat64(name, buf) - get file status info
  45. *
  46. *Purpose:
  47. * _stat64 obtains information about the file and stores it in the
  48. * structure pointed to by buf.
  49. *
  50. * Note: Unlike _stat, _stat64 uses the UTC time values returned in
  51. * WIN32_FIND_DATA struct. This means the time values will always be
  52. * correct on NTFS, but may be wrong on FAT file systems for file times
  53. * whose DST state is different from the current DST state (this an NT
  54. * bug).
  55. *
  56. *Entry:
  57. * _TSCHAR *name - pathname of given file
  58. * struct _stat *buffer - pointer to buffer to store info in
  59. *
  60. *Exit:
  61. * fills in structure pointed to by buffer
  62. * returns 0 if successful
  63. * returns -1 and sets errno if unsuccessful
  64. *
  65. *Exceptions:
  66. *
  67. *******************************************************************************/
  68. int __cdecl _tstat64 (
  69. REG1 const _TSCHAR *name,
  70. REG2 struct __stat64 *buf
  71. )
  72. {
  73. _TSCHAR * path;
  74. _TSCHAR pathbuf[ _MAX_PATH ];
  75. int drive; /* A: = 1, B: = 2, etc. */
  76. HANDLE findhandle;
  77. WIN32_FIND_DATA findbuf;
  78. /* Don't allow wildcards to be interpreted by system */
  79. #ifdef _UNICODE
  80. if (wcspbrk(name, L"?*")) {
  81. #else
  82. if (_mbspbrk(name, "?*")) {
  83. #endif
  84. errno = ENOENT;
  85. _doserrno = E_nofile;
  86. return(-1);
  87. }
  88. /* Try to get disk from name. If none, get current disk. */
  89. if (name[1] == _T(':')){
  90. if ( *name && !name[2] ){
  91. errno = ENOENT; /* return an error if name is */
  92. _doserrno = E_nofile; /* just drive letter then colon */
  93. return( -1 );
  94. }
  95. drive = _totlower(*name) - _T('a') + 1;
  96. }
  97. else
  98. drive = _getdrive();
  99. /* Call Find Match File */
  100. findhandle = FindFirstFile((_TSCHAR *)name, &findbuf);
  101. if ( findhandle == INVALID_HANDLE_VALUE ) {
  102. #ifdef _UNICODE
  103. if ( !( wcspbrk(name, L"./\\") &&
  104. #else
  105. if ( !( _mbspbrk(name, "./\\") &&
  106. #endif
  107. (path = _tfullpath( pathbuf, name, _MAX_PATH )) &&
  108. /* root dir. ('C:\') or UNC root dir. ('\\server\share\') */
  109. ((_tcslen( path ) == 3) || IsRootUNCName(path)) &&
  110. (GetDriveType( path ) > 1) ) )
  111. {
  112. errno = ENOENT;
  113. _doserrno = E_nofile;
  114. return( -1 );
  115. }
  116. /*
  117. * Root directories (such as C:\ or \\server\share\ are fabricated.
  118. */
  119. findbuf.dwFileAttributes = A_D;
  120. findbuf.nFileSizeHigh = 0;
  121. findbuf.nFileSizeLow = 0;
  122. findbuf.cFileName[0] = _T('\0');
  123. buf->st_mtime = __loctotime64_t(1980,1,1,0,0,0, -1);
  124. buf->st_atime = buf->st_mtime;
  125. buf->st_ctime = buf->st_mtime;
  126. }
  127. else {
  128. SYSTEMTIME SystemTime;
  129. FILETIME LocalFTime;
  130. if ( !FileTimeToLocalFileTime( &findbuf.ftLastWriteTime,
  131. &LocalFTime ) ||
  132. !FileTimeToSystemTime( &LocalFTime, &SystemTime ) )
  133. {
  134. _dosmaperr( GetLastError() );
  135. FindClose( findhandle );
  136. return( -1 );
  137. }
  138. buf->st_mtime = __loctotime64_t( SystemTime.wYear,
  139. SystemTime.wMonth,
  140. SystemTime.wDay,
  141. SystemTime.wHour,
  142. SystemTime.wMinute,
  143. SystemTime.wSecond,
  144. -1 );
  145. if ( findbuf.ftLastAccessTime.dwLowDateTime ||
  146. findbuf.ftLastAccessTime.dwHighDateTime )
  147. {
  148. if ( !FileTimeToLocalFileTime( &findbuf.ftLastAccessTime,
  149. &LocalFTime ) ||
  150. !FileTimeToSystemTime( &LocalFTime, &SystemTime ) )
  151. {
  152. _dosmaperr( GetLastError() );
  153. FindClose( findhandle );
  154. return( -1 );
  155. }
  156. buf->st_atime = __loctotime64_t( SystemTime.wYear,
  157. SystemTime.wMonth,
  158. SystemTime.wDay,
  159. SystemTime.wHour,
  160. SystemTime.wMinute,
  161. SystemTime.wSecond,
  162. -1 );
  163. } else
  164. buf->st_atime = buf->st_mtime ;
  165. if ( findbuf.ftCreationTime.dwLowDateTime ||
  166. findbuf.ftCreationTime.dwHighDateTime )
  167. {
  168. if ( !FileTimeToLocalFileTime( &findbuf.ftCreationTime,
  169. &LocalFTime ) ||
  170. !FileTimeToSystemTime( &LocalFTime, &SystemTime ) )
  171. {
  172. _dosmaperr( GetLastError() );
  173. FindClose( findhandle );
  174. return( -1 );
  175. }
  176. buf->st_ctime = __loctotime64_t( SystemTime.wYear,
  177. SystemTime.wMonth,
  178. SystemTime.wDay,
  179. SystemTime.wHour,
  180. SystemTime.wMinute,
  181. SystemTime.wSecond,
  182. -1 );
  183. } else
  184. buf->st_ctime = buf->st_mtime ;
  185. FindClose(findhandle);
  186. }
  187. /* Fill in buf */
  188. buf->st_mode = __tdtoxmode(findbuf.dwFileAttributes, name);
  189. buf->st_nlink = 1;
  190. buf->st_size = ((__int64)(findbuf.nFileSizeHigh)) * (0x100000000i64) +
  191. (__int64)(findbuf.nFileSizeLow);
  192. /* now set the common fields */
  193. buf->st_uid = buf->st_gid = buf->st_ino = 0;
  194. buf->st_rdev = buf->st_dev = (_dev_t)(drive - 1); /* A=0, B=1, etc. */
  195. return(0);
  196. }
  197. /*
  198. * IsRootUNCName - returns TRUE if the argument is a UNC name specifying
  199. * a root share. That is, if it is of the form \\server\share\.
  200. * This routine will also return true if the argument is of the
  201. * form \\server\share (no trailing slash) but Win32 currently
  202. * does not like that form.
  203. *
  204. * Forward slashes ('/') may be used instead of backslashes ('\').
  205. */
  206. static int IsRootUNCName(const _TSCHAR *path)
  207. {
  208. /*
  209. * If a root UNC name, path will start with 2 (but not 3) slashes
  210. */
  211. if ( ( _tcslen ( path ) >= 5 ) /* minimum string is "//x/y" */
  212. && ISSLASH(path[0]) && ISSLASH(path[1]))
  213. {
  214. const _TSCHAR * p = path + 2 ;
  215. /*
  216. * find the slash between the server name and share name
  217. */
  218. while ( * ++ p )
  219. if ( ISSLASH(*p) )
  220. break ;
  221. if ( *p && p[1] )
  222. {
  223. /*
  224. * is there a further slash?
  225. */
  226. while ( * ++ p )
  227. if ( ISSLASH(*p) )
  228. break ;
  229. /*
  230. * just final slash (or no final slash)
  231. */
  232. if ( !*p || !p[1])
  233. return 1;
  234. }
  235. }
  236. return 0 ;
  237. }