YSTest: NativeAPI.cpp 源文件

YSTest PreAlpha_b800_20170810 The YSLib Test Project

- 首页
- 相关页面
- 模块
- 命名空间
- 类
- 文件

- 文件列表
- 文件成员

NativeAPI.cpp
浏览该文件的文档.
1 /*
2 © 2012-2017 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, ::__io_dsisd;
36 # include <arm9/dldi.h> // for ::DLDI_INTERFACE;
37 //# include <nds/system.h> // for ::isDSiMode;
38
39
41 extern "C" ::DLDI_INTERFACE _io_dldi_stub;
42 #elif YCL_MinGW
43 # include <ctime> // for std::gmtime;
44 #elif YCL_Android
45 # include <sys/syscall.h> // for ::syscall, __NR_utimensat;
46 #endif
47
48 namespace
49 {
50
51 }
52
53
54 #if YCL_Win32 || YCL_API_POSIXFileSystem
55 namespace platform_ex
56 {
57
58 YF_API YB_NONNULL(2) void
59 cstat(struct ::stat& st, const char* path, bool follow_link, const char* sig)
60 {
61 const int res(estat(st, path, follow_link));
62
63 if(res < 0)
64 #if !(YCL_DS || YCL_Win32)
65 YCL_Raise_SysE(, "::stat", sig);
66 #else
67 {
68 if(follow_link)
69 YCL_Raise_SysE(, "::stat", sig);
70 else
71 YCL_Raise_SysE(, "::lstat", sig);
72 }
73 #endif
74 }
75 void
76 cstat(struct ::stat& st, int fd, const char* sig)
77 {
78 const int res(::fstat(fd, &st));
79
80 if(res < 0)
81 YCL_Raise_SysE(, "::stat", sig);
82 }
83
84
85 YB_NONNULL(2) int
86 estat(struct ::stat& st, const char* path, bool follow_link) ynothrowv
87 {
88 using platform::Nonnull;
89
90 # if YCL_DS || YCL_Win32
91 yunused(follow_link);
92 return ::stat(Nonnull(path), &st);
93 # else
94 return (follow_link ? ::stat : ::lstat)(Nonnull(path), &st);
95 # endif
96 }
97
98 } // namespace platform_ex;
99 #endif
100
101
102 #if YCL_DS
103 // NOTE: Stub to work around devkitARM r46 bug.
105 // See https://devkitpro.org/viewtopic.php?f=13&t=8643&start=10.
106 extern "C" YB_ATTR(weak) void
107 __sync_synchronize()
108 {}
109
110 namespace platform_ex
111 {
112
114 using namespace platform::Descriptions;
115
116 FileSystem::FileSystem(size_t pages)
117 : root([pages]() ynothrow -> RootKind{
118 const auto init([=](const char* name, const ::DISC_INTERFACE& disc_io)
119 ynothrow -> bool{
120 // NOTE: %DEFAULT_SECTORS_PAGE is 8 in "common.h" in libfat source.
121 // This is also the minimal value used by the cache. So the shift
122 // is 3.
123 TryRet(platform_ex::FAT::Mount(name, disc_io, 0, pages, 3))
124 CatchExpr(std::exception& e, YF_TraceRaw(Warning,
125 "FATMount failure[%s]: %s", typeid(e).name(), e.what()))
126 CatchExpr(..., YF_TraceRaw(Emergent,
127 "Unknown exception found @ InitializeFileSystem."))
128 return {};
129 });
130
131 if(::__dsimode && init("sd", ::__io_dsisd))
132 return RootKind::SD;
133 // NOTE: As %::dldiGetInternal.
134 if((::_io_dldi_stub.ioInterface.features
135 & (FEATURE_SLOT_GBA | FEATURE_SLOT_NDS)) != 0)
136 // NOTE: As %::sysSetCardOwner(BUS_OWNER_ARM9), with one less access
137 // to the volatile lvalue.
138 REG_EXMEMCNT &= ~ARM7_OWNS_CARD;
139 if(init("fat", ::_io_dldi_stub.ioInterface))
140 return RootKind::FAT;
141 return RootKind::Null;
142 }()), init_dev([this]{
143 if(root != RootKind::Null)
144 return root == RootKind::FAT ? "fat" : "sd";
145 // TODO: More descriptive message with underlying reason?
146 throw std::runtime_error("Failed initializing file system.");
147 }())
148 {
149 // NOTE: No %ARGV_MAGIC here as libfat does.
150 // NOTE: Call of %::chdir also sets default device in I/O support code. This
151 // enables relative paths available for %::GetDeviceOpTab and
152 // %platform_ex::FAT::FetchPartitionFromPath for platform %DS.
153 ::chdir(root == RootKind::FAT ? "fat:/" : "sd:/");
154 }
155
156 FileSystem::~FileSystem()
157 {
158 if(YB_UNLIKELY(!FAT::Unmount(init_dev)))
159 YF_TraceRaw(Err, "Failed uninitializing file system.");
160 }
161
162 } // namespace platform_ex;
163 #elif YCL_MinGW
164 extern "C"
165 {
166
167 # if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
168 // See FileSystem.cpp.
170 struct ::tm* __cdecl __MINGW_NOTHROW
171 _gmtime32(const ::__time32_t* p)
172 {
173 return std::gmtime(p);
174 }
175 # endif
176
177 } // extern "C";
178 #elif YCL_Android
179 // NOTE: For versions where syscalls available, see http://man7.org/linux/man-pages/man2/syscalls.2.html.
180 // NOTE: Linux kernel version since 2.6.23 should be all OK. For early kernel
181 // versions Android used, see http://elinux.org/Android_Kernel_Versions.
182 // Also https://en.wikipedia.org/wiki/Android_version_history.
183 int
184 linkat(int fd1, const char* path1, int fd2, const char* path2, int flag)
185 ynothrow
186 {
187 // NOTE: The 'linkat' syscall was introduced in Linux 2.6.16.
188 return ::syscall(__NR_linkat, fd1, path1, fd2, path2, flag);
189 }
190
191 int
192 futimens(int fd, const ::timespec times[2]) ynothrow
193 {
194 // NOTE: See https://android.googlesource.com/platform/bionic/+/840a114eb12773c5af39c0c97675b27aa6dee78c/libc/bionic/futimens.cpp.
195 return ::utimensat(fd, {}, times, 0);
196 }
197
198 int
199 utimensat(int fd, const char* path, const ::timespec times[2], int flags)
200 ynothrow
201 {
202 // NOTE: The 'utimesat' syscall was introduced in Linux 2.6.22.
203 // NOTE: See http://stackoverflow.com/questions/19374749/how-to-work-around-absence-of-futimes-in-android-ndk.
204 return ::syscall(__NR_utimensat, fd, path, times, flags);
205 }
206 #endif
207
208 namespace platform
209 {
210 }
211
YF_TraceRaw
#define YF_TraceRaw(_lv,...)
YFramework 跟踪。
Definition: Debug.h:279
platform
默认平台命名空间。
Definition: Container.h:47
platform::follow_link
bool follow_link
Definition: FileIO.cpp:1177
platform::Descriptions::Emergent
Definition: YCommon.h:163
YB_UNLIKELY
#define YB_UNLIKELY(_expr)
分支预测提示。
Definition: ydef.h:464
TryRet
#define TryRet(...)
指定表达式在 try 块中求值并返回。
Definition: YBaseMacro.h:124
CHRLib::CharSet::Null
空字符集。
Definition: Encoding.h:63
YCL_Raise_SysE
#define YCL_Raise_SysE(_t, _msg, _sig)
按错误值和指定参数抛出第一参数指定类型的对象。
Definition: FileIO.h:1178
YB_ATTR
#define YB_ATTR(...)
GNU 风格属性。
Definition: ydef.h:353
CatchExpr
#define CatchExpr(_ex,...)
指定表达式作为异常处理器。
Definition: YBaseMacro.h:129
ynothrow
#define ynothrow
YSLib 无异常抛出保证：若支持 noexcept 关键字， 指定特定的 noexcept 异常规范。
Definition: ydef.h:766
CHRLib::s
_tDst const _tSrc * s
Definition: CharacterProcessing.h:140
platform::sig
const string const char *sig const char * sig
Definition: Debug.h:473
YF_API
#define YF_API
Definition: Platform.h:56
YModules.h
yunused
#define yunused(...)
标记未使用的表达式。
Definition: ydef.h:968
ynothrowv
#define ynothrowv
YSLib 无异常抛出保证验证：有条件地使用无异常抛出规范。
Definition: ydef.h:786
CHRLib::e
const char const char * e
Definition: CharacterProcessing.h:109
platform_ex::YB_NONNULL
YB_NONNULL(1) PDefH(u16string
构造适合表示路径的 char16_t 字符串。
std
Definition: memory.hpp:1183
platform::Nonnull
_type && Nonnull(_type &&p) ynothrowv
断言并返回非空参数。
Definition: Debug.h:422
platform::cstat
cstat(st, path, follow_link, yfsig)
platform::Descriptions::Warning
Definition: YCommon.h:167
platform::Descriptions::Err
Definition: YCommon.h:166
platform_ex
平台扩展命名空间。
Definition: Android.h:45
YSLib::UI::name
yconstfn const string & name
Definition: Loader.h:130
platform::Descriptions
平台描述空间。
Definition: YCommon.h:154
YSLib::IO::int
YF_API int
Definition: File.h:51
YSLib::path
YF_API const char * path
Definition: Initialization.h:77
CHRLib::p
const auto p(d)
platform::ynothrow
const _tString &path ynothrow
Definition: YCLib/FileSystem.h:274