[fs linux]: Add more info to GetInfo

Fill in name, path and total_size.
Correct convertUnixtimeToWinFiletime which was using deprecated stat
function without nanoseconds. It now includes nanoseconds.
Add unit test for file and folder info.
This commit is contained in:
Sandy Carter 2019-08-24 19:13:53 +02:00
parent 10ea3faa8f
commit ee0b7904ed
4 changed files with 82 additions and 15 deletions

View File

@ -9,19 +9,17 @@
#include "xenia/base/assert.h"
#include "xenia/base/filesystem.h"
#include "xenia/base/logging.h"
#include "xenia/base/string.h"
#include <assert.h>
#include <dirent.h>
#include <fcntl.h>
#include <ftw.h>
#include <libgen.h>
#include <pwd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
@ -94,13 +92,13 @@ bool DeleteFolder(const std::wstring& path) {
: false;
}
static uint64_t convertUnixtimeToWinFiletime(time_t unixtime) {
// Linux uses number of seconds since 1/1/1970, and Windows uses
static uint64_t convertUnixtimeToWinFiletime(const timespec& unixtime) {
// Linux uses number of nanoseconds since 1/1/1970, and Windows uses
// number of nanoseconds since 1/1/1601
// so we convert linux time to nanoseconds and then add the number of
// nanoseconds from 1601 to 1970
// so we add the number of nanoseconds from 1601 to 1970
// see https://msdn.microsoft.com/en-us/library/ms724228
uint64_t filetime = filetime = (unixtime * 10000000) + 116444736000000000;
uint64_t filetime =
(unixtime.tv_sec * 10000000) + unixtime.tv_nsec + 116444736000000000;
return filetime;
}
@ -191,12 +189,17 @@ bool GetInfo(const std::wstring& path, FileInfo* out_info) {
if (stat(xe::to_string(path).c_str(), &st) == 0) {
if (S_ISDIR(st.st_mode)) {
out_info->type = FileInfo::Type::kDirectory;
// On Linux st.st_size can have non-zero size (generally 4096) so make 0
out_info->total_size = 0;
} else {
out_info->type = FileInfo::Type::kFile;
out_info->total_size = st.st_size;
}
out_info->create_timestamp = convertUnixtimeToWinFiletime(st.st_ctime);
out_info->access_timestamp = convertUnixtimeToWinFiletime(st.st_atime);
out_info->write_timestamp = convertUnixtimeToWinFiletime(st.st_mtime);
out_info->name = find_name_from_path(path);
out_info->path = find_base_path(path);
out_info->create_timestamp = convertUnixtimeToWinFiletime(st.st_ctim);
out_info->access_timestamp = convertUnixtimeToWinFiletime(st.st_atim);
out_info->write_timestamp = convertUnixtimeToWinFiletime(st.st_mtim);
return true;
}
return false;
@ -223,9 +226,9 @@ std::vector<FileInfo> ListFiles(const std::wstring& path) {
auto full_path = xe::to_string(xe::join_paths(path, info.name));
auto ret = stat(full_path.c_str(), &st);
assert_zero(ret);
info.create_timestamp = convertUnixtimeToWinFiletime(st.st_ctime);
info.access_timestamp = convertUnixtimeToWinFiletime(st.st_atime);
info.write_timestamp = convertUnixtimeToWinFiletime(st.st_mtime);
info.create_timestamp = convertUnixtimeToWinFiletime(st.st_ctim);
info.access_timestamp = convertUnixtimeToWinFiletime(st.st_atim);
info.write_timestamp = convertUnixtimeToWinFiletime(st.st_mtim);
if (ent->d_type == DT_DIR) {
info.type = FileInfo::Type::kDirectory;
info.total_size = 0;

View File

@ -0,0 +1,56 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2019 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/base/filesystem.h"
#include "third_party/catch/include/catch.hpp"
namespace xe {
namespace base {
namespace test {
TEST_CASE("file_get_info", "Get Info") {
auto test_file_name = L"test_file";
auto test_file_dir = xe::fix_path_separators(L"src/xenia/base/testing/res");
auto test_file_path = xe::join_paths(test_file_dir, test_file_name);
filesystem::FileInfo info = {};
REQUIRE(filesystem::GetInfo(test_file_path, &info));
CHECK(info.type == filesystem::FileInfo::Type::kFile);
CHECK(info.name == test_file_name);
CHECK(info.path == test_file_dir);
CHECK(info.total_size == 81);
CHECK(info.create_timestamp > 132111406279379842);
CHECK(info.access_timestamp > 132111406279379842);
CHECK(info.write_timestamp > 132111406279379842);
}
TEST_CASE("folder_get_info", "Get Info") {
auto test_folder_name = L"res";
auto test_folder_dir = xe::fix_path_separators(L"src/xenia/base/testing");
auto test_folder_path = xe::join_paths(test_folder_dir, test_folder_name);
filesystem::FileInfo info = {};
REQUIRE(filesystem::GetInfo(test_folder_path, &info));
CHECK(info.type == filesystem::FileInfo::Type::kDirectory);
CHECK(info.name == test_folder_name);
CHECK(info.path == test_folder_dir);
CHECK(info.total_size == 0);
CHECK(info.create_timestamp > 132111406279379842);
CHECK(info.access_timestamp > 132111406279379842);
CHECK(info.write_timestamp > 132111406279379842);
}
} // namespace test
} // namespace base
} // namespace xe

View File

@ -6,3 +6,10 @@ test_suite("xenia-base-tests", project_root, ".", {
"xenia-base",
},
})
files({
"res/*",
})
filter("files:res/*")
flags({"ExcludeFromBuild"})
filter("platforms:Windows")
debugdir(project_root)

View File

@ -0,0 +1 @@
Test file to test the xe::filesystem::GetInfo function on both Windows and Linux