From 2dfc39eb6fb344ecba50efea56f1e0a8c3b6035c Mon Sep 17 00:00:00 2001 From: Marcus Holland-Moritz Date: Tue, 27 Jun 2023 18:36:16 +0200 Subject: [PATCH] Move make_file_stat to file_stat module --- CMakeLists.txt | 1 + include/dwarfs/file_stat.h | 2 + src/dwarfs/file_stat.cpp | 173 +++++++++++++++++++++++++++++++ src/dwarfs/os_access_generic.cpp | 134 ------------------------ 4 files changed, 176 insertions(+), 134 deletions(-) create mode 100644 src/dwarfs/file_stat.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fd30f65..40d195c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -430,6 +430,7 @@ list( src/dwarfs/entry.cpp src/dwarfs/error.cpp src/dwarfs/file_scanner.cpp + src/dwarfs/file_stat.cpp src/dwarfs/file_type.cpp src/dwarfs/filesystem_extractor.cpp src/dwarfs/filesystem_v2.cpp diff --git a/include/dwarfs/file_stat.h b/include/dwarfs/file_stat.h index 1553d536..9dc2b6e9 100644 --- a/include/dwarfs/file_stat.h +++ b/include/dwarfs/file_stat.h @@ -81,6 +81,8 @@ struct file_stat { time_type ctime; }; +file_stat make_file_stat(std::filesystem::path const& path); + template void copy_file_stat(T* out, file_stat const& in) { out->st_dev = in.dev; diff --git a/src/dwarfs/file_stat.cpp b/src/dwarfs/file_stat.cpp new file mode 100644 index 00000000..46a3363c --- /dev/null +++ b/src/dwarfs/file_stat.cpp @@ -0,0 +1,173 @@ +/* vim:set ts=2 sw=2 sts=2 et: */ +/** + * \author Marcus Holland-Moritz (github@mhxnet.de) + * \copyright Copyright (c) Marcus Holland-Moritz + * + * This file is part of dwarfs. + * + * dwarfs is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * dwarfs is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with dwarfs. If not, see . + */ + +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include + +#include +#include + +#include + +#include "dwarfs/error.h" +#include "dwarfs/mmap.h" +#include "dwarfs/os_access_generic.h" + +namespace dwarfs { + +namespace { + +namespace fs = std::filesystem; + +#ifdef _WIN32 + +uint64_t time_from_filetime(FILETIME const& ft) { + static constexpr uint64_t FT_TICKS_PER_SECOND = UINT64_C(10000000); + static constexpr uint64_t FT_EPOCH_OFFSET = UINT64_C(11644473600); + uint64_t ticks = + (static_cast(ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + return (ticks / FT_TICKS_PER_SECOND) - FT_EPOCH_OFFSET; +} + +#endif + +} // namespace + +#ifdef _WIN32 + +file_stat make_file_stat(fs::path const& path) { + auto status = fs::symlink_status(path); + + file_stat rv; + rv.mode = file_status_to_mode(status); + rv.blksize = 0; + rv.blocks = 0; + + auto wps = path.wstring(); + + if (status.type() == fs::file_type::symlink) { + ::WIN32_FILE_ATTRIBUTE_DATA info; + if (::GetFileAttributesExW(wps.c_str(), GetFileExInfoStandard, &info) == + 0) { + throw std::system_error(::GetLastError(), std::system_category(), + "GetFileAttributesExW"); + } + rv.dev = 0; + rv.ino = 0; + rv.nlink = 0; + rv.uid = 0; + rv.gid = 0; + rv.rdev = 0; + rv.size = + (static_cast(info.nFileSizeHigh) << 32) + info.nFileSizeLow; + rv.atime = time_from_filetime(info.ftLastAccessTime); + rv.mtime = time_from_filetime(info.ftLastWriteTime); + rv.ctime = time_from_filetime(info.ftCreationTime); + } else { + struct ::__stat64 st; + + if (::_wstat64(wps.c_str(), &st) != 0) { + throw std::system_error(errno, std::generic_category(), "_stat64"); + } + + if (status.type() == fs::file_type::regular) { + ::HANDLE hdl = + ::CreateFileW(wps.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); + + if (hdl == INVALID_HANDLE_VALUE) { + throw std::system_error(::GetLastError(), std::system_category(), + fmt::format("CreateFileW({})", path.string())); + } + + ::BY_HANDLE_FILE_INFORMATION info; + if (!::GetFileInformationByHandle(hdl, &info)) { + throw std::system_error(::GetLastError(), std::system_category(), + "GetFileInformationByHandle"); + } + + if (!::CloseHandle(hdl)) { + throw std::system_error(::GetLastError(), std::system_category(), + "CloseHandle"); + } + + rv.ino = (static_cast(info.nFileIndexHigh) << 32) + + info.nFileIndexLow; + rv.nlink = info.nNumberOfLinks; + } else { + rv.ino = st.st_ino; + rv.nlink = st.st_nlink; + } + + rv.dev = st.st_dev; + rv.uid = st.st_uid; + rv.gid = st.st_gid; + rv.rdev = st.st_rdev; + rv.size = st.st_size; + rv.atime = st.st_atime; + rv.mtime = st.st_mtime; + rv.ctime = st.st_ctime; + } + + return rv; +} + +#else + +file_stat make_file_stat(fs::path const& path) { + struct ::stat st; + + if (::lstat(path.string().c_str(), &st) != 0) { + throw std::system_error(errno, std::generic_category(), "lstat"); + } + + file_stat rv; + rv.dev = st.st_dev; + rv.ino = st.st_ino; + rv.nlink = st.st_nlink; + rv.mode = st.st_mode; + rv.uid = st.st_uid; + rv.gid = st.st_gid; + rv.rdev = st.st_rdev; + rv.size = st.st_size; + rv.blksize = st.st_blksize; + rv.blocks = st.st_blocks; + rv.atime = st.st_atim.tv_sec; + rv.mtime = st.st_mtim.tv_sec; + rv.ctime = st.st_ctim.tv_sec; + + return rv; +} + +#endif + +} // namespace dwarfs diff --git a/src/dwarfs/os_access_generic.cpp b/src/dwarfs/os_access_generic.cpp index ac5d573d..98c2cc98 100644 --- a/src/dwarfs/os_access_generic.cpp +++ b/src/dwarfs/os_access_generic.cpp @@ -19,26 +19,8 @@ * along with dwarfs. If not, see . */ -#include -#include -#include -#include -#include - -#ifdef _WIN32 -#include -#else -#include -#endif - #include -#include -#include - -#include - -#include "dwarfs/error.h" #include "dwarfs/mmap.h" #include "dwarfs/os_access_generic.h" @@ -48,122 +30,6 @@ namespace fs = std::filesystem; namespace { -#ifdef _WIN32 - -uint64_t time_from_filetime(FILETIME const& ft) { - static constexpr uint64_t FT_TICKS_PER_SECOND = UINT64_C(10000000); - static constexpr uint64_t FT_EPOCH_OFFSET = UINT64_C(11644473600); - uint64_t ticks = - (static_cast(ft.dwHighDateTime) << 32) + ft.dwLowDateTime; - return (ticks / FT_TICKS_PER_SECOND) - FT_EPOCH_OFFSET; -} - -file_stat make_file_stat(fs::path const& path) { - auto status = fs::symlink_status(path); - - file_stat rv; - rv.mode = file_status_to_mode(status); - rv.blksize = 0; - rv.blocks = 0; - - auto wps = path.wstring(); - - if (status.type() == fs::file_type::symlink) { - ::WIN32_FILE_ATTRIBUTE_DATA info; - if (::GetFileAttributesExW(wps.c_str(), GetFileExInfoStandard, &info) == - 0) { - throw std::system_error(::GetLastError(), std::system_category(), - "GetFileAttributesExW"); - } - rv.dev = 0; - rv.ino = 0; - rv.nlink = 0; - rv.uid = 0; - rv.gid = 0; - rv.rdev = 0; - rv.size = - (static_cast(info.nFileSizeHigh) << 32) + info.nFileSizeLow; - rv.atime = time_from_filetime(info.ftLastAccessTime); - rv.mtime = time_from_filetime(info.ftLastWriteTime); - rv.ctime = time_from_filetime(info.ftCreationTime); - } else { - struct ::__stat64 st; - - if (::_wstat64(wps.c_str(), &st) != 0) { - throw std::system_error(errno, std::generic_category(), "_stat64"); - } - - if (status.type() == fs::file_type::regular) { - ::HANDLE hdl = - ::CreateFileW(wps.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); - - if (hdl == INVALID_HANDLE_VALUE) { - throw std::system_error(::GetLastError(), std::system_category(), - fmt::format("CreateFileW({})", path.string())); - } - - ::BY_HANDLE_FILE_INFORMATION info; - if (!::GetFileInformationByHandle(hdl, &info)) { - throw std::system_error(::GetLastError(), std::system_category(), - "GetFileInformationByHandle"); - } - - if (!::CloseHandle(hdl)) { - throw std::system_error(::GetLastError(), std::system_category(), - "CloseHandle"); - } - - rv.ino = (static_cast(info.nFileIndexHigh) << 32) + - info.nFileIndexLow; - rv.nlink = info.nNumberOfLinks; - } else { - rv.ino = st.st_ino; - rv.nlink = st.st_nlink; - } - - rv.dev = st.st_dev; - rv.uid = st.st_uid; - rv.gid = st.st_gid; - rv.rdev = st.st_rdev; - rv.size = st.st_size; - rv.atime = st.st_atime; - rv.mtime = st.st_mtime; - rv.ctime = st.st_ctime; - } - - return rv; -} - -#else - -file_stat make_file_stat(fs::path const& path) { - struct ::stat st; - - if (::lstat(path.string().c_str(), &st) != 0) { - throw std::system_error(errno, std::generic_category(), "lstat"); - } - - file_stat rv; - rv.dev = st.st_dev; - rv.ino = st.st_ino; - rv.nlink = st.st_nlink; - rv.mode = st.st_mode; - rv.uid = st.st_uid; - rv.gid = st.st_gid; - rv.rdev = st.st_rdev; - rv.size = st.st_size; - rv.blksize = st.st_blksize; - rv.blocks = st.st_blocks; - rv.atime = st.st_atim.tv_sec; - rv.mtime = st.st_mtim.tv_sec; - rv.ctime = st.st_ctim.tv_sec; - - return rv; -} - -#endif - class generic_dir_reader final : public dir_reader { public: explicit generic_dir_reader(fs::path const& path)