Skip to content

Commit 1d41167

Browse files
committed
refs #68, experimental support for emscripten
1 parent 2ea0017 commit 1d41167

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

include/ghc/filesystem.hpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@
6464
#define GHC_OS_SYS5R4
6565
#elif defined(BSD)
6666
#define GHC_OS_BSD
67+
#elif defined(__EMSCRIPTEN__)
68+
#define GHC_OS_WEB
69+
#include <wasi/api.h>
6770
#else
6871
#error "Operating system currently not supported!"
6972
#endif
@@ -590,7 +593,9 @@ enum class copy_options : uint16_t {
590593

591594
directories_only = 0x40,
592595
create_symlinks = 0x80,
596+
#ifndef GHC_OS_WEB
593597
create_hard_links = 0x100
598+
#endif
594599
};
595600

596601
enum class directory_options : uint16_t {
@@ -701,10 +706,14 @@ class GHC_FS_API_CLASS directory_entry
701706
uintmax_t file_size() const;
702707
#endif
703708
uintmax_t file_size(std::error_code& ec) const noexcept;
709+
710+
#ifndef GHC_OS_WEB
704711
#ifdef GHC_WITH_EXCEPTIONS
705712
uintmax_t hard_link_count() const;
706713
#endif
707714
uintmax_t hard_link_count(std::error_code& ec) const noexcept;
715+
#endif
716+
708717
#ifdef GHC_WITH_EXCEPTIONS
709718
file_time_type last_write_time() const;
710719
#endif
@@ -934,10 +943,12 @@ GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink
934943
#endif
935944
GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept;
936945

946+
#ifndef GHC_OS_WEB
937947
#ifdef GHC_WITH_EXCEPTIONS
938948
GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link);
939949
#endif
940950
GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link, std::error_code& ec) noexcept;
951+
#endif
941952

942953
#ifdef GHC_WITH_EXCEPTIONS
943954
GHC_FS_API void create_symlink(const path& to, const path& new_symlink);
@@ -969,10 +980,12 @@ GHC_FS_API uintmax_t file_size(const path& p);
969980
#endif
970981
GHC_FS_API uintmax_t file_size(const path& p, std::error_code& ec) noexcept;
971982

983+
#ifndef GHC_OS_WEB
972984
#ifdef GHC_WITH_EXCEPTIONS
973985
GHC_FS_API uintmax_t hard_link_count(const path& p);
974986
#endif
975987
GHC_FS_API uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept;
988+
#endif
976989

977990
GHC_FS_API bool is_block_file(file_status s) noexcept;
978991
#ifdef GHC_WITH_EXCEPTIONS
@@ -1815,13 +1828,15 @@ GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink,
18151828
}
18161829
}
18171830

1831+
#ifndef GHC_OS_WEB
18181832
GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlink, std::error_code& ec)
18191833
{
18201834
if (::link(target_name.c_str(), new_hardlink.c_str()) != 0) {
18211835
ec = detail::make_system_error();
18221836
}
18231837
}
18241838
#endif
1839+
#endif
18251840

