1 //
2 // LogFile_WIN32U.cpp
3 //
4 // Library: Foundation
5 // Package: Logging
6 // Module:  LogFile
7 //
8 // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
9 // and Contributors.
10 //
11 // SPDX-License-Identifier:	BSL-1.0
12 //
13 
14 
15 #include "Poco/LogFile_WIN32U.h"
16 #include "Poco/File.h"
17 #include "Poco/Exception.h"
18 #include "Poco/UnicodeConverter.h"
19 
20 
21 namespace Poco {
22 
23 
LogFileImpl(const std::string & path)24 LogFileImpl::LogFileImpl(const std::string& path): _path(path), _hFile(INVALID_HANDLE_VALUE)
25 {
26 	File file(path);
27 	if (file.exists())
28 	{
29 		if (0 == sizeImpl())
30 			_creationDate = file.getLastModified();
31 		else
32 			_creationDate = file.created();
33 	}
34 }
35 
36 
~LogFileImpl()37 LogFileImpl::~LogFileImpl()
38 {
39 	CloseHandle(_hFile);
40 }
41 
42 
writeImpl(const std::string & text,bool flush)43 void LogFileImpl::writeImpl(const std::string& text, bool flush)
44 {
45 	if (INVALID_HANDLE_VALUE == _hFile)	createFile();
46 
47 	std::string logText;
48 	logText.reserve(text.size() + 16); // keep some reserve for \n -> \r\n and terminating \r\n
49 	for (char c: text)
50 	{
51 		if (c == '\n')
52 			logText += "\r\n";
53 		else
54 			logText += c;
55 	}
56 	logText += "\r\n";
57 
58 	DWORD bytesWritten;
59 	BOOL res = WriteFile(_hFile, logText.data(), static_cast<DWORD>(logText.size()), &bytesWritten, NULL);
60 	if (!res) throw WriteFileException(_path);
61 	if (flush)
62 	{
63 		res = FlushFileBuffers(_hFile);
64 		if (!res) throw WriteFileException(_path);
65 	}
66 }
67 
68 
sizeImpl() const69 UInt64 LogFileImpl::sizeImpl() const
70 {
71 	if (INVALID_HANDLE_VALUE == _hFile)
72 	{
73 		File file(_path);
74 		if (file.exists()) return file.getSize();
75 		else return 0;
76 	}
77 
78 	LARGE_INTEGER li;
79 	li.HighPart = 0;
80 	li.LowPart  = SetFilePointer(_hFile, 0, &li.HighPart, FILE_CURRENT);
81 	return li.QuadPart;
82 }
83 
84 
creationDateImpl() const85 Timestamp LogFileImpl::creationDateImpl() const
86 {
87 	return _creationDate;
88 }
89 
90 
pathImpl() const91 const std::string& LogFileImpl::pathImpl() const
92 {
93 	return _path;
94 }
95 
96 
createFile()97 void LogFileImpl::createFile()
98 {
99 	std::wstring upath;
100 	FileImpl::convertPath(_path, upath);
101 
102 	_hFile = CreateFileW(upath.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
103 	if (_hFile == INVALID_HANDLE_VALUE) throw OpenFileException(_path);
104 	SetFilePointer(_hFile, 0, 0, FILE_END);
105 	// There seems to be a strange "optimization" in the Windows NTFS
106 	// filesystem that causes it to reuse directory entries of deleted
107 	// files. Example:
108 	// 1. create a file named "test.dat"
109 	//    note the file's creation date
110 	// 2. delete the file "test.dat"
111 	// 3. wait a few seconds
112 	// 4. create a file named "test.dat"
113 	//    the new file will have the same creation
114 	//    date as the old one.
115 	// We work around this bug by taking the file's
116 	// modification date as a reference when the
117 	// file is empty.
118 	if (sizeImpl() == 0)
119 		_creationDate = File(_path).getLastModified();
120 	else
121 		_creationDate = File(_path).created();
122 }
123 
124 
125 } // namespace Poco
126