refactor(file_stat): turn into proper object with hidden data

This commit is contained in:
Marcus Holland-Moritz 2024-07-31 21:15:43 +02:00
parent bbd8306a13
commit 964a4f49e6
17 changed files with 559 additions and 389 deletions

View File

@ -31,7 +31,8 @@
namespace dwarfs { namespace dwarfs {
struct file_stat { class file_stat {
public:
using valid_fields_type = uint32_t; using valid_fields_type = uint32_t;
using perms_type = std::underlying_type_t<std::filesystem::perms>; using perms_type = std::underlying_type_t<std::filesystem::perms>;
using mode_type = uint32_t; using mode_type = uint32_t;
@ -45,39 +46,6 @@ struct file_stat {
using blkcnt_type = int64_t; using blkcnt_type = int64_t;
using time_type = int64_t; using time_type = int64_t;
void ensure_valid(valid_fields_type fields) const;
std::filesystem::file_status status() const {
ensure_valid(mode_valid);
return file_mode_to_status(mode);
};
posix_file_type::value type() const {
ensure_valid(mode_valid);
return static_cast<posix_file_type::value>(mode & posix_file_type::mask);
};
perms_type permissions() const {
ensure_valid(mode_valid);
return mode & 07777;
};
void set_permissions(perms_type perms) { mode = type() | (perms & 07777); }
bool is_directory() const { return type() == posix_file_type::directory; }
bool is_regular_file() const { return type() == posix_file_type::regular; }
bool is_symlink() const { return type() == posix_file_type::symlink; }
bool is_device() const {
auto t = type();
return t == posix_file_type::block || t == posix_file_type::character;
}
static std::string perm_string(mode_type mode);
static std::string mode_string(mode_type mode);
static constexpr valid_fields_type dev_valid = 1 << 0; static constexpr valid_fields_type dev_valid = 1 << 0;
static constexpr valid_fields_type ino_valid = 1 << 1; static constexpr valid_fields_type ino_valid = 1 << 1;
static constexpr valid_fields_type nlink_valid = 1 << 2; static constexpr valid_fields_type nlink_valid = 1 << 2;
@ -93,42 +61,126 @@ struct file_stat {
static constexpr valid_fields_type ctime_valid = 1 << 12; static constexpr valid_fields_type ctime_valid = 1 << 12;
static constexpr valid_fields_type all_valid = (1 << 13) - 1; static constexpr valid_fields_type all_valid = (1 << 13) - 1;
uint32_t valid_fields{0}; file_stat();
dev_type dev; explicit file_stat(std::filesystem::path const& path);
ino_type ino;
nlink_type nlink; void ensure_valid(valid_fields_type fields) const;
mode_type mode;
uid_type uid; std::filesystem::file_status status() const;
gid_type gid; posix_file_type::value type() const;
dev_type rdev;
off_type size; perms_type permissions() const;
blksize_type blksize; void set_permissions(perms_type perms);
blkcnt_type blocks;
time_type atime; dev_type dev() const;
time_type mtime; dev_type dev_unchecked() const { return dev_; }
time_type ctime; void set_dev(dev_type dev);
std::exception_ptr exception;
ino_type ino() const;
ino_type ino_unchecked() const { return ino_; }
void set_ino(ino_type ino);
nlink_type nlink() const;
nlink_type nlink_unchecked() const { return nlink_; }
void set_nlink(nlink_type nlink);
mode_type mode() const;
mode_type mode_unchecked() const { return mode_; }
void set_mode(mode_type mode);
uid_type uid() const;
uid_type uid_unchecked() const { return uid_; }
void set_uid(uid_type uid);
gid_type gid() const;
gid_type gid_unchecked() const { return gid_; }
void set_gid(gid_type gid);
dev_type rdev() const;
dev_type rdev_unchecked() const { return rdev_; }
void set_rdev(dev_type rdev);
off_type size() const;
off_type size_unchecked() const { return size_; }
void set_size(off_type size);
blksize_type blksize() const;
blksize_type blksize_unchecked() const { return blksize_; }
void set_blksize(blksize_type blksize);
blkcnt_type blocks() const;
blkcnt_type blocks_unchecked() const { return blocks_; }
void set_blocks(blkcnt_type blocks);
time_type atime() const;
time_type atime_unchecked() const { return atime_; }
void set_atime(time_type atime);
time_type mtime() const;
time_type mtime_unchecked() const { return mtime_; }
void set_mtime(time_type mtime);
time_type ctime() const;
time_type ctime_unchecked() const { return ctime_; }
void set_ctime(time_type ctime);
bool is_directory() const;
bool is_regular_file() const;
bool is_symlink() const;
bool is_device() const;
static std::string perm_string(mode_type mode);
static std::string mode_string(mode_type mode);
template <typename T>
void copy_to(T* out) const {
copy_to_impl<true>(out);
}
template <typename T>
void copy_to_without_block_info(T* out) const {
copy_to_impl<false>(out);
}
private:
template <bool with_block_info = true, typename T>
void copy_to_impl(T* out) const {
constexpr valid_fields_type required_fields{
with_block_info ? all_valid
: all_valid & ~(blksize_valid | blocks_valid)};
ensure_valid(required_fields);
out->st_dev = dev_;
out->st_ino = ino_;
out->st_nlink = nlink_;
out->st_mode = mode_;
out->st_uid = uid_;
out->st_gid = gid_;
out->st_rdev = rdev_;
out->st_size = size_;
if constexpr (with_block_info) {
out->st_blksize = blksize_;
out->st_blocks = blocks_;
}
out->st_atime = atime_;
out->st_mtime = mtime_;
out->st_ctime = ctime_;
}
uint32_t valid_fields_{0};
dev_type dev_{};
ino_type ino_{};
nlink_type nlink_{};
mode_type mode_{};
uid_type uid_{};
gid_type gid_{};
dev_type rdev_{};
off_type size_{};
blksize_type blksize_{};
blkcnt_type blocks_{};
time_type atime_{};
time_type mtime_{};
time_type ctime_{};
std::exception_ptr exception_;
}; };
file_stat make_file_stat(std::filesystem::path const& path);
template <bool with_block_info = true, typename T>
void copy_file_stat(T* out, file_stat const& in) {
out->st_dev = in.dev;
out->st_ino = in.ino;
out->st_nlink = in.nlink;
out->st_mode = in.mode;
out->st_uid = in.uid;
out->st_gid = in.gid;
out->st_rdev = in.rdev;
out->st_size = in.size;
if constexpr (with_block_info) {
out->st_blksize = in.blksize;
out->st_blocks = in.blocks;
}
out->st_atime = in.atime;
out->st_mtime = in.mtime;
out->st_ctime = in.ctime;
}
} // namespace dwarfs } // namespace dwarfs

View File

@ -45,7 +45,6 @@ class logger;
struct getattr_options; struct getattr_options;
struct metadata_options; struct metadata_options;
struct filesystem_info; struct filesystem_info;
struct file_stat;
struct vfs_stat; struct vfs_stat;
class performance_monitor; class performance_monitor;

View File

@ -98,9 +98,11 @@ void perms_to_stream(std::ostream& os, file_stat::mode_type mode) {
} // namespace } // namespace
file_stat::file_stat() = default;
#ifdef _WIN32 #ifdef _WIN32
file_stat make_file_stat(fs::path const& path) { file_stat::file_stat(fs::path const& path) {
std::error_code ec; std::error_code ec;
auto status = fs::symlink_status(path, ec); auto status = fs::symlink_status(path, ec);
@ -108,11 +110,9 @@ file_stat make_file_stat(fs::path const& path) {
status = fs::status(path, ec); status = fs::status(path, ec);
} }
file_stat rv;
if (ec) { if (ec) {
rv.exception = std::make_exception_ptr(std::system_error(ec)); exception_ = std::make_exception_ptr(std::system_error(ec));
return rv; return;
} }
if (status.type() == fs::file_type::not_found || if (status.type() == fs::file_type::not_found ||
@ -125,10 +125,10 @@ file_stat make_file_stat(fs::path const& path) {
u8string_to_string(path.u8string()))); u8string_to_string(path.u8string())));
} }
rv.valid_fields = file_stat::mode_valid; valid_fields_ = file_stat::mode_valid;
rv.mode = file_status_to_mode(status); mode_ = file_status_to_mode(status);
rv.blksize = 0; blksize_ = 0;
rv.blocks = 0; blocks_ = 0;
auto wps = path.wstring(); auto wps = path.wstring();
@ -136,21 +136,21 @@ file_stat make_file_stat(fs::path const& path) {
::WIN32_FILE_ATTRIBUTE_DATA info; ::WIN32_FILE_ATTRIBUTE_DATA info;
if (::GetFileAttributesExW(wps.c_str(), GetFileExInfoStandard, &info) == if (::GetFileAttributesExW(wps.c_str(), GetFileExInfoStandard, &info) ==
0) { 0) {
rv.exception = std::make_exception_ptr(std::system_error( exception_ = std::make_exception_ptr(std::system_error(
::GetLastError(), std::system_category(), "GetFileAttributesExW")); ::GetLastError(), std::system_category(), "GetFileAttributesExW"));
} else { } else {
rv.valid_fields = file_stat::all_valid; valid_fields_ = file_stat::all_valid;
rv.dev = 0; dev_ = 0;
rv.ino = 0; ino_ = 0;
rv.nlink = 0; nlink_ = 0;
rv.uid = 0; uid_ = 0;
rv.gid = 0; gid_ = 0;
rv.rdev = 0; rdev_ = 0;
rv.size = size_ =
(static_cast<uint64_t>(info.nFileSizeHigh) << 32) + info.nFileSizeLow; (static_cast<uint64_t>(info.nFileSizeHigh) << 32) + info.nFileSizeLow;
rv.atime = time_from_filetime(info.ftLastAccessTime); atime_ = time_from_filetime(info.ftLastAccessTime);
rv.mtime = time_from_filetime(info.ftLastWriteTime); mtime_ = time_from_filetime(info.ftLastWriteTime);
rv.ctime = time_from_filetime(info.ftCreationTime); ctime_ = time_from_filetime(info.ftCreationTime);
} }
} else { } else {
struct ::__stat64 st; struct ::__stat64 st;
@ -165,83 +165,78 @@ file_stat make_file_stat(fs::path const& path) {
::BY_HANDLE_FILE_INFORMATION info; ::BY_HANDLE_FILE_INFORMATION info;
if (::GetFileInformationByHandle(hdl, &info)) { if (::GetFileInformationByHandle(hdl, &info)) {
if (::CloseHandle(hdl)) { if (::CloseHandle(hdl)) {
rv.valid_fields |= file_stat::ino_valid | file_stat::nlink_valid; valid_fields_ |= file_stat::ino_valid | file_stat::nlink_valid;
rv.ino = (static_cast<uint64_t>(info.nFileIndexHigh) << 32) + ino_ = (static_cast<uint64_t>(info.nFileIndexHigh) << 32) +
info.nFileIndexLow; info.nFileIndexLow;
rv.nlink = info.nNumberOfLinks; nlink_ = info.nNumberOfLinks;
} else { } else {
rv.exception = std::make_exception_ptr(std::system_error( exception_ = std::make_exception_ptr(std::system_error(
::GetLastError(), std::system_category(), "CloseHandle")); ::GetLastError(), std::system_category(), "CloseHandle"));
} }
} else { } else {
rv.exception = std::make_exception_ptr( exception_ = std::make_exception_ptr(
std::system_error(::GetLastError(), std::system_category(), std::system_error(::GetLastError(), std::system_category(),
"GetFileInformationByHandle")); "GetFileInformationByHandle"));
::CloseHandle(hdl); ::CloseHandle(hdl);
} }
} else { } else {
rv.exception = std::make_exception_ptr(std::system_error( exception_ = std::make_exception_ptr(std::system_error(
::GetLastError(), std::system_category(), "CreateFileW")); ::GetLastError(), std::system_category(), "CreateFileW"));
} }
} else { } else {
rv.valid_fields |= file_stat::ino_valid | file_stat::nlink_valid; valid_fields_ |= file_stat::ino_valid | file_stat::nlink_valid;
rv.ino = st.st_ino; ino_ = st.st_ino;
rv.nlink = st.st_nlink; nlink_ = st.st_nlink;
} }
rv.valid_fields |= file_stat::dev_valid | file_stat::uid_valid | valid_fields_ |= file_stat::dev_valid | file_stat::uid_valid |
file_stat::gid_valid | file_stat::rdev_valid | file_stat::gid_valid | file_stat::rdev_valid |
file_stat::size_valid | file_stat::atime_valid | file_stat::size_valid | file_stat::atime_valid |
file_stat::mtime_valid | file_stat::ctime_valid; file_stat::mtime_valid | file_stat::ctime_valid;
rv.dev = st.st_dev; dev_ = st.st_dev;
rv.uid = st.st_uid; uid_ = st.st_uid;
rv.gid = st.st_gid; gid_ = st.st_gid;
rv.rdev = st.st_rdev; rdev_ = st.st_rdev;
rv.size = st.st_size; size_ = st.st_size;
rv.atime = st.st_atime; atime_ = st.st_atime;
rv.mtime = st.st_mtime; mtime_ = st.st_mtime;
rv.ctime = st.st_ctime; ctime_ = st.st_ctime;
} else { } else {
rv.exception = std::make_exception_ptr( exception_ = std::make_exception_ptr(
std::system_error(errno, std::generic_category(), "_stat64")); std::system_error(errno, std::generic_category(), "_stat64"));
} }
} }
return rv;
} }
#else #else
file_stat make_file_stat(fs::path const& path) { file_stat::file_stat(fs::path const& path) {
struct ::stat st; struct ::stat st;
if (::lstat(path.string().c_str(), &st) != 0) { if (::lstat(path.string().c_str(), &st) != 0) {
throw std::system_error(errno, std::generic_category(), "lstat"); throw std::system_error(errno, std::generic_category(), "lstat");
} }
file_stat rv; valid_fields_ = file_stat::all_valid;
rv.valid_fields = file_stat::all_valid; dev_ = st.st_dev;
rv.dev = st.st_dev; ino_ = st.st_ino;
rv.ino = st.st_ino; nlink_ = st.st_nlink;
rv.nlink = st.st_nlink; mode_ = st.st_mode;
rv.mode = st.st_mode; uid_ = st.st_uid;
rv.uid = st.st_uid; gid_ = st.st_gid;
rv.gid = st.st_gid; rdev_ = st.st_rdev;
rv.rdev = st.st_rdev; size_ = st.st_size;
rv.size = st.st_size; blksize_ = st.st_blksize;
rv.blksize = st.st_blksize; blocks_ = st.st_blocks;
rv.blocks = st.st_blocks;
#ifdef __APPLE__ #ifdef __APPLE__
rv.atime = st.st_atimespec.tv_sec; atime_ = st.st_atimespec.tv_sec;
rv.mtime = st.st_mtimespec.tv_sec; mtime_ = st.st_mtimespec.tv_sec;
rv.ctime = st.st_ctimespec.tv_sec; ctime_ = st.st_ctimespec.tv_sec;
#else #else
rv.atime = st.st_atim.tv_sec; atime_ = st.st_atim.tv_sec;
rv.mtime = st.st_mtim.tv_sec; mtime_ = st.st_mtim.tv_sec;
rv.ctime = st.st_ctim.tv_sec; ctime_ = st.st_ctim.tv_sec;
#endif #endif
return rv;
} }
#endif #endif
@ -265,15 +260,181 @@ std::string file_stat::perm_string(mode_type mode) {
} }
void file_stat::ensure_valid(valid_fields_type fields) const { void file_stat::ensure_valid(valid_fields_type fields) const {
if ((valid_fields & fields) != fields) { if ((valid_fields_ & fields) != fields) {
if (exception) { if (exception_) {
std::rethrow_exception(exception); std::rethrow_exception(exception_);
} else { } else {
DWARFS_THROW(runtime_error, DWARFS_THROW(runtime_error,
fmt::format("missing stat fields: {:#x} (have: {:#x})", fmt::format("missing stat fields: {:#x} (have: {:#x})",
fields, valid_fields)); fields, valid_fields_));
} }
} }
} }
std::filesystem::file_status file_stat::status() const {
ensure_valid(mode_valid);
return file_mode_to_status(mode_);
};
posix_file_type::value file_stat::type() const {
ensure_valid(mode_valid);
return static_cast<posix_file_type::value>(mode_ & posix_file_type::mask);
};
file_stat::perms_type file_stat::permissions() const {
ensure_valid(mode_valid);
return mode_ & 07777;
};
void file_stat::set_permissions(perms_type perms) {
mode_ = type() | (perms & 07777);
}
bool file_stat::is_directory() const {
return type() == posix_file_type::directory;
}
bool file_stat::is_regular_file() const {
return type() == posix_file_type::regular;
}
bool file_stat::is_symlink() const {
return type() == posix_file_type::symlink;
}
bool file_stat::is_device() const {
auto t = type();
return t == posix_file_type::block || t == posix_file_type::character;
}
file_stat::dev_type file_stat::dev() const {
ensure_valid(dev_valid);
return dev_;
}
void file_stat::set_dev(dev_type dev) {
valid_fields_ |= dev_valid;
dev_ = dev;
}
file_stat::ino_type file_stat::ino() const {
ensure_valid(ino_valid);
return ino_;
}
void file_stat::set_ino(ino_type ino) {
valid_fields_ |= ino_valid;
ino_ = ino;
}
file_stat::nlink_type file_stat::nlink() const {
ensure_valid(nlink_valid);
return nlink_;
}
void file_stat::set_nlink(nlink_type nlink) {
valid_fields_ |= nlink_valid;
nlink_ = nlink;
}
file_stat::mode_type file_stat::mode() const {
ensure_valid(mode_valid);
return mode_;
}
void file_stat::set_mode(mode_type mode) {
valid_fields_ |= mode_valid;
mode_ = mode;
}
file_stat::uid_type file_stat::uid() const {
ensure_valid(uid_valid);
return uid_;
}
void file_stat::set_uid(uid_type uid) {
valid_fields_ |= uid_valid;
uid_ = uid;
}
file_stat::gid_type file_stat::gid() const {
ensure_valid(gid_valid);
return gid_;
}
void file_stat::set_gid(gid_type gid) {
valid_fields_ |= gid_valid;
gid_ = gid;
}
file_stat::dev_type file_stat::rdev() const {
ensure_valid(rdev_valid);
return rdev_;
}
void file_stat::set_rdev(dev_type rdev) {
valid_fields_ |= rdev_valid;
rdev_ = rdev;
}
file_stat::off_type file_stat::size() const {
ensure_valid(size_valid);
return size_;
}
void file_stat::set_size(off_type size) {
valid_fields_ |= size_valid;
size_ = size;
}
file_stat::blksize_type file_stat::blksize() const {
ensure_valid(blksize_valid);
return blksize_;
}
void file_stat::set_blksize(blksize_type blksize) {
valid_fields_ |= blksize_valid;
blksize_ = blksize;
}
file_stat::blkcnt_type file_stat::blocks() const {
ensure_valid(blocks_valid);
return blocks_;
}
void file_stat::set_blocks(blkcnt_type blocks) {
valid_fields_ |= blocks_valid;
blocks_ = blocks;
}
file_stat::time_type file_stat::atime() const {
ensure_valid(atime_valid);
return atime_;
}
void file_stat::set_atime(time_type atime) {
valid_fields_ |= atime_valid;
atime_ = atime;
}
file_stat::time_type file_stat::mtime() const {
ensure_valid(mtime_valid);
return mtime_;
}
void file_stat::set_mtime(time_type mtime) {
valid_fields_ |= mtime_valid;
mtime_ = mtime;
}
file_stat::time_type file_stat::ctime() const {
ensure_valid(ctime_valid);
return ctime_;
}
void file_stat::set_ctime(time_type ctime) {
valid_fields_ |= ctime_valid;
ctime_ = ctime;
}
} // namespace dwarfs } // namespace dwarfs

