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