From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.hazardy.de (mail.hazardy.de [78.94.181.132]) by sourceware.org (Postfix) with ESMTPS id 97FD23858416; Thu, 25 Apr 2024 20:16:15 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 97FD23858416 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=hazardy.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=hazardy.de ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 97FD23858416 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=78.94.181.132 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1714076177; cv=none; b=dEAdWTiJNaqZqjD6MzLBhU69A2PL3j3nI1QGQnwc8AgOwYIGFGq+qu4jQ8lF9MldkqmlFHuUnlGf2uNyjuFttJuRP3gcMqX1XjVe90QR3bhQxGUbgTby07cRW0Mj2g2eNlt6fUQ0GAvsZCnvyPdsyDQoMeaLrZ7Rcaw2VTqKOeY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1714076177; c=relaxed/simple; bh=UWAbKAHgST/KK9ny+4ReI+KcrcQWKr5JsNcq2q1onIs=; h=Message-ID:Date:MIME-Version:Subject:To:From; b=nnWOhpONXlaSqJgMKvkC/SHfxqLYHaNOMM5m1uxeF27z4xxGYWpCPLzLsM9rYcdmi47yn/ol3psR26xKQrcx5KcMmOIKyadad1WTz39nfQMPNPxBPJ5Qa8laCaFlZ0M2deubZhSAgQGjDgyXYBusGHGzvLoGWAbd+pxwZiNf65Q= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from [10.0.1.129] (hades.hazardy.de [10.0.1.129]) by mail.hazardy.de (Postfix) with ESMTPSA id 8BD137002CE; Thu, 25 Apr 2024 22:16:14 +0200 (CEST) Message-ID: Date: Thu, 25 Apr 2024 22:16:15 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH] Fix overwriting files with fs::copy_file on windows Content-Language: de-DE To: gcc-patches@gcc.gnu.org, libstdc++@gcc.gnu.org Cc: =?UTF-8?Q?Bj=C3=B6rn_Sch=C3=A4pers?= References: <20240324213401.47870-1-gcc@hazardy.de> From: =?UTF-8?Q?Bj=C3=B6rn_Sch=C3=A4pers?= In-Reply-To: <20240324213401.47870-1-gcc@hazardy.de> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00,GIT_PATCH_0,KAM_DMARC_STATUS,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Am 24.03.2024 um 22:34 schrieb Björn Schäpers: > From: Björn Schäpers > > This fixes i.e. https://github.com/msys2/MSYS2-packages/issues/1937 > I don't know if I picked the right way to do it. > > When acceptable I think the declaration should be moved into > ops-common.h, since then we could use stat_type and also use that in the > commonly used function. > > Manually tested on i686-w64-mingw32. > > -- >8 -- > libstdc++: Fix overwriting files on windows > > The inodes have no meaning on windows, thus all files have an inode of > 0. Use a differenz approach to identify equivalent files. As a result > std::filesystem::copy_file did not honor > copy_options::overwrite_existing. Factored the method out of > std::filesystem::equivalent. > > libstdc++-v3/Changelog: > > * include/bits/fs_ops.h: Add declaration of > __detail::equivalent_win32. > * src/c++17/fs_ops.cc (__detail::equivalent_win32): Implement it > (fs::equivalent): Use __detail::equivalent_win32, factored the > old test out. > * src/filesystem/ops-common.h (_GLIBCXX_FILESYSTEM_IS_WINDOWS): > Use the function. > > Signed-off-by: Björn Schäpers > --- > libstdc++-v3/include/bits/fs_ops.h | 8 +++ > libstdc++-v3/src/c++17/fs_ops.cc | 79 +++++++++++++----------- > libstdc++-v3/src/filesystem/ops-common.h | 10 ++- > 3 files changed, 60 insertions(+), 37 deletions(-) > > diff --git a/libstdc++-v3/include/bits/fs_ops.h b/libstdc++-v3/include/bits/fs_ops.h > index 90650c47b46..d10b78a4bdd 100644 > --- a/libstdc++-v3/include/bits/fs_ops.h > +++ b/libstdc++-v3/include/bits/fs_ops.h > @@ -40,6 +40,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > namespace filesystem > { > +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS > +namespace __detail > +{ > + bool > + equivalent_win32(const wchar_t* p1, const wchar_t* p2, error_code& ec); > +} // namespace __detail > +#endif //_GLIBCXX_FILESYSTEM_IS_WINDOWS > + > /** @addtogroup filesystem > * @{ > */ > diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc > index 61df19753ef..3cc87d45237 100644 > --- a/libstdc++-v3/src/c++17/fs_ops.cc > +++ b/libstdc++-v3/src/c++17/fs_ops.cc > @@ -67,6 +67,49 @@ > namespace fs = std::filesystem; > namespace posix = std::filesystem::__gnu_posix; > > +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS > +bool > +fs::__detail::equivalent_win32(const wchar_t* p1, const wchar_t* p2, > + error_code& ec) > +{ > + struct auto_handle { > + explicit auto_handle(const path& p_) > + : handle(CreateFileW(p_.c_str(), 0, > + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, > + 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)) > + { } > + > + ~auto_handle() > + { if (*this) CloseHandle(handle); } > + > + explicit operator bool() const > + { return handle != INVALID_HANDLE_VALUE; } > + > + bool get_info() > + { return GetFileInformationByHandle(handle, &info); } > + > + HANDLE handle; > + BY_HANDLE_FILE_INFORMATION info; > + }; > + auto_handle h1(p1); > + auto_handle h2(p2); > + if (!h1 || !h2) > + { > + if (!h1 && !h2) > + ec = __last_system_error(); > + return false; > + } > + if (!h1.get_info() || !h2.get_info()) > + { > + ec = __last_system_error(); > + return false; > + } > + return h1.info.dwVolumeSerialNumber == h2.info.dwVolumeSerialNumber > + && h1.info.nFileIndexHigh == h2.info.nFileIndexHigh > + && h1.info.nFileIndexLow == h2.info.nFileIndexLow; > +} > +#endif //_GLIBCXX_FILESYSTEM_IS_WINDOWS > + > fs::path > fs::absolute(const path& p) > { > @@ -858,41 +901,7 @@ fs::equivalent(const path& p1, const path& p2, error_code& ec) noexcept > if (st1.st_mode != st2.st_mode || st1.st_dev != st2.st_dev) > return false; > > - struct auto_handle { > - explicit auto_handle(const path& p_) > - : handle(CreateFileW(p_.c_str(), 0, > - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, > - 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)) > - { } > - > - ~auto_handle() > - { if (*this) CloseHandle(handle); } > - > - explicit operator bool() const > - { return handle != INVALID_HANDLE_VALUE; } > - > - bool get_info() > - { return GetFileInformationByHandle(handle, &info); } > - > - HANDLE handle; > - BY_HANDLE_FILE_INFORMATION info; > - }; > - auto_handle h1(p1); > - auto_handle h2(p2); > - if (!h1 || !h2) > - { > - if (!h1 && !h2) > - ec = __last_system_error(); > - return false; > - } > - if (!h1.get_info() || !h2.get_info()) > - { > - ec = __last_system_error(); > - return false; > - } > - return h1.info.dwVolumeSerialNumber == h2.info.dwVolumeSerialNumber > - && h1.info.nFileIndexHigh == h2.info.nFileIndexHigh > - && h1.info.nFileIndexLow == h2.info.nFileIndexLow; > + return __detail::equivalent_win32(p1.c_str(), p2.c_str(), ec); > #else > return st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino; > #endif > diff --git a/libstdc++-v3/src/filesystem/ops-common.h b/libstdc++-v3/src/filesystem/ops-common.h > index d917fddbeb1..7e67286bd01 100644 > --- a/libstdc++-v3/src/filesystem/ops-common.h > +++ b/libstdc++-v3/src/filesystem/ops-common.h > @@ -489,8 +489,14 @@ _GLIBCXX_BEGIN_NAMESPACE_FILESYSTEM > return false; > } > > - if (to_st->st_dev == from_st->st_dev > - && to_st->st_ino == from_st->st_ino) > +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS > + // st_ino is not set, so can't be used to distinguish files > + std::error_code not_used; > + if (st1.st_mode != st2.st_mode || st1.st_dev != st2.st_dev || > + fs::__detail::equivalent_win32(from, to, not_used)) > +#else > + if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) > +#endif > { > ec = std::make_error_code(std::errc::file_exists); > return false; A friendly ping.