@@ -69,10 +69,6 @@ struct FileStream::FileStreamImpl
69
69
mode (mode),
70
70
filePath (std::move(fp))
71
71
{
72
- if (truncate && mode != Read) {
73
- std::filesystem::remove (filePath);
74
- }
75
-
76
72
auto flags = [&]()
77
73
{
78
74
switch (mode)
@@ -85,12 +81,11 @@ struct FileStream::FileStreamImpl
85
81
return static_cast <DWORD>(-1 );
86
82
#else
87
83
case Read: return O_RDONLY;
88
- case Write: return O_WRONLY | O_CREAT | O_TRUNC ;
89
- case ReadWrite: return O_RDWR | O_CREAT | O_TRUNC ;
84
+ case Write: return O_WRONLY | O_CREAT;
85
+ case ReadWrite: return O_RDWR | O_CREAT;
90
86
default :
91
87
return -1 ;
92
88
#endif
93
-
94
89
}
95
90
}();
96
91
@@ -105,33 +100,38 @@ struct FileStream::FileStreamImpl
105
100
to flag param of function CreateFileX.
106
101
See: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-flushfilebuffers#remarks
107
102
*/
103
+ DWORD dwCreationDisposition = flags == GENERIC_READ ? OPEN_EXISTING : OPEN_ALWAYS;
108
104
#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
109
105
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t >> converter;
110
106
std::wstring wPath = converter.from_bytes (filePath.c_str ());
111
-
112
107
hFile = CreateFile2 (
113
108
wPath.c_str (),
114
109
flags,
115
110
FILE_SHARE_READ,
116
- (flags == GENERIC_READ ? OPEN_EXISTING : OPEN_ALWAYS) ,
111
+ dwCreationDisposition ,
117
112
nullptr
118
113
);
119
114
#else
120
115
hFile = CreateFileA (
121
116
filePath.c_str (),
122
117
flags,
123
118
FILE_SHARE_READ,
124
- NULL ,
125
- (flags == GENERIC_READ ? OPEN_EXISTING : OPEN_ALWAYS) ,
119
+ nullptr ,
120
+ dwCreationDisposition ,
126
121
FILE_ATTRIBUTE_NORMAL,
127
- NULL
122
+ nullptr
128
123
);
129
124
#endif
130
125
131
126
if (hFile == INVALID_HANDLE_VALUE) {
132
127
throw FileStreamError (getLastErrorAsString ());
133
128
}
134
129
130
+ /* Truncate file if writable */
131
+ if ((flags & GENERIC_WRITE) && truncate && !SetEndOfFile (hFile)) {
132
+ throw FileStreamError (getLastErrorAsString ());
133
+ }
134
+
135
135
/* Get file size */
136
136
LARGE_INTEGER lSize {{0 , 0 }};
137
137
if (!GetFileSizeEx (hFile, &lSize)) {
@@ -144,8 +144,12 @@ struct FileStream::FileStreamImpl
144
144
fileSize = lSize.LowPart ;
145
145
#endif
146
146
147
- #else // Not Win
147
+ #else // Unix
148
148
/* Open file */
149
+ if (mode != Read && truncate ) {
150
+ flags |= O_TRUNC;
151
+ }
152
+
149
153
fd = open (filePath.c_str (), flags, (mode_t )0600 );
150
154
if (fd == -1 ) {
151
155
throw FileStreamError (strerror (errno));
@@ -257,7 +261,7 @@ struct FileStream::FileStreamImpl
257
261
#ifdef OS_WINDOWS
258
262
LARGE_INTEGER li;
259
263
li.QuadPart = offset;
260
- li.LowPart = SetFilePointer (hFile, li.LowPart , &li.HighPart , FILE_BEGIN);
264
+ li.LowPart = SetFilePointer (hFile, li.LowPart , &li.HighPart , FILE_BEGIN);
261
265
if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR) {
262
266
#else
263
267
auto off = lseek (fd, offset, SEEK_SET);
0 commit comments