diff --git a/libraries/libim/io/impl/filestream.cpp b/libraries/libim/io/impl/filestream.cpp index a5a91cf..0a3a06f 100644 --- a/libraries/libim/io/impl/filestream.cpp +++ b/libraries/libim/io/impl/filestream.cpp @@ -69,10 +69,6 @@ struct FileStream::FileStreamImpl mode(mode), filePath(std::move(fp)) { - if(truncate && mode != Read) { - std::filesystem::remove(filePath); - } - auto flags = [&]() { switch (mode) @@ -85,12 +81,11 @@ struct FileStream::FileStreamImpl return static_cast(-1); #else case Read: return O_RDONLY; - case Write: return O_WRONLY | O_CREAT | O_TRUNC; - case ReadWrite: return O_RDWR | O_CREAT | O_TRUNC; + case Write: return O_WRONLY | O_CREAT; + case ReadWrite: return O_RDWR | O_CREAT; default: return -1; #endif - } }(); @@ -105,15 +100,15 @@ struct FileStream::FileStreamImpl to flag param of function CreateFileX. See: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-flushfilebuffers#remarks */ + DWORD dwCreationDisposition = flags == GENERIC_READ ? OPEN_EXISTING : OPEN_ALWAYS; #if _WIN32_WINNT >= _WIN32_WINNT_WIN8 std::wstring_convert> converter; std::wstring wPath = converter.from_bytes(filePath.c_str()); - hFile = CreateFile2( wPath.c_str(), flags, FILE_SHARE_READ, - (flags == GENERIC_READ ? OPEN_EXISTING : OPEN_ALWAYS), + dwCreationDisposition, nullptr ); #else @@ -121,10 +116,10 @@ struct FileStream::FileStreamImpl filePath.c_str(), flags, FILE_SHARE_READ, - NULL, - (flags == GENERIC_READ ? OPEN_EXISTING : OPEN_ALWAYS), + nullptr, + dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, - NULL + nullptr ); #endif @@ -132,6 +127,11 @@ struct FileStream::FileStreamImpl throw FileStreamError(getLastErrorAsString()); } + /* Truncate file if writable */ + if ((flags & GENERIC_WRITE) && truncate && !SetEndOfFile(hFile)) { + throw FileStreamError(getLastErrorAsString()); + } + /* Get file size */ LARGE_INTEGER lSize {{0, 0}}; if(!GetFileSizeEx(hFile, &lSize)) { @@ -144,8 +144,12 @@ struct FileStream::FileStreamImpl fileSize = lSize.LowPart; #endif - #else // Not Win + #else // Unix /* Open file */ + if (mode != Read && truncate) { + flags |= O_TRUNC; + } + fd = open(filePath.c_str(), flags, (mode_t)0600); if (fd == -1) { throw FileStreamError(strerror(errno)); @@ -257,7 +261,7 @@ struct FileStream::FileStreamImpl #ifdef OS_WINDOWS LARGE_INTEGER li; li.QuadPart = offset; - li.LowPart = SetFilePointer(hFile, li.LowPart, &li.HighPart, FILE_BEGIN); + li.LowPart = SetFilePointer(hFile, li.LowPart, &li.HighPart, FILE_BEGIN); if (li.LowPart == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) { #else auto off = lseek(fd, offset, SEEK_SET); diff --git a/programs/cndtool/main.cpp b/programs/cndtool/main.cpp index faceedf..0b87770 100644 --- a/programs/cndtool/main.cpp +++ b/programs/cndtool/main.cpp @@ -619,7 +619,7 @@ std::size_t extractAnimations(const InputStream& istream, const std::string& out } std::string keyFilePath(keyDir + "/" + key.name()); - OutputFileStream ofs(std::move(keyFilePath)); + OutputFileStream ofs(std::move(keyFilePath), /*truncate=*/true); key.serialize(TextResourceWriter(ofs), keyHeaderComment); } @@ -668,7 +668,7 @@ std::size_t extractMaterials(const InputStream& istream, const std::string& outD } std::string matFilePath(matDir + "/" + mat.name()); - mat.serialize(OutputFileStream(std::move(matFilePath))); + mat.serialize(OutputFileStream(std::move(matFilePath), /*truncate=*/true)); if(opt.verboseOutput) { @@ -759,14 +759,14 @@ std::size_t extractSounds(const InputStream& istream, const std::string& outDir, std::cout << "Extracting sound: " << s.name() << std::endl; } - OutputFileStream ofs(outPath.append(s.name())); + OutputFileStream ofs(outPath.append(s.name()), /*truncate=*/true); s.serialize(ofs, Sound::SerializeFormat::IndyWV); outPath = outPath.parent_path(); /* Save in WAV format */ if(opt.sound.convertToWav) { - OutputFileStream ofs(wavDir.append(s.name())); + OutputFileStream ofs(wavDir.append(s.name()), /*truncate=*/true); s.serialize(ofs, Sound::SerializeFormat::WAV); wavDir = wavDir.parent_path(); } diff --git a/programs/cndtool/patch.h b/programs/cndtool/patch.h index db790ca..cbd7572 100644 --- a/programs/cndtool/patch.h +++ b/programs/cndtool/patch.h @@ -25,7 +25,7 @@ using namespace libim::utils; /* Open new output cnd file */ const std::string patchedCndFile = cndFile + ".patched"; - OutputFileStream ofstream(patchedCndFile); + OutputFileStream ofstream(patchedCndFile, /*truncate=*/true); /* Copy input cnd file to output stream until materials section */ const auto matSectionOffset = CND::getOffset_Materials(ifstream); @@ -78,7 +78,7 @@ using namespace libim::utils; /* Open new output cnd file */ const std::string patchedCndFile = cndFile + ".patched"; - OutputFileStream ofstream(patchedCndFile); + OutputFileStream ofstream(patchedCndFile, /*truncate=*/true); /* Copy input cnd file to output stream until materials section */ const auto keySectionOffset = CND::getOffset_Keyframes(ifstream, cndHeader); diff --git a/programs/gobext/main.cpp b/programs/gobext/main.cpp index af96d0f..be5260e 100644 --- a/programs/gobext/main.cpp +++ b/programs/gobext/main.cpp @@ -120,7 +120,7 @@ bool extractGob(std::shared_ptr gobDir, std::string outD } /* Open output file stream */ - OutputFileStream ofs(outPath); + OutputFileStream ofs(outPath, /*truncate=*/true); /* Write entry to file */ ByteArray buffer(4096);