Support QNX platform.
thun-res opened this issue · 13 comments
platform: qnx700, aarch64, c++11 support (POSIX support)
"Operating system currently not supported!"
And It looks like the 'struct dirent' has no 'd_type'
I try to modify:
filesystem.hpp:
...
#elif defined(__QNX__)
#define GHC_OS_QNX
#else
#error "Operating system currently not supported!"
#endif
...
...
void copyToDirEntry()
{
_dir_entry._symlink_status.permissions(perms::unknown);
#ifdef GHC_OS_QNX
_dir_entry._status.type(file_type::none);
_dir_entry._status.permissions(perms::unknown);
_dir_entry._symlink_status.type(file_type::unknown);
#else
switch (_entry->d_type) {
case DT_BLK:
_dir_entry._symlink_status.type(file_type::block);
break;
case DT_CHR:
_dir_entry._symlink_status.type(file_type::character);
break;
case DT_DIR:
_dir_entry._symlink_status.type(file_type::directory);
break;
case DT_FIFO:
_dir_entry._symlink_status.type(file_type::fifo);
break;
case DT_LNK:
_dir_entry._symlink_status.type(file_type::symlink);
break;
case DT_REG:
_dir_entry._symlink_status.type(file_type::regular);
break;
case DT_SOCK:
_dir_entry._symlink_status.type(file_type::socket);
break;
default:
_dir_entry._symlink_status.type(file_type::unknown);
break;
}
if (_entry->d_type != DT_LNK) {
_dir_entry._status = _dir_entry._symlink_status;
} else {
_dir_entry._status.type(file_type::none);
_dir_entry._status.permissions(perms::unknown);
}
#endif
_dir_entry._file_size = static_cast<uintmax_t>(-1);
_dir_entry._hard_link_count = static_cast<uintmax_t>(-1);
_dir_entry._last_write_time = 0;
}
...
I don’t know if the changes are correct, but the compilation passed.
thanks.
Thank you! That looks like it should work, I'll look into it.
I tested it briefly and found it crashed(when I create dir it throw)...
Sadly, contrary to what I expected, I couldn't get access to a QNX installation and didn't want do register and apply for a 30 days evaluation, as that wouldn't allow me to further support it after 30 days, so I currently have no way to check it myself.
Thanks for trying my suggestion, I have solved it now.
...
#define GHC_OS_WEB
#include <wasi/api.h>
#elif defined(__QNX__)
#define GHC_OS_QNX
#else
#error "Operating system currently not supported!"
#endif
...
...
void copyToDirEntry()
{
_dir_entry._symlink_status.permissions(perms::unknown);
#ifdef GHC_OS_QNX
struct stat buffer;
int reval = ::stat(_dir_entry._path.c_str(), &buffer);
if (reval == 0) {
if (S_ISDIR(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::directory);
} else if (S_ISREG(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::regular);
} else if (S_ISLNK(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::symlink);
} else if (S_ISCHR(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::character);
} else if (S_ISFIFO(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::fifo);
} else if (S_ISBLK(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::block);
} else if (S_ISSOCK(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::socket);
} else {
_dir_entry._symlink_status.type(file_type::unknown);
}
_dir_entry._status = _dir_entry._symlink_status;
} else {
_dir_entry._status.type(file_type::none);
_dir_entry._symlink_status.type(file_type::unknown);
}
#else
switch (_entry->d_type) {
case DT_BLK:
_dir_entry._symlink_status.type(file_type::block);
break;
case DT_CHR:
_dir_entry._symlink_status.type(file_type::character);
break;
case DT_DIR:
_dir_entry._symlink_status.type(file_type::directory);
break;
case DT_FIFO:
_dir_entry._symlink_status.type(file_type::fifo);
break;
case DT_LNK:
_dir_entry._symlink_status.type(file_type::symlink);
break;
case DT_REG:
_dir_entry._symlink_status.type(file_type::regular);
break;
case DT_SOCK:
_dir_entry._symlink_status.type(file_type::socket);
break;
default:
_dir_entry._symlink_status.type(file_type::unknown);
break;
}
if (_entry->d_type != DT_LNK) {
_dir_entry._status = _dir_entry._symlink_status;
} else {
_dir_entry._status.type(file_type::none);
_dir_entry._status.permissions(perms::unknown);
}
#endif
_dir_entry._file_size = static_cast<uintmax_t>(-1);
_dir_entry._hard_link_count = static_cast<uintmax_t>(-1);
_dir_entry._last_write_time = 0;
}
path _base;
directory_options _options;
DIR* _dir;
struct ::dirent* _entry;
directory_entry _dir_entry;
std::error_code _ec;
};
...
I have tested and it works, you can add this.
#ifdef GHC_OS_QNX
struct stat buffer;
int reval = ::stat(_dir_entry._path.c_str(), &buffer);
bool is_link = false;
if (reval == 0) {
if (S_ISDIR(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::directory);
} else if (S_ISREG(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::regular);
} else if (S_ISLNK(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::symlink);
is_link = true;
} else if (S_ISCHR(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::character);
} else if (S_ISFIFO(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::fifo);
} else if (S_ISBLK(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::block);
} else if (S_ISSOCK(buffer.st_mode)) {
_dir_entry._symlink_status.type(file_type::socket);
} else {
_dir_entry._symlink_status.type(file_type::unknown);
}
if (is_link) {
_dir_entry._status.type(file_type::none);
_dir_entry._status.permissions(perms::unknown);
} else {
_dir_entry._status = _dir_entry._symlink_status;
}
} else {
_dir_entry._status.type(file_type::unknown);
_dir_entry._symlink_status.type(file_type::unknown);
_dir_entry._status.permissions(perms::unknown);
}
#else
switch (_entry->d_type) {
case DT_BLK:
_dir_entry._symlink_status.type(file_type::block);
break;
case DT_CHR:
_dir_entry._symlink_status.type(file_type::character);
break;
case DT_DIR:
_dir_entry._symlink_status.type(file_type::directory);
break;
case DT_FIFO:
_dir_entry._symlink_status.type(file_type::fifo);
break;
case DT_LNK:
_dir_entry._symlink_status.type(file_type::symlink);
break;
case DT_REG:
_dir_entry._symlink_status.type(file_type::regular);
break;
case DT_SOCK:
_dir_entry._symlink_status.type(file_type::socket);
break;
default:
_dir_entry._symlink_status.type(file_type::unknown);
break;
}
if (_entry->d_type != DT_LNK) {
_dir_entry._status = _dir_entry._symlink_status;
} else {
_dir_entry._status.type(file_type::none);
_dir_entry._status.permissions(perms::unknown);
}
#endif
Sorry for the delay! The reason I didn't simply use your solution was, that I wanted the way to support systems without dirent.d_type
the same way as filesystems reporting DT_UNKNOWN
as type and I had thought my default:
would be handling those correctly but it didn't. As I couldn't test myself I postponed work on it a bit.
I used a macro to select no-d_type support to allow easier integration for other systems that might need it.
platform: qnx700, aarch64, c++14 support (POSIX support)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++14")
set(CMAKE_CXX_EXTENSIONS ON)
Got error:
// using the most recent ghc_filesystem/1.5.6
filesystem.hpp:178:22: fatal error: langinfo.h: No such file or directory
2021/09/04: works totally fine on QNX. 😢 Sorry for the disruption.
latest version, compiled on android arm-64 pass
complied on qnx 700 arm fail!
complie output:
inc/include/ghc/filesystem.hpp:164:22: fatal error: langinfo.h: No such file or directory
i can't find this header : laninfo.h
if i try to note this include, will ouput error info:
/ghc/filesystem.hpp:2467:43: error: '::nl_langinfo' has not been declared
_simple_insensitive(::nl_langin
Similar problem with QNX 7.1.0 (x86_64):
/home/davide/qnx710/host/linux/x86_64/usr/bin/x86_64-pc-nto-qnx7.1.0-ld: CMakeFiles/fs_dir.dir/dir.cpp.o: in function `ghc::filesystem::u8arguments::u8arguments(int&, char**&)':
dir.cpp:(.text._ZN3ghc10filesystem11u8argumentsC2ERiRPPc[_ZN3ghc10filesystem11u8argumentsC5ERiRPPc]+0x66): undefined reference to `nl_langinfo(int)'
collect2: error: ld returned 1 exit status
examples/CMakeFiles/fs_dir.dir/build.make:96: recipe for target 'examples/fs_dir' failed
This is better kept at #169 as comments at an old issue get lost fast, but as written there, I need help or PRs to fix that.
There is no free QNX dev environment to test and debug this myself, at least I couldn't find a legal one, and I'm not willing to buy a license I don't need for myself, so QNX support sadly is not an official feature but one backed by help of others, I can't check it by CI and I can't do it myself.
I worked on QNX years ago (and ghc_filesystem worked). This patch may be useful: https://gist.github.com/district10/9937754bdcdd5321a56430f491088de9
Specially, add these to your CMakeLists.txt may resolve your problem: (I still have no idea why. It's tricky.)
add_definitions(-D_QNX_SOURCE)
add_definitions(-D_XOPEN_SOURCE=500)
Or this:
if (CMAKE_SYSTEM_NAME STREQUAL "QNX")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++")
set(CMAKE_CXX_EXTENSIONS ON)
endif()
You may read -stdlib=XXX
, -std=xxx
here: https://www.qnx.com/developers/docs/7.0.0/#com.qnx.doc.neutrino.utilities/topic/q/qcc.html