View File

@ -354,9 +354,9 @@ bool filesystem_extractor_<LoggerPolicy>::extract(
::memset(&st, 0, sizeof(st)); ::memset(&st, 0, sizeof(st));
#ifdef _WIN32 #ifdef _WIN32
copy_file_stat<false>(&st, stbuf); stbuf.copy_to_without_block_info(&st);
#else #else
copy_file_stat<true>(&st, stbuf); stbuf.copy_to(&st);
#endif #endif
#ifdef _WIN32 #ifdef _WIN32

View File

@ -160,12 +160,12 @@ void entry::update(global_entry_data& data) const {
stat_.ensure_valid(file_stat::uid_valid | file_stat::gid_valid | stat_.ensure_valid(file_stat::uid_valid | file_stat::gid_valid |
file_stat::mode_valid | file_stat::atime_valid | file_stat::mode_valid | file_stat::atime_valid |
file_stat::mtime_valid | file_stat::ctime_valid); file_stat::mtime_valid | file_stat::ctime_valid);
data.add_uid(stat_.uid); data.add_uid(stat_.uid_unchecked());
data.add_gid(stat_.gid); data.add_gid(stat_.gid_unchecked());
data.add_mode(stat_.mode); data.add_mode(stat_.mode_unchecked());
data.add_atime(stat_.atime); data.add_atime(stat_.atime_unchecked());
data.add_mtime(stat_.mtime); data.add_mtime(stat_.mtime_unchecked());
data.add_ctime(stat_.ctime); data.add_ctime(stat_.ctime_unchecked());
} }
void entry::pack(thrift::metadata::inode_data& entry_v2, void entry::pack(thrift::metadata::inode_data& entry_v2,
@ -173,33 +173,21 @@ void entry::pack(thrift::metadata::inode_data& entry_v2,
stat_.ensure_valid(file_stat::uid_valid | file_stat::gid_valid | stat_.ensure_valid(file_stat::uid_valid | file_stat::gid_valid |
file_stat::mode_valid | file_stat::atime_valid | file_stat::mode_valid | file_stat::atime_valid |
file_stat::mtime_valid | file_stat::ctime_valid); file_stat::mtime_valid | file_stat::ctime_valid);
entry_v2.mode_index() = data.get_mode_index(stat_.mode); entry_v2.mode_index() = data.get_mode_index(stat_.mode_unchecked());
entry_v2.owner_index() = data.get_uid_index(stat_.uid); entry_v2.owner_index() = data.get_uid_index(stat_.uid_unchecked());
entry_v2.group_index() = data.get_gid_index(stat_.gid); entry_v2.group_index() = data.get_gid_index(stat_.gid_unchecked());
entry_v2.atime_offset() = data.get_atime_offset(stat_.atime); entry_v2.atime_offset() = data.get_atime_offset(stat_.atime_unchecked());
entry_v2.mtime_offset() = data.get_mtime_offset(stat_.mtime); entry_v2.mtime_offset() = data.get_mtime_offset(stat_.mtime_unchecked());
entry_v2.ctime_offset() = data.get_ctime_offset(stat_.ctime); entry_v2.ctime_offset() = data.get_ctime_offset(stat_.ctime_unchecked());
} }
size_t entry::size() const { size_t entry::size() const { return stat_.size(); }
stat_.ensure_valid(file_stat::size_valid);
return stat_.size;
}
uint64_t entry::raw_inode_num() const { uint64_t entry::raw_inode_num() const { return stat_.ino(); }
stat_.ensure_valid(file_stat::ino_valid);
return stat_.ino;
}
uint64_t entry::num_hard_links() const { uint64_t entry::num_hard_links() const { return stat_.nlink(); }
stat_.ensure_valid(file_stat::nlink_valid);
return stat_.nlink;
}
void entry::override_size(size_t size) { void entry::override_size(size_t size) { stat_.set_size(size); }
stat_.size = size;
stat_.valid_fields |= file_stat::size_valid;
}
entry::type_t file::type() const { return E_FILE; } entry::type_t file::type() const { return E_FILE; }
@ -207,55 +195,25 @@ auto entry::get_permissions() const -> mode_type { return stat_.permissions(); }
void entry::set_permissions(mode_type perm) { stat_.set_permissions(perm); } void entry::set_permissions(mode_type perm) { stat_.set_permissions(perm); }
auto entry::get_uid() const -> uid_type { auto entry::get_uid() const -> uid_type { return stat_.uid(); }
stat_.ensure_valid(file_stat::uid_valid);
return stat_.uid;
}
void entry::set_uid(uid_type uid) { void entry::set_uid(uid_type uid) { stat_.set_uid(uid); }
stat_.uid = uid;
stat_.valid_fields |= file_stat::uid_valid;
}
auto entry::get_gid() const -> gid_type { auto entry::get_gid() const -> gid_type { return stat_.gid(); }
stat_.ensure_valid(file_stat::gid_valid);
return stat_.gid;
}
void entry::set_gid(gid_type gid) { void entry::set_gid(gid_type gid) { stat_.set_gid(gid); }
stat_.gid = gid;
stat_.valid_fields |= file_stat::gid_valid;
}
uint64_t entry::get_atime() const { uint64_t entry::get_atime() const { return stat_.atime(); }
stat_.ensure_valid(file_stat::atime_valid);
return stat_.atime;
}
void entry::set_atime(uint64_t atime) { void entry::set_atime(uint64_t atime) { stat_.set_atime(atime); }
stat_.atime = atime;
stat_.valid_fields |= file_stat::atime_valid;
}
uint64_t entry::get_mtime() const { uint64_t entry::get_mtime() const { return stat_.mtime(); }
stat_.ensure_valid(file_stat::mtime_valid);
return stat_.mtime;
}
void entry::set_mtime(uint64_t mtime) { void entry::set_mtime(uint64_t mtime) { stat_.set_mtime(mtime); }
stat_.mtime = mtime;
stat_.valid_fields |= file_stat::mtime_valid;
}
uint64_t entry::get_ctime() const { uint64_t entry::get_ctime() const { return stat_.ctime(); }
stat_.ensure_valid(file_stat::ctime_valid);
return stat_.ctime;
}
void entry::set_ctime(uint64_t ctime) { void entry::set_ctime(uint64_t ctime) { stat_.set_ctime(ctime); }
stat_.ctime = ctime;
stat_.valid_fields |= file_stat::ctime_valid;
}
std::string_view file::hash() const { std::string_view file::hash() const {
auto& h = data_->hash; auto& h = data_->hash;
@ -506,6 +464,6 @@ void device::accept(entry_visitor& v, bool) { v.visit(this); }
void device::scan(os_access const&, progress&) {} void device::scan(os_access const&, progress&) {}
uint64_t device::device_id() const { return status().rdev; } uint64_t device::device_id() const { return status().rdev(); }
} // namespace dwarfs::internal } // namespace dwarfs::internal

View File

@ -1540,9 +1540,7 @@ metadata_<LoggerPolicy>::getattr_impl(inode_view iv,
getattr_options const& opts) const { getattr_options const& opts) const {
file_stat stbuf; file_stat stbuf;
::memset(&stbuf, 0, sizeof(stbuf)); stbuf.set_dev(0); // TODO: should we make this configurable?
stbuf.valid_fields = file_stat::all_valid;
auto mode = iv.mode(); auto mode = iv.mode();
auto timebase = meta_.timestamp_base(); auto timebase = meta_.timestamp_base();
@ -1556,38 +1554,37 @@ metadata_<LoggerPolicy>::getattr_impl(inode_view iv,
} }
} }
stbuf.mode = mode;
if (options_.readonly) { if (options_.readonly) {
stbuf.mode &= READ_ONLY_MASK; mode &= READ_ONLY_MASK;
} }
stbuf.set_mode(mode);
if (!opts.no_size) { if (!opts.no_size) {
stbuf.size = stbuf.is_directory() ? make_directory_view(iv).entry_count() stbuf.set_size(stbuf.is_directory() ? make_directory_view(iv).entry_count()
: file_size(iv, mode); : file_size(iv, mode));
stbuf.set_blocks((stbuf.size_unchecked() + 511) / 512);
} }
stbuf.ino = inode + inode_offset_; stbuf.set_ino(inode + inode_offset_);
stbuf.blksize = options_.block_size; stbuf.set_blksize(options_.block_size);
stbuf.blocks = (stbuf.size + 511) / 512; stbuf.set_uid(iv.getuid());
stbuf.uid = iv.getuid(); stbuf.set_gid(iv.getgid());
stbuf.gid = iv.getgid(); stbuf.set_mtime(resolution * (timebase + iv.raw().mtime_offset()));
stbuf.mtime = resolution * (timebase + iv.raw().mtime_offset());
if (mtime_only) { if (mtime_only) {
stbuf.atime = stbuf.ctime = stbuf.mtime; stbuf.set_atime(stbuf.mtime_unchecked());
stbuf.set_ctime(stbuf.mtime_unchecked());
} else { } else {
stbuf.atime = resolution * (timebase + iv.raw().atime_offset()); stbuf.set_atime(resolution * (timebase + iv.raw().atime_offset()));
stbuf.ctime = resolution * (timebase + iv.raw().ctime_offset()); stbuf.set_ctime(resolution * (timebase + iv.raw().ctime_offset()));
} }
stbuf.nlink = options_.enable_nlink && stbuf.is_regular_file() stbuf.set_nlink(options_.enable_nlink && stbuf.is_regular_file()
? DWARFS_NOTHROW(nlinks_.at(inode - file_inode_offset_)) ? DWARFS_NOTHROW(nlinks_.at(inode - file_inode_offset_))
: 1; : 1);
if (stbuf.is_device()) { stbuf.set_rdev(stbuf.is_device() ? get_device_id(inode) : 0);
stbuf.rdev = get_device_id(inode);
}
return stbuf; return stbuf;
} }

