群晖中文未按拼音排序问题排查
群晖桌面是 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,而不是根据用户的语言设置来的,所以排序跟语言无关,所以中文不会按拼音排序。
参考: