filest.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #include <errno.h>
  12. #include <io.h>
  13. #include <sys\types.h>
  14. #include <sys\stat.h>
  15. #ifdef AFX_CORE1_SEG
  16. #pragma code_seg(AFX_CORE1_SEG)
  17. #endif
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22. #define new DEBUG_NEW
  23. ////////////////////////////////////////////////////////////////////////////
  24. // Status information for all file classes
  25. // In this file so everyone doesn't get the CTime package
  26. /////////////////////////////////////////////////////////////////////////////
  27. // CFileStatus diagnostics
  28. #ifdef _DEBUG
  29. void CFileStatus::Dump(CDumpContext& dc) const
  30. {
  31. dc << "a CFileStatus at " << (void*)this;
  32. dc << "\nm_ctime = " << m_ctime;
  33. dc << "\nm_mtime = " << m_mtime;
  34. dc << "\nm_atime = " << m_atime;
  35. dc << "\nm_size = " << m_size;
  36. dc << "\nm_attribute = " << m_attribute;
  37. dc << "\nm_szFullName = " << m_szFullName;
  38. dc << "\n";
  39. }
  40. #endif
  41. /////////////////////////////////////////////////////////////////////////////
  42. // CFile name handlers
  43. CString CFile::GetFileName() const
  44. {
  45. ASSERT_VALID(this);
  46. CFileStatus status;
  47. GetStatus(status);
  48. CString strResult;
  49. AfxGetFileName(status.m_szFullName, strResult.GetBuffer(_MAX_FNAME),
  50. _MAX_FNAME);
  51. strResult.ReleaseBuffer();
  52. return strResult;
  53. }
  54. CString CFile::GetFileTitle() const
  55. {
  56. ASSERT_VALID(this);
  57. CFileStatus status;
  58. GetStatus(status);
  59. CString strResult;
  60. AfxGetFileTitle(status.m_szFullName, strResult.GetBuffer(_MAX_FNAME),
  61. _MAX_FNAME);
  62. strResult.ReleaseBuffer();
  63. return strResult;
  64. }
  65. CString CFile::GetFilePath() const
  66. {
  67. ASSERT_VALID(this);
  68. CFileStatus status;
  69. GetStatus(status);
  70. return status.m_szFullName;
  71. }
  72. /////////////////////////////////////////////////////////////////////////////
  73. // CFile Status implementation
  74. BOOL CFile::GetStatus(CFileStatus& rStatus) const
  75. {
  76. ASSERT_VALID(this);
  77. memset(&rStatus, 0, sizeof(CFileStatus));
  78. // copy file name from cached m_strFileName
  79. lstrcpyn(rStatus.m_szFullName, m_strFileName,
  80. _countof(rStatus.m_szFullName));
  81. if (m_hFile != hFileNull)
  82. {
  83. // get time current file size
  84. FILETIME ftCreate, ftAccess, ftModify;
  85. if (!::GetFileTime((HANDLE)m_hFile, &ftCreate, &ftAccess, &ftModify))
  86. return FALSE;
  87. if ((rStatus.m_size = ::GetFileSize((HANDLE)m_hFile, NULL)) == (DWORD)-1L)
  88. return FALSE;
  89. if (m_strFileName.IsEmpty())
  90. rStatus.m_attribute = 0;
  91. else
  92. {
  93. DWORD dwAttribute = ::GetFileAttributes(m_strFileName);
  94. // don't return an error for this because previous versions of MFC didn't
  95. if (dwAttribute == 0xFFFFFFFF)
  96. rStatus.m_attribute = 0;
  97. else
  98. {
  99. rStatus.m_attribute = (BYTE) dwAttribute;
  100. #ifdef _DEBUG
  101. // MFC BUG: m_attribute is only a BYTE wide
  102. if (dwAttribute & ~0xFF)
  103. TRACE0("Warning: CFile::GetStatus() returns m_attribute without high-order flags.\n");
  104. #endif
  105. }
  106. }
  107. // convert times as appropriate
  108. rStatus.m_ctime = CTime(ftCreate);
  109. rStatus.m_atime = CTime(ftAccess);
  110. rStatus.m_mtime = CTime(ftModify);
  111. if (rStatus.m_ctime.GetTime() == 0)
  112. rStatus.m_ctime = rStatus.m_mtime;
  113. if (rStatus.m_atime.GetTime() == 0)
  114. rStatus.m_atime = rStatus.m_mtime;
  115. }
  116. return TRUE;
  117. }
  118. BOOL PASCAL CFile::GetStatus(LPCTSTR lpszFileName, CFileStatus& rStatus)
  119. {
  120. // attempt to fully qualify path first
  121. if (!AfxFullPath(rStatus.m_szFullName, lpszFileName))
  122. {
  123. rStatus.m_szFullName[0] = '\0';
  124. return FALSE;
  125. }
  126. WIN32_FIND_DATA findFileData;
  127. HANDLE hFind = FindFirstFile((LPTSTR)lpszFileName, &findFileData);
  128. if (hFind == INVALID_HANDLE_VALUE)
  129. return FALSE;
  130. VERIFY(FindClose(hFind));
  131. // strip attribute of NORMAL bit, our API doesn't have a "normal" bit.
  132. rStatus.m_attribute = (BYTE)
  133. (findFileData.dwFileAttributes & ~FILE_ATTRIBUTE_NORMAL);
  134. // get just the low DWORD of the file size
  135. ASSERT(findFileData.nFileSizeHigh == 0);
  136. rStatus.m_size = (LONG)findFileData.nFileSizeLow;
  137. // convert times as appropriate
  138. rStatus.m_ctime = CTime(findFileData.ftCreationTime);
  139. rStatus.m_atime = CTime(findFileData.ftLastAccessTime);
  140. rStatus.m_mtime = CTime(findFileData.ftLastWriteTime);
  141. if (rStatus.m_ctime.GetTime() == 0)
  142. rStatus.m_ctime = rStatus.m_mtime;
  143. if (rStatus.m_atime.GetTime() == 0)
  144. rStatus.m_atime = rStatus.m_mtime;
  145. return TRUE;
  146. }
  147. void AFX_CDECL AfxTimeToFileTime(const CTime& time, LPFILETIME pFileTime)
  148. {
  149. SYSTEMTIME sysTime;
  150. sysTime.wYear = (WORD)time.GetYear();
  151. sysTime.wMonth = (WORD)time.GetMonth();
  152. sysTime.wDay = (WORD)time.GetDay();
  153. sysTime.wHour = (WORD)time.GetHour();
  154. sysTime.wMinute = (WORD)time.GetMinute();
  155. sysTime.wSecond = (WORD)time.GetSecond();
  156. sysTime.wMilliseconds = 0;
  157. // convert system time to local file time
  158. FILETIME localTime;
  159. if (!SystemTimeToFileTime((LPSYSTEMTIME)&sysTime, &localTime))
  160. CFileException::ThrowOsError((LONG)::GetLastError());
  161. // convert local file time to UTC file time
  162. if (!LocalFileTimeToFileTime(&localTime, pFileTime))
  163. CFileException::ThrowOsError((LONG)::GetLastError());
  164. }
  165. void PASCAL CFile::SetStatus(LPCTSTR lpszFileName, const CFileStatus& status)
  166. {
  167. DWORD wAttr;
  168. FILETIME creationTime;
  169. FILETIME lastAccessTime;
  170. FILETIME lastWriteTime;
  171. LPFILETIME lpCreationTime = NULL;
  172. LPFILETIME lpLastAccessTime = NULL;
  173. LPFILETIME lpLastWriteTime = NULL;
  174. if ((wAttr = GetFileAttributes((LPTSTR)lpszFileName)) == (DWORD)-1L)
  175. CFileException::ThrowOsError((LONG)GetLastError());
  176. if ((DWORD)status.m_attribute != wAttr && (wAttr & readOnly))
  177. {
  178. // Set file attribute, only if currently readonly.
  179. // This way we will be able to modify the time assuming the
  180. // caller changed the file from readonly.
  181. if (!SetFileAttributes((LPTSTR)lpszFileName, (DWORD)status.m_attribute))
  182. CFileException::ThrowOsError((LONG)GetLastError());
  183. }
  184. // last modification time
  185. if (status.m_mtime.GetTime() != 0)
  186. {
  187. AfxTimeToFileTime(status.m_mtime, &lastWriteTime);
  188. lpLastWriteTime = &lastWriteTime;
  189. // last access time
  190. if (status.m_atime.GetTime() != 0)
  191. {
  192. AfxTimeToFileTime(status.m_atime, &lastAccessTime);
  193. lpLastAccessTime = &lastAccessTime;
  194. }
  195. // create time
  196. if (status.m_ctime.GetTime() != 0)
  197. {
  198. AfxTimeToFileTime(status.m_ctime, &creationTime);
  199. lpCreationTime = &creationTime;
  200. }
  201. HANDLE hFile = ::CreateFile(lpszFileName, GENERIC_READ|GENERIC_WRITE,
  202. FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  203. NULL);
  204. if (hFile == INVALID_HANDLE_VALUE)
  205. CFileException::ThrowOsError((LONG)::GetLastError());
  206. if (!SetFileTime((HANDLE)hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime))
  207. CFileException::ThrowOsError((LONG)::GetLastError());
  208. if (!::CloseHandle(hFile))
  209. CFileException::ThrowOsError((LONG)::GetLastError());
  210. }
  211. if ((DWORD)status.m_attribute != wAttr && !(wAttr & readOnly))
  212. {
  213. if (!SetFileAttributes((LPTSTR)lpszFileName, (DWORD)status.m_attribute))
  214. CFileException::ThrowOsError((LONG)GetLastError());
  215. }
  216. }
  217. ///////////////////////////////////////////////////////////////////////////////
  218. // CMemFile::GetStatus implementation
  219. BOOL CMemFile::GetStatus(CFileStatus& rStatus) const
  220. {
  221. ASSERT_VALID(this);
  222. rStatus.m_ctime = 0;
  223. rStatus.m_mtime = 0;
  224. rStatus.m_atime = 0;
  225. rStatus.m_size = m_nFileSize;
  226. rStatus.m_attribute = normal;
  227. rStatus.m_szFullName[0] = '\0';
  228. return TRUE;
  229. }
  230. /////////////////////////////////////////////////////////////////////////////