filest.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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. #ifndef WINSCP
  44. CString CFile::GetFileName() const
  45. {
  46. ASSERT_VALID(this);
  47. CFileStatus status;
  48. GetStatus(status);
  49. CString strResult;
  50. AfxGetFileName(status.m_szFullName, strResult.GetBuffer(_MAX_FNAME),
  51. _MAX_FNAME);
  52. strResult.ReleaseBuffer();
  53. return strResult;
  54. }
  55. CString CFile::GetFileTitle() const
  56. {
  57. ASSERT_VALID(this);
  58. CFileStatus status;
  59. GetStatus(status);
  60. CString strResult;
  61. AfxGetFileTitle(status.m_szFullName, strResult.GetBuffer(_MAX_FNAME),
  62. _MAX_FNAME);
  63. strResult.ReleaseBuffer();
  64. return strResult;
  65. }
  66. #endif
  67. CString CFile::GetFilePath() const
  68. {
  69. ASSERT_VALID(this);
  70. CFileStatus status;
  71. GetStatus(status);
  72. return status.m_szFullName;
  73. }
  74. /////////////////////////////////////////////////////////////////////////////
  75. // CFile Status implementation
  76. BOOL CFile::GetStatus(CFileStatus& rStatus) const
  77. {
  78. ASSERT_VALID(this);
  79. memset(&rStatus, 0, sizeof(CFileStatus));
  80. // copy file name from cached m_strFileName
  81. lstrcpyn(rStatus.m_szFullName, m_strFileName,
  82. _countof(rStatus.m_szFullName));
  83. if (m_hFile != hFileNull)
  84. {
  85. // get time current file size
  86. FILETIME ftCreate, ftAccess, ftModify;
  87. if (!::GetFileTime((HANDLE)m_hFile, &ftCreate, &ftAccess, &ftModify))
  88. return FALSE;
  89. if ((rStatus.m_size = ::GetFileSize((HANDLE)m_hFile, NULL)) == (DWORD)-1L)
  90. return FALSE;
  91. if (m_strFileName.IsEmpty())
  92. rStatus.m_attribute = 0;
  93. else
  94. {
  95. DWORD dwAttribute = ::GetFileAttributes(m_strFileName);
  96. // don't return an error for this because previous versions of MFC didn't
  97. if (dwAttribute == 0xFFFFFFFF)
  98. rStatus.m_attribute = 0;
  99. else
  100. {
  101. rStatus.m_attribute = (BYTE) dwAttribute;
  102. #ifdef _DEBUG
  103. // MFC BUG: m_attribute is only a BYTE wide
  104. if (dwAttribute & ~0xFF)
  105. TRACE0("Warning: CFile::GetStatus() returns m_attribute without high-order flags.\n");
  106. #endif
  107. }
  108. }
  109. // convert times as appropriate
  110. rStatus.m_ctime = CTime(ftCreate);
  111. rStatus.m_atime = CTime(ftAccess);
  112. rStatus.m_mtime = CTime(ftModify);
  113. if (rStatus.m_ctime.GetTime() == 0)
  114. rStatus.m_ctime = rStatus.m_mtime;
  115. if (rStatus.m_atime.GetTime() == 0)
  116. rStatus.m_atime = rStatus.m_mtime;
  117. }
  118. return TRUE;
  119. }
  120. BOOL PASCAL CFile::GetStatus(LPCTSTR lpszFileName, CFileStatus& rStatus)
  121. {
  122. // attempt to fully qualify path first
  123. if (!AfxFullPath(rStatus.m_szFullName, lpszFileName))
  124. {
  125. rStatus.m_szFullName[0] = '\0';
  126. return FALSE;
  127. }
  128. WIN32_FIND_DATA findFileData;
  129. HANDLE hFind = FindFirstFile((LPTSTR)lpszFileName, &findFileData);
  130. if (hFind == INVALID_HANDLE_VALUE)
  131. return FALSE;
  132. VERIFY(FindClose(hFind));
  133. // strip attribute of NORMAL bit, our API doesn't have a "normal" bit.
  134. rStatus.m_attribute = (BYTE)
  135. (findFileData.dwFileAttributes & ~FILE_ATTRIBUTE_NORMAL);
  136. // get just the low DWORD of the file size
  137. ASSERT(findFileData.nFileSizeHigh == 0);
  138. rStatus.m_size = (LONG)findFileData.nFileSizeLow;
  139. // convert times as appropriate
  140. rStatus.m_ctime = CTime(findFileData.ftCreationTime);
  141. rStatus.m_atime = CTime(findFileData.ftLastAccessTime);
  142. rStatus.m_mtime = CTime(findFileData.ftLastWriteTime);
  143. if (rStatus.m_ctime.GetTime() == 0)
  144. rStatus.m_ctime = rStatus.m_mtime;
  145. if (rStatus.m_atime.GetTime() == 0)
  146. rStatus.m_atime = rStatus.m_mtime;
  147. return TRUE;
  148. }
  149. void AFX_CDECL AfxTimeToFileTime(const CTime& time, LPFILETIME pFileTime)
  150. {
  151. SYSTEMTIME sysTime;
  152. sysTime.wYear = (WORD)time.GetYear();
  153. sysTime.wMonth = (WORD)time.GetMonth();
  154. sysTime.wDay = (WORD)time.GetDay();
  155. sysTime.wHour = (WORD)time.GetHour();
  156. sysTime.wMinute = (WORD)time.GetMinute();
  157. sysTime.wSecond = (WORD)time.GetSecond();
  158. sysTime.wMilliseconds = 0;
  159. // convert system time to local file time
  160. FILETIME localTime;
  161. if (!SystemTimeToFileTime((LPSYSTEMTIME)&sysTime, &localTime))
  162. CFileException::ThrowOsError((LONG)::GetLastError());
  163. // convert local file time to UTC file time
  164. if (!LocalFileTimeToFileTime(&localTime, pFileTime))
  165. CFileException::ThrowOsError((LONG)::GetLastError());
  166. }
  167. void PASCAL CFile::SetStatus(LPCTSTR lpszFileName, const CFileStatus& status)
  168. {
  169. DWORD wAttr;
  170. FILETIME creationTime;
  171. FILETIME lastAccessTime;
  172. FILETIME lastWriteTime;
  173. LPFILETIME lpCreationTime = NULL;
  174. LPFILETIME lpLastAccessTime = NULL;
  175. LPFILETIME lpLastWriteTime = NULL;
  176. if ((wAttr = GetFileAttributes((LPTSTR)lpszFileName)) == (DWORD)-1L)
  177. CFileException::ThrowOsError((LONG)GetLastError());
  178. if ((DWORD)status.m_attribute != wAttr && (wAttr & readOnly))
  179. {
  180. // Set file attribute, only if currently readonly.
  181. // This way we will be able to modify the time assuming the
  182. // caller changed the file from readonly.
  183. if (!SetFileAttributes((LPTSTR)lpszFileName, (DWORD)status.m_attribute))
  184. CFileException::ThrowOsError((LONG)GetLastError());
  185. }
  186. // last modification time
  187. if (status.m_mtime.GetTime() != 0)
  188. {
  189. AfxTimeToFileTime(status.m_mtime, &lastWriteTime);
  190. lpLastWriteTime = &lastWriteTime;
  191. // last access time
  192. if (status.m_atime.GetTime() != 0)
  193. {
  194. AfxTimeToFileTime(status.m_atime, &lastAccessTime);
  195. lpLastAccessTime = &lastAccessTime;
  196. }
  197. // create time
  198. if (status.m_ctime.GetTime() != 0)
  199. {
  200. AfxTimeToFileTime(status.m_ctime, &creationTime);
  201. lpCreationTime = &creationTime;
  202. }
  203. HANDLE hFile = ::CreateFile(lpszFileName, GENERIC_READ|GENERIC_WRITE,
  204. FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  205. NULL);
  206. if (hFile == INVALID_HANDLE_VALUE)
  207. CFileException::ThrowOsError((LONG)::GetLastError());
  208. if (!SetFileTime((HANDLE)hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime))
  209. CFileException::ThrowOsError((LONG)::GetLastError());
  210. if (!::CloseHandle(hFile))
  211. CFileException::ThrowOsError((LONG)::GetLastError());
  212. }
  213. if ((DWORD)status.m_attribute != wAttr && !(wAttr & readOnly))
  214. {
  215. if (!SetFileAttributes((LPTSTR)lpszFileName, (DWORD)status.m_attribute))
  216. CFileException::ThrowOsError((LONG)GetLastError());
  217. }
  218. }
  219. ///////////////////////////////////////////////////////////////////////////////
  220. // CMemFile::GetStatus implementation
  221. BOOL CMemFile::GetStatus(CFileStatus& rStatus) const
  222. {
  223. ASSERT_VALID(this);
  224. rStatus.m_ctime = 0;
  225. rStatus.m_mtime = 0;
  226. rStatus.m_atime = 0;
  227. rStatus.m_size = m_nFileSize;
  228. rStatus.m_attribute = normal;
  229. rStatus.m_szFullName[0] = '\0';
  230. return TRUE;
  231. }
  232. /////////////////////////////////////////////////////////////////////////////