18261841
template <typename T>
18271842
GHC_INLINE file_status file_status_from_st_mode(T mode)
@@ -3402,9 +3417,11 @@ GHC_INLINE void copy(const path& from, const path& to, copy_options options, std
34023417
if ((options & copy_options::create_symlinks) != copy_options::none) {
34033418
create_symlink(from.is_absolute() ? from : canonical(from, ec), to, ec);
34043419
}
3420+
#ifndef GHC_OS_WEB
34053421
else if ((options & copy_options::create_hard_links) != copy_options::none) {
34063422
create_hard_link(from, to, ec);
34073423
}
3424+
#endif
34083425
else if (is_directory(fs_to)) {
34093426
copy_file(from, to / from.filename(), options, ec);
34103427
}
@@ -3697,6 +3714,7 @@ GHC_INLINE void create_directory_symlink(const path& to, const path& new_symlink
36973714
detail::create_symlink(to, new_symlink, true, ec);
36983715
}
36993716

3717+
#ifndef GHC_OS_WEB
37003718
#ifdef GHC_WITH_EXCEPTIONS
37013719
GHC_INLINE void create_hard_link(const path& to, const path& new_hard_link)
37023720
{
@@ -3712,6 +3730,7 @@ GHC_INLINE void create_hard_link(const path& to, const path& new_hard_link, std:
37123730
{
37133731
detail::create_hardlink(to, new_hard_link, ec);
37143732
}
3733+
#endif
37153734

37163735
#ifdef GHC_WITH_EXCEPTIONS
37173736
GHC_INLINE void create_symlink(const path& to, const path& new_symlink)
@@ -3900,6 +3919,7 @@ GHC_INLINE uintmax_t file_size(const path& p, std::error_code& ec) noexcept
39003919
#endif
39013920
}
39023921

3922+
#ifndef GHC_OS_WEB
39033923
#ifdef GHC_WITH_EXCEPTIONS
39043924
GHC_INLINE uintmax_t hard_link_count(const path& p)
39053925
{
@@ -3940,6 +3960,7 @@ GHC_INLINE uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcep
39403960
return ec ? static_cast<uintmax_t>(-1) : result;
39413961
#endif
39423962
}
3963+
#endif
39433964

39443965
GHC_INLINE bool is_block_file(file_status s) noexcept
39453966
{
@@ -4176,7 +4197,7 @@ GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::err
41764197
times[0].tv_sec = 0;
41774198
times[0].tv_nsec = UTIME_OMIT;
41784199
times[1].tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
4179-
times[1].tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000;
4200+
times[1].tv_nsec = 0; //std::chrono::duration_cast<std::chrono::nanoseconds>(d).count() % 1000000000;
41804201
if (::utimensat(AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) {
41814202
ec = detail::make_system_error();
41824203
}
@@ -4945,6 +4966,7 @@ GHC_INLINE uintmax_t directory_entry::file_size(std::error_code& ec) const noexc
49454966
return filesystem::file_size(path(), ec);
49464967
}
49474968

4969+
#ifndef GHC_OS_WEB
49484970
#ifdef GHC_WITH_EXCEPTIONS
49494971
GHC_INLINE uintmax_t directory_entry::hard_link_count() const
49504972
{
@@ -4967,6 +4989,7 @@ GHC_INLINE uintmax_t directory_entry::hard_link_count(std::error_code& ec) const
49674989
#endif
49684990
return filesystem::hard_link_count(path(), ec);
49694991
}
4992+
#endif
49704993

49714994
#ifdef GHC_WITH_EXCEPTIONS
49724995
GHC_INLINE file_time_type directory_entry::last_write_time() const

test/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,16 @@ else()
1818
add_executable(filesystem_test filesystem_test.cpp catch.hpp)
1919
target_link_libraries(filesystem_test ghc_filesystem)
2020
target_compile_options(filesystem_test PRIVATE
21+
$<$<BOOL:${EMSCRIPTEN}>:-s DISABLE_EXCEPTION_CATCHING=0>
2122
$<$<CXX_COMPILER_ID:Clang>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror>
2223
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Wno-psabi -Werror>
2324
$<$<CXX_COMPILER_ID:MSVC>:/WX>)
2425
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
2526
target_compile_definitions(filesystem_test PRIVATE _CRT_SECURE_NO_WARNINGS)
2627
endif()
28+
if(EMSCRIPTEN)
29+
set_target_properties(filesystem_test PROPERTIES LINK_FLAGS "-g4 -s DISABLE_EXCEPTION_CATCHING=0 -s ALLOW_MEMORY_GROWTH=1")
30+
endif()
2731
ParseAndAddCatchTests(filesystem_test)
2832
AddExecutableWithStdFS(std_filesystem_test filesystem_test.cpp catch.hpp)
2933
if(WIN32)

test/filesystem_test.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1229,19 +1229,23 @@ TEST_CASE("30.10.12 class directory_entry", "[filesystem][directory_entry][fs.di
12291229
ec.clear();
12301230
CHECK(std::abs(std::chrono::duration_cast<std::chrono::seconds>(de.last_write_time(ec) - now).count()) < 3);
12311231
CHECK(!ec);
1232+
#ifndef GHC_OS_WEB
12321233
CHECK(de.hard_link_count() == 1);
12331234
CHECK(de.hard_link_count(ec) == 1);
12341235
CHECK(!ec);
1236+
#endif
12351237
CHECK_THROWS_AS(de.replace_filename("bar"), fs::filesystem_error);
12361238
CHECK_NOTHROW(de.replace_filename("foo"));
12371239
ec.clear();
12381240
CHECK_NOTHROW(de.replace_filename("bar", ec));
12391241
CHECK(ec);
12401242
auto de2none = fs::directory_entry();
12411243
ec.clear();
1244+
#ifndef GHC_OS_WEB
12421245
CHECK(de2none.hard_link_count(ec) == static_cast<uintmax_t>(-1));
12431246
CHECK_THROWS_AS(de2none.hard_link_count(), fs::filesystem_error);
12441247
CHECK(ec);
1248+
#endif
12451249
ec.clear();
12461250
CHECK_NOTHROW(de2none.last_write_time(ec));
12471251
CHECK_THROWS_AS(de2none.last_write_time(), fs::filesystem_error);
@@ -1593,6 +1597,7 @@ TEST_CASE("30.10.15.3 copy", "[filesystem][operations][fs.op.copy]")
15931597
CHECK(fs::is_symlink("dir3/dir2/file3"));
15941598
#endif
15951599
}
1600+
#ifndef GHC_OS_WEB
15961601
{
15971602
TemporaryDirectory t(TempOpt::change_path);
15981603
std::error_code ec;
@@ -1613,6 +1618,7 @@ TEST_CASE("30.10.15.3 copy", "[filesystem][operations][fs.op.copy]")
16131618
CHECK(fs::exists("dir3/dir2/file3"));
16141619
CHECK(fs::hard_link_count("dir1/dir2/file3") == f3hl + 1);
16151620
}
1621+
#endif
16161622
}
16171623

16181624
TEST_CASE("30.10.15.4 copy_file", "[filesystem][operations][fs.op.copy_file]")
@@ -1780,6 +1786,7 @@ TEST_CASE("30.10.15.8 create_directory_symlink", "[filesystem][operations][fs.op
17801786

17811787
TEST_CASE("30.10.15.9 create_hard_link", "[filesystem][operations][fs.op.create_hard_link]")
17821788
{
1789+
#ifndef GHC_OS_WEB
17831790
TemporaryDirectory t(TempOpt::change_path);
17841791
std::error_code ec;
17851792
generateFile("foo", 1234);
@@ -1793,6 +1800,7 @@ TEST_CASE("30.10.15.9 create_hard_link", "[filesystem][operations][fs.op.create_
17931800
CHECK_THROWS_AS(fs::create_hard_link("nofoo", "bar"), fs::filesystem_error);
17941801
CHECK_NOTHROW(fs::create_hard_link("nofoo", "bar", ec));
17951802
CHECK(ec);
1803+
#endif
17961804
}
17971805

17981806
TEST_CASE("30.10.15.10 create_symlink", "[filesystem][operations][fs.op.create_symlink]")
@@ -1927,6 +1935,7 @@ TEST_CASE("30.10.15.14 file_size", "[filesystem][operations][fs.op.file_size]")
19271935

19281936
TEST_CASE("30.10.15.15 hard_link_count", "[filesystem][operations][fs.op.hard_link_count]")
19291937
{
1938+
#ifndef GHC_OS_WEB
19301939
TemporaryDirectory t(TempOpt::change_path);
19311940
std::error_code ec;
19321941
#ifdef GHC_OS_WINDOWS
@@ -1952,6 +1961,9 @@ TEST_CASE("30.10.15.15 hard_link_count", "[filesystem][operations][fs.op.hard_li
19521961
CHECK_NOTHROW(fs::hard_link_count(t.path() / "bar", ec));
19531962
CHECK(ec);
19541963
ec.clear();
1964+
#else
1965+
WARN("Test for unsupportet features are disabled on JS/Wasm target.");
1966+
#endif
19551967
}
19561968

19571969
class FileTypeMixFixture
@@ -1968,7 +1980,7 @@ class FileTypeMixFixture
19681980
fs::create_symlink("regular", "file_symlink");
19691981
fs::create_directory_symlink("directory", "dir_symlink");
19701982
}
1971-
#ifndef GHC_OS_WINDOWS
1983+
#if !defined(GHC_OS_WINDOWS) && !defined(GHC_OS_WEB)
19721984
REQUIRE(::mkfifo("fifo", 0644) == 0);
19731985
_hasFifo = true;
19741986
struct ::sockaddr_un addr;
@@ -2271,6 +2283,7 @@ TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.24 is_symlink", "[filesystem][ope
22712283
CHECK(!fs::is_symlink(fs::file_status(fs::file_type::unknown)));
22722284
}
22732285

2286+
#ifndef GHC_OS_WEB
22742287
static fs::file_time_type timeFromString(const std::string& str)
22752288
{
22762289
struct ::tm tm;
@@ -2282,6 +2295,7 @@ static fs::file_time_type timeFromString(const std::string& str)
22822295
}
22832296
return from_time_t<fs::file_time_type>(std::mktime(&tm));
22842297
}
2298+
#endif
22852299

22862300
TEST_CASE("30.10.15.25 last_write_time", "[filesystem][operations][fs.op.last_write_time]")
22872301
{
@@ -2304,16 +2318,21 @@ TEST_CASE("30.10.15.25 last_write_time", "[filesystem][operations][fs.op.last_wr
23042318
// checks that the time of the symlink is fetched
23052319
CHECK(ft == fs::last_write_time("foo2"));
23062320
}
2321+
#ifndef GHC_OS_WEB
23072322
auto nt = timeFromString("2015-10-21T04:30:00");
23082323
CHECK_NOTHROW(fs::last_write_time(t.path() / "foo", nt));
23092324
CHECK(std::abs(std::chrono::duration_cast<std::chrono::seconds>(fs::last_write_time("foo") - nt).count()) < 1);
23102325
nt = timeFromString("2015-10-21T04:29:00");
23112326
CHECK_NOTHROW(fs::last_write_time("foo", nt, ec));
2327+
std::cout << "about to call last_write_time" << std::endl;
23122328
CHECK(std::abs(std::chrono::duration_cast<std::chrono::seconds>(fs::last_write_time("foo") - nt).count()) < 1);
23132329
CHECK(!ec);
2330+
std::cout << "about to call last_write_time" << std::endl;
23142331
CHECK_THROWS_AS(fs::last_write_time("bar", nt), fs::filesystem_error);
2332+
std::cout << "about to call last_write_time" << std::endl;
23152333
CHECK_NOTHROW(fs::last_write_time("bar", nt, ec));
23162334
CHECK(ec);
2335+
#endif
23172336
}
23182337

23192338
TEST_CASE("30.10.15.26 permissions", "[filesystem][operations][fs.op.permissions]")

0 commit comments

Comments
 (0)