View File

@ -92,7 +92,7 @@ os_access_generic::opendir(fs::path const& path) const {
} }
file_stat os_access_generic::symlink_info(fs::path const& path) const { file_stat os_access_generic::symlink_info(fs::path const& path) const {
return make_file_stat(path); return file_stat(path);
} }
fs::path os_access_generic::read_symlink(fs::path const& path) const { fs::path os_access_generic::read_symlink(fs::path const& path) const {

View File

@ -375,7 +375,7 @@ void op_lookup(fuse_req_t req, fuse_ino_t parent, char const* name) {
struct ::fuse_entry_param e; struct ::fuse_entry_param e;
::memset(&e.attr, 0, sizeof(e.attr)); ::memset(&e.attr, 0, sizeof(e.attr));
copy_file_stat(&e.attr, stbuf); stbuf.copy_to(&e.attr);
e.generation = 1; e.generation = 1;
e.ino = e.attr.st_ino; e.ino = e.attr.st_ino;
e.attr_timeout = std::numeric_limits<double>::max(); e.attr_timeout = std::numeric_limits<double>::max();
@ -406,7 +406,7 @@ int op_getattr_common(LogProxy& log_, dwarfs_userdata& userdata,
if (!ec) { if (!ec) {
::memset(st, 0, sizeof(*st)); ::memset(st, 0, sizeof(*st));
copy_file_stat(st, stbuf); stbuf.copy_to(st);
} }
return ec.value(); return ec.value();
@ -793,7 +793,7 @@ int op_readdir_common(filesystem_v2& fs, Policy& policy, file_off_t off,
return ec.value(); return ec.value();
} }
copy_file_stat(&st, stbuf); stbuf.copy_to(&st);
if (!policy.add_entry(name, st, off)) { if (!policy.add_entry(name, st, off)) {
break; break;

View File

@ -110,7 +110,7 @@ int dwarfsbench_main(int argc, sys_char** argv, iolayer const& iol) {
pool.add_job([&fs, &iol, inode_data] { pool.add_job([&fs, &iol, inode_data] {
try { try {
auto stbuf = fs.getattr(inode_data); auto stbuf = fs.getattr(inode_data);
std::vector<char> buf(stbuf.size); std::vector<char> buf(stbuf.size());
int fh = fs.open(inode_data); int fh = fs.open(inode_data);
fs.read(fh, buf.data(), buf.size()); fs.read(fh, buf.data(), buf.size());
} catch (std::exception const& e) { } catch (std::exception const& e) {

View File

@ -73,7 +73,7 @@ void do_list_files(filesystem_v2& fs, iolayer const& iol, bool verbose) {
file_stat::off_type max_inode_size{0}; file_stat::off_type max_inode_size{0};
fs.walk([&](auto const& de) { fs.walk([&](auto const& de) {
auto st = fs.getattr(de.inode()); auto st = fs.getattr(de.inode());
max_inode_size = std::max(max_inode_size, st.size); max_inode_size = std::max(max_inode_size, st.size());
}); });
inode_size_width = fmt::format("{:L}", max_inode_size).size(); inode_size_width = fmt::format("{:L}", max_inode_size).size();
} }
@ -96,7 +96,7 @@ void do_list_files(filesystem_v2& fs, iolayer const& iol, bool verbose) {
iol.out << fmt::format( iol.out << fmt::format(
"{3} {4:{0}}/{5:{1}} {6:{2}L} {7:%Y-%m-%d %H:%M} {8}\n", uid_width, "{3} {4:{0}}/{5:{1}} {6:{2}L} {7:%Y-%m-%d %H:%M} {8}\n", uid_width,
gid_width, inode_size_width, iv.mode_string(), iv.getuid(), gid_width, inode_size_width, iv.mode_string(), iv.getuid(),
iv.getgid(), st.size, fmt::localtime(st.mtime), name); iv.getgid(), st.size(), fmt::localtime(st.mtime()), name);
} else if (!name.empty()) { } else if (!name.empty()) {
iol.out << name << "\n"; iol.out << name << "\n";
} }

View File

@ -229,14 +229,14 @@ TEST_P(options_test, cache_stress) {
auto iv = inodes[inode_dist(rng)]; auto iv = inodes[inode_dist(rng)];
auto stat = fs.getattr(iv); auto stat = fs.getattr(iv);
if (stat.is_regular_file()) { if (stat.is_regular_file()) {
auto offset = rng() % stat.size; auto offset = rng() % stat.size();
auto size = rng() % (stat.size - offset); auto size = rng() % (stat.size() - offset);
reqs.push_back({iv, offset, size}); reqs.push_back({iv, offset, size});
while (reqs.size() < num_read_reqs && while (reqs.size() < num_read_reqs &&
offset + size < static_cast<size_t>(stat.size / 2)) { offset + size < static_cast<size_t>(stat.size() / 2)) {
offset += rng() % (stat.size - (offset + size)); offset += rng() % (stat.size() - (offset + size));
size = rng() % (stat.size - offset); size = rng() % (stat.size() - offset);
reqs.push_back({iv, offset, size}); reqs.push_back({iv, offset, size});
} }
} }

View File

@ -807,9 +807,8 @@ std::vector<std::string> headers_v2{
file_stat make_stat(posix_file_type::value type, file_stat::perms_type perms, file_stat make_stat(posix_file_type::value type, file_stat::perms_type perms,
file_stat::off_type size) { file_stat::off_type size) {
file_stat st; file_stat st;
std::memset(&st, 0, sizeof(st)); st.set_mode(type | perms);
st.mode = type | perms; st.set_size(size);
st.size = size;
return st; return st;
} }
@ -839,14 +838,14 @@ void check_compat(logger& lgr, filesystem_v2 const& fs,
ASSERT_TRUE(entry); ASSERT_TRUE(entry);
auto st = fs.getattr(*entry); auto st = fs.getattr(*entry);
EXPECT_EQ(94, st.size); EXPECT_EQ(94, st.size());
EXPECT_EQ(S_IFREG | 0755, st.mode); EXPECT_EQ(S_IFREG | 0755, st.mode());
EXPECT_EQ(1000, st.uid); EXPECT_EQ(1000, st.uid());
EXPECT_EQ(100, st.gid); EXPECT_EQ(100, st.gid());
EXPECT_EQ(1606256045, st.mtime); EXPECT_EQ(1606256045, st.mtime());
if (has_ac_time) { if (has_ac_time) {
EXPECT_EQ(1616013831, st.atime); EXPECT_EQ(1616013831, st.atime());
EXPECT_EQ(1616013816, st.ctime); EXPECT_EQ(1616013816, st.ctime());
} }
EXPECT_TRUE(fs.access(*entry, R_OK, 1000, 0)); EXPECT_TRUE(fs.access(*entry, R_OK, 1000, 0));
@ -855,10 +854,10 @@ void check_compat(logger& lgr, filesystem_v2 const& fs,
EXPECT_GE(inode, 0); EXPECT_GE(inode, 0);
std::error_code ec; std::error_code ec;
std::vector<char> buf(st.size); std::vector<char> buf(st.size());
auto rv = fs.read(inode, &buf[0], st.size, ec); auto rv = fs.read(inode, &buf[0], st.size(), ec);
EXPECT_FALSE(ec); EXPECT_FALSE(ec);
EXPECT_EQ(rv, st.size); EXPECT_EQ(rv, st.size());
EXPECT_EQ(format_sh, std::string(buf.begin(), buf.end())); EXPECT_EQ(format_sh, std::string(buf.begin(), buf.end()));
entry = fs.find("/foo/bad"); entry = fs.find("/foo/bad");
@ -944,8 +943,10 @@ void check_compat(logger& lgr, filesystem_v2 const& fs,
for (auto special : {"dev/null", "dev/zero", "foo/pipe"}) { for (auto special : {"dev/null", "dev/zero", "foo/pipe"}) {
ref_entries.erase(special); ref_entries.erase(special);
} }
ref_entries["dev"].size -= 2; auto& dev = ref_entries["dev"];
ref_entries["foo"].size -= 1; auto& foo = ref_entries["foo"];
dev.set_size(dev.size() - 2);
foo.set_size(foo.size() - 1);
} }
for (auto mp : {&filesystem_v2::walk, &filesystem_v2::walk_data_order}) { for (auto mp : {&filesystem_v2::walk, &filesystem_v2::walk_data_order}) {
@ -954,7 +955,7 @@ void check_compat(logger& lgr, filesystem_v2 const& fs,
(fs.*mp)([&](dir_entry_view e) { (fs.*mp)([&](dir_entry_view e) {
auto stbuf = fs.getattr(e.inode()); auto stbuf = fs.getattr(e.inode());
inodes.push_back(stbuf.ino); inodes.push_back(stbuf.ino());
EXPECT_TRUE(entries.emplace(e.unix_path(), stbuf).second); EXPECT_TRUE(entries.emplace(e.unix_path(), stbuf).second);
}); });
@ -964,15 +965,15 @@ void check_compat(logger& lgr, filesystem_v2 const& fs,
auto it = ref_entries.find(p); auto it = ref_entries.find(p);
EXPECT_TRUE(it != ref_entries.end()) << p; EXPECT_TRUE(it != ref_entries.end()) << p;
if (it != ref_entries.end()) { if (it != ref_entries.end()) {
EXPECT_EQ(it->second.mode, st.mode) << p; EXPECT_EQ(it->second.mode(), st.mode()) << p;
if (st.type() == posix_file_type::character) { if (st.type() == posix_file_type::character) {
EXPECT_EQ(0, st.uid) << p; EXPECT_EQ(0, st.uid()) << p;
EXPECT_EQ(0, st.gid) << p; EXPECT_EQ(0, st.gid()) << p;
} else { } else {
EXPECT_EQ(1000, st.uid) << p; EXPECT_EQ(1000, st.uid()) << p;
EXPECT_EQ(100, st.gid) << p; EXPECT_EQ(100, st.gid()) << p;
} }
EXPECT_EQ(it->second.size, st.size) << p; EXPECT_EQ(it->second.size(), st.size()) << p;
} }
} }
} }
@ -1015,12 +1016,12 @@ void check_compat(logger& lgr, filesystem_v2 const& fs,
if (ri != ref_entries.end()) { if (ri != ref_entries.end()) {
auto const& st = ri->second; auto const& st = ri->second;
EXPECT_EQ(kv["mode"], fmt::format("{0:o}", st.mode & 0777)); EXPECT_EQ(kv["mode"], fmt::format("{0:o}", st.mode() & 0777));
EXPECT_EQ(std::stoi(kv["uid"]), kv["type"] == "char" ? 0 : 1000); EXPECT_EQ(std::stoi(kv["uid"]), kv["type"] == "char" ? 0 : 1000);
EXPECT_EQ(std::stoi(kv["gid"]), kv["type"] == "char" ? 0 : 100); EXPECT_EQ(std::stoi(kv["gid"]), kv["type"] == "char" ? 0 : 100);
if (kv["type"] == "file") { if (kv["type"] == "file") {
EXPECT_EQ(std::stoi(kv["size"]), st.size); EXPECT_EQ(std::stoi(kv["size"]), st.size());
} }
} }
} }
@ -1268,8 +1269,8 @@ TEST_P(set_uidgid_test, read_legacy_image) {
EXPECT_EQ(44444, v->getgid()) << path; EXPECT_EQ(44444, v->getgid()) << path;
auto st = fs.getattr(*v); auto st = fs.getattr(*v);
EXPECT_EQ(33333, st.uid) << path; EXPECT_EQ(33333, st.uid()) << path;
EXPECT_EQ(44444, st.gid) << path; EXPECT_EQ(44444, st.gid()) << path;
} }
} }

View File

@ -228,10 +228,11 @@ class filesystem : public ::benchmark::Fixture {
auto st = fs->getattr(*iv); auto st = fs->getattr(*iv);
auto i = fs->open(*iv); auto i = fs->open(*iv);
std::string buf; std::string buf;
buf.resize(st.size); auto size = st.size();
buf.resize(size);
for (auto _ : state) { for (auto _ : state) {
auto r = fs->read(i, buf.data(), st.size); auto r = fs->read(i, buf.data(), size);
::benchmark::DoNotOptimize(r); ::benchmark::DoNotOptimize(r);
} }
} }

View File

@ -257,56 +257,56 @@ void basic_end_to_end_test(std::string const& compressor,
ASSERT_TRUE(entry); ASSERT_TRUE(entry);
auto st = fs.getattr(*entry); auto st = fs.getattr(*entry);
EXPECT_EQ(st.size, 23456); EXPECT_EQ(st.size(), 23456);
EXPECT_EQ(st.uid, set_uid ? 0 : 1337); EXPECT_EQ(st.uid(), set_uid ? 0 : 1337);
EXPECT_EQ(st.gid, 0); EXPECT_EQ(st.gid(), 0);
EXPECT_EQ(st.atime, set_time ? 4711 : keep_all_times ? 4001 : 4002); EXPECT_EQ(st.atime(), set_time ? 4711 : keep_all_times ? 4001 : 4002);
EXPECT_EQ(st.mtime, set_time ? 4711 : keep_all_times ? 4002 : 4002); EXPECT_EQ(st.mtime(), set_time ? 4711 : keep_all_times ? 4002 : 4002);
EXPECT_EQ(st.ctime, set_time ? 4711 : keep_all_times ? 4003 : 4002); EXPECT_EQ(st.ctime(), set_time ? 4711 : keep_all_times ? 4003 : 4002);
{ {
std::error_code ec; std::error_code ec;
auto st2 = fs.getattr(*entry, {.no_size = true}, ec); auto st2 = fs.getattr(*entry, {.no_size = true}, ec);
EXPECT_FALSE(ec); EXPECT_FALSE(ec);
EXPECT_EQ(st2.size, 0); EXPECT_THROW(st2.size(), runtime_error);
EXPECT_EQ(st2.uid, st.uid); EXPECT_EQ(st2.uid(), st.uid());
EXPECT_EQ(st2.gid, st.gid); EXPECT_EQ(st2.gid(), st.gid());
EXPECT_EQ(st2.atime, st.atime); EXPECT_EQ(st2.atime(), st.atime());
EXPECT_EQ(st2.mtime, st.mtime); EXPECT_EQ(st2.mtime(), st.mtime());
EXPECT_EQ(st2.ctime, st.ctime); EXPECT_EQ(st2.ctime(), st.ctime());
} }
{ {
auto st3 = fs.getattr(*entry, {.no_size = true}); auto st3 = fs.getattr(*entry, {.no_size = true});
EXPECT_EQ(st3.size, 0); EXPECT_THROW(st3.size(), runtime_error);
EXPECT_EQ(st3.uid, st.uid); EXPECT_EQ(st3.uid(), st.uid());
EXPECT_EQ(st3.gid, st.gid); EXPECT_EQ(st3.gid(), st.gid());
EXPECT_EQ(st3.atime, st.atime); EXPECT_EQ(st3.atime(), st.atime());
EXPECT_EQ(st3.mtime, st.mtime); EXPECT_EQ(st3.mtime(), st.mtime());
EXPECT_EQ(st3.ctime, st.ctime); EXPECT_EQ(st3.ctime(), st.ctime());
} }
int inode = fs.open(*entry); int inode = fs.open(*entry);
EXPECT_GE(inode, 0); EXPECT_GE(inode, 0);
std::error_code ec; std::error_code ec;
std::vector<char> buf(st.size); std::vector<char> buf(st.size());
auto rv = fs.read(inode, &buf[0], st.size, ec); auto rv = fs.read(inode, &buf[0], st.size(), ec);
EXPECT_FALSE(ec); EXPECT_FALSE(ec);
EXPECT_EQ(rv, st.size); EXPECT_EQ(rv, st.size());
EXPECT_EQ(std::string(buf.begin(), buf.end()), test::loremipsum(st.size)); EXPECT_EQ(std::string(buf.begin(), buf.end()), test::loremipsum(st.size()));
entry = fs.find("/somelink"); entry = fs.find("/somelink");
ASSERT_TRUE(entry); ASSERT_TRUE(entry);
st = fs.getattr(*entry); st = fs.getattr(*entry);
EXPECT_EQ(st.size, 16); EXPECT_EQ(st.size(), 16);
EXPECT_EQ(st.uid, set_uid ? 0 : 1000); EXPECT_EQ(st.uid(), set_uid ? 0 : 1000);
EXPECT_EQ(st.gid, set_gid ? 0 : 100); EXPECT_EQ(st.gid(), set_gid ? 0 : 100);
EXPECT_EQ(st.rdev, 0); EXPECT_EQ(st.rdev(), 0);
EXPECT_EQ(st.atime, set_time ? 4711 : keep_all_times ? 2001 : 2002); EXPECT_EQ(st.atime(), set_time ? 4711 : keep_all_times ? 2001 : 2002);
EXPECT_EQ(st.mtime, set_time ? 4711 : keep_all_times ? 2002 : 2002); EXPECT_EQ(st.mtime(), set_time ? 4711 : keep_all_times ? 2002 : 2002);
EXPECT_EQ(st.ctime, set_time ? 4711 : keep_all_times ? 2003 : 2002); EXPECT_EQ(st.ctime(), set_time ? 4711 : keep_all_times ? 2003 : 2002);
auto link = fs.readlink(*entry); auto link = fs.readlink(*entry);
EXPECT_EQ(link, "somedir/ipsum.py"); EXPECT_EQ(link, "somedir/ipsum.py");
@ -317,7 +317,7 @@ void basic_end_to_end_test(std::string const& compressor,
ASSERT_TRUE(entry); ASSERT_TRUE(entry);
st = fs.getattr(*entry); st = fs.getattr(*entry);
EXPECT_EQ(st.size, 6); EXPECT_EQ(st.size(), 6);
link = fs.readlink(*entry); link = fs.readlink(*entry);
EXPECT_EQ(link, "../foo"); EXPECT_EQ(link, "../foo");
@ -327,14 +327,14 @@ void basic_end_to_end_test(std::string const& compressor,
if (with_specials) { if (with_specials) {
ASSERT_TRUE(entry); ASSERT_TRUE(entry);
st = fs.getattr(*entry); st = fs.getattr(*entry);
EXPECT_EQ(st.size, 0); EXPECT_EQ(st.size(), 0);
EXPECT_EQ(st.uid, set_uid ? 0 : 1000); EXPECT_EQ(st.uid(), set_uid ? 0 : 1000);
EXPECT_EQ(st.gid, set_gid ? 0 : 100); EXPECT_EQ(st.gid(), set_gid ? 0 : 100);
EXPECT_EQ(st.type(), posix_file_type::fifo); EXPECT_EQ(st.type(), posix_file_type::fifo);
EXPECT_EQ(st.rdev, 0); EXPECT_EQ(st.rdev(), 0);
EXPECT_EQ(st.atime, set_time ? 4711 : keep_all_times ? 8001 : 8002); EXPECT_EQ(st.atime(), set_time ? 4711 : keep_all_times ? 8001 : 8002);
EXPECT_EQ(st.mtime, set_time ? 4711 : keep_all_times ? 8002 : 8002); EXPECT_EQ(st.mtime(), set_time ? 4711 : keep_all_times ? 8002 : 8002);
EXPECT_EQ(st.ctime, set_time ? 4711 : keep_all_times ? 8003 : 8002); EXPECT_EQ(st.ctime(), set_time ? 4711 : keep_all_times ? 8003 : 8002);
} else { } else {
EXPECT_FALSE(entry); EXPECT_FALSE(entry);
} }
@ -344,11 +344,11 @@ void basic_end_to_end_test(std::string const& compressor,
if (with_devices) { if (with_devices) {
ASSERT_TRUE(entry); ASSERT_TRUE(entry);
st = fs.getattr(*entry); st = fs.getattr(*entry);
EXPECT_EQ(st.size, 0); EXPECT_EQ(st.size(), 0);
EXPECT_EQ(st.uid, 0); EXPECT_EQ(st.uid(), 0);
EXPECT_EQ(st.gid, 0); EXPECT_EQ(st.gid(), 0);
EXPECT_EQ(st.type(), posix_file_type::character); EXPECT_EQ(st.type(), posix_file_type::character);
EXPECT_EQ(st.rdev, 259); EXPECT_EQ(st.rdev(), 259);
} else { } else {
EXPECT_FALSE(entry); EXPECT_FALSE(entry);
} }
@ -358,18 +358,18 @@ void basic_end_to_end_test(std::string const& compressor,
if (with_devices) { if (with_devices) {
ASSERT_TRUE(entry); ASSERT_TRUE(entry);
st = fs.getattr(*entry); st = fs.getattr(*entry);
EXPECT_EQ(st.size, 0); EXPECT_EQ(st.size(), 0);
EXPECT_EQ(st.uid, 0); EXPECT_EQ(st.uid(), 0);
EXPECT_EQ(st.gid, 0); EXPECT_EQ(st.gid(), 0);
EXPECT_EQ(st.type(), posix_file_type::character); EXPECT_EQ(st.type(), posix_file_type::character);
EXPECT_EQ(st.rdev, 261); EXPECT_EQ(st.rdev(), 261);
EXPECT_EQ(st.atime, set_time ? 4711 EXPECT_EQ(st.atime(), set_time ? 4711
: keep_all_times ? 4000010001 : keep_all_times ? 4000010001
: 4000020002); : 4000020002);
EXPECT_EQ(st.mtime, set_time ? 4711 EXPECT_EQ(st.mtime(), set_time ? 4711
: keep_all_times ? 4000020002 : keep_all_times ? 4000020002
: 4000020002); : 4000020002);
EXPECT_EQ(st.ctime, set_time ? 4711 EXPECT_EQ(st.ctime(), set_time ? 4711
: keep_all_times ? 4000030003 : keep_all_times ? 4000030003
: 4000020002); : 4000020002);
} else { } else {
@ -427,10 +427,10 @@ void basic_end_to_end_test(std::string const& compressor,
auto st1 = fs.getattr(*entry); auto st1 = fs.getattr(*entry);
auto st2 = fs.getattr(*e2); auto st2 = fs.getattr(*e2);
EXPECT_EQ(st1.ino, st2.ino); EXPECT_EQ(st1.ino(), st2.ino());
if (enable_nlink) { if (enable_nlink) {
EXPECT_EQ(2, st1.nlink); EXPECT_EQ(2, st1.nlink());
EXPECT_EQ(2, st2.nlink); EXPECT_EQ(2, st2.nlink());
} }
entry = fs.find("/"); entry = fs.find("/");
@ -443,14 +443,14 @@ void basic_end_to_end_test(std::string const& compressor,
ASSERT_TRUE(entry); ASSERT_TRUE(entry);
EXPECT_GT(entry->inode_num(), 0); EXPECT_GT(entry->inode_num(), 0);
st1 = fs.getattr(*entry); st1 = fs.getattr(*entry);
EXPECT_EQ(23456, st1.size); EXPECT_EQ(23456, st1.size());
e2 = fs.find(0, "somedir"); e2 = fs.find(0, "somedir");
ASSERT_TRUE(e2); ASSERT_TRUE(e2);
st2 = fs.getattr(*e2); st2 = fs.getattr(*e2);
entry = fs.find(st2.ino, "ipsum.py"); entry = fs.find(st2.ino(), "ipsum.py");
ASSERT_TRUE(entry); ASSERT_TRUE(entry);
st1 = fs.getattr(*entry); st1 = fs.getattr(*entry);
EXPECT_EQ(access_fail ? 0 : 10000, st1.size); EXPECT_EQ(access_fail ? 0 : 10000, st1.size());
EXPECT_TRUE(fs.access(*entry, R_OK, 1000, 100)); EXPECT_TRUE(fs.access(*entry, R_OK, 1000, 100));
entry = fs.find(0, "baz.pl"); entry = fs.find(0, "baz.pl");
ASSERT_TRUE(entry); ASSERT_TRUE(entry);
@ -464,7 +464,7 @@ void basic_end_to_end_test(std::string const& compressor,
(fs.*mp)([&](dir_entry_view e) { (fs.*mp)([&](dir_entry_view e) {
auto stbuf = fs.getattr(e.inode()); auto stbuf = fs.getattr(e.inode());
inodes.push_back(stbuf.ino); inodes.push_back(stbuf.ino());
auto path = e.path(); auto path = e.path();
if (!path.empty()) { if (!path.empty()) {
path = "/" + path; path = "/" + path;
@ -477,14 +477,14 @@ void basic_end_to_end_test(std::string const& compressor,
for (auto const& [p, st] : entries) { for (auto const& [p, st] : entries) {
auto ref = input->symlink_info(p); auto ref = input->symlink_info(p);
EXPECT_EQ(ref.mode, st.mode) << p; EXPECT_EQ(ref.mode(), st.mode()) << p;
EXPECT_EQ(set_uid ? 0 : ref.uid, st.uid) << p; EXPECT_EQ(set_uid ? 0 : ref.uid(), st.uid()) << p;
EXPECT_EQ(set_gid ? 0 : ref.gid, st.gid) << p; EXPECT_EQ(set_gid ? 0 : ref.gid(), st.gid()) << p;
if (!st.is_directory()) { if (!st.is_directory()) {
if (input->access(p, R_OK) == 0) { if (input->access(p, R_OK) == 0) {
EXPECT_EQ(ref.size, st.size) << p; EXPECT_EQ(ref.size(), st.size()) << p;
} else { } else {
EXPECT_EQ(0, st.size) << p; EXPECT_EQ(0, st.size()) << p;
} }
} }
} }
@ -824,7 +824,7 @@ TEST_P(compression_regression, github45) {
ASSERT_TRUE(entry); ASSERT_TRUE(entry);
auto st = fs.getattr(*entry); auto st = fs.getattr(*entry);
EXPECT_EQ(st.size, file_size); EXPECT_EQ(st.size(), file_size);
int inode = fs.open(*entry); int inode = fs.open(*entry);
EXPECT_GE(inode, 0); EXPECT_GE(inode, 0);
@ -1117,10 +1117,10 @@ TEST(filesystem, uid_gid_32bit) {
auto st16 = fs.getattr(*iv16); auto st16 = fs.getattr(*iv16);
auto st32 = fs.getattr(*iv32); auto st32 = fs.getattr(*iv32);
EXPECT_EQ(60000, st16.uid); EXPECT_EQ(60000, st16.uid());
EXPECT_EQ(65535, st16.gid); EXPECT_EQ(65535, st16.gid());
EXPECT_EQ(65536, st32.uid); EXPECT_EQ(65536, st32.uid());
EXPECT_EQ(4294967295, st32.gid); EXPECT_EQ(4294967295, st32.gid());
} }
TEST(filesystem, uid_gid_count) { TEST(filesystem, uid_gid_count) {
@ -1154,12 +1154,12 @@ TEST(filesystem, uid_gid_count) {
auto st50000 = fs.getattr(*iv50000); auto st50000 = fs.getattr(*iv50000);
auto st99999 = fs.getattr(*iv99999); auto st99999 = fs.getattr(*iv99999);
EXPECT_EQ(50000, st00000.uid); EXPECT_EQ(50000, st00000.uid());
EXPECT_EQ(250000, st00000.gid); EXPECT_EQ(250000, st00000.gid());
EXPECT_EQ(100000, st50000.uid); EXPECT_EQ(100000, st50000.uid());
EXPECT_EQ(300000, st50000.gid); EXPECT_EQ(300000, st50000.gid());
EXPECT_EQ(149999, st99999.uid); EXPECT_EQ(149999, st99999.uid());
EXPECT_EQ(349999, st99999.gid); EXPECT_EQ(349999, st99999.gid());
} }
TEST(section_index_regression, github183) { TEST(section_index_regression, github183) {
@ -1233,8 +1233,8 @@ TEST(section_index_regression, github183) {
EXPECT_NO_THROW(inode = fs.open(*entry)); EXPECT_NO_THROW(inode = fs.open(*entry));
std::error_code ec; std::error_code ec;
std::vector<char> buf(st.size); std::vector<char> buf(st.size());
auto rv = fs.read(inode, &buf[0], st.size, ec); auto rv = fs.read(inode, &buf[0], st.size(), ec);
EXPECT_TRUE(ec); EXPECT_TRUE(ec);
EXPECT_EQ(rv, 0); EXPECT_EQ(rv, 0);
@ -1294,9 +1294,9 @@ TEST(file_scanner, file_start_hash) {
auto st1 = fs.getattr(*link1); auto st1 = fs.getattr(*link1);
auto st2 = fs.getattr(*link2); auto st2 = fs.getattr(*link2);
EXPECT_EQ(st1.ino, st2.ino); EXPECT_EQ(st1.ino(), st2.ino());
EXPECT_EQ(st1.nlink, 2); EXPECT_EQ(st1.nlink(), 2);
EXPECT_EQ(st2.nlink, 2); EXPECT_EQ(st2.nlink(), 2);
} }
TEST(filesystem, root_access_github204) { TEST(filesystem, root_access_github204) {

View File

@ -49,18 +49,19 @@ namespace {
file_stat make_file_stat(simplestat const& ss) { file_stat make_file_stat(simplestat const& ss) {
file_stat rv; file_stat rv;
::memset(&rv, 0, sizeof(rv)); rv.set_dev(0);
rv.valid_fields = file_stat::all_valid; rv.set_ino(ss.ino);
rv.ino = ss.ino; rv.set_nlink(ss.nlink);
rv.nlink = ss.nlink; rv.set_mode(ss.mode);
rv.mode = ss.mode; rv.set_uid(ss.uid);
rv.uid = ss.uid; rv.set_gid(ss.gid);
rv.gid = ss.gid; rv.set_rdev(ss.rdev);
rv.rdev = ss.rdev; rv.set_size(ss.size);
rv.size = ss.size; rv.set_blocks(0);
rv.atime = ss.atime; rv.set_blksize(0);
rv.mtime = ss.mtime; rv.set_atime(ss.atime);
rv.ctime = ss.ctime; rv.set_mtime(ss.mtime);
rv.set_ctime(ss.ctime);
return rv; return rv;
} }

View File

@ -375,9 +375,9 @@ std::set<uint64_t> get_all_fs_times(filesystem_v2 const& fs) {
std::set<uint64_t> times; std::set<uint64_t> times;
fs.walk([&](auto const& e) { fs.walk([&](auto const& e) {
auto st = fs.getattr(e.inode()); auto st = fs.getattr(e.inode());
times.insert(st.atime); times.insert(st.atime());
times.insert(st.ctime); times.insert(st.ctime());
times.insert(st.mtime); times.insert(st.mtime());
}); });
return times; return times;
} }
@ -386,7 +386,7 @@ std::set<uint64_t> get_all_fs_uids(filesystem_v2 const& fs) {
std::set<uint64_t> uids; std::set<uint64_t> uids;
fs.walk([&](auto const& e) { fs.walk([&](auto const& e) {
auto st = fs.getattr(e.inode()); auto st = fs.getattr(e.inode());
uids.insert(st.uid); uids.insert(st.uid());
}); });
return uids; return uids;
} }
@ -395,7 +395,7 @@ std::set<uint64_t> get_all_fs_gids(filesystem_v2 const& fs) {
std::set<uint64_t> gids; std::set<uint64_t> gids;
fs.walk([&](auto const& e) { fs.walk([&](auto const& e) {
auto st = fs.getattr(e.inode()); auto st = fs.getattr(e.inode());
gids.insert(st.gid); gids.insert(st.gid());
}); });
return gids; return gids;
} }
@ -877,7 +877,7 @@ TEST(mkdwarfs_test, metadata_path) {
fs.walk([&](auto e) { fs.walk([&](auto e) {
auto stat = fs.getattr(e.inode()); auto stat = fs.getattr(e.inode());
if (stat.is_regular_file()) { if (stat.is_regular_file()) {
entries.emplace(stat.size, e); entries.emplace(stat.size(), e);
} }
}); });
@ -1008,7 +1008,7 @@ TEST(mkdwarfs_test, metadata_specials) {
EXPECT_FALSE(ec); EXPECT_FALSE(ec);
EXPECT_TRUE(stat.is_device()); EXPECT_TRUE(stat.is_device());
EXPECT_EQ(77, stat.rdev); EXPECT_EQ(77, stat.rdev());
} }
TEST(mkdwarfs_test, metadata_time_resolution) { TEST(mkdwarfs_test, metadata_time_resolution) {
@ -1032,9 +1032,9 @@ TEST(mkdwarfs_test, metadata_time_resolution) {
std::error_code ec; std::error_code ec;
auto stat = fs.getattr(*iv, ec); auto stat = fs.getattr(*iv, ec);
EXPECT_FALSE(ec); EXPECT_FALSE(ec);
EXPECT_EQ(3300, stat.atime); EXPECT_EQ(3300, stat.atime());
EXPECT_EQ(2220, stat.mtime); EXPECT_EQ(2220, stat.mtime());
EXPECT_EQ(1080, stat.ctime); EXPECT_EQ(1080, stat.ctime());
} }
TEST(mkdwarfs_test, metadata_readdir) { TEST(mkdwarfs_test, metadata_readdir) {
@ -2561,8 +2561,8 @@ TEST_P(map_file_error_test, delayed) {
ASSERT_TRUE(small_link2); ASSERT_TRUE(small_link2);
EXPECT_EQ(large_link1->inode_num(), large_link2->inode_num()); EXPECT_EQ(large_link1->inode_num(), large_link2->inode_num());
EXPECT_EQ(small_link1->inode_num(), small_link2->inode_num()); EXPECT_EQ(small_link1->inode_num(), small_link2->inode_num());
EXPECT_EQ(0, fs.getattr(*large_link1).size); EXPECT_EQ(0, fs.getattr(*large_link1).size());
EXPECT_EQ(0, fs.getattr(*small_link1).size); EXPECT_EQ(0, fs.getattr(*small_link1).size());
} }
std::unordered_map<fs::path, std::string, fs_path_hash> actual_files; std::unordered_map<fs::path, std::string, fs_path_hash> actual_files;
@ -2571,7 +2571,7 @@ TEST_P(map_file_error_test, delayed) {
if (iv.is_regular_file()) { if (iv.is_regular_file()) {
std::string data; std::string data;
auto stat = fs.getattr(iv); auto stat = fs.getattr(iv);
data.resize(stat.size); data.resize(stat.size());
ASSERT_EQ(data.size(), fs.read(iv.inode_num(), data.data(), data.size())); ASSERT_EQ(data.size(), fs.read(iv.inode_num(), data.data(), data.size()));
ASSERT_TRUE(actual_files.emplace(dev.fs_path(), std::move(data)).second); ASSERT_TRUE(actual_files.emplace(dev.fs_path(), std::move(data)).second);
} }
@ -2703,10 +2703,10 @@ TEST(block_cache, sequential_access_detector) {
ASSERT_TRUE(iv); ASSERT_TRUE(iv);
ASSERT_TRUE(iv->is_regular_file()); ASSERT_TRUE(iv->is_regular_file());
auto st = fs.getattr(*iv); auto st = fs.getattr(*iv);
ASSERT_EQ(data.size(), st.size); ASSERT_EQ(data.size(), st.size());
std::string buffer; std::string buffer;
buffer.resize(data.size()); buffer.resize(data.size());
auto nread = fs.read(iv->inode_num(), buffer.data(), st.size); auto nread = fs.read(iv->inode_num(), buffer.data(), st.size());
EXPECT_EQ(data.size(), nread); EXPECT_EQ(data.size(), nread);
EXPECT_EQ(data, buffer); EXPECT_EQ(data, buffer);
} }
@ -2808,8 +2808,8 @@ TEST(file_scanner, large_file_handling) {
ASSERT_TRUE(iv) << i; ASSERT_TRUE(iv) << i;
auto st = fs.getattr(*iv); auto st = fs.getattr(*iv);
std::string buffer; std::string buffer;
buffer.resize(st.size); buffer.resize(st.size());
auto nread = fs.read(iv->inode_num(), buffer.data(), st.size); auto nread = fs.read(iv->inode_num(), buffer.data(), st.size());
EXPECT_EQ(data[i].size(), nread) << i; EXPECT_EQ(data[i].size(), nread) << i;
EXPECT_EQ(data[i], buffer) << i; EXPECT_EQ(data[i], buffer) << i;
} }

View File

@ -772,8 +772,8 @@ bool check_readonly(fs::path const& p, bool readonly) {
size_t num_hardlinks(fs::path const& p) { size_t num_hardlinks(fs::path const& p) {
#ifdef _WIN32 #ifdef _WIN32
auto stat = dwarfs::make_file_stat(p); dwarfs::file_stat stat(p);
return stat.nlink; return stat.nlink();
#else #else
return fs::hard_link_count(p); return fs::hard_link_count(p);
#endif #endif