前言
之前在Mac电脑上拷贝文件到Windows电脑时,文件夹里会额外多出文件,就是我们今天要说的.DS_Store文件,当时并没有在意。
昨天在写一个文件流读取功能时,解析一直出问题,后面发现是文件夹里多了.DS_Store文件,导致文件遍历解析出了些问题,过程我就不再详述。
因此也对这个.DS_Store文件产生了一些兴趣,特地分享记录下。
正文
简介
.DS_Store,全称 Desktop Services Store,是Mac OS中保存文件夹自定义属性的隐藏文件,目的在于存储文件夹的自定义属性,例如文件图标位置、视图设置,或背景色等,相当于Windows下的 desktop.ini。.DS_Store 默认放在每个文件夹的下面。
解析
当我们尝试用文本打开时可以发现它是乱码的,我们接下来尝试解读一下它。
我们使用Notepad++,在其 插件-插件管理 添加Hex-Editor插件,安装好此插件后Notepad++可以以十六进制形式打开指定文件。
我们使用Notepad++借助此插件可以打开.DS_Store,可以看到它的十六进制格式。
当然我们也可以使用VSCode,安装hexdump for vscode插件,来显示十六进制格式。
两种方式插件的安装过程略,有兴趣的可以查看相关文章等。
这儿我们使用VSCode结合插件来打开该文件,如下图,我们尝试解析一下该十六进制数据。
关于该文件二进制的结构说明我们可以参考这篇文章 解析.DS_Store文件格式。
.DS_Store文件转为二进制树后,根据上面这篇文章,它的结构大致如下:
- 文件头部(Header)
- 根块
- 偏移部分(Offsets)
- 内容表(Toc)
- 空闲表(FreeList)
文件头部: 通常文件头部用来进行校验,判断这个文件是不是.DS_Store文件(详见代码readHeader方法)。
偏移部分: 偏移部分记录了有关文件中树(叶)块的偏移量信息,这些块存储的都是目录的实际信息,如文件名。获得偏移量需要遍历这个树(详见代码readOffsets方法)。
内容表: 在偏移部分结束后,内容表部分就会呈现出来。他通常存在只有一个名为DSDB的表,并且值为1。这个特殊的表通常引用了我们将要遍历的第一个块的ID(详见代码readTOC方法)。
空闲表: 最后一部分是空闲表,也就是在树中还有哪些地方是没有使用的或者是空闲的模块(详见代码readFreelist方法)。
然后我们使用Java来解析下这个二进制结构数据。代码如下:
1 | public class DataBlock { |
上述代码过程较复杂,有兴趣的可以参考最后面的参考资料部分,先对.DS_Store文件结构有些了解,在看代码就比较容易了。
我们运行上述代码后会看到如下输出:
可以看到这里面包含着我们的一些文件目录信息等,这些文件信息时是当前目录下的所有文件信息。这就可能造成一些安全问题。
有什么安全问题呢?我们来看下。
信息安全问题
当这一文件上传到了web服务器时,往往会带来一定的危害。
它带来的危害是它包含的文件名。MacOs在几乎所有文件夹都创建了一个.DS_Store文件。
信息泄漏(敏感文件)问题:
我们可以在https://en.internetwache.org/scanning-the-alexa-top-1m-for-ds-store-files-12-03-2018/ 这里查看。这篇文章涉及的Internetwache.org网站项目,对Alexa Top 1000的网站的根目录进行扫描,证明在有的网站中的确存在这一文件,导致信息泄漏。通过解析这一文件,他们发现了数据库备份,配置文件,以及一些缓存文件,甚至是密钥。
产生这种情况的原因就是我们在Git合作中,将.DS_Store进行了上传,而后对项目进行了部署。
PS:需要说明的一个事实是,存储在.DS_Store文件中的文件名仅代表本地MacOS系统上的目录内容。这就意味着解析出来的文件列表中有些文件可能不存在于我们的服务器或者要查找的机器上。
解决方案
尽管这样,我们在使用MacOS系统传输文件或者上传文件时,还是要尽量避免该文件的产生。
这个文件除了会记录目录信息,我们在使用程序遍历文件读取时也可能遇到它引起的问题(如我开头所说),我们在版本协作时,也有可能产生由此文件产生的不必要的冲突问题等。
我们处理.DS_Store文件大概有以下一些方法。
通常,在传输文件时,我们可以直接删除文件目录下的.DS_Store文件,如在MacOS上传输文件给Windows系统,这些.DS_Store文件就成了垃圾文件,对我们是毫无用处的。
对于提交给版本控制系统的文件,我们可以将.DS_Store文件加入到.gitignore文件中以达到忽略提交的目的。
如果我们想查询服务器(Linux)或者MacOS上有多少.DS_Store文件,可以使用下面的命令。
1
find . -name '*.DS_Store'
如果要删除它们,可以使用下面的指令。
1
find . -name '*.DS_Store' -type f -delete
上面的两个命令可以查询和删除当前目录下的.DS_Store文件。
PS:在MacOS上删除后会影响到如文件图标位置等问题,需要注意。
我们也可以让.DS_Store文件不在MacOS外接设备上(U盘等)继续生成,如下指令:
1
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool TRUE
如果要开启外接设备继续生成.DS_Store文件,指令如下:
1
defaults write com.apple.desktopservices DSDontWriteNetworkStores -bool FALSE
如果想直接禁止.DS_Store在MacOS上生成,可以使用Asepsis。
Asepsis的工作原理是拦截所有.DS_Store文件的创建或写入,并将它们重定向到 /usr/local/.dscage。 这样 Finder 如常工作,且不会有这种无用文件污染文件系统。
不幸的是,在 OS X 10.11 El Capitan 发布之后,Apple 启用了 System Integrity Protection (SIP),它会阻止 Asepsis 的安装和正常运行。Asepsis 的作者已经放弃了对它的后续支持,因为他不希望用户为了使用这个工具而禁用系统关键安全服务。
然而网上也有相关可以继续使用Asepsis的方法,如这篇文章禁止.DS_store生成,有兴趣的可以看一看。
总结
.DS_Store文件一般情况下是无用文件,也不会造成多大问题,但我们也应该对其存在提高警惕,尤其是在服务器上出现时,我是因为遇到了它造成的一个bug才决定研究下它,同时用程序解析一下锻炼自己,网上关于该文件的解析文章不算多,下面我把一些参考资料分享给大家,希望大家对其有更深的了解。
参考资料
- DS_Store Format
- DS_Store_File_Format
- fdb.php
- 解析.DS_Store文件格式
- Scanning the Alexa Top 1M for .DS_Store files
- mac-dumpster-diving-identifying-deleted-file-references-in-the-trash-ds_store-files-part-1
- mac-dumpster-diving-identifying-deleted-file-references-in-the-trash-ds_store-files-part-2
源码地址
上述代码地址: GitHub .DS_Store Parser