YSTest: NativeAPI.cpp 源文件

YSTest PreAlpha_b900_20201012 The YSLib Test Project

NativeAPI.cpp
浏览该文件的文档.
1 /*
2 © 2012-2020 FrankHB.
3
4 This file is part of the YSLib project, and may only be used,
5 modified, and distributed under the terms of the YSLib project
6 license, LICENSE.TXT. By continuing to use, modify, or distribute
7 this file you indicate that you have read the license and
8 understand and accept it fully.
9 */
10
28 #include "YCLib/YModules.h"
29 #include YFM_YCLib_NativeAPI // for ::stat, ::lstat;
30 #if YCL_Win32 || YCL_API_POSIXFileSystem
31 # include YFM_YCLib_FileIO // for platform::Nonnull, YCL_Raise_SysE;
32 #endif
33 #if YCL_DS
34 # include YFM_DS_YCLib_DSIO // for ::DISC_INTERFACE, Disc,
35 // platform_ex::FAT::Mount;
36 # include <arm9/dldi.h> // for ::DLDI_INTERFACE;
37 //# include <nds/system.h> // for ::isDSiMode;
38
39
41 extern "C" const ::DLDI_INTERFACE _io_dldi_stub;
42
44 extern const ::DISC_INTERFACE __io_dsisd;
45
47 // NOTE: Stub to work around devkitARM r46 bug.
48 // See https://devkitpro.org/viewtopic.php?f=13&t=8643&start=10.
49 extern "C" YB_ATTR(weak) void
50 __sync_synchronize()
51 {}
52
57 extern "C" YB_ATTR(weak) const yimpl(int) __secure_area__ = 0;
58 #elif YCL_MinGW
59 # include <ctime> // for std::gmtime;
60 #elif YCL_Android
61 # include <sys/syscall.h> // for ::syscall, __NR_utimensat;
62 #endif
63
64 namespace
65 {
66
67 }
68
69
70 #if YCL_Win32 || YCL_API_POSIXFileSystem
71 namespace platform_ex
72 {
73
74 void
75 cstat(struct ::stat& st, const char* path, bool follow_link, const char* sig)
76 {
77 const int res(estat(st, path, follow_link));
78
79 if(res < 0)
80 #if !(YCL_DS || YCL_Win32)
81 YCL_Raise_SysE(, "::stat", sig);
82 #else
83 {
84 if(follow_link)
85 YCL_Raise_SysE(, "::stat", sig);
86 else
87 YCL_Raise_SysE(, "::lstat", sig);
88 }
89 #endif
90 }
91 void
92 cstat(struct ::stat& st, int fd, const char* sig)
93 {
94 YCL_Call_CAPI(, ::fstat, sig, fd, &st);
95 }
96
97 int
98 estat(struct ::stat& st, const char* path, bool follow_link) ynothrowv
99 {
100 using platform::Nonnull;
101
102 # if YCL_DS || YCL_Win32
103 yunused(follow_link);
104 return ::stat(Nonnull(path), &st);
105 # else
106 return (follow_link ? ::stat : ::lstat)(Nonnull(path), &st);
107 # endif
108 }
109
110 } // namespace platform_ex;
111 #endif
112
113
114 #if YCL_DS
115 namespace platform_ex
116 {
117
119 using namespace platform::Descriptions;
120
121 FileSystem::FileSystem(size_t pages)
122 : root([pages]() ynothrow -> RootKind{
123 const auto init([=](const char* name, const ::DISC_INTERFACE& disc_io)
124 ynothrow -> bool{
125 // NOTE: %DEFAULT_SECTORS_PAGE is 8 in "common.h" in LibFAT source.
126 // This is also the minimal value used by the cache. So the shift
127 // is 3.
128 TryRet(platform_ex::FAT::Mount(name, disc_io, 0, pages, 3))
129 CatchExpr(std::exception& e, YF_TraceRaw(Warning,
130 "FATMount failure[%s]: %s", typeid(e).name(), e.what()))
131 CatchExpr(..., YF_TraceRaw(Emergent,
132 "Unknown exception found @ InitializeFileSystem."))
133 return {};
134 });
135
136 #if false
137 // XXX: This would cause "undefined reference to `get_io_dsisd()'" with
138 // devkitARM r48. It should be defined in LibNDS, though.
139 if(const auto p = ::get_io_dsisd())
140 if(init("sd", *p))
141 #else
142 // XXX: Nevertheless, this is same to the call in previous revisions. It
143 // just requires one more magic number.
144 if(::isDSiMode()
145 && reinterpret_cast<::tNDSHeader*>(0x02FFFE00)->unitCode != 0)
146 if(init("sd", ::__io_dsisd))
147 #endif
148 return RootKind::SD;
149 // NOTE: As %::dldiGetInternal.
150 if((::_io_dldi_stub.ioInterface.features
151 & (FEATURE_SLOT_GBA | FEATURE_SLOT_NDS)) != 0)
152 // NOTE: As %::sysSetCardOwner(BUS_OWNER_ARM9), with one less access
153 // to the volatile lvalue.
154 REG_EXMEMCNT &= ~ARM7_OWNS_CARD;
155 if(init("fat", ::_io_dldi_stub.ioInterface))
156 return RootKind::FAT;
157 return RootKind::Null;
158 }()), init_dev([this]{
159 if(root != RootKind::Null)
160 return root == RootKind::FAT ? "fat" : "sd";
161 // TODO: More descriptive message with underlying reason?
162 throw std::runtime_error("Failed initializing file system.");
163 }())
164 {
165 // NOTE: No %ARGV_MAGIC here as LibFAT does.
166 // NOTE: Call of %::chdir also sets default device in I/O support code. This
167 // enables relative paths available for %::GetDeviceOpTab and
168 // %platform_ex::FAT::FetchPartitionFromPath for platform %DS.
169 ::chdir(root == RootKind::FAT ? "fat:/" : "sd:/");
170 }
171
172 FileSystem::~FileSystem()
173 {
174 if(YB_UNLIKELY(!FAT::Unmount(init_dev)))
175 YF_TraceRaw(Err, "Failed uninitializing file system.");
176 }
177
178 } // namespace platform_ex;
179 #elif YCL_MinGW
180 extern "C"
181 {
182
183 # if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
184 // See FileSystem.cpp.
186 struct ::tm* __cdecl __MINGW_NOTHROW
187 _gmtime32(const ::__time32_t* p)
188 {
189 return std::gmtime(p);
190 }
191 # endif
192
193 } // extern "C";
194 #elif YCL_Android
195 // NOTE: For versions where syscalls available, see http://man7.org/linux/man-pages/man2/syscalls.2.html.
196 // NOTE: Linux kernel version since 2.6.23 should be all OK. For early kernel
197 // versions Android used, see http://elinux.org/Android_Kernel_Versions.
198 // Also https://en.wikipedia.org/wiki/Android_version_history.
199 # if !(__ANDROID_API__ >= 21)
200 int
201 linkat(int fd1, const char* path1, int fd2, const char* path2, int flag)
202 yimpl(ynothrow)
203 {
204 // NOTE: The 'linkat' syscall was introduced in Linux 2.6.16.
205 return ::syscall(__NR_linkat, fd1, path1, fd2, path2, flag);
206 }
207 # endif
208
209 # if !(__ANDROID_API__ >= 19)
210 int
211 futimens(int fd, const ::timespec times[2]) yimpl(ynothrow)
212 {
213 // NOTE: See https://android.googlesource.com/platform/bionic/+/840a114eb12773c5af39c0c97675b27aa6dee78c/libc/bionic/futimens.cpp.
214 return ::utimensat(fd, {}, times, 0);
215 }
216 # endif
217
218 # if !(__ANDROID_API__ >= 12)
219 int
220 utimensat(int fd, const char* path, const ::timespec times[2], int flags)
221 yimpl(ynothrow)
222 {
223 // NOTE: The 'utimesat' syscall was introduced in Linux 2.6.22.
224 // NOTE: See http://stackoverflow.com/questions/19374749/how-to-work-around-absence-of-futimes-in-android-ndk.
225 return ::syscall(__NR_utimensat, fd, path, times, flags);
226 }
227 # endif
228 #endif
229
230 namespace platform
231 {
232 }
233
YF_TraceRaw
#define YF_TraceRaw(_lv,...)
YFramework 直接日志追踪。
Definition: Debug.h:378
CHRLib::e
const char const char * e
Definition: CharacterProcessing.h:112
platform::Nonnull
YB_PURE _type && Nonnull(_type &&p) ynothrowv
断言并返回非空参数。
Definition: Debug.h:518
platform::follow_link
bool follow_link
Definition: FileIO.cpp:1225
platform_ex
平台扩展命名空间。
Definition: Android.h:46
platform::Descriptions::Emergent
@ Emergent
Definition: YCommon.h:179
CHRLib::CharSet::Null
@ Null
空字符集。
Definition: Encoding.h:63
NPL::tm
tm
Definition: NPLA.h:1941
YCL_Raise_SysE
#define YCL_Raise_SysE(_t, _msg, _sig)
按错误值和指定参数抛出第一参数指定类型的对象。
Definition: YCommon.h:201
platform_ex::Windows::path
const wchar_t * path
Definition: Win32/include/YCLib/MinGW32.h:615
platform::ynothrow
const _tString &path ynothrow
Definition: YCLib/FileSystem.h:453
std
Definition: optional.h:982
YB_ATTR
#define YB_ATTR(...)
GNU 风格属性。
Definition: ydef.h:567
platform::Descriptions::Err
@ Err
Definition: YCommon.h:182
platform::Descriptions
平台描述空间。
Definition: YCommon.h:171
platform::Descriptions::Warning
@ Warning
Definition: YCommon.h:183
YSLib::path
YB_ATTR_nodiscard YF_API const char * path
Definition: Initialization.h:116
CatchExpr
#define CatchExpr(_ex,...)
指定表达式作为异常处理器。
Definition: YBaseMacro.h:129
platform
默认平台命名空间。
Definition: Container.h:56
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:143
NPL::A1::name
const char * name
Definition: NPLA1.h:1876
ynothrowv
#define ynothrowv
YSLib 无异常抛出保证验证：有条件地使用无异常抛出规范。
Definition: ydef.h:1219
YModules.h
YCLib 库模块配置文件。
platform::cstat
cstat(st, path, follow_link, yfsig)
YB_UNLIKELY
#define YB_UNLIKELY(_expr)
分支预测提示。
Definition: ydef.h:828
platform::p
return p p
Definition: YCLib/FileSystem.h:209
yimpl
#define yimpl(...)
实现标签。
Definition: ydef.h:413
YCL_Call_CAPI
#define YCL_Call_CAPI(_t, _fn, _sig,...)
Definition: YCommon.h:257
ynothrow
#define ynothrow
YSLib 无异常抛出保证：若支持 noexcept 关键字， 指定特定的 noexcept 异常规范。
Definition: ydef.h:1199
TryRet
#define TryRet(...)
指定表达式在 try 块中求值并返回。
Definition: YBaseMacro.h:124
yunused
#define yunused(...)
标记未使用的表达式。
Definition: ydef.h:1458