群晖中文未按拼音排序问题排查
群晖桌面是 Web 页面,通过浏览器的 DevTools 可以捕获到点击排序所发出的请求。以下是在 File Station 中点击排序的请求的 Form Data:
offset: 0
limit: 1000
sort_by: "name"
sort_direction: "DESC"
action: "list"
check_dir: true
additional: ["real_path","size","owner","time","perm","type","mount_point_type","description","indexed"]
filetype: "all"
folder_path: "/music"
api: SYNO.FileStation.List
method: list
version: 2
从上可以得到关键信息 api、action 和 sort_direction,这些是排查的重要线索。
SSH 连上群晖,
find / -name FileStation
我们可以发现
/usr/local/packages/@appstore/FileStation
。这很明显就是 File Station 应用所在目录。
找到应用所在目录,接下去就可以找
SYNO.FileStation.List
在哪个文件中出现。通过
grep -rn . -e 'SYNO.FileStation.List | more'
可以进行搜索。会发现
./webapi/SYNO.FileStation.List.so
,很明显这就是处理
SYNO.FileStation.List
的模块。
用 IDA 打开 SYNO.FileStation.List.so,查看字符串 sort_direction 的引用情况,可以看到被
FileStation::FileStationShareHandler::WebFMShareList
函数引用,这个函数又调用了
WfmEnum::WfmLibShareEntryListEnum
,但
WfmEnum::WfmLibShareEntryListEnum
并不在 SYNO.FileStation.List.so 内。
用 grep 搜素包含
WfmLibShareEntryListEnum
的文件,可以发现
./lib/libwebfm.so
,看名字就知道是它了,继续用 IDA 进行分析。可以看到这样的调用顺序
WfmEnum::WfmLibShareEntryListEnum
->
WfmEnum::EntryListSort
->
std::list<DIRENTRY_INFO,std::allocator<DIRENTRY_INFO>>::sort<EnumCompare>
->
EnumCompare
->
EnumCompare::NaturalCmp
->
SLIBCUnicodeUTF8StrCmp
,最后的
SLIBCUnicodeUTF8StrCmp
并不在 libwebfm.so 内。
用 grep 搜索包含
SLIBCUnicodeUTF8StrCmp
的文件,可以发现
/usr/lib/libsynocore.so.6
,也很明显肯定是这里,因为这个函数是个很基础的字符串比较,会被到处用,肯定属于 core。 继续用 IDA 进行分析。 可以看到这样的调用顺序
SLIBCUnicodeUTF8StrCmp
->
SLIBCUnicodeIOpenCollator
->
ucol_open
。
ucol_open
是第三方库 ICU 的函数,我们可以看到传给
ucol_open
的 locale 是个空字符串,根据
ucol_open
的文档说明,如果 locale 是空字符串,则使用 Root Collator,也就是跟你本地 LANG、LC_ALL 设置没有关系。
至此,问题排查结束。结论就是群晖在调用
ucol_open
时使用 Root Collator,而不是根据用户的语言设置来的,所以排序跟语言无关,所以中文不会按拼音排序。
参考: